View Full Version : Helkp with Serial Plugin
johnp
August 28th, 2008, 12:30 PM
Just getting started writing serial devices and hitting a speed bump.
I am just trying to see data coming back from a device and print it to the lua console at this point. Here is my code:
local Super = serial.Classes.Simple
local device = Super:New({
Name = "RT1080",
GlobalName = "RT1080_Serial",
Description = "Rotel RT-1080 AM-FM Tuner",
BaudRate = 4800,
Parity = 0,
DataBits = 8,
StopBits = 0,
FlowControl = 'N',
IntraCharacterDelay = 1,
CallbackType = serial.CB_MARKEDLENGTH1,
ReceiveStartByte = 'FE',
ReceiveTerminatorLength = 40,
-- SendStartByte = '',
-- SendTerminator = '',
IncompleteResponseTimeout = 100,
NoResponseTimeout = 1000,
LogLevel = 0,-- change this to a higher number or false when the device is working
Initialize = function(self)
if Super.Initialize(self) then
-- add your own initializations here
self.Status = 'Initialized'
return true
end
end,
ReceiveResponse = function(self, data, code)
if math.band(code, serial.RXCHAR) > 0 then
print (data)
--gir.TriggerEvent("RT1080_Data",18, data)
-- add code here to process the data parameter
end
Super.ReceiveResponse(self, data, code) -- must call the parent's ReceiveResponse
end,
})
serial.AddDevice(device)
When I activate the deivce (assign it to a serial port), I get this error:
Serial: RT1080 : Opened Device: RT1080 Port: 3 Settings: 4800 N 0 8 0
Serial Error (set_devices, 2): ...gram Files\Promixis\Girder5\/plugins/serial/init.lua:259: bad argument #2 to `Callback' (number expected, got string)
stack traceback:
[C]: in function `Callback'
...gram Files\Promixis\Girder5\/plugins/serial/init.lua:259: in function `Initialize'
...am Files\Promixis\Girder5\/plugins/serial/RT1080.lua:23: in function <...am Files\Promixis\Girder5\/plugins/serial/RT1080.lua:22>
(tail call): ?
[string "iterate"]:13: in main chunk
Rob H
August 28th, 2008, 12:46 PM
Um, you posted the device code a second time, rather than the error message.
Also, could you use code tags around any code which will preserve the formatting.
johnp
August 28th, 2008, 01:18 PM
Sorry, I was in a hurry (as evidenced by the typo in the thread title)... had to blast off to a lunch date.
I seem to have found the issue. I have a hex byte FE in the ReceiveStartByte location and that appears to want a deciaml number????
I tried 254 and while that eliminates the error, there is still something wrong.
What is thee proper way to indicate a hex start byte?
johnp
August 28th, 2008, 02:54 PM
I've tried several combinations of values and can't quite seem to get this right.
Here is what I am dealing with:
The tuner receives a command that looks something like this:
Serial: RT1080 : Simple Send: FE 03 21 10 FF 33
It responds with an echo of the previous command:
FE 03 21 10 FF 33
and with the staus of the tuner in the form:
FE 12 21 20 10 06 34 FC 47 20 39 34 2E 35 30 4D 48 1E 20 35 08
What is the best way to set this device up to simply regurgitate the string?
Rob H
August 28th, 2008, 04:36 PM
Sorry, I was in a hurry (as evidenced by the typo in the thread title)... had to blast off to a lunch date.
I seem to have found the issue. I have a hex byte FE in the ReceiveStartByte location and that appears to want a deciaml number????
I tried 254 and while that eliminates the error, there is still something wrong.
What is thee proper way to indicate a hex start byte?
You should use math.hextobyte('FE')
johnp
August 28th, 2008, 04:43 PM
Thanks,
Unfortunately I still get a similar error???
I am also unclear on the proper syntax for other values like
current state of code is below...
Error-
Serial: RT1080 : Opened Device: RT1080 Port: 3 Settings: 4800 N 0 8 0
Serial Error: ...gram Files\Promixis\Girder5\/plugins/serial/init.lua:259: bad argument #2 to `Callback' (number expected, got string)
stack traceback:
[C]: in function `Callback'
...gram Files\Promixis\Girder5\/plugins/serial/init.lua:259: in function `Initialize'
...am Files\Promixis\Girder5\/plugins/serial/RT1080.lua:24: in function <...am Files\Promixis\Girder5\/plugins/serial/RT1080.lua:23>
(tail call): ?
...gram Files\Promixis\Girder5\/plugins/serial/init.lua:1654: in function `DeviceInitialize'
...gram Files\Promixis\Girder5\/plugins/serial/init.lua:1515: in function <...gram Files\Promixis\Girder5\/plugins/serial/init.lua:1511>
Welcome to Promixis Girder 5.0.1 build 535
local Super = serial.Classes.Simple
local device = Super:New({
Name = "RT1080",
GlobalName = "Rotel 1080",
Description = "Rotel RT-1080 AM-FM Tuner",
BaudRate = 4800,
Parity = 0,
DataBits = 8,
StopBits = 0,
FlowControl = 'N',
IntraCharacterDelay = 1,
CallbackType = serial.CB_MARKEDLENGTH1,
ReceiveStartByte = math.hextobyte('FE'),
ReceiveFixedLength = 21,
-- ReceiveTerminatorLength = '',
-- SendStartByte = '',
-- SendTerminator = '',
IncompleteResponseTimeout = 1000,
NoResponseTimeout = 1000,
LogLevel = 0,-- change this to a higher number or false when the device is working
Initialize = function(self)
if Super.Initialize(self) then
-- add your own initializations here
self.Status = 'Initialized'
return true
end
end,
ReceiveResponse = function(self, data, code)
if math.band(code, serial.RXCHAR) > 0 then
print ("this"..self)
print ("that"..data)
print ("other"..code)
--gir.TriggerEvent("RT1080_Data",18, data)
-- add code here to process the data parameter
end
Super.ReceiveResponse(self, data, code) -- must call the parent's ReceiveResponse
end,
})
serial.AddDevice(device)
Rob H
August 28th, 2008, 04:55 PM
My bad, that should have been math.hextodecimal, not math.hextobyte
Rob H
August 28th, 2008, 05:01 PM
I'm a little confused by the responses you're getting.
e.g.
FE 03 21 10 FF 33
The second byte there indicates that you should expect 3 characters to follow, not four. Is that last character a checksum perhaps?
If it is, and you want to ignore it, then set ReceiveTerminatorLength = 1
Rob H
August 28th, 2008, 05:02 PM
Check your typing
johnp
August 28th, 2008, 05:03 PM
youre too fast. I tried to delete the message, but you already read it.
Still that leaves me just as I was when I entered 254 in manually.
I am not getting what I expect when I receive data from the device.
Rob H
August 28th, 2008, 05:10 PM
Okay, what is it that you're expecting but not seeing?
johnp
August 28th, 2008, 05:10 PM
I'm a little confused by the responses you're getting.
e.g.
FE 03 21 10 FF 33
The second byte there indicates that you should expect 3 characters to follow, not four. Is that last character a checksum perhaps?
If it is, and you want to ignore it, then set ReceiveTerminatorLength = 1
Yes the last byte is a checksum, but I am not too concerned with that.
I guess my first most basic question is when the values are asking for lengths of things, are they nibbles or bytes?
johnp
August 28th, 2008, 05:24 PM
Okay, what is it that you're expecting but not seeing?
First off no matter the length I set ReceiveFixedLength to I get the same response. Is that only valid for FIXEDLENGTH messages and not MARKEDLENGTH1 messages?
Second, I am always seeing the third byte first. I would expect each message to start with 0xFE (the first byte) or 0x12 (the second byte if the start character was automatically stripped out (not desirable for me as I get a warm fuzzy from seeing the entire raw message, I like to be able to toggle the striping out of message components)
Lastly, when things are asking for length are they asking for bytes or nibbles????
With those questions answered, I might be able to make some sense of this thing.
Rob H
August 29th, 2008, 05:23 AM
ReceiveFixedLength does indeed only apply to CB_FIXEDLENGTH
It sounds as though you are receiving what I would expect to see. Girder is stripping out the framing characters (in this case the 0xFE and length byte);
it's not optional.
Lengths are in bytes.
If you really want to see all the characters then you'll have to use CB_FIXEDLENGTH with a suitably high value of ReceiveFixedLength and change your ReceiveResponse method to check for serial.INCOMPLETERESPONSETIMEOUT e.g.
if math.band(code, serial.INCOMPLETERESPONSETIMEOUT) > 0 then
-- we don't want this treated as an error in the parent class
code = math.zerobits(code, serial.INCOMPLETERESPONSETIMEOUT)
-- your processing code here
end
Super.ReceiveResponse(self, data, code)
Ron
August 29th, 2008, 09:28 AM
Or if you really want to handle it all your self, with the performance impact that goes with it use transport.constants.parser.STREAM. It sends ever byte as it comes in. I would not advise this, use this as a debug parser.
johnp
August 29th, 2008, 10:53 AM
Thanks for the info. I am really not so interested in grabbing each byte as it comes along. I had to do that with 3.3 and it is a pain and as you mentioned a CPU hog. I just want to understand what I am seeing with this receive response method.
Now I'd really like to understand why am I losing the second byte? Thankfully in this case it is more or less meaningless data, (the second byte is the device type which is always the same and I'd probably strip it out anyway) but I am still am unclear how this works.
For example:
The incoming data is
FE 12 21 20 10 06 34 F8 C7 20 39 36 2E 35 30 4D 48 1E 31 31 93
With ReceiveTerminatorLength = '1', I get back the following with no errors.
Serial: RT1080 : Simple Receive: Data 21 20 10 06 34 F8 C7 20 39 36 2E 35 30 4D 48 1E 31 31 93 ! ..4øÇ 96.50MH.11“ Code: 1
This would make sense if the character to be stripped is the ReceiveStartByte + ReceiveTerminatorLength
Since this seems to be how it works, and makes sense after reading through the help file a few more times, let me assume this is true.
The help file describe it as follows, "ReceiveTerminatorLength: Number, default=0. The number of characters expected after the counted characters and before the marker for the next message in a MARKEDLENGTH1 message".
What exactly are the "counted characters" Perhaps that is where I am missing the boat??
So from that I would expect that setting the ReceiveTerminatorLength = '0', I would get the entire message less the start byte.
what I do get is this:
Serial: RT1080 : Simple Receive: Data 21 20 10 06 34 F8 C7 20 39 36 2E 35 30 4D 48 1E 31 31 ! ..4øÇ 96.50MH.11 Code: 1
Serial: RT1080 : Simple Receive: Data 93 “ Code: 8192
Serial: RT1080 : ERROR: Incomplete response to last command
It has the same start point, and the last byte is received as a separate message with an incomplete response error. The timeout is set to 500 ms and I have had it as high as 1 sec with the same result so I am pretty sure it has nothing to do with that.
How can this be explained? Still no second byte and the last byte gets dropped as well.
Can you understand my confusion now?
If I set the ReceiveTerminatorLength = '21', which is the actual place the checksum is located on the status messages, then I get both the echo of the command (less the first two bytes) and the status message on the same line with the last byte received as separate message.
Serial: RT1080 : Simple Receive: Data 21 10 FF 33 FE 12 21 20 10 06 34 F8 47 20 39 36 2E 35 30 4D 48 1E 31 31 !.ÿ3þ.! ..4øG 96.50MH.11 Code: 1
Serial: RT1080 : Simple Receive: Data 13 . Code: 8192
Serial: RT1080 : ERROR: Incomplete response to last command
So, I am still struggling with how this is supposed to work.
I guess I just want a clear description of how manipulate these constants and what to expect when I do.
Thanks again for your patience.
Rob H
August 29th, 2008, 11:06 AM
The second byte is the marked length byte, so that is being dropped too. I'd be surprised (and horrified) if that's also supposed to be the device type as it implies that all devices would have to return different lengths of response.
You need to set ReceiveTerminatorLength to 1 to grab the checksum as it isn't included in the given length. Alternatively you can leave it at 0 and handle the incomplete response timeout just for the checksum (ensuring that length(data) == 1 to be on the safe side.
johnp
August 29th, 2008, 11:12 AM
Thanks again for your patience with me. I am really starting to feel thick here.
Can you explain to me how is the second byte the marked length byte? I just don't get it
Also can you please explain how the length is determined?
Sorry for the continual questions, but I really need to understand what I am seeing to be productive.
Ron
August 29th, 2008, 11:14 AM
Marked Length is defined as follows:
First byte is fixed id byte
Second byte is the length of the payload
then one can have optional extra bytes at the end
Ron
August 29th, 2008, 11:16 AM
from your example:
FE 12 21 20 10 06 34 F8 C7 20 39 36 2E 35 30 4D 48 1E 31 31 93
FE = Identifier
12(hex) = 18(dec) number of bytes in message
+ 1 trailing byte.
Ron
August 29th, 2008, 11:17 AM
What value is your incomplete response timeout set to?
johnp
August 29th, 2008, 11:18 AM
500 ms currently.
Ron
August 29th, 2008, 11:21 AM
Serial: RT1080 : Simple Receive: Data 21 20 10 06 34 F8 C7 20 39 36 2E 35 30 4D 48 1E 31 31 93 ! ..4øÇ 96.50MH.11“ Code: 1
That is EXACTLY correct and expected.
So from that I would expect that setting the ReceiveTerminatorLength = '0', I would get the entire message less the start byte.
No this would be not good. What happens then is that you drop the LAST terminator byte from the output and on top of that the input stream get out of sequence. If that last terminator byte happens to be equal to the ID start byte things go funny until it can resequence again.
The first two bytes are never passed to the Lua code as they are protocol bytes and confer no information.
johnp
August 29th, 2008, 11:22 AM
Marked Length is defined as follows:
First byte is fixed id byte
Second byte is the length of the payload
then one can have optional extra bytes at the end
That explains it. The second byte in this message is not the payload. The third byte is the payload length. The second byte for this device is the "Device ID"
So would it be possible to create a constant for the message length byte so I can change it from 2 to 3?
Ron
August 29th, 2008, 11:31 AM
Ah, you are simply using a parser that is not suited to this data stream. This would require a new parser if you would like to keep the parsing on the C++ side. We can add a parser for your specific case contact me if you want this done. The other option is to drop to the STREAM parser, which I really can't advise.
johnp
August 29th, 2008, 11:32 AM
I'll give you a call...
Ron
August 29th, 2008, 11:37 AM
Thanks. We'll add a new parser then.
Rob H
August 29th, 2008, 12:11 PM
That explains it. The second byte in this message is not the payload. The third byte is the payload length. The second byte for this device is the "Device ID"
So would it be possible to create a constant for the message length byte so I can change it from 2 to 3?
Are you sure about that? When it echoes back the command it sends
FE 03 21 10 FF 33
correct?
The 03 there is the length, the third byte would imply that the length was 33 bytes!
Similarly, for
FE 12 21 20 10 06 34 FC 47 20 39 34 2E 35 30 4D 48 1E 20 35 08
The second byte is 12 ie 18 which fits with the length of the received data, and the third byte is again 21.
Are you sure that the third byte isn't the device id?
Ron
August 29th, 2008, 12:16 PM
Looking back at your examples it does seem like Rob has a point here. Can you send me (in private if need be) the protocol?
Ron
September 2nd, 2008, 11:02 AM
This mistake was corrected offline and boiled down to a hex vs. decimal issue. The parser included in Girder will do just fine for this device.
johnp
September 2nd, 2008, 11:06 AM
Yes, my bad (very embarrassed)
vBulletin® v3.7.4, Copyright ©2000-2009, Jelsoft Enterprises Ltd.