0
votes

I have a program that reads temperature and pressure sensors and does internal ADC conversion on them, then save data to the EEPROM, then convert back to original value and display it on the LCD. The issue is that when I debug the program in Atmel, it seems to work fine. But, the code doesn't actually on my circuit. IT seems to only write and read the first 2 bytes properly, then just writes the same byte over and over.

Here's my code for writing data. I'm using the included eeprom.h library, and writing a 16-bit value by splitting to lower and higher bytes.

void WriteToEEPROM(uint16_t value, int address){
    
    uint8_t low_value = value;
    uint8_t high_value = (value & 0xFF00) >> 8;
    if ((address == 0) || (address == 100)){}
    else {address++;}
    
    while(!eeprom_is_ready()){}
    eeprom_write_byte((uint8_t*)address, low_value);
    while(!eeprom_is_ready()){}
    address++;
    eeprom_write_byte((uint8_t*)address, high_value);
    while(!eeprom_is_ready()){}
}

This is the contents of the EEPROM after finishing writing values. Note that the value should not change because I'm keeping it constant. Correct values should be 0x134 at '0x0000' and 0x0073 at 0x0064. I'm lost on why this is not working.

Any help is appreciated!

enter image description here

full code

#define __DELAY_BACKWARD_COMPATIBLE__
#define F_CPU 8000000UL
#define  eeprom_is_ready()  
#include <avr/io.h>
#include <avr/delay.h>
#include <stdint.h>
#include <avr/eeprom.h>
#include <stdio.h>

//******************LCD PROGRAM STARTS*********************//
#define LCD_DATA PORTD  // port D is selected as LCD data port
#define ctrl PORTC  // port C is selected as LCD command port
#define en PC2  // enable signal is connected to port D pin 7
#define rw PC1  // read/write signal is connected to port D pin 6
#define rs PC0  // register select signal is connected to port D pin 5

void LCD_cmd(unsigned char cmd);
void init_LCD(void);
void LCD_write(unsigned char data);
void LCD_write_string(char*str);
void WriteToEEPROM(uint16_t value, int address);


void scaled_delay(int delay){
    _delay_ms(delay * 1000);
}

void setup(void){
     DDRA = 0x00;               //PORTA is set as an input
     DDRD = 0xFF;               //PORTD is set as an output
     DDRC = 0xFF;
}

//Temperature sensor output connected to PA0
void ReadTemp(int address){
        
    ADCSRA = ADCSRA | 0b10000111;       //enable ADC, CLK/128 conversion speed
    ADMUX  = ADMUX | 0b01000000;        //Use internal 2.56V Vref and PA0 as input, right-hand justified
        
    ADCSRA |= (1 << ADSC);              //start conversion

    while(!(ADCSRA & (1 << ADIF))) {}
    
    WriteToEEPROM(ADC, address);
}

//Temperature sensor output connected to PA1
void ReadPressure(int address){
    
    ADCSRA = ADCSRA | 0b10000111;       //enable ADC, CLK/128 conversion speed
    ADMUX  = ADMUX | 0b01000001;        //Use AVCC and PA0 as input, right-hand justified
        
    ADCSRA |= (1 << ADSC);              //start conversion
        
    while(!(ADCSRA & (1 << ADIF))){}        // wait until process is finished
    address = address + 100;
    WriteToEEPROM(ADC, address);     
}

void WriteToEEPROM(uint16_t value, int address){
    
    uint8_t low_value = value;
    uint8_t high_value = (value & 0xFF00) >> 8;
    if ((address == 0) || (address == 100)){}
    else {address++;}
    
    while(!eeprom_is_ready()){}
    eeprom_write_byte((uint8_t*)address, low_value);
    while(!eeprom_is_ready()){}
    address++;
    eeprom_write_byte((uint8_t*)address, high_value);
    while(!eeprom_is_ready()){}
}

void ReadEEPROM_Temp(uint8_t address){
    
    uint8_t temp_value_low;
    uint8_t temp_value_high;

    char value_buffer_temp[100] = "";

    if(address != 0) {address++;}
    
    temp_value_low = eeprom_read_byte((uint8_t*)address);       
    address++;
    temp_value_high = eeprom_read_byte((uint8_t*)address);          
    
    uint16_t temp_value = (temp_value_high << 8) | temp_value_low;
    int temperature = (temp_value * 4.88) / 10;

    sprintf(value_buffer_temp,"%s %d %s  ", "Temp ", temperature, "C");
        
    init_LCD();
    LCD_cmd(0x0C);
    _delay_ms(100);
    
    LCD_write_string(value_buffer_temp);
}


