serrxd havin problems with fast back-to-back data

womai

Senior Member
I have a piece of VB6 code that sends command to a Picaxe 28X1. Those commands consist of 3 bytes in a row - first one is the command code, the next two are parameters. I'm running the 28X1 at 16 MHz (external resonator) and the serial speed is 19200 baud.

My intial VB6 code was this (command, param1 and param2 are byte variables):

Code:
.Output = Chr(Command)
.Output = Chr(Param1)
.Output = Chr(Param2)
My problem was - about 20% of the transmission attempts failed because the Picaxe received corrupted data (I can tell it did receive something - but corrupted - because the Picaxe responds with a checksum - a single byte that is all three data byte xor'ed together.

Now after a lot of troubleshooting (with the side benefit that I made the communication code much more failure tolerant so it wouldn't get stuck when a transmission did not go through) I discovered that if I insert short pauses (1 msec) between the transmission, it suddenly starts to work flawlessly, no more corrupted data at all:

Code:
.Output = Chr(Command)
Sleep 1
.Output = Chr(Param1)
Sleep 1
.Output = Chr(Param2)
Sleep 1
Has anybody experienced similar problems? Also, I did not yet check if serin behaves the same, but suspect it will (since both are software serial routines). It may also explain why on a previous project I couldn't get it to work at all when sending all three commands in a row:

Code:
.Output = Chr(Command) & Chr(Param1) & Chr(Param2)
which was the reason that I split it up into three commands in the first place.

I tried several different computers (laptops as well as desktops, all running Windows XP), with the same outcome.



As an additional question, it looks like sertxd automatically does a "reconnect" after it receives data, is that true?
 
Last edited:

hippy

Ex-Staff (retired)
Back-to-back comms can be a pain. The worse case is where each byte is read in a separate command and when reading in numbers using #var. The problems can get worse at higher baud rates even though the PICAXE is itself running at higher speeds.

SerRxd and SerIn are bit-banged so the PICAXE has to grab the data byte and after sampling midway through the last data bit it has one and a half bit times to process the data before it has to be ready for the next byte sent.

At 19200 that's just 78uS to store the data, read the program to determine what to do next, read the variable's identifier to determine where to store the next data and what format it will be in and be back ready for the data. At 16MHz, 78uS is just over 300 PICmicro instructions. That sounds like a lot but there's also a lot which goes into extracting control data from the stored program.

Other interpreter systems can have the same problems. Another thing you can try is opening the serial port with two stop bits instead of the usual one. This gives the PICAXE an extra 60% time to handle the data in. It should be possible to still receive data from the PICAXE in many cases as there is some processing time when sending using SerOut between bytes, otherwise you have to apply the same delaying tactics on the PICAXE side.

The most reliable method I've found is to have VB send a byte and have the PICAXE echo it. VB can wait on a flag which will be set when a byte is received back, then it will send the next. It can get a little complicated though.
 
Last edited:

womai

Senior Member
Well, as far as being tough on the Picaxe, it seems 4800 baud @ 4 MHz clock is exactly as hard (or easy) as 19200 baud @ 16 MHz - same number of instruction cycle per bit interval. I haven't tried it but I'd thus guess the same problem can occur at a measly 4800 baud. Not good. Note that I don't use any fancy processing (#b0 or the like), just straight 3 bytes of binary data read into 3 byte variables.

Two stop bits won't work in my case: To maximize data transfer from the Picaxe to the PC (when reading back the record that the scope has captured) I use hserout, which runs in the background, and my "real" scope shows that data is sent virtually continuously - apart from background send I discovered that hserout does not need additional "dead time" between data bytes, while serout and sertxd do (approx. 1 bit in addition to the stop bit). So it wouldn't be a good idea to have the PC wait for two bits, since it would miss the start of the next byte.

My data volume is strongly asynchronous - the PC sending just a few bytes (start acquisition, query of done and so on), the Picaxe is sending >500 bytes for each capture cycle. So for now I'll just add 1ms (i.e. approx. 2 bit periods at 19200 baud) after each byte, that seems to give the Picaxe enough time - almost 3 stop bits total - and does not measurably impact my capture rate.
 

hippy

Ex-Staff (retired)
I'm sure there's some reason that there's an issue between 4800 @ 4MHz and 19200 @ 16MHz although I cannot for the life of me recall what it is. You're right, it should work, it's the same number of instructions allowed, but I recall having similar problems in a non-PICAXE project.

Re 1mS, at 19200 that's 20 bit periods ( 2.5 bytes ), but if there's no impact it doesn't matter. Any Sleep/DoEvents could cause VB/OS to go and do a task switch so it could actually be a much longer period.
 

womai

Senior Member
yeah, got it mixed up, I was thinking bytes rather than bits. Anyway, I am happy I finally figured out a way to get it to work - ran several hundred kilobytes (really "bytes" this time :) of data without a single transmission error.
 
Top