Resistor divider doubt

Hello from Barcelona

In my company we do have a dinamometer to measure load of the compression springs we do produce.

It can measure forces form 0g to 5000g and it works with two scales. With the first scale it can measure from 0g to 500g with 0,5g steps and the second scale let’s us measure from up to 5000g with 5g steps.

The first scale is just fine for our porposes but the second one is not as much accurated as we need.
We have notice that the machine has two outputs where you can get a voltage that increases as you are compressing the springs:



On each scale the max value you can get in the segment’s light screen is

When you reach that value you have to pass to the second scale if you were at the first one and stop compressing the spring if you already were in the second one. But if you keep compressing the spring you get higher values with a voltimeter while the dinamometer screen is freezed:

So we wanted to create a voltimeter using one Arduino Uno to be able to measure the voltage changing int he second scale and determinate the load of the springs with the same precision for loads bigger than 500g.

As the Uno was only able to give us 1024 steps of resolution using the analog inputs we found on ebay a 24bits ADC module that would give us up to 6 decimal places values:

http://cgi.ebay.es/ws/eBayISAPI.dll?ViewItem&item=111005456125&fromMakeTrack=true&ssPageName=VIP:watchlink:top:es

One of the good thing of this module is that it can get up to 17v inputs, so we had not to be afraid about using resistors to protect our Arduino. To allow up to 17v measures you have to shorter a jumper. Our dinamometer can output up to 15,6 volts when you are blocking something against the load cell.

With the module comes an sketch:

//LTC2400 24bit ADC Module 
//
//Application Demo: 7 digit voltmeter 
//24bit ADC IC: LTC2400
//4.096 precision reference: TI REF3040
//By coldtears electronics
//LTC2400 code is adapted from Martin Nawrath
//Kunsthochschule fuer Medien Koeln
//Academy of Media Arts Cologne
//
#include <Stdio.h>
#include<stdlib.h>
#ifndef cbi
#define cbi(sfr, bit)     (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit)     (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define LTC_CS 2         // LTC2400 Chip Select Pin  on Portb 2
#define LTC_MISO  4      // LTC2400 SDO Select Pin  on Portb 4
#define LTC_SCK  5       // LTC2400 SCK Select Pin  on Portb 5


void setup() {

 cbi(PORTB,LTC_SCK);      // LTC2400 SCK low
 sbi (DDRB,LTC_CS);       // LTC2400 CS HIGH

 cbi (DDRB,LTC_MISO);
 sbi (DDRB,LTC_SCK);

 Serial.begin(38400);
 
 // init SPI Hardware
 sbi(SPCR,MSTR) ; // SPI master mode
 sbi(SPCR,SPR0) ; // SPI speed
 sbi(SPCR,SPR1);  // SPI speed
 sbi(SPCR,SPE);   //SPI enable

}
float volt;
float v_ref=4.094;          // Voltaje de referencia. Viene indicado por un chip que lleva la plaquita que siempre devuelve 4.094v
          
long int ltw = 0;         // ADC Data ling int
int cnt;                  // counter
byte b0;                  //
byte sig;                 // sign bit flag
char st1[20];             // float voltage text
/****************/
void loop() {

 cbi(PORTB,LTC_CS);             // LTC2400 CS Low
 delayMicroseconds(1);
 if (!(PINB & (1 << 4))) {    // ADC Converter ready ?
   //    cli();
   ltw=0;
   sig=0;

   b0 = SPI_read();             // read 4 bytes adc raw data with SPI
   if ((b0 & 0x20) ==0) sig=1;  // is input negative ?
   b0 &=0x1F;                   // discard bit 25..31
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;

   delayMicroseconds(1);

   sbi(PORTB,LTC_CS);           // LTC2400 CS Low

   if (sig) ltw |= 0xf0000000;    // if input negative insert sign bit
   ltw=ltw/16;                    // scale result down , last 4 bits have no information
   volt = ltw * v_ref / 16777216; // max scale
   char tmp[10];
   dtostrf(volt,6,6,tmp);
   tmp[8]='V';
   tmp[9]='\n';
  printFloat(volt,6);           // print voltage as floating number
  Serial.println("  ");

  
 }
 sbi(PORTB,LTC_CS); // LTC2400 CS hi
 delay(20);

}
/********************************************************************/
byte SPI_read()
{
 SPDR = 0;
 while (!(SPSR & (1 << SPIF))) ; /* Wait for SPI shift out done */
 return SPDR;
}
/********/
//  printFloat from  tim / Arduino: Playground
// printFloat prints out the float 'value' rounded to 'places' places
//after the decimal point
void printFloat(float value, int places) {
 // this is used to cast digits
 int digit;
 float tens = 0.1;
 int tenscount = 0;
 int i;
 float tempfloat = value;

 // if value is negative, set tempfloat to the abs value

   // make sure we round properly. this could use pow from
 //<math.h>, but doesn't seem worth the import
 // if this rounding step isn't here, the value  54.321 prints as

 // calculate rounding term d:   0.5/pow(10,places)
 float d = 0.5;
 if (value < 0)
   d *= -1.0;
 // divide by ten for each decimal place
 for (i = 0; i < places; i++)
   d/= 10.0;
 // this small addition, combined with truncation will round our

 tempfloat +=  d;

 if (value < 0)
   tempfloat *= -1.0;
 while ((tens * 10.0) <= tempfloat) {
   tens *= 10.0;
   tenscount += 1;
 }

 // write out the negative if needed
 if (value < 0)
   Serial.print('-');

 if (tenscount == 0)
   Serial.print(0, DEC);

 for (i=0; i< tenscount; i++) {
   digit = (int) (tempfloat/tens);
   Serial.print(digit, DEC);
   tempfloat = tempfloat - ((float)digit * tens);
   tens /= 10.0;
 }

 // if no places after decimal, stop now and return
 if (places <= 0)
   return;

 // otherwise, write the point and continue on
 Serial.print(',');

 for (i = 0; i < places; i++) {
   tempfloat *= 10.0;
   digit = (int) tempfloat;
   Serial.print(digit,DEC);
   // once written, subtract off that digit
   tempfloat = tempfloat - (float) digit;
 }
}

