Go Down

Topic: SoftwareSerial magic numbers (Read 15114 times) previous topic - next topic

robtillaart

what I meant to explain is that timing tables are tuned manually because of the fact the same code executes faster / slower on different boards.

Please note that the accuracy of micros() is 4 us which makes it harder to use for timing than delayMicros() which has a stepsize of 1 us and is reasonably accurate..
an example:
a baudrate of 57600 has a new bit every 17.36 us.  With micros() the best I can do is 16 us.
Given that you need to send 10 bits for a byte this timing error add up to 13.6 us. (almost one whole bit)
with a 1us accuracy of the delayMicros() the timing error adds up to 3.6us  (about 1/5 bit)

That said your idea is theoretical sound, only you need a more accurate clock than micros() for high speeds.
and yes for low baud rates, 9600 and below the idea will work.

Quote
Indeed I suspect it should be possible to write a sketch that would automatically adjust its timing if it was sent a stream of known bytes against which to test itself.

Yes that can be done. It is a well known method to optimize long communication lines to get the highest baud rate possible. This optimization can be done continuously by adding codes to check reception quality and to decrease speed if line get worse and increase again when line is stable again. Not trivial but possible.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Robin2

I think we are talking at cross-purposes to some extent. My comments all relate to the adjustments for different baud rates on any single board rather than across boards. However if one can do the timing in usecs rather than CPU steps code should work on any board.

As far as I can see my simple micros() based system works up to 38400 baud with a 16MHz cpu and very nearly works at 57600 but, as you say, the positioning uncertainty due to micros() seems to be a problem. I don't thing this is a cumulative problem but rather due to the fact that the timing of any individual read might vary +/- 4usecs almost at random.

I guess if one tweaked micros() to give (say) 2usec accuracy it would consume too much CPU time to be practical.

