NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » Hacking a weight scale

March 17, 2011
by abd445
abd445's Avatar

Hello,

I am trying to build on to the weight scale project proposed in nerd kits, but instead of using python i am using C and I want to display the weight on the LCD that I got from nerdkits instead of the LCD of the weight scale. I tried this code but I am unable to display the weight. It just displays a constant number 01 and it doesnt change no matter how much pressure i put on the scale. Please give me any suggestions and help me.

Here's the code:

// seniordesign.c
// using NerdKits with ATmega168
// ****taken from example temperature sensor code  
//     and changed to apply to distance sensor EZ-4
//     and then added weight scale to project *******

#define F_CPU 14745600

#include <stdio.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PIN DEFINITIONS:
//
// PC0 -- height sensor analog input
// PC1 -- weight scale analog in
//
// PB4 - bridge excite
// PB3 - bridge excite

void adc_init() {
  // set analog to digital converter
  // for external reference (5v), single ended input ADC0
  ADMUX = 0;

  // set analog to digital converter
  // to be enabled, with a clock prescale of 1/128
  // so that the ADC clock runs at 115.2kHz.
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

  // fire a conversion just to get the ADC warmed up
  ADCSRA |= (1<<ADSC);
}

uint16_t adc_read() {

  // set ADSC bit to get the conversion started
  ADCSRA |= (1<<ADSC);

  while(ADCSRA & (1<<ADSC)) {
    // do nothing... just hold your breath.
  }
  // bit is cleared, so we have a result.

  // read from the ADCL/ADCH registers, and combine the result
  // Note: ADCL must be read first (datasheet pp. 259)
  uint16_t result = ADCL;
  uint16_t temp = ADCH;
  result = result + (temp<<8);

  return result;
}

double sampleToInches(uint16_t sample) {
  // conversion ratio in INCHES/STEP:
  // (5000 mV / 1024 steps) * (1 cm / 4.8828125 mV) * (0.3937 in / 1 cm)
  //       ^^^^^^^^^^^              ^^^^^^^^^^              ^^^^^^
  //        from ADC                 from EZ4          in/cm conversion
  return (sample * (4937.5 / 1024.0 / 4.8828125 * 0.3937));  
}

int main() {
  // start up the LCD
  lcd_init();
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  lcd_home();

  // set PB3, PB4 as outputs
  DDRD |= (1<<PB3) | (1<<PB4);

  // start up the Analog to Digital Converter
  adc_init();

  // start up the serial port
  uart_init();
  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;

  // holder variables for distance data
  uint16_t last_sample = 0;
  double this_dist;
  double dist_avg;
  int8_t rounded;
  uint8_t i;

  // holder variables for weight scale
  int16_t reading;

  while(1) {
    // ***********************DISTANCE SENSOR PART*********************
    // take 100 samples and average them!
    ADMUX = 0;
    dist_avg = 0.0; 
    for(i=0; i<100; i++) {
      last_sample = adc_read();
      this_dist = sampleToInches(last_sample);

      // add this contribution to the average
      dist_avg = dist_avg + this_dist/100.0;
      rounded = dist_avg;
    }

    // *************************WEIGHT SCALE PART**********************
    ADMUX = 1;

    // set polarity +-
    PORTD |= (1<<PB3);
    PORTD &= ~(1<<PB4);
    // wait 5 time constants (bw=12kHz, T=13.2us)
    delay_us(66);
    // take reading
    reading = adc_read();
    //printf_P(PSTR("%d "), adc_read());

    // set polarity -+
    PORTD |= (1<<PB4);
    PORTD &= ~(1<<PB3);
    // wait 5 time constants (bw=12kHz, T=13.2us)
    delay_us(66);
    // take reading
    reading = reading - adc_read();
    //printf_P(PSTR("%d\r\n"), adc_read());

    // send over serial port
    //printf_P(PSTR("%d\r\n"), reading);

    // write message to LCD
    lcd_home();
    lcd_write_string(PSTR("ADC: "));
    lcd_write_int16(last_sample);
    lcd_write_string(PSTR(" of 1024   "));
    lcd_line_two();
    fprintf_P(&lcd_stream, PSTR("Distance: %.2f"), dist_avg);
    lcd_write_string(PSTR("in.     "));

    lcd_line_three();
    lcd_write_string(PSTR("Weight: "));
    lcd_write_int16(reading);

    // write message to serial port
    //printf_P(PSTR("%.2f degrees F\r\n"), dist_avg);
  }

  return 0;
}

Post a Reply

Please log in to post a reply.

Did you know that two resistors can be used to make a voltage divider? Learn more...