Our problem is that when we try to read from Vin2 (the pin that allows up to 17v) we do not get realistic data
(for example, a 1,2 volts rechargeable battery gives back 0,30567v and when we were trying on the Vin1 it was 1,31677v.)

With the module there was a PDF explaining that when you allow the Vin2 shortening a jumper the value of the voltage (up to 17v) was obtained doing a resistor divider opertion, but I haven’t seen anything of this in the code provided (I’m a total newbie with Arduino, I’m going to send the data via serial port to work with a program writted in Autoit, wich i’m not as newbie)

The PDF that comes with the board claims:

If the input source is connect to Voltage_IN2, the measured voltage will be
multiplied by the value of the resistor divider ( around (33k+10k)/10k)

And there is this electrical schematic:

But I don’t have any idea of how to get the resistor division inside the code
I have tried to contact with the seller of the board but I get no results.

Any kind of help would be trully apreciatted.

Greets from Barcelona

Manual.pdf (221 KB)

LTC2400_DS.pdf (470 KB)

Divide the result of the Vin2 reading by 4.3 ?

Strike that!

Adolfito121: Our problem is that when we try to read from Vin2 (the pin that allows up to 17v) we do not get realistic data (for example, a 1,2 volts rechargeable battery gives back 0,30567v and when we were trying on the Vin1 it was 1,31677v.)

The PDF that comes with the board claims:

If the input source is connect to Voltage_IN2, the measured voltage will be multiplied by the value of the resistor divider ( around (33k+10k)/10k)

around (33k+10k)/10k) = around 4.3

1.2 / 0.30567 = 3.9258

It's that "around" bit.

>> 1,31677 / 0.30567 = 4.3078

MULTIPLY the result by 4.3 (or your calibration factor)

EDIT: I got it!!

Thanks a lot for your help.

//LTC2400 24bit ADC Module 
//
//Application Demo: 7 digit voltmeter 
//24bit ADC IC: LTC2400
//4.096 precision reference: TI REF3040
//
//By coldtears electronics
//
//LTC2400 code is adapted from Martin Nawrath
//Kunsthochschule fuer Medien Koeln
//Academy of Media Arts Cologne
//


#include <Stdio.h>
#include<stdlib.h>


#ifndef cbi
#define cbi(sfr, bit)     (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit)     (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define LTC_CS 2         // LTC2400 Chip Select Pin  on Portb 2
#define LTC_MISO  4      // LTC2400 SDO Select Pin  on Portb 4
#define LTC_SCK  5       // LTC2400 SCK Select Pin  on Portb 5


void setup() {

 cbi(PORTB,LTC_SCK);      // LTC2400 SCK low
 sbi (DDRB,LTC_CS);       // LTC2400 CS HIGH

 cbi (DDRB,LTC_MISO);
 sbi (DDRB,LTC_SCK);

 Serial.begin(115200);
 
 // init SPI Hardware
 sbi(SPCR,MSTR) ; // SPI master mode
 sbi(SPCR,SPR0) ; // SPI speed
 sbi(SPCR,SPR1);  // SPI speed
 sbi(SPCR,SPE);   //SPI enable

}
float volt;
float v_ref=4.094;          // Voltaje de referencia. Viene indicado por un chip que lleva la plaquita que siempre devuelve 4.094v
          
