Test RS232 Communication

Test the Rs232 Communication and SunEzy Communication Protocol

After some time of searching on the internet for wisdom how to pull data from the SunEzy 2800, I came across this Python module: https://pv.codeplex.com/. It describes the communication protocol in detail. Looking into the Python sources, one can immediately see that this is professionally written software. For me as a  Python beginner it was clear I would use this module, study it and hopefully learn a lot from it. But first I have to verify that the communication protocol works with my Sunezy 2800.

As I had to wait for Raspberry Pi to arrive, I first connected the SunEzy to my PC using a USB-RS232 cable and verified that the Sunezy Control Software worked. It took some time though, this piece of software is thought to connect to and manage multiple inverters.

The first test without this software was to query the serial number from the Sunezy inverter. Sounds simple. Send some bytes to the inverter, and read some bytes back – for this purpose there are terminal programs available, like TeraTerm. This sequence – expressed as hexadecimal numbers is to be sent to the inverter:

aa aa 01 00 00 00 00 04 00 01 59

Unfortunately, when I open a terminal in TeraTerm, I can send only characters that are available on the keyboard. But already the first character to send is hexadecimal ‘aa’ (representation of the ASCII character number 170, or binary 10101010). The normal Alphabet is represented by ASCII codes between 32 and 127. Some language specific characters can be represented by values between 128 and 255, but not all values can be generated easily with the keyboard. Worse, values below 32 are control characters, for example LF (line feed, ASCII code 10) or CR (carriage return, ASCII code 13).

The solution to this is: use a Hex Editor like Pspad, save the hex string to a to a file, start TeraTerm, and send data from this file.

Playing with this method wasn’t satisfying because I had to connect the inverter with my PC with a 3m cable in that very small boxroom where the heating is.

Below is a code snippet that demonstrates the serial connection to a CMS / Sunezy inverter. It does the following:

  1. the serial port is opened. We use a normal 9600 Bd, 8N1 connection type.
  2. A reset is sent and then the serial number is queried. The programming approach is like a C programmer coming to learn Python (like myself) would do it.
  3. A reset is sent and then the serial number is queried. The programming is more “pythonic”.
#!/usr/bin/env python

import serial
import time

#Oeffne Seriellen Port
port = serial.Serial('/dev/ttyAMA0',9600, timeout=0.2)

# timeout?
if not port.isOpen():
print "cannot connect to Sunezy."
sys.exit(1)

print "Port opened."

"""
THIS IS THE BEGINNERS WAY OF SENDING A STRING OF ASCII CODES TO THE DEVICE
AND RECEIVING THE SERIAL NUMBER AS A HUMAN READABLE STRING.
"""

#Reset
'''
| sync | src | dst | cmd | len | payload | checksum |
| 2B | 2B | 2B | 2B | 1B | len B | 2B |
aaaa 0100 0000 0004 00 0159
'''
SYNC = chr(0xaa) + chr(0xaa)
SRC = chr(0x01) + chr(0x00)
DST = chr(0x00) + chr(0x0)
cmd = chr(0x00) + chr(0x04)
leng = chr(0x00)
chksum = chr(0x01) + chr(0x59)

send = SYNC + SRC + DST + cmd + leng + chksum
print "Reset - % i Bytes written." % port.write(send)

time.sleep(0.2)
#Query serial number
"""

2B 2B 2B 2B 1B len B 2B
aaaa 0100 0000 0000 00 0155
"""

cmd = chr(0x00) + chr(0x00)
leng = chr(0x00)
chksum = chr(0x01) + chr(0x55)

send = SYNC + SRC + DST + cmd + leng + chksum
print "Query - %i Bytes written." % port.write(send)

time.sleep(.2)
raw_line =""
if port.inWaiting() > 0:
raw_line = port.read(port.inWaiting())

if len(raw_line) > 10:
sn = raw_line[9:-2]
print "Serial Number: %s" % sn
else:
print len(raw_line)

'''
PYTHON PROVIDES SOME POWERFUL METHODS TO SIMPLIFY THE STRING OPERATIONS WITH ASCII CODES
'''

import struct

SYNC = 0xaaaa
SRC = 0x0100
DST = 0x0000

CMD_RST = 0x0004 #Reset
CMD_DSC = 0x0000 #Discover - query serial number

data = struct.pack('!HHHHB', SYNC, SRC, DST, CMD_RST, 0x00)
checksum = struct.pack('!H', sum(map(ord, data))) # sum over the entire data string without the checksum itself
data = data + checksum

if port.write(data) is len(data):
print"--> ", data.encode('hex_codec')

data = struct.pack('!HHHHB', SYNC, SRC, DST, CMD_DSC, 0x00)
checksum = struct.pack('!H', sum(map(ord, data)))
data = data + checksum

if port.write(data) is len(data):
print"--> ", data.encode('hex_codec')

time.sleep(.2)

in_data =""
if port.inWaiting() > 0:
in_data = port.read(port.inWaiting())
print "<-- ", in_data.encode('hex_codec') if len(in_data) > 10:
sn = in_data[9:-2]
print "Serial Number: %s" % sn
else:
print "Bytes received: %i" % len(in_data)

port.close()

Continue with next step

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s