mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-12-29 14:13:08 +00:00
169 lines
No EOL
6.4 KiB
C
169 lines
No EOL
6.4 KiB
C
#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;
|
||
} |