Voltage input help (possible reward for help)

Hello all I’m working on a data acquisition project, and am attempting to read voltages out of a strain gauge, with amplification from a wheat stone bridge.

I’m having troubles reading input voltage into the arduino, I don’t know if it is in the code or something else, but even when I hook up 5V from the battery pack, it only shows 1023 ( max voltage ) part of the time. Other times it sits at random voltages even with nothing in the inputs. Attached is my code and a sample file.

In the excel file, it goes
Time, x, y,z, sensor (where the voltage should be read at)

Where x,y,z are accelerometer inputs that are working fine.

If anyone can tell me why this is the way it is, I would REALLY appreciate it. I’m eventually going to hook this up to a breadboard with a low pass filter and the wheatstone bridge, so I’d like to get this debugged before hand.

If someone helps me a ton I would be willing to give a charitable donation to help me trouble shoot this from the point i’m at right now, to reading my breadboarded circuit.
Thanks a ton!!!
Layvon

Code:

// BST DATA AQUISITION SYSTEM 
//this code was written Spring 2010



/* THINGS TO KNOW
Serial.print prints to the computer
File.print   prints to the Micro SD Card
*/

// A simple data logger for the Arduino analog pins
#define LOG_INTERVAL  100 // mills between entries
#define SENSOR_COUNT     1 // number of analog pins to log
#define ECHO_TO_SERIAL   1 // echo data to serial port 1=on 0=off (turn this on if you want values to print to the computer screen)
#define WAIT_TO_START    0 // Wait for serial input in setup() 1=on 0=off 
#define SYNC_INTERVAL 1000 // mills between calls to sync()
uint32_t syncTime = 0;     // time of last sync()

// this library is for the accelerometer
#include <Wire.h>
// these librarys make the card reader work
#include <microfat.h>
#include <SdFat.h>
#include <SdFatUtil.h>

//Give convenient names to the control pins for multiplexer
#define CONTROL0 5    
#define CONTROL1 4
#define CONTROL2 3
#define CONTROL3 2

// accelerometer definitions
#define DEVICE (0x53)    //ADXL345 device address
#define TO_READ (6)      //num of bytes we are going to read each time (two bytes for each axis)



//Create arrays for data from the the MUXs
//See the Arduino Array Reference: http://www.arduino.cc/en/Reference/Array
int data0[16];
int data1[16];
int data2[16];


// card prep
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

//accelerometer prep
byte buff[TO_READ] ;    //6 bytes buffer for saving data read from the device
char str[512];          //string buffer to transform data before sending it to the serial port


// store error strings in flash to save RAM these errors are from the card reader if something is wrong
#define error(s) error_P(PSTR(s))
void error_P(const char *str)
{
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}

void setup(void)
{
  
  Serial.begin(9600);
  pinMode(8, OUTPUT);
  digitalWrite (8, HIGH);
  Wire.begin();        // join i2c bus 

  //Turning on the ADXL345
  writeTo(DEVICE, 0x2D, 0);      
  writeTo(DEVICE, 0x2D, 16);
  writeTo(DEVICE, 0x2D, 8);

  

  
#if WAIT_TO_START
  Serial.println("Type any character to start");
  while (!Serial.available());
#endif //WAIT_TO_START

  // initialize the SD card
  if (!card.init(true)) error("card.init");
  
  // initialize a FAT volume
  if (!volume.init(card)) error("volume.init");
  
  // open root directory
  if (!root.openRoot(volume)) error("openRoot");
  
  // create a new file
  char name[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (file.open(root, name, O_CREAT | O_EXCL | O_WRITE)) break;
  }
  if (!file.isOpen()) error ("file.create");
  
  Serial.print("Logging to: ");
  Serial.println(name);

  // write header in file this is automaticaly commented out so matlab will be happy
  file.writeError = 0;
  file.print("%millis");
  file.print(" ,x");
  file.print(" ,y");
  file.print(" ,z");
#if ECHO_TO_SERIAL 
  Serial.print("%millis");
  Serial.print(" ,x");
  Serial.print(" ,y");
  Serial.print(" ,z");
#endif //ECHO_TO_SERIAL

#if SENSOR_COUNT > 15
#error SENSOR_COUNT too large
#endif //SENSOR_COUNT

  for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
    file.print(" ,sens");file.print(i, DEC);    
#if ECHO_TO_SERIAL
    Serial.print(" ,sens");Serial.print(i, DEC);
#endif //ECHO_TO_SERIAL
  }
  file.println();  
