carduinomicrocontrollerspianalog-digital-converter

Multiple analog to digital converters on Arduino using SPI bit banging


I am using a Nano Arduino (ATMega 328) to communicate to two 12-bit MCP3208 ADC chips based on this code. I have another device (LED driver TLC5940) tied to the pins that are suggested on this page but since I am using bit banging, it should not matter what pins I use. So, my configuration is the same as the above example except that:

    For ADC 1:
    CLK -> Arduino D6
    DOUT (MISO) -> Arduino D5
    DIN (MOSI) -> Arduino D12
    SS -> Arduino D7

    For ADC 2:
    CLK -> Arduino D6
    DOUT (MISO) -> Arduino D5
    DIN (MOSI) -> Arduino D12
    SS -> Arduino D8

So, the problem is that I get data from ADC 1 but not from ADC 2. I should be able to select ADC 2 by by pulling the selection pin low but all I get is 0. There are 16 photodiodes connected to 4 TLC2274 op-amps. Here is the Arduino code:

//Scott Little, BrainGoggles, 2013, GNU GPL v3
#include <SoftwareSerial.h>
#include "Tlc5940.h"
SoftwareSerial bluetooth(4,2);  //TX 4, RX 2

#define SELPIN 7 //Selection Pin for 1st ADC
#define SELPIN2 8 //Selection Pin for 2nd ADC
#define DATAOUT 12//MOSI 
#define DATAIN  5//MISO 
#define SPICLOCK  6//Clock 
int readvalue;
byte readvaluearray[32];
int intensity = 0;

void setup()
{
  /* Call Tlc.init() to setup the tlc.
     You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
  Tlc.init();  //interferes with other SPI
  Tlc.clear();  //set pin modes 

  pinMode(SELPIN, OUTPUT); //adc 1 selection pin
  pinMode(SELPIN2, OUTPUT); //adc 2 selection pin
  pinMode(DATAOUT, OUTPUT); 
  pinMode(DATAIN, INPUT); 
  pinMode(SPICLOCK, OUTPUT); 
  //disable devices to start with 
  digitalWrite(SELPIN,HIGH); 
  digitalWrite(SELPIN2,HIGH);
  digitalWrite(DATAOUT,LOW); 
  digitalWrite(SPICLOCK,LOW); 
  bluetooth.begin(9600); 
  Serial.begin(9600);

}

void loop()
{
  if (bluetooth.available()) // Wait until a character is received
  {
    char val = (char)bluetooth.read();
    Serial.println(val);

    switch(val) // Perform an action depending on the command
    {
      case 't'://increase intensity when an 'e' is received
    intensity = plus(intensity);
      break;      

      case 'y'://decrease intensity when an 'r' is received
    intensity = minus(intensity);
      break;

      case 'q'://turn the light on when a 'q' is received
    on();
      break;

      case 'w'://turn the light off when a 'w' is received
    off();
      break;
    }
  }

  for (int i=0; i<8; i++){        //read from ADC 1
    readvalue = read_adc(i+1);
    readvaluearray[2*i] = highByte(readvalue);
    readvaluearray[2*i+1] = lowByte(readvalue);
  }

  for (int i=8; i<16; i++){        //read from ADC 2
    readvalue = read_adc2(i-7);
    readvaluearray[2*i] = highByte(readvalue);
    readvaluearray[2*i+1] = lowByte(readvalue);
  }

  bluetooth.write(readvaluearray,32);
  Serial.println("new");
  for (int i=0;i<16;i++){
    Serial.println(word(readvaluearray[2*i],readvaluearray[2*i+1]));
  }

  delay(2000);
}


int read_adc(int channel){
  int adcvalue = 0;
  byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

  //allow channel selection
  commandbits|=((channel-1)<<3);

  digitalWrite(SELPIN,LOW); //Select adc

  // setup bits to be written
  for (int i=7; i>=3; i--){
    digitalWrite(DATAOUT,commandbits&1<<i);
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);    
  }

  digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWrite(SPICLOCK,LOW);
  digitalWrite(SPICLOCK,HIGH);  
  digitalWrite(SPICLOCK,LOW);

  //read bits from adc
  for (int i=11; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device

  return adcvalue;
}

int read_adc2(int channel){
  int adcvalue = 0;
  byte commandbits = B11000000; //command bits - start, mode, chn (3), dont care (3)

  //allow channel selection
  commandbits|=((channel-1)<<3);

  digitalWrite(SELPIN2,LOW); //Select adc

  // setup bits to be written
  for (int i=7; i>=3; i--){
    digitalWrite(DATAOUT,commandbits&1<<i);
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);    
  }

  digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWrite(SPICLOCK,LOW);
  digitalWrite(SPICLOCK,HIGH);  
  digitalWrite(SPICLOCK,LOW);

  //read bits from adc
  for (int i=11; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN2, HIGH); //turn off device

  return adcvalue;
}

void on(void)
{
  Tlc.set(1, 4095);  //set pin 5 to max brightness
  Tlc.update();  //execute set
  //bluetooth.println("on");
  //Serial.println("on");
}

void off(void)
{
  Tlc.set(1, 0);  //set pin 5 to min brightness
  Tlc.update();  //execute set
  //bluetooth.println("off");
  //Serial.println("off");
}

int plus(int value)
{
  value = value + 64;
  if (value > 4095){value = 4095;}
  Tlc.set(1, value);  //set pin 5 to min brightness
  Tlc.update();  //execute set
  Serial.println(value);
  return value;
}

int minus(int value)
{
  value = value - 64;
  if (value < 0){value = 0;}
  Tlc.set(1, value);  //set pin 5 to min brightness
  Tlc.update();  //execute set
  Serial.println(value);
  return value;
}

Here is sample output that I am getting:

new
374
372
311
313
356
276
337
387
0
0
0
0
0
0
0
0

Solution

  • It is working now. I physically changed the pin on the ADC corresponding to DOUT (ADC 12) to the pin on the Arduino corresponding to MISO (Arduino 12) and changed the code as such:

    #define DATAOUT 5  //MOSI 
    #define DATAIN  12 //MISO 
    

    It should have worked as I had it before since I am bit banging, but it seems to work now as MISO is on the "correct" pin.