PDA

View Full Version : Generic Serial Question



johnp
April 13th, 2007, 06:44 AM
Hi All,

I am using Girder 3.3 and ran into a device I can't quite figure out how to deal with.

It's a Compool swimming pool / spa controller.

The part that has me stuck is that in the data coming in from the device, it does not have a termination string like most protocols, instead it has a pair of sync bytes at the front of the string. The serial plugin does not have a built in way of dealing with this, so I have to somehow process the strings one byte at a time and reformat them into a status word that I can parse and process.

To make things a little more complicated it has two different word lengths, 23 bytes for normal status and 8 bytes for NACKs / ACKs

The Status Packet is formatted as follows:

Byte 0 SYNC BYTE 0 0xFFh (always)
Byte 1 SYNC BYTE 1 0xAAh (always)
Byte 2 Destination Address 0x0Fh (always)
Byte 3 LX3xxx Version 0x??h (see definitions)
Byte 4 OpCode 0x02h (always)
Byte 5 Info Field Length 0x10h (always)
Byte 6 Minutes 0x00h - 0x3Bh (see definitions)
Byte 7 Hours 0x00h - 0x17h (see definitions)
Byte 8 Primary Equipment 0x??h (see definitions)
Byte 9 Secondary Equipment 0x??h (see defiintions)
Byte 10 Delay/Heat Source 0x??h (see definitions)
Byte 11 Water Temperature 0x??h (see definitions)
Byte 12 Solar Temperature 0x??h (see definitions)
Byte 13 Spa Water Temp 0x??h (3830 only - see definitions)
Byte 14 Spa Solar Temp 0x??h (3830 only - see definitions)
Byte 15 Desired Pool Temp 0x??h (see definitions)
Byte 16 Desired Spa Temp 0x??h (see definitions)
Byte 17 Air Temperature 0x??h (see definitions)
Byte 18 Spare/Future Use 0x??h (see definitions)
Byte 19 Spare/Future Use 0x??h (see definitions)
Byte 20 Equip/Sensor Stat 0x??h (see definitions)
Byte 21 Product Type/Stat 0x??h (see definitions)
Byte 22 Hi Byte of Checksum 0x??h (see definitions)
Byte 23 Lo Byte of Checksum 0x??h (see definitions)

The ACK / NACK Packets looks like this:

ACK Packet:
.................................................. .
Byte 0 SYNC BYTE 0 0xFFh (always)
Byte 1 SYNC BYTE 1 0xAAh (always)
Byte 2 Destination Address 0x01h (always)
Byte 3 LX3xxx Version 0x??h (see definitions)
Byte 4 OpCode (ACK) 0x01h (always)
Byte 5 Info Field Length 0x01h (always)
Byte 6 Packet type ACK'd 0x82h (always)
Byte 7 Hi Byte of Checksum 0x??h (see definitions)
Byte 8 Lo Byte of Checksum 0x??h (see definitions)


NACK Packet:
..................................................
Byte 0 SYNC BYTE 0 0xFFh (always)
Byte 1 SYNC BYTE 1 0xAAh (always)
Byte 2 Destination Address 0x0Fh (always)
Byte 3 LX3xxx Version 0x??h (see definitions)
Byte 4 OpCode (NACK) 0x00h (always)
Byte 5 Info Field Length 0x01h (always)
Byte 6 NACK data 0xFFh (always)
Byte 7 Hi Byte of Checksum 0x??h (see definitions)
Byte 8 Lo Byte of Checksum 0x??h (see definitions)

So I need to figure out how to compile the data in a format that I can process the rest of the information.

I'm sure LUA can do this pretty easily, but I am just not that advanced of a user.

Thanks in advance for any help.

johnp
April 14th, 2007, 08:40 AM
Anyone? Please.

Ron
April 14th, 2007, 09:51 PM
I'm sorry John, this is very different from the Girder 4/5 way of handling serial devices so I can't give you a quick answer. I would have to dive into this and charge for the hours. Maybe "Mark F" has a quick tip on how to do this. You might try PM-ing him.

Mark F
April 15th, 2007, 05:48 PM
You could try a fixed length (23) message with a timeout. Although, if the packets come fast and furious, you may get more than one on top of each other and have to parse the data anyway.

I thought there was a sample in the Serial Plugin distribution that does one byte at a time stuff; but, I haven't look at this for quite a while so I could be wrong.

