Expanding Arduino ADC inputs with external 10 channel ADC
Many microcontroller projects involve the use of sensors like Accelerometers, Gyroscopes, Temperature, Compass, Barometric, Current, Proximity and others. Some sensors have I2C or SPI interfaces but there are still a great many which produce an analogue output voltage. These are measured with the use of the built-in Analogue to Digital Converters (ADC) included in microcontrollers. However, if you are using many sensors and don’t have enough ADC inputs, or have used those pins for other functions, you either have to upgrade to a larger microcontroller with more inputs or resort to using an external (and sometimes expensive) ADC chip.
With this in mind we have programmed our own microcontroller to provide you with 10 additional ADC inputs available via I2C as a slave device. ADC I2C Slave IC
Here is the pinout for the ADC chip
Apart from supplying power to the chip, simply connect pin 13 (SDA) to Arduino UNO pin A4 (SDA) and connect pin 11 (SCL) to Arduino UNO pin A5 (SCL). Use pullup resistors on these 2 pins (4K7).
Use the sketch below and try it out.
/* ** Wire Master Reader of Hobbytronics 10 channel ADC ** Created 06 Feb 2010 ** ** This example code is in the public domain. ** www.hobbytronics.co.uk */ #include <Wire.h> const int adc_address=40; // I2C Address of ADC Chip const int adc_config=B00000011; // 8-bit data, complementary filter // output (see datasheet) unsigned int adc_data[10]; // Array to store ADC values void setup() { //Send settings to ADC_I2C device (optional) Wire.begin(); // join i2c bus (address optional for master) Wire.beginTransmission(adc_address); // transmit to device Wire.send(adc_config); // send config options Wire.endTransmission(); // stop transmitting //Start Serial port Serial.begin(9600); // start serial for output } void get_adc_8() { // Get 8-bit ADC data // We only want single byte values (0 to 255) unsigned char data_values_rcvd=0; // keep track of how many chars received Wire.requestFrom(adc_address, 10); // request 10 bytes from slave device data_values_rcvd=0; while(Wire.available()) { if(data_values_rcvd < 10) adc_data[data_values_rcvd] = Wire.receive(); // receive a byte as character data_values_rcvd++; } } void get_adc_10() { // Get 10-bit ADC data // We want double byte values (0 to 1024) // We will reconstruct an unsigned int from the two bytes received unsigned char hi_lo_byte; unsigned char data_values_rcvd=0; // keep track of how many chars received Wire.requestFrom(adc_address, 20); // request 20 bytes from slave device data_values_rcvd=0; hi_lo_byte=1; // First byte will be a high byte while(Wire.available()) { if(data_values_rcvd < 10) { if(hi_lo_byte) { // Its a high byte adc_data[data_values_rcvd] = Wire.receive() << 8; // receive high byte and shift left 8 hi_lo_byte=0; // next byte will be a low byte } else { adc_data[data_values_rcvd] += Wire.receive(); // receive low byte and add to existing value data_values_rcvd++; hi_lo_byte=1; // next byte will be a high byte } } } } void loop() { unsigned char i; if(bitRead(adc_config, 0)) get_adc_8(); // get 8-bit data else get_adc_10(); // get 10-bit data // Print out our data for(i=0;i<10;i++) { Serial.print(adc_data[i], DEC); // print the character Serial.print(","); // print comma } Serial.println(""); // print carriage return delay(500); }