Need help for fast (10bits) analogRead & serial TX

Hello Everyone, I'm trying to make a XY tube curve tracer project and need to send 2 (synchronous as possible) 10bits analogReads as fast as possible (using serial) to processing. I'm also using a digitalWrite in the loop.

I don't know really where to start, if I understood correctly, it's better to split the analogReads 10 bits of data in 2 bytes (instead of 4 for an int) to speed up serial communication (and bandwidth). Also the most important part to achieve is having the 2 analogReads (per loop) being within less than 1ms between each other, or synchronous if possible ? Synchronous transmission of the data is not required, I can use a buffer or memory (I have an I2C chip). Could someone help please, I'm totally ignorant regardint interrupts buffering or serial com, (should I use an external library ?) Thanks a lot

20 bits total, three bytes minimum, four if your bit-packing isn't up to spec. ;) So, to transmit four bytes serially requires 4 * 10 bits = 40 bits. 40 bits in 1mS gives a minimum speed of 40000 bits per second. Go for 57600.

In fact I should transmit two 0-1024 readings (that are as simultaneous in time as possible) to the sofware, 1ms between them being quite bad BTW), I think that if I "bit-pack" I have to add some kind of "separators" too? And I'm confused with "bit packing" some example code would be appreciated !

PS: the data transmission could happen later, it has not to be real time nor synchronous, it can wait in a buffer or be stocked somewhere. the key here is short time between the 2 succesive analog readings of the loop (I can spend time between loops and pairs of readings). I'm measuring 0 to 500V sine pulses (0 to 1024) that are 20ms long so few µs would be far better ! Excuse my poor english please, I hope I'm clear.

I think that if I “bit-pack” I have to add some kind of “separators” too

No, because you’d always be packing two lots of ten bits.
Probably not worth the effort, anyway - it only saves you ten bit periods on the serial line.
So, instead of 40000 bps, you’d need 30000bps.
You may still need occasional sync points.

Analogue conversion rate is about 10kHz, so consecutive samples should be about 100uS (0.1mS) apart.

Analogue conversion rate is about 10kHz, so consecutive samples should be about 100uS (0.1mS) apart.

thanks AWOL, I'm now able to calculate the error ratio. I still can't figure out how convert int into 2 bytes then to spilt it & send data & merge in processing. (should I use an external library) Maybe there is some typical protocole code I haven't found with google ? thanks again, I'm more confortable with vacuum tubes ;)

I still can’t figure out how convert int into 2 bytes then to spilt it & send data & merge in processing. (should I use an external library)

Something like:

unsigned short readingA = analogRead (apin);
unsigned short readingB = analogRead (bpin);
Serial.print (readingA >> 8, BYTE);
Serial.print (readingA & 0xFF, BYTE);
Serial.print (readingB >> 8, BYTE);
Serial.print (readingB & 0xFF, BYTE);

Voila

merci beacoup !

I'll still need to merge it but it shouldn't be that hard ... is there an interest using interrupts (or a library like new software serial) for faster speed ?

thanks again

Software serial is if anything going to be slower, because the hardware USART does a lot of things (like automatically generating start and stop bits) that the software serial library has to emulate in software.

For the timeframe of <1mS, you should be able to do everything with the default arduino functions with plenty of time left over.

Note also that you can set the serial baud rate faster than even the 115200baud listed as the max baud rate in the Arduino IDE. I’ve set the baud rate to 250000 and still been able to send and receive with no errors, although I had to optimize the code pretty carefully in some places. Not sure how well Processing will support those speeds, though.

After calculating the error ratio (sorry to be late), in fact, if I want the I/V curve to be < 1V precision (which is the purpose of such a device) with 500V peaks lasting 10mS (I’m stuck with mains frequency, 50 Hz here).
So I need a timeframe of 10µS (roughly a bit less than 0,5V resolution which correspond to the global horizontal Volts scale precision of 500V/1024).
I understand the limitation of the serial communication bandwidth but that’s not an issue here, only the two reading per cycle have to be close each others and then do as many cycles as needed to have enough values to plot a nice curve.
I found two topics on this forum that let me think that it should be achievable but I’m a bit lost to implement the code.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1242967991/2
(arduinoscope up to 360000 samples/sec)
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1242466935/8#8
improved serial communication