long int ltw = 0;         // ADC Data ling int
int cnt;                  // counter
byte b0;                  //
byte sig;                 // sign bit flag
char st1[20];             // float voltage text
char Address;  //Variable to store Incoming Packets ID
/********************************************************************/
void loop() {



 cbi(PORTB,LTC_CS);             // LTC2400 CS Low
 delayMicroseconds(1);
 if (!(PINB & (1 << 4))) {    // ADC Converter ready ?
   //    cli();
   ltw=0;
   sig=0;

   b0 = SPI_read();             // read 4 bytes adc raw data with SPI
   if ((b0 & 0x20) ==0) sig=1;  // is input negative ?
   b0 &=0x1F;                   // discard bit 25..31
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;

   delayMicroseconds(1);

   sbi(PORTB,LTC_CS);           // LTC2400 CS Low

   if (sig) ltw |= 0xf0000000;    // if input negative insert sign bit
   ltw=ltw/16;                    // scale result down , last 4 bits have no information
   volt = 4.3 * (ltw * v_ref / 16777216); // max scale
   char tmp[10];
   dtostrf(volt,6,6,tmp);
   tmp[8]='V';
   tmp[9]='\n';
  printFloat(volt,4);           // print voltage as floating number
  Serial.println("");

  
 }
 sbi(PORTB,LTC_CS); // LTC2400 CS hi
 delay(20);

}
/********************************************************************/
byte SPI_read()
{
 SPDR = 0;
 while (!(SPSR & (1 << SPIF))) ; /* Wait for SPI shift out done */
 return SPDR;
}
/********************************************************************/
//  printFloat from  tim / Arduino: Playground
// printFloat prints out the float 'value' rounded to 'places' places
//after the decimal point
void printFloat(float value, int places) {
 // this is used to cast digits
 int digit;
 int digit2;
 float tens = 0.1;
 int tenscount = 0;
 int i;
 float tempfloat = value;

 // if value is negative, set tempfloat to the abs value

   // make sure we round properly. this could use pow from
 //<math.h>, but doesn't seem worth the import
 // if this rounding step isn't here, the value  54.321 prints as

 // calculate rounding term d:   0.5/pow(10,places)
 float d = 0.5;
 if (value < 0)
   d *= -1.0;
 // divide by ten for each decimal place
 for (i = 0; i < places; i++)
   d/= 10.0;
 // this small addition, combined with truncation will round our

 tempfloat +=  d;

 if (value < 0)
   tempfloat *= -1.0;
 while ((tens * 10.0) <= tempfloat) {
   tens *= 10.0;
   tenscount += 1;
 }

 // write out the negative if needed
// if (value < 0)
  Serial.print('-');

 if (tenscount == 0)
   Serial.print(0, DEC);

 for (i=0; i< tenscount; i++) {
   digit = (int) (tempfloat/tens);
   Serial.print(digit, DEC);
   tempfloat = tempfloat - ((float)digit * tens);
   tens /= 10.0;
 }

 // if no places after decimal, stop now and return
 if (places <= 0)
   return;

 // otherwise, write the point and continue on
 Serial.print(',');

 for (i = 0; i < places; i++) {
   tempfloat *= 10.0;
   digit = (int) tempfloat;
   Serial.print(digit,DEC);
   // once written, subtract off that digit
   tempfloat = tempfloat - (float) digit;
 }
}

Adolfito121:
I tried to modify the code:

 Serial.print(',');

for (i = 0; i < places; i++) {
  tempfloat *= 10.0;
  digit = (int) tempfloat;
  digit2 = digit * 4.3; //I’m not sure if this is the way of multiplying the value :S Pathetic, I Know

So, you do not know well (at all?) this sketch?

Near the top of the loop there are:

   ltw=ltw/16;                    // scale result down , last 4 bits have no info
   volt = ltw * v_ref / 16777216; // max scale

Is ltw the result of the scale read?
What is volt? Some conversion?

What if “we” change that to:

   ltw=(ltw/16)*4.3;               // scale result down , last 4 bits have no info
   volt = ltw * v_ref / 16777216; // max scale

or

   ltw=ltw/16;                    // scale result down , last 4 bits have no infO
   volt = (ltw * v_ref / 16777216)*4.3; // max scale

??

Yeh, thanks a lot again. I just edited when I saw the way of solving it.

Thanks a lot for your help.

Hello again.

The Arduino is giving us reliable result for voltages lower than 5v.

:~

I've been trying to contact with the dealer of the 24 ADC bits converter board but he doens't give any solution.

In theory it could manage voltages up to 17v. Is there anyone out here that have the same board or any idea of what we're doing wrong?

Thanks again for your help.

Greets from Barcelona