AC - ENERGY Meter monitor


#1

Dear Cayanne group

I’d like to connect energy metter ( SDM 120 ) to your system.

Everybody can get this energy meter from the any china store or european store.

From the beginning I can mentioned that we have a CODE for this energy meter, and it’s also running under our system. But our development is stoped now.

I’d like to share how to connec it and you can have it as a new module for add.

Connection is running via RS485 ( modbus ), you can connect it via CHIP ( CH340 USB ) on each raspberry PI.

See what we have now adn what we can share with you:

You can see frequency of AC network
Current IN and OUT
AC Voltage
and count of energy consumption

Can somebody help me to run it under your cayanne?

Please provide me some feedback or contact me for cooperation and help on my email gerek@esolar.sk

Thank you and looking for your feedback.


#2

Hi @gerek,

It would probably be best to get it going on Arduino first. Pi will take more effort.

Looks like there is some code already here:

/*  SDM120C Modbus RTU Protocol con Arduino.
*  version 0.0.4  by @cosmopaco. 
*  modified by Electra.
*  Materiales 
*    Arduino Mega
*    Modulo RS485 
*    Conexiones (Configuracion por defecto) Puerto serial 1
*    Arduino pin   Modulo RS485 pin
*    19            RO (receive out) 
*    18            DI (data in)
*    17            DE/RE (data enable/receive enable).
*    
*  
*/
#include <SimpleModbusMasterSDM120.h>

// Direcciones registros de datos solo lectura. Valores tipo float.
// Utilizar funcion 04 lectura, numero de bytes 4.
// Las marcadas en MAYUSCULAS son las de el este ejemplo.

 #define VOL_ADR 0X0000    // VOLTAJE.
 #define CUR_ADR 0X0006    // CORRIENTE.
 #define POW_ADR 0X000C    // POTENCIA ACTIVA. 
 #define VAM_ADR 0X0012    // Potencia Aparente.
 #define PRE_ADR 0X0018    // Potencia Reactiva.
 #define PFA_ADR 0X001E    // Factor de potencia.
 #define FRE_ADR 0X0046    // Frecuencia.
 #define ENE_ADR 0X0048    // ENERGIA IMPORTADA KWH
 #define POE_ADR 0X004A    // Energia exportada.
 #define NEE_ADR 0X0156    // Energia activa Total.
//

/*
Constants are provided for:
  Function 1  - READ_COIL_STATUS
  Function 2  - READ_INPUT_STATUS
  Function 3  - READ_HOLDING_REGISTERS 
  Function 4  - READ_INPUT_REGISTERS
  Function 15 - FORCE_MULTIPLE_COILS
  Function 16 - PRESET_MULTIPLE_REGISTERS 

   Valid modbus byte formats are:
    SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
    SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
    SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
*/
// Estos parametros son un poco confusos dependiendo del manual la opción por defecto puede cambiar.
// Verificar que realmente tiene estos parametros.
 #define SDM120C_METER_NUMBER   1                
 #define SDM120C_BAUDRATE       2400
 #define SDM120C_BYTEFORMAT     SERIAL_8N2    //Prty n
// 


 #define TIMEOUT 1000
 #define POLLING 2000    // the scan rate 
 #define RETRYCOUNT 10   // numero de reintentos, para volver set the "connection" variable to true.
 #define TXENPIN  17     // Pin cambio recibir/trasmiste para el driver RS485


// Direcciones registros de configuración lectura/escritura  Valores tipo HEX.
// Utilizar funcion 10 escritura, 04 lectura numeor de bytes 1.

// IMPLEMENTAR.

// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
 PACKET1,
 PACKET2,
 PACKET3,
 PACKET4,
 TOTAL_NO_OF_PACKETS // leave this last entry
};

// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];

// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer volPacket = &packets[PACKET1];
packetPointer curPacket = &packets[PACKET2];
packetPointer powPacket = &packets[PACKET3];
packetPointer enePacket = &packets[PACKET4]; 
 
// Union 
union datas{
 byte  b[4];
 float f;
 unsigned int Array[2]; 
}voltage, current ,power, energy;

void setup() {

 // modbus_construct(packet, id, function, address, data, register array)    
 // For functions 1 & 2 data is the number of points
 // For functions 3, 4 & 16 data is the number of registers
 // For function 15 data is the number of coils
 modbus_construct_SDM120(volPacket, SDM120C_METER_NUMBER, VOL_ADR, voltage.Array);
 modbus_construct_SDM120(curPacket, SDM120C_METER_NUMBER, CUR_ADR, current.Array);
 modbus_construct_SDM120(powPacket, SDM120C_METER_NUMBER, POW_ADR, power.Array);
 modbus_construct_SDM120(enePacket, SDM120C_METER_NUMBER, ENE_ADR, energy.Array);
 
 /* Initialize communication settings:
    parameters(HardwareSerial* SerialPort,
   long baud, 
   unsigned char byteFormat,
   unsigned int timeout, 
   unsigned int polling, 
   unsigned char retry_count, 
   unsigned char TxEnablePin,
   Packet* packets, 
   unsigned int total_no_of_packets);

    Valid modbus byte formats are:
    SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
    SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
    SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
    
    You can obviously use SERIAL_8N1 but this does not adhere to the
    Modbus specifications. That said, I have tested the SERIAL_8N1 option 
    on various commercial masters and slaves that were suppose to adhere
    to this specification and was always able to communicate... Go figure.
    
    These are already defined in the Arduino global name space. 
 */ 
 // Iniciamos comunicación modbus SERIAL1 Arduino Mega.
 modbus_configure(&Serial1, SDM120C_BAUDRATE, SDM120C_BYTEFORMAT, TIMEOUT, POLLING, RETRYCOUNT, TXENPIN, packets, TOTAL_NO_OF_PACKETS);
 
 //Iniciamos puerto serial"0" Arduino Mega para visualizar datos.
 Serial.begin(9600);
 Serial.println(F("Test SDM120-Modbus"));
 pinMode(13, OUTPUT);  // Led pin de Arduino Mega;
 digitalWrite(13, LOW);
}

void loop() {
 static boolean b = false ;
 static unsigned long oldMillis;  
 modbus_update();
 if( (millis()-oldMillis) > POLLING){
   unsigned long temp;
   float v;
   digitalWrite(13,b);
   b++;    
   oldMillis=millis();
   
   Serial.println("    MEDIDAS:");
   
   v = (float)voltage.f;
   Serial.print(F(" Voltaje="));
   Serial.println(v, 1);
   
   v= (float)current.f;
   Serial.print(F(" Corriente="));
   Serial.println(v, 2);
   
   v= (float)power.f;
   Serial.print(F(" Potencia="));
   Serial.println(v, 1);
   
   v= (float)energy.f;
   Serial.print(F(" Energia="));
   Serial.println(v, 2);  
 } 
}

Cheers,

Craig