#include <avr/io.h>
#define F_CPU 8000000
#include<util/delay.h>
#define LCD_DATA PORTC // LCD data port
#define ctrl PORTA
#define en PA6 // enable signal
#define rw PA5 // read/write signal
#define rs PA4 // register select signal
void LCD_cmd(unsigned char cmd);
void LCD_init(void); // initialization of LCD
void LCD_write_data(unsigned int data); //Single Character Display
void LCD_send_string(char *string); //Character Array Display
void ADC_init(void); //initialization of ADC
unsigned int ADC_StartConversion(unsigned int channel);//function of ADC
void LCD_read_data(unsigned int data);
int main(void)
{
unsigned int adc_result,adc_ppm;
DDRC=0xFF; // Port C as output port
DDRB=0xFF; // Port B as output port
DDRA=(1<<PA6)|(1<<PA5)|(1<<PA4); // making PORTA pins 4,5,6 as output for LCD
PORTC=0x00; // Clearing Port C
MCUCSR|=(1<<JTD); // sending 1 to JTD to disable JTAG interface with Port C
MCUCSR|=(1<<JTD);
ADC_init(); //initialization of ADC
_delay_ms(10);
LCD_init(); // initialization of LCD
_delay_ms(2); // delay of 1 milli seconds
LCD_cmd(0x80); //cursor on the 1st line
_delay_ms(2);
LCD_send_string("CO Level:"); // Display "CO level" on first line
_delay_ms(2);
while (1)
{
adc_result=ADC_StartConversion(0); //Get the adc value of channel zero
adc_ppm=(adc_result/20); /*since 1ppm=20counts the adc_result is divided by 20
inorder to get the CO ppm Value*/
LCD_cmd(0x89); //cursor on 1st line 10th position
_delay_ms(10);
LCD_write_data(adc_ppm); //sending ppm value to LCD
LCD_cmd(0x8C); //cursor on 1st line 13th position
_delay_ms(2);
LCD_send_string("PPM"); //Displaying PPM "the unit" of gas to LCD
if(adc_ppm<=20)
{
LCD_cmd(0xC7); //cursor on the 2nd line 7th position
_delay_ms(2);
LCD_send_string(" SAFE "); //displays SAFE when ppm value is <20
PORTB=0x00;
_delay_ms(500);
PORTB=0x01;
_delay_ms(500);
}
else if(adc_ppm>20)
{
LCD_cmd(0xC6); //cursor on the 2nd line 6th position
_delay_ms(2);
LCD_send_string(" DANGER "); //displays DANGER when ppm value is >20
PORTB=0x00;
_delay_ms(500);
PORTB=0x02;
_delay_ms(500);
}
}
return 0;
}
void LCD_send_string(char *string) //Character Array Display
{
while(*string)
{
LCD_DATA= *string;
ctrl = (1<<rs)|(0<<rw)|(1<<en); // RW as LOW and RS, EN as HIGH
_delay_ms(2);
ctrl = (1<<rs)|(0<<rw)|(0<<en); // EN and RW as LOW and RS HIGH
_delay_ms(2); // delay to get things executed
string++;
}
}
void LCD_init(void) // initialization of 16X2 LCD in 8bit mode
{
LCD_cmd(0x38);
_delay_ms(2);
LCD_cmd(0x01); // Clear Display, Cursor to Home
_delay_ms(2);
LCD_cmd(0x0E); // Display, Cursor, and Cursor Blink OFF
_delay_ms(2);
LCD_cmd(0x80); // ---8 go to first line and --0 is for 0th position
_delay_ms(2);
return;
}
void LCD_cmd(unsigned char cmd)
{
LCD_DATA=cmd;
ctrl =(0<<rs)|(0<<rw)|(1<<en); // RS and RW as LOW and EN as HIGH
_delay_ms(2);
ctrl =(0<<rs)|(0<<rw)|(0<<en); // RS, RW , LOW and EN as LOW
_delay_ms(2);
return;
}
void LCD_write_data(unsigned int data) //Single Character Display
{
LCD_DATA= data;
ctrl = (1<<rs)|(0<<rw)|(1<<en); // RW as LOW and RS, EN as HIGH
_delay_ms(2);
ctrl = (1<<rs)|(0<<rw)|(0<<en); // EN and RW as LOW and RS HIGH
_delay_ms(2); // delay to get things execute
return;
}
void LCD_read_data(unsigned int data) //Single Character Display
{
LCD_DATA= data;
ctrl = (1<<rs)|(1<<rw)|(1<<en); // RW as LOW and RS, EN as HIGH
_delay_ms(2);
ctrl = (1<<rs)|(1<<rw)|(0<<en); // EN and RW as LOW and RS HIGH
_delay_ms(2); // delay to get things execute
return;
}
void ADC_init() //initialization of ADC
{
ADCSRA=0x82; //Enable ADC , sampling freq=osc_freq/64
_delay_ms(10);
ADMUX=0x40; //Result right justified, select channel zero
}
unsigned int ADC_StartConversion(unsigned int channel)
{
ADMUX=channel; //Select a channel
_delay_ms(10); //Wait till the channel is selected
ADCSRA|=(1<<ADSC); //Start the ADC conversion by setting bits for ADEN, ADSC, Prescaler to /64
while((ADCSRA & (1<<ADIF))==0); //Wait till the conversion is over
//ADIF will be set once ADC conversion is complete
return(ADC); //Return the 10-bit result
}