#if ECHO_TO_SERIAL
  Serial.println();
#endif  //ECHO_TO_SERIAL

  if (file.writeError || !file.sync()) {
    error("write header");
  }
}

void loop(void)
{
  // clear print error
  file.writeError = 0;
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
  
  // log time
  uint32_t m = millis();
  file.print(m);  
#if ECHO_TO_SERIAL
  Serial.print(m);
#endif //ECHO_TO_SERIAL

//Read Data From Accelerometer      
  int regAddress = 0x32;    //first axis-acceleration-data register on the ADXL345
  int x, y, z;
  readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
   //each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!!

   //thus we are converting both bytes in to one int
  x = (((int)buff[1]) << 8) | buff[0];   
  y = (((int)buff[3]) << 8) | buff[2];
  z = (((int)buff[5]) << 8) | buff[4];

 
  //we send the x y z values as a string to the card
    file.print(',');    
    file.print(x);
    file.print(',');
    file.print(y);
    file.print(',');
    file.print(z);
  //we send the x y z values as a string to the serial port
  #if ECHO_TO_SERIAL
    Serial.print(',');   
    Serial.print(x);
    Serial.print(',');   
    Serial.print(y);
    Serial.print(',');   
    Serial.print(z);
  #endif //ECHO_TO_SERIAL


    //This for loop is used to scroll through and store the 16 inputs on the FIRST multiplexer ** to add the other multiplexers copy and past the loop and change data0 to the correct number (1 or 2)
  for (uint8_t i=0; i< SENSOR_COUNT; i++)
  {
    //The following 4 commands set the correct logic for the control pins to select the desired input
    //See the Arduino Bitwise AND Reference: http://www.arduino.cc/en/Reference/BitwiseAnd
    //See the Aruino Bitshift Reference: http://www.arduino.cc/en/Reference/Bitshift
    digitalWrite(CONTROL0, (i&15)>>3); 
    digitalWrite(CONTROL1, (i&7)>>2);  
    digitalWrite(CONTROL2, (i&3)>>1);  
    digitalWrite(CONTROL3, (i&1));     
    
    //Read and store the input value at a location in the array
    data0[i] = analogRead(0);
  
    file.print(',');    
    file.print(data0[i]);
#if ECHO_TO_SERIAL
    Serial.print(',');   
    Serial.print(data0[i]);
#endif //ECHO_TO_SERIAL
  }
    file.println();  
  #if ECHO_TO_SERIAL
    Serial.println();
  #endif //ECHO_TO_SERIAL

  if (file.writeError) error("write data");
  
  //don't sync too often - requires 2048 bytes of I/O to SD card
  if ((millis() - syncTime) <  SYNC_INTERVAL) return;
  syncTime = millis();
  if (!file.sync()) error("sync");
}

//---------------- Functions to read the data from the ADXL345

//Writes values to address register on the Accelerometer
void writeTo(int device, byte address, byte val) {
   Wire.beginTransmission(device); //start transmission to device 
   Wire.send(address);        // send register address
   Wire.send(val);        // send value to write
   Wire.endTransmission(); //end transmission
}


//reads num bytes starting from address register on device in to buff array