thank you for your help.

PS: I’ve manage 115200 Bauds com. between arduino & processing without problems.
And to recapitulate the only things needed in the loop are 2 close analogReads, 1 digitalWrite(that changes only, let’s say every seconds) and occasional (if it can shorten the timeframe) TX of the data.

The two channel requirement is a bit a killer at these kind of speeds. The 'scope presented above is a single channel device - the documentation for analogRead warns against switching sources too rapidly here: http://arduino.cc/en/Tutorial/AnalogInputPins in "Details and Caveats".

The Atmega168 datasheet also cautions against switching analog pins in close temporal proximity to making A/D readings (analogRead) on other analog pins. This can cause electrical noise and introduce jitter in the analog system. It may be desirable, after manipulating analog pins (in digital mode), to add a short delay before using analogRead() to read other analog pins.

Doesn't it apply only to "switching" a pin from digital to analog ? (which is not my case)

Hmm, not sure now - I assumed it referred to switching the analogue input mux to the A/D converter. I'll have to check the datasheet.

So far I’ve tried a standart arduin-o-scope sketch with 6 analogReads in a for loop like (i=0, i<6, i++) analogread(i) without apparent noise.

I had a look to Port register in the documentation, and it says that:

the PIN register reads the state of INPUT pins set to input with pinMode() ... PINB is the input register variable It will read all of the digital input pins at the same time.

Sometimes you might need to set multiple output pins at exactly the same time. Calling digitalWrite(10,HIGH); followed by digitalWrite(11,HIGH); will cause pin 10 to go HIGH several microseconds before pin 11, which may confuse certain time-sensitive external digital circuits you have hooked up. Alternatively, you could set both pins high at exactly the same moment in time using PORTB |= B1100;

Can I use these properties using PINC and achieve two analog readings at the same time or in less than 10µS ? I don't clearely understand if PINC return the state of the pin (Input/Output) or its value (0-1024) ?

Thank you for your help.

Unfortunately you can't. Each analog value must be read separately.

Theoretically you could save a little time by using low level register functions instead of the Arduino analogRead function But you would need to study and understand the low level register functions documented in the ATmega datasheet to get this to work and its probably not worth the trouble because you would not get anywhere near the improvement that you get with direct port io compared to digitalRead..

Damned ! but should it speed up things a bit? I'll have to achieve this *** 10µs timeframe !

If you really want to try to speed things up then read the section on ADC conversion in the ATmega 168/328 datasheet. But the techniques described are outside the scope of typical Arduino use and you may find that specialist forums such as avrfreaks has more information on the low level coding needed. It can be done but its not something that will be easy if you are not familiar with coding at the register level.

BTW, I don't think the ADC in the Arduino chip is capable of 10us conversions

Thank you for your precise answer Mem. With my small imagination there seems to be two "inelegant" alternatives now, use the soundcard stereo DAC (no isolation) . or a long long string of salvaged from TV's 430nS delay lines :-/

Any ideas are welcome.

I would be surprised to hear that a soundcard could provide 10us conversion rates – do you mean 10ms?

Not sure how you would use the delay lines, could you say more about what you are thinking of doing.

I would be surprised to hear that a soundcard could provide 10us conversion rates – do you mean 10ms?

the important thing for me is close readings between two readings so stereo DACs are supposed to be synchronous between R & L (my X&Y scope channels) Anyway although I don't need it 96kHz is close to 10µS

Not sure how you would use the delay lines, could you say more about what you are thinking of doing.

Just an ugly string of dozen of devices to match the lag between two successive analogReads (pin X then pin Y that are supposed to be synchronous)