#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#define F_CPU 16000000UL
#define LDR_PIN 0
#define DHT_PIN 6 // DHT22 sensörünün bağlı olduğu pin
// LCD ve I2C fonksiyonları için tanımlamalar
#define LCD_I2C_ADDRESS 0x27
#define LCD_BACKLIGHT 0x08
#define ENABLE 0x04
#define COMMAND_MODE 0x00
#define DATA_MODE 0x01
// 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
}
// LDR değerini LCD'ye yazdırma fonksiyonu
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_DHT22_Values(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;
// Pin konfigürasyonu
DDRD |= (1 << DHT_PIN); // DHT_PIN çıkış olarak ayarla
PORTD &= ~(1 << DHT_PIN); // DHT_PIN'i düşük yap
_delay_ms(20); // 20 ms bekle
PORTD |= (1 << DHT_PIN); // DHT_PIN'i yüksek yap
_delay_us(40); // 40 us bekle
DDRD &= ~(1 << DHT_PIN); // DHT_PIN giriş yap
_delay_us(10); // 10 us bekle
// Sensörden 40 bit veri okuma
for (i = 0; i < 5; ++i) {
for (j = 0; j < 8; ++j) {
uint32_t timeout = 10000; // Zaman aşımı kontrolü için
while (!(PIND & (1 << DHT_PIN)) && timeout--); // DHT_PIN'in yüksek olmasını bekle
if (timeout == 0) {
return 0; // Zaman aşımında hata dön
}
_delay_us(30); // 30 us bekle
if (PIND & (1 << DHT_PIN)) bits[i] |= (1 << (7 - j)); // Eğer DHT_PIN yüksek ise
timeout = 10000;
while (PIND & (1 << DHT_PIN) && timeout--); // DHT_PIN'in düşük olmasını bekle
if (timeout == 0) {
return 0; // Zaman aşımında hata dön
}
}
}
// Veri doğrulama
if ((uint8_t)(bits[0] + bits[1] + bits[2] + bits[3]) == bits[4]) {
*humidity = (bits[0] << 8 | bits[1]) * 0.1;
*temperature = ((bits[2] & 0x7F) << 8 | bits[3]) * 0.1;
if (bits[2] & 0x80) *temperature *= -1;
return 1;
} else {
return 0; // Checksum hatasında hata dön
}
}
// I2C'yi başlatma fonksiyonu
void setup() {
LCD_Init(); // Initialize LCD
LCD_SetCursor(0, 0); // Set cursor to first line, first position
}
// Ana döngü
void loop() {
uint16_t ldr_value = adc_read(LDR_PIN); // LDR değerini oku
Display_LDR_Value(ldr_value);
float temperature = 0.0, humidity = 0.0;
if (DHT22_Read(&temperature, &humidity)) {
Display_DHT22_Values(temperature, humidity);
} else {
LCD_Clear();
LCD_String("Error reading DHT22");
}
_delay_ms(1000); // 1 saniye bekle
}
// 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
}