void readFrom(int device, byte address, int num, byte buff[]) {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.send(address);        //sends address to read from
  Wire.endTransmission(); //end transmission
  Wire.beginTransmission(device); //start transmission to device
  Wire.requestFrom(device, num);    // request 6 bytes from device
  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
  { 
    buff[i] = Wire.receive(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission
}

Over character limit....

Excel ( this is echo'd to the serial port on computer as well. . )

72100 -38 -54 241 0 72199 -26 -65 240 18 72300 -29 -42 240 31 72398 -37 -39 240 17 72499 -24 -59 248 13 72599 -32 -49 247 24 72699 -31 -54 238 0 72799 -28 -45 241 15 72899 -34 -51 243 26 72998 -21 -57 223 13 73099 -30 -49 229 28 73199 -28 -48 240 1023 73298 -31 -44 234 1023 73399 -25 -48 247 1023 73500 -15 -47 242 1023 73598 -13 -59 234 1023 73699 -28 -44 227 377 73800 -16 -46 251 647 73899 -20 -43 246 1023 73999 -25 -40 250 1023 74100 -19 -37 242 599 74199 -32 -31 241 1012 74299 -56 -58 231 1023 74399 -10 -40 249 258 74499 -18 -33 245 1006 74600 -17 -36 247 375 74699 -20 -34 243 296 74799 -19 -36 248 52 74899 -18 -41 239 714 74998 -18 -35 245 1023 75100 -14 -42 243 727 75199 -6 -40 246 1023 75299 -12 -36 234 224

After the first 1023 reading, the +5V wire wasn't taken out during that whole run, so I don't know what the problem is.

My setup is a 128 demovuelve (powered by the USB connection from PC) Mayhew labs Mux shield Liquid ware lithium backpack (only used to provide 5V to rail on Arduino)

If you read the analog input pin with nothing connected, the input ‘floats’ so you will get unstable readings.
I would add a 10K resistor to ground to ensure readings of ~0 when nothing is connected.
I am not familiar with the apparent external mux you have connected. It could be you’re just swithing too fast -try slowing things down some. Give the signal some time to settle thru the max and then settle on the ADC circuit in the atmega.

    //This for loop is used to scroll through and store the 16 inputs on the FIRST multiplexer ** to add the other multiplexers copy and past the loop and change data0 to the correct number (1 or 2)
  for (uint8_t i=0; i< SENSOR_COUNT; i++)
  {
    //The following 4 commands set the correct logic for the control pins to select the desired input
    //See the Arduino Bitwise AND Reference: http://www.arduino.cc/en/Reference/BitwiseAnd
    //See the Aruino Bitshift Reference: http://www.arduino.cc/en/Reference/Bitshift
    digitalWrite(CONTROL0, (i&15)>>3); 
    digitalWrite(CONTROL1, (i&7)>>2);  
    digitalWrite(CONTROL2, (i&3)>>1);  
    digitalWrite(CONTROL3, (i&1));     
    
    //Read and store the input value at a location in the array
    data0[i] = analogRead(0);
  
    file.print(',');    
    file.print(data0[i]);
#if ECHO_TO_SERIAL
    Serial.print(',');   
    Serial.print(data0[i]);
#endif //ECHO_TO_SERIAL
  }
[code]

[/code]

Wheatstone bridges do not provide amplification. They only convert changes in resistance to changes in voltage. (and with strain gauges it’s usually VERY small changes in voltage)

You will need to use an amplifier to increase the signal voltage. Most load cells/strain gauges only put out a maximum of ~20/mv per volt of input when they are fully flexed.

Thank you very much! I might try to implement that asap. Shouldn't be to hard to figure that out, but what do you think about the arduino not measuring the voltages?

Any help appreciated

If you put a meter on the A0 pin, what kind of voltage do you see? Write a simple sketch, just read the input & report, see if you can get consistent results out.

You were completely right about the floating point on the voltage, as soon as I connected a resistor to the 0 pin on my mux board, it zero'd out. good. Now I trust the data a little bit more.

I'll keep playing with the speeds of polling and see what I come up with.

Thanks again for the help

Here is the picture of how the MUX shield looks.

After doing some wheatstone bridge calculations, the arduino does a pretty good job of accurately measuring the voltage! I was super impressed. Now to get the whole 0-1023 spectrum covered I plan on using an opamp to bump up the voltage at the nominal resistance of the strain gauge from ~108mV to roughly 2.5V. Do you guys think that an LM386 would work for this? It has voltage gains from 20-200 and is capable of operating on 5Vdc.

Here is a link to the app notes for it if anyone cares to help me look into it: http://www.national.com/ds/LM/LM386.pdf

this might be the final link to complete the project as far as the arduino is concerned!

So excited

Do you guys think that an LM386 would work for this? It has voltage gains from 20-200 and is capable of operating on 5Vdc.

No, a LM386 is an opamp optimized to be an audio amplifier, you just need standard opamps and there are a zillion different ones to choose from and most would work fine.

I recommend an ina125. It has a precision voltage reference for load cell excitation and resistor selectable gain.

It is specifically meant for what you want to do. Especially if you NEED consistent results.

I've built this board using the provided wiring with excellent results. http://www.jamesyawn.com/electronicstand/amp/index.html

landru, is there a schematic in there somewhere? I'm not seeing one.

Bah. I must have linked the wrong page.

http://www.jamesyawn.com/electronicstand/amp/board2.html

It's a hacked simple wiring diagram, but it is simple enough.

The ina125 data sheet should also give you a sample amplifier circuit.