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.

Microcontroller Programming » Changing Message with Temperature and a Scrolling Message

February 20, 2011
by 1nizboy
1nizboy's Avatar

Since this is my first program since the tutorial I have decided to combine a few programs.

February 20, 2011
by 1nizboy
1nizboy's Avatar

I am having trouble getting the temperature readings to refresh and I cannot see why a few letters are out of place.

Here is the program:

// tempsensor.c
// for NerdKits with ATmega168
// mrobbins@mit.edu

#define F_CPU 14745600

#include <stdio.h>
#include <stdlib.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 -- temperature sensor analog input

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() {
  // read from ADC, waiting for conversion to finish
  // (assumes someone else asked for a conversion.)
  // wait for it to be cleared
  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);

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

  return result;
}

double sampleToFahrenheit(uint16_t sample) {
  // conversion ratio in DEGREES/STEP:
  // (5000 mV / 1024 steps) * (1 degree / 10mV)
  //    ^^^^^^^^^^^      ^^^^^^^^^^
  //     from ADC         from LM34
  return sample * (5000.0 / 1024.0 / 10.0);  
}

int main() {

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

  // 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 temperature data
  uint16_t last_sample = 0;
  double this_temp;
  double temp_avg;
  uint8_t i;
  const char *linefour = PSTR("R is a measure of how the current temperature compares to normal room temperature. ");
  uint8_t linetwolen = strlen_P(linefour);
  uint16_t scrollPos=0;

  while(1) {
    // take 100 samples and average them!
    temp_avg = 0.0;
    for(i=0; i<100; i++) {
      last_sample = adc_read();
      this_temp = sampleToFahrenheit(last_sample);

     // add this contribution to the average
      temp_avg = temp_avg + this_temp/100.0;
    }

    //Write to the LCD
lcd_home();

lcd_write_string(PSTR("Temperature: "));
lcd_line_two();
fprintf_P(&lcd_stream, PSTR("%.2f"), temp_avg);
lcd_write_data(0xdf);
lcd_write_string(PSTR("F"));
lcd_write_string(PSTR("  "));//change f to c
fprintf_P(&lcd_stream, PSTR("%.2f"), (temp_avg-32)*.5556);
lcd_write_data(0xdf);
lcd_write_string(PSTR("C"));
lcd_write_string(PSTR("  "));
lcd_line_three(); //change f to k
fprintf_P(&lcd_stream, PSTR("%.2f"), ((temp_avg-32)*.5556) + 274.15);
lcd_write_data(0xdf);
lcd_write_string(PSTR("K"));
lcd_write_string(PSTR("  "));// change f to r
fprintf_P(&lcd_stream, PSTR("%.2f"), ((temp_avg-35)*1) - 35);
lcd_write_data(0xdf);
lcd_write_string(PSTR("R"));

lcd_line_four();

      scrollPos = (scrollPos + 1) % linetwolen;
  delay_ms(150);

for(i=0; i<20; i++) {
    lcd_write_data(pgm_read_byte(linefour + ((scrollPos+i)%linetwolen)));

delay_ms(5000);  
lcd_line_one();  
lcd_write_string(PSTR("Hello!"));  
lcd_line_two();  
lcd_write_string(PSTR("It's going to be a "));  
lcd_line_three();  
lcd_write_string(PSTR(" beautiful day"));  
lcd_line_four(); 
lcd_write_string(PSTR("today!"));

} }

  return 0;
}

Thanks!

February 21, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi 1nizboy,

I don't really know what you are trying to do here. If you go over how the scrolling code works, it takes a message and scrolls it by one step every time the while loop goes around. In your code you seem to be writing lots of thing to the same line of the LCD every time the while loop goes around. First you write out a temperature, then you do a scrolling line, and then you write your own beautiful day package.

You should take a little bit and go through your program step by step and try to follow what you are doing.

Humberto

Post a Reply

Please log in to post a reply.

Did you know that interrupts can be used to trigger pieces of code when events happen? Learn more...