Regulador Morningstar TriStar MPPT a través de modbus

Mi familia tiene una casa en la montaña con una pequeña instalación solar(1240Wp) de la cual escribiré dando mas detalles en otro momento. El caso es que como regulador de carga utilizo un MPPT de la marca MorningStar, en concreto el modelo TS-MPPT-60. Con este regulador tenemos la opción de comprar y conectarle un pequeño display lcd para visualizar la información de carga y por otra parte también  nos ofrece la posibilidad de conexión mediante rs-232, EIA-485 y ethernet con interfaz web. La interfaz web nos perm

Lo primero que tenemos que hacer es descargar la librería libmodbus  y después la compilamos e instalamos.
 wget http://github.com/downloads/stephane/libmodbus/libmodbus-3.0.1.tar.gz tar -zxvf  libmodbus-3.0.1.tar.gz cd libmodbus-3.0.1 ./configure --prefix=/usr make sudo make install
  Una vez ya tenemos la librería instalada solo tenemos que escribir un pequeño programa que nos permita extraer la información del regulador de carga para lo cual haremos uso de las especificaciones que el fabricante pone a nuestra disposición en las que indica en que dirección se encuentra cada dato y como tratarlo para obtener el valor real. Este programa es específico para nuestro caso pero podemos adaptarlo a cualquier otro aparato que utilice Modbus.
 /*
Copyright (C) 2011 Jesus Perez <jepefe@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License at <http://www.gnu.org/licenses/>
for more details.
*/

/* Compile: gcc mppt.c -o mppt -lmodbus */
/* Run: ./mppt IP PORT */

#include <stdio.h>
#include <stdlib.h>
#include <modbus/modbus.h>

double valuemod(int i, uint16_t *tab);
void main(int argvc, char *argv[]){
  modbus_t *mb;
  uint16_t tab_reg[92];
  int i=0;
  //Nombre de las variables y direccion logica segun el datasheet
 enum var_name {
V_PU=1, V_PU_LO, I_PU, I_PU_LO, ver_sw, adc_vb_f_med=25, adc_vbterm_f,
 adc_vbs_f, adc_va_f, adc_ib_f_shadow,adc_ia_f_shadow, adc_p12_f,
adc_p3_f, adc_pmeter_f, adc_p18_f, adc_v_ref, T_hs, T_rts, T_batt,
adc_vb_f_lm, adc_ib_f_lm, vb_min, vb_max, hourmeter_HI, hourmeter_LO,
 faultall, alarm_HI=47, alarm_LO,dip_all, led_state, charge_state,
vb_ref, ahc_r, ahc_r_LO, ahc_t_HI, ahc_t_LO, kwhc_r,kwhc_t,
power_out_shadow, power_in_shadow, sweep_Pin_max, sweep_vmp, sweep_voc,
 vb_min_daily=65,vb_max_daily, va_max_daily, ahc_daily, whc_daily,
flags_daily, pout_max_daily, tb_min_daily,tb_max_daily, fault_daily,
alarm_daily_hi=76, alarm_daily_lo, time_ab_daily, time_fl_daily,
vb_ref_slave=90,va_ref_fixed, va_ref_fixed_pct};

  //Nombres de las variables para mostrar
  char *var_label[]= {
"V_PU", "V_PU_LO", "I_PU", "I_PU_LO", "ver_sw","RESV",
"RESV","RESV","RESV","RESV","RESV","RESV","RESV","RESV","RESV","RESV",
"RESV","RESV","RESV","RESV","RESV","RESV","RESV","RESV","adc_vb_f_med",
"adc_vbterm_f", "adc_vbs_f", "adc_va_f", "adc_ib_f_shadow","adc_ia_f_shadow",
"adc_p12_f", "adc_p3_f", "adc_pmeter_f", "adc_p18_f", "adc_v_ref", "T_hs",
"T_rts", "T_batt","adc_vb_f_lm", "adc_ib_f_lm", "vb_min", "vb_max",
"hourmeter_HI", "hourmeter_LO", "faultall", "RESV", "alarm_HI","alarm_LO",
"dip_all", "led_state", "charge_state", "vb_ref", "ahc_r", "ahc_r_LO",
"ahc_t_HI", "ahc_t_LO", "kwhc_r","kwhc_t", "power_out_shadow", "power_in_shadow",
"sweep_Pin_max", "sweep_vmp", "sweep_voc","RESV", "vb_min_daily","vb_max_daily",
"va_max_daily", "ahc_daily", "whc_daily", "flags_daily", "pout_max_daily",
"tb_min_daily","tb_max_daily", "fault_daily", "RESV","alarm_daily_hi",
"alarm_daily_lo", "time_ab_daily", "time_fl_daily","RESV","RESV","RESV","RESV",
"RESV","RESV","RESV","RESV","RESV","vb_ref_slave", "va_ref_fixed",
"va_ref_fixed_pct"};

  //Creamos una nueva conexion tcp indicando IP y puerto
mb = modbus_new_tcp(argv[1], atoi(argv[2]));
modbus_set_slave(mb,1);

//Conectamos con el dispositivo
modbus_connect(mb);
 if ( mb == NULL ) printf("Error al conectar\n");

//Leemos los registros desde el 0 al 91
modbus_read_registers(mb, 0,91, tab_reg);

//Mostramos datos realizando las operaciones que nos indica el fabricante
for(i=0;i<91;i++){
         printf("%s:%.3f\n ",var_label[i],tab_reg[i]*valuemod(i,tab_reg));
        }

  modbus_close(mb);
  modbus_free(mb);
}

double valuemod(int id, uint16_t *tab){
	/*Dependiendo de la direccion del registro
          realizamos las operaciones correspondientes*/
        double val;
        switch(id){
                case 24:
                case 25:
                case 26:
                case 27:
                case 38:
                case 40:
                case 41:
                case 51:
                case 61:
                case 62:
                case 64:
                case 65:
                case 66:
                case 89:
                case 90:
                   val = tab[0]*0.000030518;
                break;
                case 28:
                case 29:
                case 39:
                  val = tab[2]*0.000030518;
                break;
                case 58:
                case 59:
                case 60:
                case 70:
                  val = tab[0]*tab[2]*0.0000076294;
                break;
                default:
                 val=1;

        }
return val;
}
Con este código solo accedemos los registros de la RAM, para acceder a la EEPROM leeremos a partir del registro 0x151B. El código no está nada optimizado y no muestra todos los valores, pero sirve como base y con poco que se indague uno puede adaptarlo a sus necesidades fácilmente. Actualmente el código lo ejecuto compilado para la arquitectura MIPS en un router Comtrend de Jazztel con firmware OpenWRT, ya os explicare como compilarlo y utilizar un móvil Android y RPC para visualizar los datos que nos ofrece el regulador.

Categories

Development

Tags

C modbus
comments powered by Disqus