Обновить DHT_22.c

This commit is contained in:
Александра Абрамова 2024-02-19 20:24:40 +00:00
parent 965250ecd0
commit b77eb4bf4f

289
DHT_22.c
View File

@ -1,147 +1,150 @@
unsigned char data[5];
static float temperature, humidity;
float value;
#define F_CPU 16000000UL
ISR(TIMER1_OVF_vect) // процедура обработки прерывания переполнения счетчика
{
TCNT1 = value; // preload timer
}
void timer_set(float value_1, byte Dev)
{
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = value_1; // preload timer
TCCR1B |= Dev; // (коэффициент деления предделителя)
TIMSK1 |= (1 << TOIE1); //(разрешаем вызов процедуры обработки прерывания переполнения счетчика)
interrupts(); // разрешаем все прерывания
value = value_1;
}
#include <avr/interrupt.h>
#include <avr/io.h>
void DHT22_setup()
{
#define DHT_PORT PORTD
#define DHT_DDR DDRD
#define DHT_PIN PIND
#define DHT_BIT 4 //по ардуиновски D5
Serial.begin(9600);
}
unsigned int read_dht_hum() //подпрограмма работы с DHT
{
int temp;
unsigned char i, j;
ReLoad: //метка для ошибок
//=============MCU send START
DHT_DDR |= (1 << DHT_BIT); //выход
DHT_PORT &= ~(1 << DHT_BIT); //низкий уровень, подтягиваем линию, разбудим датчик
delayEquivalent2(18); //18 мс по условиям документации.
DHT_PORT |= (1 << DHT_BIT); //отпускаем линию
DHT_DDR &= ~(1 << DHT_BIT); //пин как выход
//============= инциализация DHT
delayEquivalent3(1); //задержка по условию
if (DHT_PIN &(1 << DHT_BIT))
{
Serial.println("NO init ");
goto ReLoad;
} //датчик должен ответить 0
delayEquivalent4(0.99);
//по истечению 80 мкс, датчик должен отпустить шину
//===============Приём 40 бит данных
while (DHT_PIN &(1 << DHT_BIT)); //ждем пока на шине появится 1
for (j = 0; j < 5; j++) //цикл для 0-4 байт
{
data[j] = 0;
for (i = 0; i < 8; i++) //приём битов и укладка их в байты
{
while (!(DHT_PIN &(1 << DHT_BIT))); //ждем когда датчик отпустит шину
delayEquivalent5(0.99); //задержка высокого уровня при 0 30 мкс
if (DHT_PIN &(1 << DHT_BIT)) //если по истечению времени сигнал на линии высокий, значит передается 1
data[j] |= 1 << (7 - i); //тогда i-й бит устанавливаем 1
while (DHT_PIN &(1 << DHT_BIT)); // ждем окончание 1
}
}
if ((unsigned char)(data[0] + data[1] + data[2] + data[3]) != data[4]) //checksum
{
Serial.println("checksum Error ");
goto ReLoad;
}
} //конец подрограммы
void delayEquivalent2(uint8_t delayTime)//Для 18 Милисеунд
{
for(volatile uint8_t i1 = 0; i1 < 10; ++i1)
{
for(volatile uint8_t i2 = 0; i2 < 100; ++i2)
{
for(volatile uint8_t i3 = 0; i3 < delayTime; ++i3)
{
}
}
}
}
void delayEquivalent3(uint8_t delayTime1)//Для 50 микросекунд
{
for(volatile uint8_t i1 = 0; i1 < 10; ++i1)
{
for(volatile uint8_t i2 = 0; i2 < 5; ++i2)
{
for(volatile uint8_t i3 = 0; i3 < delayTime1; ++i3)
{
}
}
}
}
void delayEquivalent4(uint8_t delayTime2)//Для 80 микросекунд
{
for(volatile uint8_t i1 = 0; i1 < 10; ++i1)
{
for(volatile uint8_t i2 = 0; i2 < 8; ++i2)
{
for(volatile uint8_t i3 = 0; i3 < delayTime2; ++i3)
{
}
}
}
}
void delayEquivalent5(uint8_t delayTime3)//Для 80 микросекунд
{
for(volatile uint8_t i1 = 0; i1 < 10; ++i1)
{
for(volatile uint8_t i2 = 0; i2 < 3; ++i2)
{
for(volatile uint8_t i3 = 0; i3 < delayTime3; ++i3)
{
}
}
}
}
int get_DHT_value_temperature()
{
read_dht_hum(); //вызов подпрограммы DHT11
temperature = (data[3] *0.1) + ((data[2] &0b01111111) *25.6); //нюанс расчета температуры для DHT22
if (data[2] &0b10000000) temperature *= -1; //если отрицательная температура
timer_set(0, 4); //хватает задержки в 1 сек, для этого скетча хватает скорости 180
return temperature;
// Определения портов и битов
#define DHT_PORT PORTD
#define DHT_DDR DDRD
#define DHT_PIN PIND
#define DHT_BIT 4
// Глобальные переменные
unsigned char data[5];
float temperature, humidity;
// Флаг прерывания
volatile unsigned char interrupt_flag = 0;
// Таймер для задержки
volatile unsigned int timer_counter = 0;
// Прерывание таймера
ISR(TIMER1_COMPA_vect)
{
// Увеличиваем счетчик таймера
timer_counter++;
// Проверяем, достигли ли мы нужной задержки
if (timer_counter == 180000)
{
// Сбрасываем счетчик таймера
timer_counter = 0;
// Устанавливаем флаг прерывания
interrupt_flag = 1;
}
}
int get_DHT_value_humidity()
{
read_dht_hum(); //вызов подпрограммы DHT11
humidity = (data[1] *0.1) + (data[0] *25.6); //нюанс расчета влажности для DHT22
timer_set(0, 4);
return humidity;
// Функция чтения данных с DHT
unsigned int read_dht_hum()
{
int temp;
unsigned char i, j;
ReLoad:
// Выставляем пин как выход и устанавливаем низкий уровень
DHT_DDR |= (1 << DHT_BIT);
DHT_PORT &= ~(1 << DHT_BIT);
// Задержка 18 мс
//timer_counter = 18000;
timer_counter = 0;
while(timer_counter < 18000) timer_counter++;
//for (volatile unsigned int i = 0; i < timer_counter; i++);
// Отпускаем линию и переводим пин как вход
DHT_PORT |= (1 << DHT_BIT);
DHT_DDR &= ~(1 << DHT_BIT);
// Задержка 50 мкс
//timer_counter = 50;
timer_counter = 0;
while(timer_counter < 50) timer_counter++;
//for (volatile unsigned int i = 0; i < timer_counter; i++);
// Проверяем, ответил ли датчик
if (DHT_PIN & (1 << DHT_BIT))
{
Serial.println("No init");
//goto ReLoad;
}
// Задержка 80 мкс
//timer_counter = 50;
timer_counter = 0;
while(timer_counter < 50) timer_counter++;
//for (volatile unsigned int i = 0; i < timer_counter; i++);
// Принимаем 40 бит данных
while (DHT_PIN & (1 << DHT_BIT));
for (j = 0; j < 5; j++)
{
data[j] = 0;
for (i = 0; i < 8; i++)
{
while (!(DHT_PIN & (1 << DHT_BIT)));
// Задержка 30 мкс
timer_counter = 0;
while(timer_counter < 30) timer_counter++;
//for (volatile unsigned int i = 0; i < timer_counter; i++);
if (DHT_PIN & (1 << DHT_BIT)) data[j] |= 1 << (7 - i);
while (DHT_PIN & (1 << DHT_BIT));
}
}
// Проверяем контрольную сумму
if ((unsigned char)(data[0] + data[1] + data[2] + data[3]) != data[4])
{
Serial.println("Check summ error");
//goto ReLoad;
}
}
// Установка таймера
void setup_timer()
{
// Настраиваем таймер 1 в режиме CTC
TCCR1A = (1 << WGM12);
TCCR1B = (1 << CS12) | (1 << WGM13);
// Устанавливаем значение сравнения для частоты 1 Гц
OCR1A = 15624;
// Разрешаем прерывание сравнения A
TIMSK1 |= (1 << OCIE1A);
}
// Настройка
void setup()
{
// Инициализируем UART
Serial.begin(9600);
// Настраиваем таймер
setup_timer();
// Разрешаем прерывания
sei();
}
// Основной цикл
void loop()
{
// Ожидаем прерывания
while (interrupt_flag);
// Сбрасываем флаг прерывания
interrupt_flag = 0;
// Читаем данные с DHT
read_dht_hum();
// Вычисляем температуру и влажность
temperature = (data[3] * 0.1) + ((data[2] & 0b01111111) * 25.6);
if (data[2] & 0b10000000) temperature *= -1;
humidity = (data[1] * 0.1) + (data[0] * 25.6);
// Выводим данные на UART
Serial.print(humidity);
Serial.print("% ");
Serial.print(temperature);
Serial.println("C");
}