Receive packets
Tumbler
Posts: 323
Hi,
I have a question about the fullduplexserial object.
I want to receive some packets and want to save one in memory.
A packet always starts with $FB and ends with $04. (packet lenght is between 8 and 16 bytes)
I can receive a packet, but have trouble to hold one in memory.
Can somebody help me further with this?
this is what i have so far...
I have a question about the fullduplexserial object.
I want to receive some packets and want to save one in memory.
A packet always starts with $FB and ends with $04. (packet lenght is between 8 and 16 bytes)
I can receive a packet, but have trouble to hold one in memory.
Can somebody help me further with this?
this is what i have so far...
CON _clkmode = XTAL1|PLL16X _xinfreq = 5_000_000 OBJ com: "FullDuplexSerial" serial: "Parallax Serial Terminal" VAR byte char byte packet[16] byte packetStart PUB Main | ptr 'com.start(rxpin, txpin, mode, baudrate) com.start(0,1, 00, 38400) serial.start(115200) repeat com.RxFlush char:=com.rx if char == -1 ptr:=0 if char == 15 'packet start packet[ptr]:=char ptr++ if char == 4 'packet end packet[ptr]:=char serial.dec(ptr) serial.char(10) serial.char(13) ptr:=0
Comments
You said the packet starts with $FB, but your code indicates that it starts with 15. In any event, try this for your main loop. (I'm assuming that $FB is correct.) It will store everything between $FB and $04 to your packet array.
-Phil
(If you indentation is really like it's displayed here in the thread)
And here a suggestion for an enhancement of Phils code. It can happen that you have transmission problems ... or maybe do a mistake in setup of the senders baud-rate ... whatever.
If you have such kind of problems it can happen that you don't see the END-character after 16 bytes. With Phils code you'd continue to read and store and you'd overwrite important memory locations sooner or later.
It's only a small amount of additional memory needed for a small check, but it saves your program in case of these transmission problems.
BTW with phils code a buffer size of 14 is enough, as the start- and end-characters are not stored
It's also a good practice to use constants. One reason is for making the code better readable and second reason is to allow easy changes without searching all the places that have to be changed. For example if you want to increase the size of the buffer. So, here is my final proposal:
So, the START/END_OF_PAKET constants are mainly for better readability. But it might also help later on in copy and paste code development. If you are in a new project and realize that this piece of code would also work there but with different characters you only have to change the constants.
Constants like BUFFER_SIZE are always usefull. It avoids bugs due to typos and in bigger code it's easier to resize the buffer because no code-change is needed. For example you might find out that it's better to read 2 packets before processing.
In the event your code doesn't want to sit around waiting on a packet, that is, it could be doing other things, this structure may be helpful (combined with the other great tips in this thread).
Just solved a little problem here with the package length.
Sometimes i received a $04 char as the third byte (package length)
This is what i have at the moment.
Now the package sender needs some data back. But first i have to look how i can do it.
For those who are interested
I'm experimenting with some velbus modules: http://www.velbus.eu/products/view/?id=387354
First thing: what is the difference in those 2 pieces of code (with really no additional code inside of the repeat!) ??
Flush will simply throw away everything in the full duplex internal buffer. The repeat-loop on the other hand will only throw away something if there is unexpected garbage.
Let's say after receiving a valid package you will do some more time consuming processing. The full duplex still buffers bytes coming from your device even if you are busy. So, most propable it will send START_OF_PACKET followed by the first bytes of the next package. When you're done with processing, why would you want to throw away this valid data?
Second thing: why would you add all this extra code?
Reading from START_OF_PACKET til END_OF_PACKET will perfectly do the job! You can inspect all the bytes after receiving! AND it is safer! What happens if you simply have a bit-read-error in the packetlength when receiving the most significant bit? This would make your inner repeat run 128+x times instead of x times.
My proposal:
The code in red saves your *** if you have transmission-problems. For example you switch on the light exactly when the most significant bit of the packetlength is transferred. I know these things propably won't happen for days, weeks, month or longer, but when these things happen it even can destroy your device.
Let's imagine your code would then overwrite a variable or some piece of code which sets the DIRA-register and by accident some pins attached to output pins of pheripherals will be set to output on the propeller as well. *BAZINGA* ;o)
I don't know the specs of your packages, so I did not add the CRC-code. This is the only thing I would add to the original receiving loop because then you can immediately decide if the package is OK after receiving the END_OF_PACKET. But you need to know which bytes are included in the CRC. Is it only the data or is it data and header (priority, address and packetlength)? What CRC-function is used? Simple XOR?
PS: LOL .... saves your *** ... are you so prude on the other side of the ocean? Then you need to check this as well: ass
Got this from the velleman forum about the crc:
Your code: repeat until ((char := com.rx) == END_OF_PACKET) or
What if the second byte is the 'end_of_packet'? it simply stopsI don't know if you noticed, i'm from Belgium
So, what happens if the second byte is END_OF_PACKET?
Of course the 3rd loop will immediately end, leaving prt set to 0. Now have a look at the following part of the if statement: which evaluates to ?+OFFSET == 0, which is false in any case because OFFSET alone is > 0.
? reminds me that the buffer should be initialized before getting filled with data again. So the following lines should be added/changed:
Hopefully I did not add to many bugs, as I can't test at the moment.
What do you mean with that? Do loops work different in Belgium? ;o)
PS:
@JonnyMac:
Thanks for sharing this! I'm not sure if it's needed in Tumbler's project, that's why I did not add it to my proposed code so far.
I'd propably not put the waitcnt(t += (25 * MS_001)) into the code addressed to a beginner without further comments. Guess it means that the loop will be executed each 25ms. But 25 ms makes 360 bytes that can be received in the meantime with the current baudrate. So it very much depends on the device attached if this code workes over the long run. Having a device continuously sending at that speed means that the buffer of the full duplex serial will overflow very soon. Am I right?
http://www.velleman.eu/downloads/0/velbus/manuals/protocol/protocol_vmb8pbu.pdf
Funny thing is that it's really easy for me to understand what's written on the page in your language.
What puzzles me a bit is that this document says the START_OF_FRAME is always zero and the END_OF_FRAME is $7F, it lists some more bytes to be send before the data length code.
All in all this is a bad documentation! It does not say a single word about the baudrate and how many frames are send per second ..... or whether the inter-frame byte is continuously send ...
Good documentation always comes with examples.
So, without having such a device you can't get ready to run code from the forum. You have to find out things by yourself.
PS: The CRC code in my post has to be changed, because the CRC is 16 bit - I thought we were talking about 8 bit. Can you do that by yourself? The idea stays the same.
PPS: WAAAAAAA .... bad documentation ... or is the CRC 15 bit because the document says CRC15...CRC1? Typo? Who knows?!
Good luck ;o)
I have a lot of modules here, nice thing is that i have a log function in the software (velbus link)
I can see what packages are send and received between the modules.
I'm sure, the crc is only 8 bit.
baud is 38400, and i thougt 60 or 100 mSecs between a package.
I will take a look at your code later, thx for the help
Grtz Luc