unleashed-firmware/applications/plugins/dht_temp_sensor/DHT.c
2022-11-02 01:38:09 +03:00

169 lines
No EOL
6.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "DHT.h"
#define lineDown() furi_hal_gpio_write(sensor->GPIO, false)
#define lineUp() furi_hal_gpio_write(sensor->GPIO, true)
#define getLine() furi_hal_gpio_read(sensor->GPIO)
#define Delay(d) furi_delay_ms(d)
DHT_data DHT_getData(DHT_sensor* sensor) {
DHT_data data = {-128.0f, -128.0f};
#if DHT_POLLING_CONTROL == 1
/* Ограничение по частоте опроса датчика */
//Определение интервала опроса в зависимости от датчика
uint16_t pollingInterval;
if(sensor->type == DHT11) {
pollingInterval = DHT_POLLING_INTERVAL_DHT11;
} else {
pollingInterval = DHT_POLLING_INTERVAL_DHT22;
}
//Если интервал маленький, то возврат последнего удачного значения
if((furi_get_tick() - sensor->lastPollingTime < pollingInterval) &&
sensor->lastPollingTime != 0) {
data.hum = sensor->lastHum;
data.temp = sensor->lastTemp;
return data;
}
sensor->lastPollingTime = furi_get_tick() + 1;
#endif
//Опускание линии данных на 18 мс
lineDown();
#ifdef DHT_IRQ_CONTROL
//Выключение прерываний, чтобы ничто не мешало обработке данных
__disable_irq();
#endif
Delay(18);
//Подъём линии
lineUp();
/* Ожидание ответа от датчика */
uint16_t timeout = 0;
while(!getLine()) {
timeout++;
if(timeout > DHT_TIMEOUT) {
#ifdef DHT_IRQ_CONTROL
__enable_irq();
#endif
//Если датчик не отозвался, значит его точно нет
//Обнуление последнего удачного значения, чтобы
//не получать фантомные значения
sensor->lastHum = -128.0f;
sensor->lastTemp = -128.0f;
return data;
}
}
//Ожидание спада
while(getLine()) {
timeout++;
if(timeout > DHT_TIMEOUT) {
#ifdef DHT_IRQ_CONTROL
__enable_irq();
#endif
//Если датчик не отозвался, значит его точно нет
//Обнуление последнего удачного значения, чтобы
//не получать фантомные значения
sensor->lastHum = -128.0f;
sensor->lastTemp = -128.0f;
return data;
}
}
timeout = 0;
//Ожидание подъёма
while(!getLine()) {
timeout++;
if(timeout > DHT_TIMEOUT) {
if(timeout > DHT_TIMEOUT) {
#ifdef DHT_IRQ_CONTROL
__enable_irq();
#endif
//Если датчик не отозвался, значит его точно нет
//Обнуление последнего удачного значения, чтобы
//не получать фантомные значения
sensor->lastHum = -128.0f;
sensor->lastTemp = -128.0f;
return data;
}
}
}
timeout = 0;
//Ожидание спада
while(getLine()) {
timeout++;
if(timeout > DHT_TIMEOUT) {
#ifdef DHT_IRQ_CONTROL
__enable_irq();
#endif
//Если датчик не отозвался, значит его точно нет
//Обнуление последнего удачного значения, чтобы
//не получать фантомные значения
sensor->lastHum = -128.0f;
sensor->lastTemp = -128.0f;
return data;
}
}
/* Чтение ответа от датчика */
uint8_t rawData[5] = {0, 0, 0, 0, 0};
for(uint8_t a = 0; a < 5; a++) {
for(uint8_t b = 7; b != 255; b--) {
uint16_t hT = 0, lT = 0;
//Пока линия в низком уровне, инкремент переменной lT
while(!getLine() && lT != 65535) lT++;
//Пока линия в высоком уровне, инкремент переменной hT
timeout = 0;
while(getLine() && hT != 65535) hT++;
//Если hT больше lT, то пришла единица
if(hT > lT) rawData[a] |= (1 << b);
}
}
#ifdef DHT_IRQ_CONTROL
//Включение прерываний после приёма данных
__enable_irq();
#endif
/* Проверка целостности данных */
if((uint8_t)(rawData[0] + rawData[1] + rawData[2] + rawData[3]) == rawData[4]) {
//Если контрольная сумма совпадает, то конвертация и возврат полученных значений
if(sensor->type == DHT22) {
data.hum = (float)(((uint16_t)rawData[0] << 8) | rawData[1]) * 0.1f;
//Проверка на отрицательность температуры
if(!(rawData[2] & (1 << 7))) {
data.temp = (float)(((uint16_t)rawData[2] << 8) | rawData[3]) * 0.1f;
} else {
rawData[2] &= ~(1 << 7);
data.temp = (float)(((uint16_t)rawData[2] << 8) | rawData[3]) * -0.1f;
}
}
if(sensor->type == DHT11) {
data.hum = (float)rawData[0];
data.temp = (float)rawData[2];
//DHT11 производства ASAIR имеют дробную часть в температуре
//А ещё температуру измеряет от -20 до +60 *С
//Вот прикол, да?
if(rawData[3] != 0) {
//Проверка знака
if(!(rawData[3] & (1 << 7))) {
//Добавление положительной дробной части
data.temp += rawData[3] * 0.1f;
} else {
//А тут делаем отрицательное значение
rawData[3] &= ~(1 << 7);
data.temp += rawData[3] * 0.1f;
data.temp *= -1;
}
}
}
}
#if DHT_POLLING_CONTROL == 1
sensor->lastHum = data.hum;
sensor->lastTemp = data.temp;
#endif
return data;
}