#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 A6
#define LCD_I2C_ADDRESS 0x27
#define LCD_BACKLIGHT 0x08
#define ENABLE 0x04
#define COMMAND_MODE 0x00
#define DATA_MODE 0x01
#define BUZZER_PIN PD6 // Örnek olarak kullanılan bir GPIO pini
void buzzer_on() {
DDRD |= (1 << BUZZER_PIN); // Buzzer pinini çıkış olarak ayarla
PORTD |= (1 << BUZZER_PIN); // Buzzerı aktif et
}
void buzzer_off() {
PORTD &= ~(1 << BUZZER_PIN); // Buzzerı kapat
}
// I2C başlatma fonksiyonu
void I2C_Init() {
TWSR = 0x00; // Set prescaler to 1
TWBR = 0x47; // Set SCL frequency to 100 kHz
TWCR = (1 << TWEN); // Enable TWI
}
void I2C_Start() {
TWCR = (1 << TWSTA) | (1 << TWEN) | (1 << TWINT); // Send start condition
while (!(TWCR & (1 << TWINT))); // Wait for TWINT flag set
}
void I2C_Stop() {
TWCR = (1 << TWSTO) | (1 << TWEN) | (1 << TWINT); // Send stop condition
while (TWCR & (1 << TWSTO)); // Wait for stop condition to be executed
}
void I2C_Write(uint8_t data) {
TWDR = data; // Load data into TWDR register
TWCR = (1 << TWEN) | (1 << TWINT); // Start transmission
while (!(TWCR & (1 << TWINT))); // Wait for TWINT flag set
}
void I2C_Write_Byte(uint8_t data) {
I2C_Start();
I2C_Write(LCD_I2C_ADDRESS << 1);
I2C_Write(data | LCD_BACKLIGHT);
I2C_Stop();
}
// I2C başlatma fonksiyonunun geri kalanı buraya eklenebilir
void LCD_Write_Nibble(uint8_t nibble, uint8_t mode) {
I2C_Write_Byte(nibble | mode | ENABLE);
I2C_Write_Byte(nibble | mode);
}
// LCD'ye bir byte gönderme fonksiyonu
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);
}
// LCD'ye bir karakter gönderme fonksiyonu
void LCD_Char(uint8_t data) {
LCD_Write_Byte(data, DATA_MODE);
_delay_ms(2);
}
// LCD'ye bir string gönderme fonksiyonu
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); // Set to 4-bit mode
LCD_Command(0x28); // 2 line, 5x7 matrix
LCD_Command(0x0C); // Display on, cursor off
LCD_Command(0x06); // Increment cursor
LCD_Command(0x01); // Clear display
_delay_ms(2);
}
void LCD_SetCursor(uint8_t row, uint8_t col) {
uint8_t pos = (row == 0) ? (0x80 + col) : (0xC0 + col);
LCD_Command(pos);
}
// LCD ekranını temizleme fonksiyonu
void LCD_Clear() {
LCD_Write_Byte(0x01, COMMAND_MODE); // LCD ekranını temizle
_delay_ms(2); // Bekleme süresi
}
void Display_LDR_Value(uint16_t ldr_value) {
char buffer[10];
LCD_Clear(); // Ekranı temizle
sprintf(buffer, "LDR: %d", ldr_value); // LDR değerini stringe çevir
LCD_String(buffer); // LDR değerini LCD'ye yaz
}
void Display_Warning(uint16_t ldr_value, float temperature, float humidity) {
LCD_Clear();
uint8_t warning_flag = 0;
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 (humidity < 50 && temperature > 40) {
LCD_String("Warning Hum-Temp!");
warning_flag = 1;
} else if (humidity < 50) {
LCD_String("Warning Hum!");
warning_flag = 1;
} else if (ldr_value > 300 && temperature > 40) {
LCD_String("Warning LDR-Temp!");
warning_flag = 1;
} else if (temperature > 40) {
LCD_String("Warning Temp!");
warning_flag = 1;
} else if (temperature > 40 && humidity < 50 && ldr_value > 300) {
LCD_String("Warning LDR-Temp-Hum!");
warning_flag = 1;
} else {
LCD_Clear();
LCD_String("All Values OK");
}
if (warning_flag == 1) {
buzzer_on(); // Zil sesini etkinleştir
} else {
buzzer_off(); // Hiçbir uyarı durumunda zil sesini kapat
}
}
void LCD_Display_DHT22_Data(int temperature, int humidity) {
char buffer[20];
LCD_Clear(); // Ekranı temizle
sprintf(buffer, "Temp: %d C", temperature); // Sıcaklık değerini stringe çevir
LCD_String(buffer); // Sıcaklık değerini LCD'ye yaz
LCD_SetCursor(1, 0); // İkinci satıra geç
sprintf(buffer, "Humidity: %d%%", humidity); // Nem değerini stringe çevir
LCD_String(buffer); // Nem değerini LCD'ye yaz
}
uint8_t dht22_read(float* temperature, float* humidity) {
uint8_t bits[5]={0};
uint8_t i, j = 0;
// Request sample
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);
// Check start condition 1
if ((PIND & (1<<DHT22_PIN))) {
return 1;
}
_delay_us(80);
// Check start condition 2
if (!(PIND & (1<<DHT22_PIN))) {
return 2;
}
_delay_us(80);
// Read the data
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;
}
// Verify checksum
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(); // Initialize ADC
LCD_Init(); // Initialize LCD
LCD_SetCursor(0, 0); // Set cursor position
while (1) {
// Read LDR value and display it on LCD
ldr_value = adc_read(LDR_PIN);
Display_LDR_Value(ldr_value);
_delay_ms(1000);
// Read DHT22 sensor data
result = dht22_read(&temperature, &humidity);
if (result == 0) {
// Display DHT22 data on LCD
LCD_Display_DHT22_Data(temperature, humidity);
_delay_ms(1000);
// Display warning if necessary
Display_Warning(ldr_value, temperature, humidity);
_delay_ms(1000);
}
_delay_ms(2000);
}
}
// ADC başlatma fonksiyonu
void adc_init(void) {
ADMUX = (1 << REFS0); // Referans voltajını AVCC olarak ayarla
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // ADC'yi etkinleştir, öntanımlı bölücü 128
}
// ADC okuma fonksiyonu
uint16_t adc_read(uint8_t channel) {
ADMUX = (ADMUX & 0xF0) | (channel & 0x0F); // ADC kanalını seç
ADCSRA |= (1 << ADSC); // Dönüşümü başlat
while (ADCSRA & (1 << ADSC)); // Dönüşümün tamamlanmasını bekle
return ADC; // ADC değerini döndür
}