I had obtained three samples of a DDM18SD DIN rail mounted energy meter unit. I got mine from a UK supplier on eBay, but they are available here at AliExpress and in many different places. The unit I obtained was a single phase unit for directly measuring up to 5A and 240V AC, but up to 100A with a 100:5 current transducer.
The best thing about this unit is that, apart from having a display of the various values on the front, it also has an RS485 interface which uses MODBUS-RTU to get and set information from the meter. This should allow me to get voltage, current, power factor, real and reactive power, which I can the record with a datalogger. It also has a pulse output for every 1/1000th of a kWh. This might be useful, but more info from the RS485 is better!
Getting set up I put the unit into a decent enclosure with the display through the top. I’m only using an amp or so, so thin cables used for this test version. When it started up it showed 021 (unit ID) , 9600 (baud rate) , 1000 (impulses per kWh) and then starts to display the parameters.
I set up a Sparkfun USB to RS485 converter. I had used this before for initial testing of RS485 networks. It’s incredibly useful, especially for initial set-up & fault finding! I installed RealTerm onto my (Windows) computer. This is a highly configurable serial port terminal read/write program which is highly recommended.
I read from the booklet (also info in the AliExpress link above) that the voltage from the unit can be obtained by requesting data from a specific register (this is MODBUS-RTU protocol). You need to have the device ID and also a CRC (error) check. I used the example from the booklet of sending “01 04 00 00 00 02 71 CB”. This is in HEX. So to send that I needed to write “0x01 0x04 0x00 0x00 0x00 0x02 0x71 0xCB”. I sent this info, but got nothing back!
So I realised I had the wrong device ID. This request is for device ID “01” and my unit is 021 according to the start up menu. So I tried with “21 04 00 00 00 02 76 AB”. The “76 AB” were calculated with an online CRC calculator, here. I put in the first part of the hex number and clicked on “HEX”. I then calculated CRC-16, as this is a 4 digit HEX CRC check. You then need to scroll down to CRC-16/MODBUS and this is the CRC to use. But you also need to put the last two digits first (so “AB76” becomes “76AB”). So I tried this out, but still got nothing back!!
So the next thing I realised is that I have the device ID in decimal, not HEX. So converting 21 (decimal) into 15 (HEX) and then re-calculating the CRC check, I got “15 04 00 00 00 02 72 DF”. I put this into RealTerm and sent the line “0x15 0x04 0x00 0x00 0x00 0x02 0x72 0xDF”. I got something back!! Whoop! So now I know that communications works and that I have A and B of the RS485 correct.
The next step was to use an Arduino Nano unit and a MAX485 module. These are both freely available and low cost. The MAX485 unit is ‘half duplex’ which means you have to control when the unit is sending data and when it is receiving data. This is done with an additional digital pin and I soldered together the DE/RE pins so I just had one wire to this joint pin. I connected digital pin 10 to Software Serial Rx, digital pin 11 to Software Serial Tx and digital pin 9 to the DERE pin. Excuse the bad photo and wiring, but this was a quick test!
I found an arduino library for these energy meter modules. There are a range of energy meters, including the SDM (three phase units) and the DDM (single phase units). The Arduino library (SDM_Energy_Meter) is not in the library repository, so I needed to download the .zip from the GITHUB repository and install using the ‘install .zip’ in Arduino IDE. This has a config file to control the baud rate and digital pins required. I adjusted this for my set-up and uploaded code.
It worked and started to send data via the RS485 (I checked by looping the data back into my computer through the USB-RS485 unit). But the data was not correct. It only showed me the correct data when I set the ‘Parity’ to NONE for the serial settings. So something is not right. I checked the Energy Meter booklet again and it says that the unit must have ‘EVEN’ parity. Parity looks at all the bits in the byte being sent. With EVEN parity, if the total number of set bits are odd, then it is set high (to make total bits set high even). If the total set bits are even, then this is set to zero.
I did a double check with my DDM18SD unit. I used the USB-RS485 converter and sent the correct code with no parity. There was no reply from the unit. If it was set to even parity then it worked and I got an answer back. So I needed EVEN parity. I was using SoftwareSerial for the serial comms to the MAX485. I needed to keep the hardware serial free for other uses. But SoftwareSerial arduino library does not let you set the parity. There is no parity on that library.
So I needed to find a software serial library with parity. I found this called (you guessed it) ‘SoftwareSerialParity’. This did not work directly with the SDM library. I needed to change all the references to SoftwareSerial to SoftwareSerialParity. I also needed to add the baud and parity type to the begin command of SoftwareSerialParity. This took a bit of messing around. I decided to bring the two libraries into my project, as I had converted them slightly. I needed to remove references within my arduino library folder (as they conflicted). And I also used local references for the .h files. But this seemed to work and I uploaded the code & it built. I then looked at the output on the USB-RS485 converter and, sure enough, I was seeing the correct HEX data being sent when ‘EVEN’ parity was selected.
The next thing was to wire this up to my DDM18SD and try and get data back. This worked OK! See the RS485 terminal here and the arduino serial port output:
In that blob of code you can (maybe) see that I am sending “15 04 00 00 00 02 72 DF” and then I get back a bit of data. The arduino code converts that into the value, which can be seen on the serial port. This is voltage and shows 247.00V..
I’ve done a quick repository for this simple test code which works with an Arduino Nano talking to the DDM18SD with a MAX485 and EVEN parity. The repository is here if it is useful to you:
Hope thats some use to others – it took me a day or so of head scratching to get to this point. I’m going to incorporate the code into my remote monitoring unit to relatively easily measure isolated AC powers.
Using a Pro-Mini 3.3V Unit to talk to the DDM18SD
I wanted to use the unit with an Arduino Pro Mini running at 3.3V. This caused more issues! I used the 3.3V version of the MAX485 (The MAX3485, from Farnell here). I replaced the MAX485 on the converter board I had. Also I needed to lower the baud rate for the data from 115200 for serial and 9600 for software serial to 57600 for serial and 1200 for software serial. This did not work! I can see that the data is being written correctly and being returned correctly, but the softwareserial buffer returns all zeros. I can do fake data which does show using the RS485 unit. The code runs correctly on a Nano powered by 5V. So I think maybe something to do with timing for the software serial port?
I tried changing the baud rate to 2400 to see if that helped.
To do this I check the example to change to 1200 baud rate, which was: 01 10 00 00 00 02 04 “44 96 00 00” 07 73. The bit in quotes is the baud rate value, but how?…
I used this conversion program to change from HEX to floating point: https://gregstoll.com/~gregstoll/floattohex/
I can see that in an example writing 44 96 00 00 sets 1200 baud rate. Using the above converter I can see that 44 96 00 00 is 1200 in floating point.
So I converted 2400 to hex which is 45 16 00 00. With my ID number of 15 & with CRC applied the actual code to send is: 15 10 00 00 00 02 04 45 16 00 00 46 97. Lets see if that works!
Yes – it changed the baud rate to 2400. Let see if the Pro Mini works…
Still nothing back in the receive of the pro-mini.
I do see that the DDM18SD requires 5-24V to work. This is not provided by the pro-mini. But what is strange is that the RS485 converter sees the correct data being sent back. So the AC monitor is sending back correct HEX data.
I’m getting an error code ‘2’ which is “SDM_ERR_WRONG_BYTES”. I can see the bytes are all zero. So it’s getting something back but not converting it quickly enough. Could going faster help?
Setting the baud rate to 9600 is 46 16 00 00, so I needed to send: 15 10 00 00 00 02 04 46 16 00 00 46 D3.
Ah! This gives me data in the frame buffer, so I’m getting there. It is reading an additional 0 at the start, so lets hack the code to read one more byte and dismiss the first byte.
I decided (after a lot of playing) to use a 3.3V top 5V converter and a level shifter for the data. I used a CD40109 level shifter (as I had one lying around). I uses a low power 3.3 to 5V DC-DC converter. I put the transmit line and the direction control for the 5V version of the MAX485 TTL to RS485 IC. I also tried to use the receive pin through this, but it did not work. I also tried using a resistor voltage divider to reduce the 5V to 3.3V. This also did not work! I then just tried putting the receive line directly into the Rx of softwareSerialParity line on the Pro-Mini. This worked!
The data is not totally reliable but 90% of the time I get data back. I’m going to try with a bi-directional level shifter to check that works. But basically with a DC DC converter to give me 5V locally and a level shifter, I can use the 5V version of the MAX485 to give me RS485 with EVEN parity which talks to the DDM18SD energy monitor. This is not ideal (additional energy lost through the DC-DC converter) but at least it works!