Can't get the SB/X Interrupt UART sample code to run
John Bond
Posts: 369
Hi Guys
·
Please help – I’ve spent 2 frustrating days…
·
I would like to run a UART in the background while multiplexing LEDs in the main program
·
I’ve taken the interrupt driven code from the SX/B Help Manual but I can’t get it to work. I started using a PC to output the string but have now resorted using a BS2p. The setup works fine when I use the SERIN command on the SX but not with the sample code out of·the help file.
·
What am I missing?
Kind Regards from Darkest Africa
John Bond
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (John Bond) : 9/5/2007 1:04:25 PM GMT
·
Please help – I’ve spent 2 frustrating days…
·
I would like to run a UART in the background while multiplexing LEDs in the main program
·
I’ve taken the interrupt driven code from the SX/B Help Manual but I can’t get it to work. I started using a PC to output the string but have now resorted using a BS2p. The setup works fine when I use the SERIN command on the SX but not with the sample code out of·the help file.
·
What am I missing?
Kind Regards from Darkest Africa
John Bond
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (John Bond) : 9/5/2007 1:04:25 PM GMT
Comments
I didn't study the code, but the first thing I saw was: You need to sample at least 3 times the baud rate.
I saw you were using X2. Try X3 and see if things work.
HTH, Chris
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'm not scared of your robot. I'm covered by Old Glory (youtube)
· Your BS2 program is using 9600 baud, and the SX/B program is using 19,200 baud.
· Change the line "BitTm CON B19K2" to "BitTm CON B9600".
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The first rule to being successful is "Learn from your mistakes",
The second rule is "Be willing to make mistakes"
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
www.hittconsulting.com
·
·
I was using B9600 baud on the·SX side, I also tried 19K2 and 2400 on both SX and BS2p. I'd butchered the original code so much that·I just copied the original code from the help manual into this post so people didn't have to look for it.
·
I·know that one can't use Debug on time related interrupts so I was using ports RB, RC, RD and RE in an effort to see what was happening (not shown here - Yes I also changed the code to suite·SX48). The problem appears in the assembler code in the Interrupt.
·
I've seen this ongoing discussion on whether to sample 3 or 4 for incoming Comms. I·was taught in (business and quality)·Math that sampling an "either or" on a fixed cycle can be perfumed in 3 samples (is it called Nysquithe's formula? -·Hey I'm getting old!). The result will be reliable·ONLY·if the timing is exact and constant (and in the case of electronics,·there is no slope on the switching) but that it is much better and more stable to use 4 samples. (Sampling used to form a big part of productivity measurement·in 1972·- long before the PC). When you've got the speed though, why take the risk, just play it by the book.
·
The sample rate at 9600 baud in the Example is actually 8 (It's a good bit of code - if I could only get it to work!!!)
·
Kind regards
John
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Post Edited (John Bond) : 9/6/2007 7:02:06 AM GMT
As I wrote the original demo it pains me when someone has trouble. So... I have modernized the SX/B program to bring it up to standards (I wasn't involved in the last help file update) and connected it to a version of your program -- it works.
Two things: 1) You had no delay between bytes going out of the Stamp so that would have been very tough to see on the SX -- at 9600 baud the RC LEDs would be changing every millisecond, and 2) -- which is question: Did you have a pull-up on RA.0? You need this for True mode comms; I use 4.7K.
I've attached updated programs that are happily running on my PDB.
The truth is that as your signal frequency approaches the sample rate, the reconstructed fidelity gets lower and lower. This is easy to understand if you imagine sampling a 20 kHz sine wave at 40 kHz. If your sample rate was perfectly synchronized with the signal (not likely, but lets pretend), and you just happened be sampling at the peaks of the sine wave, then you would have one sample at maximum value and one at minimum. Of course, this means that your nice pretty since wave has now been converted into a square wave. In the real world, folks depend on output filtering of the DAC to reconstruct the sine wave, but the fact is that your sine wave is gone and won't be coming back with any fidelity any time soon. It only gets worse when the signal isn't some simple sine wave, but is instead some bit of real audio.
What does this have to do with UART sampling? Basically nothing. We are not attempting to reconstruct the sampled signal. We are merely interested in the absolute value at the moment the sample was taken, and our amplitude is limited not to 16 bits, but 1 bit - simply on or off. Further, we can happily sample at the exact same rate as the incoming signal all day long. Yes, I am stating that Nyquist be damned, it doesn't apply to the problem we are solving.
The whole point of oversampling in a UART is if we take the multiple samples and average them together to come up with a consensus. In other words, if there is some noise on the line and during one of our sample periods we got a one when we should have received a zero, then by having 2 or 3 or 8 other samples, we can easily see that if only one of them has a value of one and all the rest are zero, then our true result should be zero.
But what about drift? We have two different clocks! Who cares? That's the whole point of the start bit. The entire sampling duration starts over on each new start bit. Every UART on the planet is designed to see the start bit, wait 1 1/2 bit times, and then start sampling on each bit time. The 1 1/2 bit widths gets us past the entire start bit and halfway into the first bit where we take a sample. By then sampling every bit time width, we are now sampling in the middle of each bit in the data stream. Remember, we are not not concerned with reconstructing a signal. We merely want to get the sample value in the middle of each bit. From that single sample, we have all the information we will ever need to decode the bitstream.
Everything else is just icing on the cake. Sampling at 2X or 3X or 100x of the baud rate won't get us any better information than sampling at 1X the baud rate if we don't do some sort of statistical analysis of the over sampled data. Simply taking a ton of samples and then using the one in the middle is exactly the same as sampling at 1X. In fact, it is sampling at 1X.
So, if you aren't doing the extra work with all those samples, save yourself the trouble and just sample at 1X. If you need a higher interrupt rate to run multiple VPs in a single interrupt, go right ahead. However, you will still only take one sample in the middle of the bit time width and not do any UART work the rest of the time.
You are now returned to your normally scheduled programming...
Thanks,
PeterM
PJ Monty, I would like to suggest that your explanation of sampling only once per bit is valid, but only after you have adequately detected the biginning of the START bit. This can be done by a "change on port" interrupt, and then sample the next bit in its middle, at 1.5 bit times, and all other consecutive bits in their middle, 1.0 bit time from the previous bit.
However, there are many instances when a "port change" interrupt is not used, and the start bit is detected by polling the data line, and that must be done often enough to "adequately" determine the beginning of the START bit. In such a case, one MUST sample at a rate of 3 or more per bit time. Anything less will not assure sufficient determinism, especially considering un-synchonized transmit and receive clocks.
I generally operate my UARTs this way, sampling at a rate of either 3 or 5 times per bit, and once a START is detected then an appropriate time from that point forward so as to land the next samples in the middle third or middle fifth of the data bits.
On occasion I chose to use the internal RC oscillator as my clock, and I will do some extra samples further into the byte, looking for edges, and then adjusting the (interrupt) sample timer slightly to "track" the clock drift to the data.
Interestingly, the over-sampling scheme to detect to start bit works best (as in has greatest tolerance for bounce in the bit timing) when the sample number is an odd number, because only an odd number permits consistent sampling around the center of a bit. With an even number this is not possible.
So my summary is (for poll detection of the START bit) odd integer sample intervals are better than even numbers, and larger numbers (that is shorter times) are better than longer times.
In my experience, all that reduces to : Less than three will not work, three is good, five is great, any more is a waste.
Cheers,
Peter (pjv)
I agree completely. Very lucid explanation of the start bit detection issue.
Thanks,
PeterM
In addition, you've simplified the code and made some of the mods I was going to do once I'd got the example to work. Talk about providing help!
Thanks Peter for your very clear description of Comms sampling. As always you combine the theory with your practical experience. Us rookies appreciate your (and all the other regular contributors) input.
The lesson I've learned here is how dependant I am on the debugger. When I’m flying blind, I am really blind. I am probably suffering from Old-Timers Disease. Most South Africans don’t speak English as a 1st language so Alzheimer’s disease is referred to as Old-Timers.
Kind regards
John Bond
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