Solved.
Now i have the two SDM630 and the two Arduino Nano slaves on the same Modbus network and they all send data to my Modbus Master, Arduino Uno. See attached layout image.
Modbus Master
#include <SoftwareSerial.h>
#include <ModbusM485RTU.h>
#include <LiquidCrystal_I2C.h>
SoftwareSerial swSerSDM(6, 7);
SDM sdm(swSerSDM, 9600, 5);
LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup() {
Serial.begin (9600);
sdm.begin();
lcd.begin(20,4);
lcd.setCursor(1,0);
lcd.print("Home");
lcd.setCursor(1,1);
lcd.print("Version_M_v927");
lcd.setCursor(1,2);
lcd.print("Mr. ZYX");
lcd.setCursor(0,3);
lcd.print("--------------------");
delay(5000);
lcd.clear();
}
void loop() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("KAM-ID3(W):");
lcd.setCursor(11,0);
lcd.print(sdm.readVal(KAM382_POWERTOTAL_1, 0x03), 2);
lcd.print(" ");
delay (200);
lcd.setCursor(0,1);
lcd.print ("KAM-ID3(W):");
lcd.setCursor(11,1);
lcd.print(sdm.readVal(KAM382_POWERTOTAL_2, 0x03), 2);
lcd.print(" ");
delay (200);
lcd.setCursor(0,2);
lcd.print ("SDM-ID1(W):");
lcd.setCursor(11,2);
lcd.print(sdm.readVal(SDM630_POWERTOTAL, 0x01), 2);
lcd.print(" ");
delay (200);
lcd.setCursor(0,3);
lcd.print ("SDM-ID2(W):");
lcd.setCursor(11,3);
lcd.print(sdm.readVal(SDM630_POWERTOTAL, 0x02), 2);
lcd.print(" ");
delay (2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print ("KAM-ID4(W):");
lcd.setCursor(11,0);
lcd.print(sdm.readVal(KAM382_POWERTOTAL_1, 0x04), 2);
lcd.print(" ");
delay (200);
lcd.setCursor(0,1);
lcd.print ("KAM-ID4(W):");
lcd.setCursor(11,1);
lcd.print(sdm.readVal(KAM382_POWERTOTAL_2, 0x04), 2);
lcd.print(" ");
delay (2000);
}
Modbus Slav ID:3
#include <LiquidCrystal_I2C.h>
#include <ModbusS485RTU.h>
#define TXEN 5 // RE/DE Pin for MAX485
#define ID 3 // Set slave ID on Mudbus network
Modbus slave(ID,0,TXEN); // 0 stands for Hardwareserial
uint16_t au16data[6]; // Array for Calculated IEEE745 values.
// [0] and [1] is not in use.
// [2] and [3] is for value from IRQ 0 = pin2 / D2. Master query: start address 0x0002 and read two adresses.
// [4] and [5] is for value from IRQ 1 = pin3 / D3. Master query: start address 0x0004 and read two adresses.
volatile unsigned long counter = 0;
volatile unsigned long lastImpulse = 0;
volatile unsigned long diffImpulse = 0;
float currentWatt = 0;
float LcdcurrentWatt = 0;
int byte_1_0 = 0;
int byte_1_1 = 0;
int byte_1_2 = 0;
int byte_1_3 = 0;
volatile unsigned long counter2 = 0;
volatile unsigned long lastImpulse2 = 0;
volatile unsigned long diffImpulse2 = 0;
float currentWatt2 = 0;
float LcdcurrentWatt2 = 0;
int byte_2_0 = 0;
int byte_2_1 = 0;
int byte_2_2 = 0;
int byte_2_3 = 0;
LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup()
{
slave.begin( 9600 );
lcd.begin(16,2);
lcd.setCursor(0,0);
lcd.print("Home S_v67");
lcd.setCursor(0,1);
lcd.print("Kam382 Slave:");
lcd.setCursor(13,1);
lcd.print(ID);
delay(3000);
lcd.clear();
attachInterrupt(0, onPulse, FALLING); // KWH interrupt attached to IRQ 0 = pin2 / D2
attachInterrupt(1, onPulse2, FALLING); // KWH interrupt attached to IRQ 1 = pin3 / D3
}
void loop()
{
noInterrupts();
LcdcurrentWatt = currentWatt;
LcdcurrentWatt2 = currentWatt2;
interrupts();
lcd.setCursor(0,0);
lcd.print("EL-1(W):");
lcd.setCursor(8,0);
lcd.print(LcdcurrentWatt);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print ("EL-2(W):");
lcd.setCursor(8,1);
lcd.print(LcdcurrentWatt2);
lcd.print(" ");
Bytebreakout1 (LcdcurrentWatt); // Make IEEE 745 Bytes of calculated energy meater value
au16data[2] = ((unsigned int)byte_1_0 << 8) + byte_1_1; // merge two bytes into oa 16-bit value and put it in the array.
au16data[3] = ((unsigned int)byte_1_2 << 8) + byte_1_3;
Bytebreakout2 (LcdcurrentWatt2);
au16data[4] = ((unsigned int)byte_2_0 << 8) + byte_2_1;
au16data[5] = ((unsigned int)byte_2_2 << 8) + byte_2_3;
slave.poll(au16data ,6 ); // Modbus recieve query and send back data.
}
void Bytebreakout1(float f1)
{
byte * b = (byte *) &f1;
byte_1_3 = (b[0]);
byte_1_2 = (b[1]);
byte_1_1 = (b[2]);
byte_1_0 = (b[3]);
}
void Bytebreakout2(float f2)
{
byte * b = (byte *) &f2;
byte_2_3 = (b[0]);
byte_2_2 = (b[1]);
byte_2_1 = (b[2]);
byte_2_0 = (b[3]);
}
void onPulse()
{
unsigned long currentImpulse = millis();
// Increment counter
counter++;
// Calculate current Watt usage by measuring the time difference between two impulses
if (lastImpulse != 0) { // we can now calculcate
diffImpulse = currentImpulse - lastImpulse;
currentWatt = long((3600UL * 1000UL) / diffImpulse); // 2500UL for energy meters whit 400imp/kWh and 1000UL for energy meters whit 1000 imp/kWh.
}
lastImpulse = currentImpulse;
}
void onPulse2()
{
unsigned long currentImpulse2 = millis();
// Increment counter
counter2++;
// Calculate current Watt usage by measuring the time difference between two impulses
if (lastImpulse2 != 0) { // we can now calculcate
diffImpulse2 = currentImpulse2 - lastImpulse2;
currentWatt2 = long((3600UL * 1000UL) / diffImpulse2); // 2500UL for energy meters whit 400imp/kWh and 1000UL for energy meters whit 1000 imp/kWh.
}
lastImpulse2 = currentImpulse2;
}
As you can see, there is still some improvement to do. But not critical.
- Replace delays in the Master sketch.
- Replace duplicate use of void functions in the slave sketch.
- Use Control Structure “for” to reduce the amount of code.
Next step is to:
- Implement WiFi on the Uno.
- Send data to KepServerEX
- Publish data on a WEB page.
//--------------------------------------//
A little heads up about this line:
LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
Bee aware that the address “0x3f” could be different between LCD displays of the same type. I had one with the address 0x3f (Slave ID:3) and one with 0x27 (Slave ID:4). Very time consuming.
//-------------------------------------//
Thanks all for the support.
All files is attached down below.
// Vind
sdm630kam382_Master_v927.ino (1.76 KB)
Slave_KAM382v67.ino (4.08 KB)
Slave_KAM382v68.ino (4.08 KB)
ModbusM485RTU.zip (4.35 KB)
ModbusS485RTU.zip (5.42 KB)