Energy Meter EASTRON SDM120 come leggerlo?

Salve,

sto tentando da parecchio tempo, senza grossi risultati, di comunicare tramite RS 485 MODBUS con l' energy meter in oggetto di cui allego il manuale .
Ho letto e riletto le caratteristiche del protocollo Modbus e a grandi linee ho capito come funziona, sono riuscito anche a stabilire una comunicazione con relativa risposta dal dispositivo tramite software di controllo, oggetto di un mio post di alcuni giorni fa, questo http://forum.arduino.cc/index.php?topic=348036.0. Quello che proprio non riesco a fare è creare una comunicazione con relativa risposta con il parametro che mi serve con Arduino.
Ho trovato alcune librerie RS485 ma purtroppo come capita spesso sono poco o nulla commentate/spiegate in maniera chiara limitandosi a qualche esempio striminzito...
Dopo questo preambolo vi chiedo se qualcuno ha già utilizzato l' energy meter in oggetto ed in caso affermativo se può allegare la parte del listato per ottenere un parametro qualsiasi, base che mi servirà per capirci qualcosa in più e casomai lavorarci per modificarlo alle mie esigenze.
Grazie in anticipo

PS: link ai manuali
http://ge.tt/3kJRRRO2/v/0?c
http://ge.tt/9tdgRRO2/v/0?c

Ho aggiunto i link ai manuali nel post precedente

Ciao,
sono quasi nella stessa tua situazione, solo che non ho ancora con me l’energy meter sdm120c.
Nel frattempo però sto cercando in rete qualcosa che io poi possa modificare e caricare su Arduino.
Al momento, dopo svariate ricerche, ho trovato quello che secondo me, con un minimo di adeguamento, può fare al caso nostro:

#include <ModbusMaster.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
ModbusMaster node(1);

void setup() {
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW);
  node.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
uint16_t m_startAddress=0x07D6;
uint8_t m_length=2;
uint8_t result;

  lcd.clear();

  result = node.readHoldingRegisters(m_startAddress, m_length);
  //result = node.readInputRegisters(m_startAddress, m_length);
 
  if (result == node.ku8MBSuccess) {
    lcd.print("DATA: ");
    for (uint8_t j = 0; j < m_length; j++)
       {
       lcd.print(node.getResponseBuffer(j), HEX);
       }
  }
  else {
    lcd.print("ERR ");
    lcd.print(result, HEX);
  }
  delay(1000);
}

Ovviamente bisognerà cambiare i valori di m_startAddress=0x07D6 e m_length=2 sulla base del valore che vuoi leggere dall’energy meter facendo riferimento alle tabelle presenti sui manuali che tu hai linkato.
Questo sketc prevede output su lcd, con semplici modifiche ovviamente si può stampare direttemente su seriale.
Fammi sapere se dovessi fare delle prove e se dovessi avere dei risultati soddisfacenti.
Io devo ancora ordinarli (me ne servono 2) e non posso fare ancora alcuna prova, arghhhhh!!

Ciao,

Enzo

Ciao Enzo,
ho letto con interesse il tuo post ed avrei da chiederti una cosa:
nel listato non vedo nessuna indicazione a come connettere fisicamente il bus 485 ad Arduino ossia non vedo nessuna dichiarazione dei pin del bus 485.

Attualmente il SDM120 lo collego al pc tramite convertitore 485> USB e tramite sw di simulazione riesco a comunicare correttamente.

Questo che segue è uno sketch per SDM320 ma dovrebbe andare bene anche per il tuo SDM120 (il protocollo è identico). E’ scritto per arduino mega e sfrutta la serial1 per il modbus (Rx=pin19, Tx=pin18) lasciando libera la serial per il monitor. Se hai una sola seriale hardware devi un pò adattarlo.

#include <SimpleModbusMaster.h>

//////////////////// Port information ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate

#define retry_count 10

// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2 

enum
{
  PACKET1,
  TOTAL_NO_OF_PACKETS // leave this last entry
};

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

packetPointer packet1 = &packets[PACKET1];

unsigned int readRegs[2];

unsigned long currentMillis;
long previousMillis = 0;
long interval = 1000;


void setup()
{
  // read 2 registers starting at address 0  
  // This is the Line to neutral voltage
  // The value received needs to be transposed to floating value
  modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 2, readRegs);
 
  modbus_configure(&Serial1, baud, SERIAL_8E1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}

void loop()
{
  modbus_update();
  
  // shift and cast value to float
  float voltage;
  unsigned long temp = (unsigned long)readRegs[0] << 16 | readRegs[1];
  voltage = *(float*)&temp;
  
  // use the following code to avoid using delay()
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    Serial.print("Low byte: ");
    Serial.println(readRegs[0]);
    Serial.print("High byte: ");
    Serial.println(readRegs[1]);
    Serial.print("Voltage: ");
    Serial.println(voltage);
    Serial.println("********");
    previousMillis = currentMillis;
  }
}

Perfetto, grazie della dritta.

Ai pin che citi (TX -Rx) non posso attaccarci direttamente il bus 485 vero?
Devo adottare questo schema ?

Grazie

Per fare dei test va bene lo schema che hai linkato.

Franchelli:
Ai pin che citi (TX -Rx) non posso attaccarci direttamente il bus 485 vero?

