#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
#define F_CPU 16000000UL
#define LDR_PIN 0
#define DHT22_PIN PD5
#define LCD_I2C_ADDRESS 0x27
#define LCD_BACKLIGHT 0x08
#define ENABLE 0x04
#define COMMAND_MODE 0x00
#define DATA_MODE 0x01
#define BUZZER_PIN PD6
void buzzer_on() {
DDRD |= (1 << BUZZER_PIN);
PORTD |= (1 << BUZZER_PIN);
}
void buzzer_off() {
PORTD &= ~(1 << BUZZER_PIN);
}
void I2C_Init() {
TWSR = 0x00;
TWBR = 0x47;
TWCR = (1 << TWEN);
}
void I2C_Start() {
TWCR = (1 << TWSTA) | (1 << TWEN) | (1 << TWINT);
while (!(TWCR & (1 << TWINT)));
}
void I2C_Stop() {
TWCR = (1 << TWSTO) | (1 << TWEN) | (1 << TWINT);
while (TWCR & (1 << TWSTO)); }
void I2C_Write(uint8_t data) {
TWDR = data;
TWCR = (1 << TWEN) | (1 << TWINT);
while (!(TWCR & (1 << TWINT)));
}
void I2C_Write_Byte(uint8_t data) {
I2C_Start();
I2C_Write(LCD_I2C_ADDRESS << 1);
I2C_Write(data | LCD_BACKLIGHT);
I2C_Stop();
}
void LCD_Write_Nibble(uint8_t nibble, uint8_t mode) {
I2C_Write_Byte(nibble | mode | ENABLE);
I2C_Write_Byte(nibble | mode);
}
void LCD_Write_Byte(uint8_t data, uint8_t mode) {
LCD_Write_Nibble(data & 0xF0, mode);
LCD_Write_Nibble((data << 4) & 0xF0, mode);
}
void LCD_Command(uint8_t cmnd) {
LCD_Write_Byte(cmnd, COMMAND_MODE);
_delay_ms(2);
}
void LCD_Char(uint8_t data) {
LCD_Write_Byte(data, DATA_MODE);
_delay_ms(2);
}
void LCD_String(char *str) {
while (*str) {
LCD_Char(*str++);
}
}
void LCD_Init() {
I2C_Init();
_delay_ms(50);
LCD_Write_Nibble(0x30, COMMAND_MODE);
_delay_ms(5);
LCD_Write_Nibble(0x30, COMMAND_MODE);
_delay_ms(1);
LCD_Write_Nibble(0x30, COMMAND_MODE);
_delay_ms(1);
LCD_Write_Nibble(0x20, COMMAND_MODE);
LCD_Command(0x28);
LCD_Command(0x0C);
LCD_Command(0x06);
LCD_Command(0x01);
_delay_ms(2);
}
void LCD_SetCursor(uint8_t row, uint8_t col) {
uint8_t pos;
if (row == 0) {
pos = col % 20;
LCD_Command(0x80 + pos);
} else if (row == 1) {
pos = col % 20;
LCD_Command(0xC0 + pos);
} else if (row == 2) {
pos = col % 20;
LCD_Command(0x94 + pos);
} else if (row == 3) {
pos = col % 20;
LCD_Command(0xD4 + pos);
}
}
void LCD_Clear() {
LCD_Write_Byte(0x01, COMMAND_MODE);
_delay_ms(2);
}
void Display_Values(uint16_t ldr_value, int temperature, int humidity) {
char buffer[20];
sprintf(buffer, "LDR: %d", ldr_value);
LCD_Clear();
LCD_String(buffer);
LCD_SetCursor(1, 0);
sprintf(buffer, "Temp: %d C", temperature);
LCD_String(buffer);
sprintf(buffer, "Humidity: %d%%", humidity);
LCD_SetCursor(2, 0);
LCD_String(buffer);
_delay_ms(1000);
}
void Display_Warning(uint16_t ldr_value, float temperature, float humidity) {
LCD_Clear();
uint8_t warning_flag = 0;
if (temperature > 40 && humidity < 50 && ldr_value > 300) {
LCD_String("Warning LDR-Temp-Hum");
warning_flag = 1;
}
else if (humidity < 50 && temperature > 40) {
LCD_String("Warning Hum-Temp!");
warning_flag = 1;
}
else if (temperature > 40 && ldr_value > 300) {
LCD_String("Warning LDR-Temp!");
warning_flag = 1;
}
else if (ldr_value > 300 && humidity < 50) {
LCD_String("Warning LDR-Hum!");
warning_flag = 1;
}
else if (ldr_value > 300) {
LCD_String("Warning LDR!");
warning_flag = 1;
}
else if (temperature > 40) {
LCD_String("Warning Temp!");
warning_flag = 1;
}
else if (humidity < 50) {
LCD_String("Warning Hum!");
warning_flag = 1;
} else {
LCD_Clear();
LCD_String("All Values OK");
}
if (warning_flag == 1) {
buzzer_on();
} else {
buzzer_off();
}
}
uint8_t dht22_read(float* temperature, float* humidity) {
uint8_t bits[5]={0};
uint8_t i, j = 0;
DDRD |= (1<<DHT22_PIN);
PORTD &= ~(1<<DHT22_PIN);
_delay_ms(18);
PORTD |= (1<<DHT22_PIN);
_delay_us(40);
DDRD &= ~(1<<DHT22_PIN);
_delay_us(40);
if ((PIND & (1<<DHT22_PIN))) {
return 1;
}
_delay_us(80);
if (!(PIND & (1<<DHT22_PIN))) {
return 2;
}
_delay_us(80);
for (j = 0; j < 5; j++) {
uint8_t result = 0;
for (i = 0; i < 8; i++) {
while (!(PIND & (1<<DHT22_PIN)));
_delay_us(30);
if (PIND & (1<<DHT22_PIN))
result |= (1<<(7-i));
while (PIND & (1<<DHT22_PIN));
}
bits[j] = result;
}
if ((uint8_t)(bits[0] + bits[1] + bits[2] + bits[3]) != bits[4]) {
return 3;
}
*humidity = ((bits[0] << 8) + bits[1]) * 0.1;
*temperature = (((bits[2] & 0x7F) << 8) + bits[3]) * 0.1;
if (bits[2] & 0x80) {
*temperature = -(*temperature);
}
return 0;
}
int main(void) {
uint16_t ldr_value;
float temperature = 0;
float humidity = 0;
uint8_t result;
adc_init();
LCD_Init();
LCD_SetCursor(0, 0);
while (1) {
ldr_value = adc_read(LDR_PIN);
result = dht22_read(&temperature, &humidity);
if (result == 0) {
Display_Values(ldr_value, (int)temperature, (int)humidity);
Display_Warning(ldr_value, temperature, humidity);
}
_delay_ms(1000);
}
}
void adc_init(void) {
ADMUX = (1 << REFS0);
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
}
uint16_t adc_read(uint8_t channel) {
ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC));
return ADC;
}