void ReadEEPROM_Pres(uint8_t address){
    
    uint8_t pres_value_low;
    uint8_t pres_value_high;
    
    char value_buffer_pres[100] = "";
    
    if(address != 100) {address++;}
    
    pres_value_low = eeprom_read_byte((uint8_t*)address);  
    address++;
    pres_value_high = eeprom_read_byte((uint8_t*)address);  
    
    uint16_t pres_value = (pres_value_high << 8) | pres_value_low;
    int v_out =  (pres_value * 4.88)/1000;
    int pressure = ((v_out/5.1) + 0.095) / 0.009;
    
    sprintf(value_buffer_pres,"%s %d %s  ", "Pres ", pressure, "kPa");
    LCD_cmd(0xC0);
    _delay_ms(100);
    LCD_write_string(value_buffer_pres);
}

void init_LCD(void){
    LCD_cmd(0x38);
    // initialization in 8bit mode of 16X2 LCD
    _delay_ms(1);
    LCD_cmd(0x01);
    // make clear LCD
    _delay_ms(1);
    LCD_cmd(0x02);
    // return home
    _delay_ms(1);
    LCD_cmd(0x06);
    // make increment in cursor
    _delay_ms(1);
    LCD_cmd(0x80);
    // “8” go to first line and “0” is for 0th position
    _delay_ms(1);
    return;
}

//**************sending command on LCD***************//

void LCD_cmd(unsigned char cmd){

    LCD_DATA = cmd; // data lines are set to send command
    PORTC   &= ~(1<<rs);    // RS sets 0
    PORTC   &= ~(1<<rw);    // RW sets 0
    PORTC   |= (1<<en); // make enable from high to low
    _delay_ms(100);
    PORTC   &= ~(1<<en);
    return;
}

//*****************write data on LCD*****************//

void LCD_write(unsigned char data){

    LCD_DATA=   data;   // data lines are set to    send command
    PORTC   |=  (1<<rs);    // RS sets  1
    PORTC   &=  ~(1<<rw);   //  RW sets 0
    PORTC   |=  (1<<en);    //  make enable from high   to low
    

    _delay_ms(100);

    PORTC &= ~(1<<en);

    return ;
}
//store address value of the string in pointer *str
void LCD_write_string(char *str) {
    
    int i=0;

    for(i; str[i]!=0; i++){
        // loop will go on till the NULL character in the string
        LCD_write(str[i]); // sending data on LCD byte by byte i++;
    }
    return;
}

int main(void)
{   
    setup();
    int counter = 0;
   while (1)
   {  
        scaled_delay(1);            //delay 1 hour
        ReadTemp(counter);          //get temperature reading
        ReadPressure(counter);      //get pressure reading
        counter++;                  //keep track of number of conversions
        //get reading 24 times                  
        if(counter == 23){
            counter = 0;
            while (counter  != 24)
            {
                ReadEEPROM_Temp(counter);
                ReadEEPROM_Pres(counter + 100);
                counter++;
            }
            counter = 0;
        }
   }
}



2
It seems that my logic for moving to next address in eeprom is flawed. So, values are being overriden which is what's causing the same byte to be written over and over.SegFaulter

2 Answers

1
votes

There seems to be a mistake in the address variable. It is of type int but should be of type unsigned int (address can not be negative). Can you try the following code:

void WriteToEEPROM(unsigned int value, unsigned int address)
{   
  unsigned char low_value = (unsigned char)value;
  unsigned char high_value = (unsigned char)(value>>8);

  eeprom_write_word((unsigned char*)address ,value);
  address++;
  address++;
}

Pleas also change the delay.h path to

#include <util/delay.h>

The read function maybe contains also some unnecessary stuff:

void ReadEEPROM_Temp(unsigned int address)
{
  char buffer[100];

  unsigned int temp = eeprom_read_word((unsigned char*)address) * 4.88 / 10UL;
  address++;
  address++;

  sprintf(buffer,"Temp %5d C", temp);

  init_LCD();
  LCD_cmd(0x0C);
  _delay_ms(100);

  LCD_write_string(buffer);
}

WARNING:

It is possible that your EEPROM is currently destroyed cause of you are writing several times to same addresse space in your main routine:

while (1)
{
  scaled_delay(1);            // !!!THIS CREATES A DELAY OF 1 SECOND
  ReadTemp(counter);          // WRITE DATA TO EEPROM
  ReadPressure(counter);      // WRITE DATA TO EEPROM
// ...

Normaly if your functions are above the main routine it is not necessary to declare prototypes. Are you developing with Atmel Studio?

0
votes

Try using an EEPROM clear program and retry running your program.