I suspect one could make one of the timers keep a suitable count in the background (perhaps that's what AltSerial does) but to my mind that level of complexity isn't justified for something that is really a stop-gap.

Because of the difficulty of debugging the Attiny (I assume, I haven't yet tried) I prefer the idea of simple code that can be ported almost unchanged. If I can get 38400 baud at 16Mhz I would hope that 2400 will work on the Attiny at 1MHz. Of course I don't yet know how "coarse" micros() are on an Attiny.

...R

Paul Stoffregen

Quote
I suspect one could make one of the timers keep a suitable count in the background (perhaps that's what AltSerial does)


Yes, that's pretty much exactly what AltSoftSerial does.  The hardware timer automatically increments at the full clock rate.  Each time the input signal changes, the 16 bit count is captured.  That's all done by hardware, so it's accurate to within 1 clock cycle.

There's no calibration of software execution time.  The input signal's timing is measured directly and simple math is done with the captured timer values to deduce if the signal was high or low at the center of each bit.  As long as the interrupt can respond before the signal changes again (so no capture values are overwritten), the input is measured precisely to within CPU clock cycle.

Unlike SoftwareSerial, where varying interrupt latency (eg, if the millis or normal Serial interrupt is running) causes reception of all the bits to begin late and sample off the center of each bit, using the timer's input capture achieves perfect accuracy because the timer's dedicated input capture hardware stores the rapidly increasing timer's value at the exact instant the signal actually changed, rather than when the interrupt code later responds.

Robin2

But not on an Attiny, according to your earlier post?

...R

Paul Stoffregen

#49
Sep 18, 2013, 11:35 am Last Edit: Sep 18, 2013, 11:39 am by Paul Stoffregen Reason: 1
Well, that depends on the specific ATTINY.  Has the specific chip been mentioned anywhere in this thread?  I searched for every occurrence of "tiny" but didn't see the part number.

The ATTINY48, for example, has a 16 bit timer with input capture and 2 compare units, so odds are very good that one might work, or the code/technique could be ported fairly easily.

The ATTINY45, for another example, has only 8 bit timers.  Its timers do have compare units, but not input capture.  While AltSoftSerial's code couldn't work directly, the same general approach could (probably) be used for transmit, but doing it with only 8 bits might limit it to certain ranges of baud rates for each prescaler option?  Pin change interrupts might be able to substitute for input capture, but without true timer-based input capture, the accuracy will degrade with varying interrupt latency.

Edit: the ATTINY2313A is another one with a 16 bit timer that has input capture and compare units with waveform generation.  Atmel's "product search" only tells how many timers are in a chip, but not if they're 8 or 16 bits or whether they have input capture and compare features, so it seems the only way to search involves reading each datasheet.

Robin2

I bought Attiny 45s before I realized I might have these interesting problems. I don't think I want to take on the job of debugging complex code on the Attiny if there is a simple alternative. Ultimately I just want them to briefly pulse an electromagnet when their number is called.

However the business of decoding (if that's the right word) the serial bit stream is fascinating.

...R

pmelo

Hi everyone,

I've been striving to communicate with a device I have that uses a baud rate of 111111 using an arduino nano v3.0 (16 Mhz). Rob's work is very interesting and I have tried to use his formulas to communicate with the device however with no success (the device's response has been unreliable until now). 
My device only receives data at 111111 bps and it doesn't send any data, so do I only need to tweak the TX value in the delay table? Or do the other 3 values also need to be tweaked?

Another thing that I remembered as I was looking to Rob's formulas was that he mention some errors at higher baudrates. SO i decided to fit a power function to every parameter of the delay table and I got a very good fit. Here are the results that you might want to try and see if it improves the communication. This was only done for 16 Mhz.

RXCENTER


General model Power2:
     f(x) = a*x^b+c
Coefficients (with 95% confidence bounds):
       a =   1.131e+06  (1.116e+06, 1.145e+06)<= -/+ 5%
       b =     -0.9981  (-1, -0.9959)
       c =      -6.842  (-8.296, -5.387)

Goodness of fit:
  SSE: 25.22
  R-square: 1
  Adjusted R-square: 1
  RMSE: 1.588


RXINTRA


General model Power2:
     f(x) = a*x^b+c
Coefficients (with 95% confidence bounds):
       a =   2.292e+06  (2.284e+06, 2.3e+06)
       b =          -1  (-1.001, -0.9999)
       c =      -2.217  (-2.988, -1.446)

Goodness of fit:
  SSE: 7.105
  R-square: 1
  Adjusted R-square: 1
  RMSE: 0.8429


TX


General model Power2:
     f(x) = a*x^b+c
Coefficients (with 95% confidence bounds):
       a =   2.292e+06  (2.279e+06, 2.304e+06)
       b =          -1  (-1.001, -0.9995)
       c =      -5.443  (-6.689, -4.197)

Goodness of fit:
  SSE: 18.56
  R-square: 1
  Adjusted R-square: 1
  RMSE: 1.362

This is a different strategy and maybe it doesn't make any sense from the conceptual point of view but numerically it yields very good fits to the tables.

Robin2

How is it that they all seem to have a perfect fit? Should we be suspicious?

...R

pmelo

#53
Jan 11, 2014, 06:35 pm Last Edit: Jan 11, 2014, 06:42 pm by pmelo Reason: 1
This was done with optimization techniques, so that's why the results look good, but you can confirm with the equations I gave and check that they are pretty close. However don't forget these fits go up to the thousandths and the delay table values are rounded, so it might sometimes be off by one unit or so.

ralphd

It's not interrupt driven like SoftwareSerial, but my bit-bang serial code is very small and works reliably up to 460,800bps at 16Mhz, and 230,400 at 8Mhz, even working of the internal RC oscillator.
http://code.google.com/p/picoboot/source/browse/trunk/BBUart.S
Unthinking respect for authority is the greatest enemy of truth - Einstein.

robtillaart


I've been striving to communicate with a device I have that uses a baud rate of 111111 using an arduino nano v3.0 (16 Mhz). Rob's work is very interesting and I have tried to use his formulas to communicate with the device however with no success (the device's response has been unreliable until now). 
My device only receives data at 111111 bps and it doesn't send any data, so do I only need to tweak the TX value in the delay table? Or do the other 3 values also need to be tweaked?


As stated in one of the previous posts in this thread you should have noticed that Software Serial is reliable up to 70-80K 
Above that the timing is not reliable enough to have good communication (unless you add error correction).
So 111Kbaud will not work with Software Serial. You might check out the ALTSerial of Paul Stoffregen

For speeds below the 70K you might need to play a little with the baud rate. Every device has its error.
So it might be that you should use a bit lower or higher.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart


How is it that they all seem to have a perfect fit? Should we be suspicious?

...R

The original tables were manually tuned, the formulas should have at least no or minimal error for these points.
So the formulas were engineered to fit the points. Seems that worked.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

pmelo



I've been striving to communicate with a device I have that uses a baud rate of 111111 using an arduino nano v3.0 (16 Mhz). Rob's work is very interesting and I have tried to use his formulas to communicate with the device however with no success (the device's response has been unreliable until now). 
My device only receives data at 111111 bps and it doesn't send any data, so do I only need to tweak the TX value in the delay table? Or do the other 3 values also need to be tweaked?


As stated in one of the previous posts in this thread you should have noticed that Software Serial is reliable up to 70-80K 
Above that the timing is not reliable enough to have good communication (unless you add error correction).
So 111Kbaud will not work with Software Serial. You might check out the ALTSerial of Paul Stoffregen

For speeds below the 70K you might need to play a little with the baud rate. Every device has its error.
So it might be that you should use a bit lower or higher.



Thanks for the info Rob. Now I understand, and I was able to fix with AltSoftSerial as you mentioned.

Go Up