Puoi usare dei moduli come questo
http://www.ebay.it/itm/RS485-To-TTL-RS485-module-SP3485-communication-module-RS-485-Breakout-TOP-/321530549888?hash=item4adcb6d680
Da completare con i pin e la morsettiera.

Datasheet → https://www.sparkfun.com/datasheets/Components/General/sp3485CN-LTR.pdf

Ora che mi sono arrivati i moduli RS485 questi
http://www.lctech-inc.com/Hardware/Detail.aspx?id=608101e2-7167-4926-bd6d-b49c5b9465e7
riprendo in mano il thread per cercare di leggere qualche dato da questo misuratore di enegia

Sia nel post di marinaio67 che di Enzo_Arduino non trovo (o non capisco io) come collegare il convertitore in oggetto.

Qualcuno mi puo aiutare a venirne fuori?
Grazie mille

Colleghi A con A e B con B. Può darsi che tu debba aggiungere le resistenze di terminazione da 120ohm. Una normale rete rs485.

Ok, questo l'avevo capito, è lato arduino che non ho capito come collegarlo: sul sensore mi trovo le diciture DI DE RE RO .

R0 <—> Rx
DI <—> Tx
DE+RE <—> Pin digitale (esempio Pin 2)
Per ricevere Pin 2=LOW ; per trasmettere Pin 2=HIGH
Se hai un Mega usa la serial1 così la 0 resta per il terminale; se hai un Uno puoi usare la SoftwareSerial

Volendo connettere il modulo rs485 al misuratore per interrogarlo tramite software sul PC dovrei creare questa catena( e correggetemi se sbaglio): [USB] convertitoreUSB>TTL >>> modulo RS485 >>> [bus 485]

Convertitore USB>TTL https://tinyurl.com/hx5ydv2

Per fare una verifica prima di questo ho utilizzato un modulo che riunisce questi due componenti quindi un modulo USBRS485 ed interrogando il misuratore con il software, il tutto funziona correttamente riuscendo a leggere senza problemi i valori richiesti.
Con la catena suddetta questo non avviene. Ho controllato con l'oscilloscopio l'uscita dei pin DTR e CTS e sono sempre alti anche quando avviene l'interrogazione da parte del software. Probabilmente è questo che impedisce al modulo RS 485 di porsi in trasmissione e ricezione quando necessario. Questo cambiamento di stato avviene correttamente con il convertitore "all in one". Ho verificato andando a pescare il segnale sui pin del medesimo integrato che fa la funzione di conversione RS485 (il MAX 485).

Mi chiedo una cosa: i pin DTR e CTS come vengono utilizzati e qual'è il loro funzionamento tipico ? Dove sto sbagliando?

Appena risolto questo problema passerò a capire come sfruttare il modulo RS485 con Arduino...
Grazie

Franco ti allego una libreria modbus modificata per il tuo energy meter. Non è farina del mio sacco ma dovrebbe funzionare. Lo sketch d esempio che è all’interno, usa la serial1 dell’arduino mega. Fammi sapere.

SimpleModbusMasterSDM120.zip (8.89 KB)

Franco ti rispondo qui al messaggio così l'informazione resta a beneficio di tutti... Mi fa piacere che ti funzioni, anche se ti da qualche piccolo errore... La libreria l'ho trovata qui e come vedi, è una discussione di questi giorni ed è quindi comprensibile che la libreria abbia ancora qualcosa da sistemare. La discussione è in spagnolo, ma se riesci a mandargli qualche feedback, credo che gli faccia piacere e magari riescono a risolvere anche quegli errori che ti dava al momento che spegnevi il carico.

Grazie mille, quel sito non lo conoscevo. Ho scritto e spiegato i problemi e vedo che sono molto attivi e disponibili. Qualora pure qui ci sia qualcuno veramente ferrato e volenteroso allego lo sketch su cui ci sono i problemi di instabilita di lettura:

/*  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);  
 } 
}

Invece la libreria utilizzata è quella allegata.
La connessione di Arduino al SDM120 avviene ma dopo poche letture rispondenti a realtà i valori di tensione e corrente visualizzati si invertono così come quelli di potenza ed energia. Alle volte taluni valori sono irreali. Facendo visualizzare solo un valore per volta (disabilitando quindi parti di codice) questo è sempre corretto mentre gia con due valori visualizzati dopo un po’ avviene il problema suddetto. La libreria contiene all’interno delle variabili utilizzabili per il debug ma onestamente non ho capito come utilizzarle.
Se ci sono delle news sul sito spagnolo, provvederò riportarle qui per conoscenza.

SimpleModbusMasterSDM120Modif.zip (22.1 KB)

Ciao ho provato le sketch su arduino mega e funziona bene :slight_smile: .Chiedevo se è possibile aggiungerne altri SDM120C .grazie

I apologize but I do not understand Italian :slight_smile:
Will you please tell me which code works better, this one here is posted or that the link GitHub - peninquen/Modbus-Energy-Monitor-Arduino: A class to collect data from a energy monitor that uses modbus protocol. , which is in Spanish?

Ciao a tutti,
ho installato questo energy meter: eastron sdm230-pulse manuale PDF
Ha solo l'uscita pulse e il manuale dice che e' passiva...
Non sono riuscito a utilizzarla per fare scattare un interrupt su arduino per leggere l'impulso.
Qualcuno puo' darmi qualche dritta per piacere?

grazie!!

>paonza: buonasera, essendo il tuo primo post, nel rispetto del regolamento, ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo