The "packet" structure is very simple: each ADC reading consists of two bytes with the following structure:
Byte # | Interpretation |
---|---|
0 | 1PPPxVVV |
1 | 0VVVVVVV |
Communication takes place at 9600 baud, and it takes 120 bits (including start and stop bits) to update all analog inputs. This makes the maximum update rate 80Hz. However, some additional time is required for the analogRead() function to execute, and there are no timing guarantees for the HAL userspace component running on the PC.
The program consists of two parts. First, the part that runs on the AVR, "adc6.pde" (see Listing 1). Second, the part that runs on the PC, "arduino-adc6.py" (see Listing 2).
I don't have any analog sources handy, but instead I hooked the several supply voltages available up to the first three analog inputs. Here's a sample session:
The nominal voltages are 0V, 5V, and 3.3V. It looks like the AVR's "sample and hold" circuitry tends to read near the previous value when the input is actually floating.$ halrun halcmd: loadusr -Wn arduino-adc6 python ./arduino-adc6.py halcmd: show pin Component Pins: Owner Type Dir Value Name 28114 float OUT 0 arduino-adc6.analog-in-0 28114 float OUT 5 arduino-adc6.analog-in-1 28114 float OUT 3.377322 arduino-adc6.analog-in-2 28114 float OUT 3.333333 arduino-adc6.analog-in-3 28114 float OUT 3.29912 arduino-adc6.analog-in-4 28114 float OUT 3.294233 arduino-adc6.analog-in-5
There are some obvious next steps: First, there are 6 bidirectional digital I/O pins available. It would be nice to read these. Second, it would be nice to use some of them as outputs, and also use the 6 8-bit PWM generators that are available.
Besides the caveat that this driver is not realtime, it is also important to note that neither USB nor RS232 serial provide isolation, and that only voltages in the range 0..5V may be applied to the AVR's ADC pins.
Listing 1: adc6.pde
void setup() { Serial.begin(9600); } void loop() { for(int i=0; i<6; i++) { uint16_t v = analogRead(i) | (i << 10); Serial.print((v >> 7) | 0x80, BYTE); Serial.print(v & 0x7f, BYTE); } }
Listing 2: arduino-adc6.py
#!/usr/bin/python import serial import hal import sys PORT = "/dev/ttyUSB0" if len(sys.argv) > 1: PORT = sys.argv[1] ser = serial.Serial(PORT, 9600, timeout=2) c = hal.component("arduino-adc6") for port in range(6): c.newpin("analog-in-%d" % port, hal.HAL_FLOAT, hal.HAL_OUT) c.newparam("analog-in-%d-offset" % port, hal.HAL_FLOAT, hal.HAL_RW) c.newparam("analog-in-%d-gain" % port, hal.HAL_FLOAT, hal.HAL_RW) c['analog-in-%d-gain' % port] = 1.0 c.ready() while 1: b1 = ord(ser.read()) if b1 & 0x80 != 0x80: continue # First bit of packet has high bit set b2 = ord(ser.read()) if b2 & 0x80 != 0: continue # Second bit of packet has high bit clear v = (b1 << 7) | b2 port = (v >> 10) & 7 gain = c['analog-in-%d-gain' % port] offset = c['analog-in-%d-offset' % port] value = (v & 1023) / 1023. * 5.0 * gain + offset c['analog-in-%d' % port] = value
(originally posted on the AXIS blog)
Entry first conceived on 24 December 2007, 19:46 UTC, last modified on 15 January 2012, 3:46 UTC
Website Copyright © 2004-2024 Jeff Epler