Sorry, this is all I have. :(

johnp
April 16th, 2007, 06:31 AM
Hi Guys,

Thanks for taking a look anyway.

I have it worked out for the most part now, I did end up processing one byte at a time and looking for the pattern FF AA as follows, the only thing I am missing is how to set a variable name based on another variable, I can't seem to find a suitable example or explanation on how to do this in the LUA docs. The line in the code below that is commented out fails, but is the closest I could think of for the correct syntax.


if ((ByteCount == nil) or (ByteCount > 23)) and (LastByte ~= "FF") then
LastByte = (SerialValue)
elseif (LastByte == "FF") and (SerialValue == "AA") then
LastByte = (SerialValue)
ByteCount = 2
elseif (ByteCount >= 2) then
LastByte = (SerialValue)
-- ByteNum(ByteCount) = (SerialValue)
ByteCount = ((ByteCount) + 1)
end

This would then (hopefully) give me a string of variables as such...

Byte2 = 0F
Byte3 = 1B
Byte4 = 02
Byte5 = 10
Byte6 = 07
Byte7 = 09
Byte8 = 00
Byte9 = 00
Byte10 = 10
Byte11 = 5C
Byte12 = 00
Byte13 = 4F
Byte14 = 00
Byte15 = 5E
Byte16 = 8D
Byte17 = 2D
Byte18 = 00
Byte19 = 00
Byte20 = F0
Byte21 = E0
Byte22 = 05
Byte23 = 98

Rob H
April 16th, 2007, 09:16 AM
You probably want to use a table for this - first create the table


Bytes = {}

Then add the values


Bytes[byteCount] = value

johnp
April 16th, 2007, 01:54 PM
Thanks Rob,

Unfortunately that does not seem to be creating any variables for me. Any idea what I am doing wrong?



ByteIn = {}
if ((ByteCount == nil) or (ByteCount > 23)) and (LastByte ~= "FF") then
LastByte = (SerialValue)
elseif (LastByte == "FF") and (SerialValue == "AA") then
LastByte = (SerialValue)
ByteCount = 2
elseif (ByteCount >= 2) then
LastByte = (SerialValue)
Byte(ByteIn[ByteCount]) = (SerialValue)
ByteCount = ((ByteCount) + 1)
end


Thanks

Rob H
April 16th, 2007, 02:20 PM
Byte(ByteIn[ByteCount]) = (SerialValue)

Should be just

ByteIn[ByteCount] = SerialValue

You don't need to put all those brackets in either.

If you don't have it installed already, you should install and enable MarkF's logger plugin (can't remember if it comes with G3.3 by default), and disable the C and Lua function logging. That way you'll get to see any errors.

johnp
April 16th, 2007, 08:29 PM
Hi Again,

I tried that before, but no variables get populated. If I try to print ByteIn2 it comes back nil.

???

Rob H
April 17th, 2007, 02:56 AM
Because it's a table you would refer to that as ByteIn[2]

johnp
April 17th, 2007, 10:26 AM
Thanks again Rob for your help.

I think I am making progress, but I am still not getting the varialbes (or table values) that I need set.

If I manually create a table like this I can get the print funtion to display the table contents properly



ByteIn = {}
ByteIn[2] = 2
ByteIn[3] = 3
ByteIn[4] = 4
ByteIn[5] = 5
ByteIn[6] = 6
ByteIn[7] = 7
ByteIn[8] = 8
ByteIn[9] = 9
ByteIn[10] = 10
ByteIn[11] = 11
ByteIn[12] = 12
ByteIn[13] = 13
ByteIn[14] = 14
ByteIn[15] = 15
ByteIn[16] = 16
ByteIn[17] = 17
ByteIn[18] = 18
ByteIn[19] = 19
ByteIn[20] = 20
ByteIn[21] = 21
ByteIn[22] = 22
ByteIn[23] = 23


but if I just do this:



ByteIn = {}
ByteIn[ByteCount] = SerialValue


I get nothing in the table and the print function returns nil even though I can see the ByteCount variable incrementing properly and the LastByte data is also incrementing properly.

I am really amazed that I am having such a hard time with something that I think would be so easy to do. Really frustrating.

Any ideas? Thanks again.

Rob H
April 17th, 2007, 11:22 AM
Please post the full source code of what you're doing

johnp
April 17th, 2007, 02:13 PM
Please post the full source code of what you're doing

Here it is...


ByteIn = {}
--[[
ByteIn[2] = 2
ByteIn[3] = 3
ByteIn[4] = 4
ByteIn[5] = 5
ByteIn[6] = 6
ByteIn[7] = 7
ByteIn[8] = 8
ByteIn[9] = 9
ByteIn[10] = 10
ByteIn[11] = 11
ByteIn[12] = 12
ByteIn[13] = 13
ByteIn[14] = 14
ByteIn[15] = 15
ByteIn[16] = 16
ByteIn[17] = 17
ByteIn[18] = 18
ByteIn[19] = 19
ByteIn[20] = 20
ByteIn[21] = 21
ByteIn[22] = 22
ByteIn[23] = 23
--]]

if ((ByteCount == nil) or (ByteCount > 25)) and (LastByte ~= "FF") then
LastByte = (SerialValue)
elseif (LastByte == "FF") and (SerialValue == "AA") then
LastByte = (SerialValue)
ByteCount = 2
elseif (ByteCount >= 2) then
LastByte = SerialValue
ByteIn[ByteCount] = SerialValue
ByteCount = ByteCount + 1
end

print ("Last Byte = "..(LastByte))
print ("Byte Count = "..(ByteCount))
print ("Byte # ="..(ByteIn[ByteCount]))

Rob H
April 18th, 2007, 04:31 AM
Here it is...


ByteIn = {}

-- commented code deleted

if ((ByteCount == nil) or (ByteCount > 25)) and (LastByte ~= "FF") then
LastByte = (SerialValue)
elseif (LastByte == "FF") and (SerialValue == "AA") then
LastByte = (SerialValue)
ByteCount = 2
elseif (ByteCount >= 2) then
LastByte = SerialValue
ByteIn[ByteCount] = SerialValue
ByteCount = ByteCount + 1
end

print ("Last Byte = "..(LastByte))
print ("Byte Count = "..(ByteCount))
print ("Byte # ="..(ByteIn[ByteCount]))


Okay, I think I see what's happening here, ByteCount starts at nil, then gets set to 2 and is incremented for each subsequent character after the most recent character is added. This means that ByteIn[ByteCount] will always be nil. I'd initialise ByteCount to 1 when you see the FF/AA and then increment it before doing the ByteIn[ByteCount] = SerialValue

johnp
April 19th, 2007, 06:19 AM
Thanks again for continuing to work with me on this.

Sadly I can not get there from here yet.

I tried several variations of the following code with no joy. Including this:


ByteIn = {}
ByteIn[1] = "Init"
ByteIn[2] = "Init"
ByteIn[3] = "Init"
ByteIn[4] = "Init"
ByteIn[5] = "Init"
ByteIn[6] = "Init"
ByteIn[7] = "Init"
ByteIn[8] = "Init"
ByteIn[9] = "Init"
ByteIn[10] = "Init"
ByteIn[11] = "Init"
ByteIn[12] = "Init"
ByteIn[13] = "Init"
ByteIn[14] = "Init"
ByteIn[15] = "Init"
ByteIn[16] = "Init"
ByteIn[17] = "Init"
ByteIn[18] = "Init"
ByteIn[19] = "Init"
ByteIn[20] = "Init"
ByteIn[21] = "Init"
ByteIn[22] = "Init"
ByteIn[23] = "Init"
ByteIn[24] = "Init"
ByteIn[25] = "Init"

if ((ByteCount == nil) or (ByteCount > 24)) and (LastByte ~= "FF") then
LastByte = SerialValue
elseif (LastByte == "FF") and (SerialValue == "AA") then
LastByte = SerialValue
ByteCount = 1
elseif (ByteCount >= 1) then
LastByte = SerialValue
ByteIn[ByteCount] = SerialValue
ByteCount = ByteCount + 1
end

print ("Last Byte = "..LastByte)
print ("Byte Count = "..ByteCount)
print ("Byte#"..ByteCount.." = "..ByteIn[ByteCount])


And This:


ByteIn = {}

if ((ByteCount == nil) or (ByteCount > 24)) and (LastByte ~= "FF") then
LastByte = SerialValue
elseif (LastByte == "FF") and (SerialValue == "AA") then
LastByte = SerialValue
ByteCount = 1
elseif (ByteCount >= 1) then
LastByte = SerialValue
ByteIn[ByteCount] = SerialValue
ByteCount = ByteCount + 1
end

print ("Last Byte = "..LastByte)
print ("Byte Count = "..ByteCount)
print ("Byte#"..ByteCount.." = "..ByteIn[ByteCount])



the issue seems to be in this line

ByteIn[ByteCount] = SerialValue

It just does not seem to be doing what I think it should be.

In the first example, ByteIn[1..25] are always "init"
In the second example, ByteIn[1..25] are always nil.

Any other ideas?

johnp
April 19th, 2007, 06:38 AM
Hold the phone, I think I did not read your last post correctly.

I just changed one line and it seems to be working now!!



ByteIn = {}
ByteIn[1] = "Init"

if ((ByteCount == nil) or (ByteCount > 27)) and (LastByte ~= "FF") then
LastByte = SerialValue
elseif (LastByte == "FF") and (SerialValue == "AA") then
LastByte = SerialValue
ByteCount = 1
elseif (ByteCount >= 1) then
LastByte = SerialValue
ByteCount = ByteCount + 1
ByteIn[ByteCount] = SerialValue
end

print ("Byte#"..ByteCount.." = "..ByteIn[ByteCount])

collectgarbage ()


What I am not quite so surte about is why changing the order of the byte count increment made a difference since it was already previously initialised to 1 ? Or maybe it wasn't. Maybe my logic was just wrong??

At any rate, thank you very much for your help!!

Rob H
April 19th, 2007, 09:25 AM
Glad it's working now.