Пятница, 29.11.2024
Мой сайт
Меню сайта
Статистика

Онлайн всего: 90
Гостей: 90
Пользователей: 0
Главная » 2022 » Ноябрь » 4 » Драйвер термометра
17:04
Драйвер термометра

Драйвер термометра

Термометр этот:
https://www.chipdip.ru/product/troyka-temperature-humidity-sensor-dht11

Из этого набора:
https://www.chipdip.ru/product0/9000318627

На странице набора есть ссылка на библиотеку (DHT11), которую я буду разбирать и на описание (datasheet) датчика, по которому писалась библиотека.
Описание объекта (TroykaDHT11.h) совсем короткое:
class DHT11
{
 
public:
   // Создание объекта, присвоение внутренней переменной _
pin номера пина
   
explicit DHT11(uint8_t pin);
   // Чтение информации датчика:
   
uint8_t read();
   // Температура и влажность из внутренних переменных, заполненных функцией
read():
   
uint8_t getTemperatureC() const { return _temperatureC; }
   
uint8_t getHumidity() const { return _humidity; }
 
private:
   
uint8_t _pin; // Номер подключенного к датчику пина
   
uint8_t _temperatureC; // Температура
   
uint8_t _humidity; // Влажность
}

Нету в тексте ничего, кроме функции read(). Начну, все-таки с неё, а не с описания датчика. Я её чуть изменила. Почерк у всех разный. По-моему, эта экономия на скобках делает текст плохочитаемым. Не люблю))). Начало функции:
uint8_t DHT11::read() {
    uint8_t bits[5];    // буфер данных датчика на 5 байт, т.е на 8*5=40 бит
   
uint8_t cnt = 7;   // счетчик по номеру бита (от 0 до 7, т.е 8 бит)
   
uint8_t idx = 0;   // Номер считываемого байта (от 0 до 4, т.е 5 штук)
   // Длина цикла задержки (за время выполнений цикла должны прийти данные,
   // иначе – ошибка:
   
unsigned int loopCnt = 10000;
   
unsigned long t; //  Переменная для времени (в микросекундах)
  
uint8_t sum; // Переменная для значения суммы, проверяющей корректность полученных данных
    // очистка буфера (видимо в нём может быть грязь, т.е не нули):
   
for (int i = 0; i < 5; i++)
       {
       
bits[i] = 0;
       }

Дальше – начало общения с датчиком:
    // согласование с датчиком
   
pinMode(_pin, OUTPUT);
    
digitalWrite(_pin, LOW);
   
delay(18); // миллисекунды
   
digitalWrite(_pin, HIGH);
   
delayMicroseconds(40); // микросекунды
    pinMode(_pin, INPUT);

    // проверка отвечает ли датчик
    // Возврат ошибки (
DHT_ERROR_TIMEOUT), если на пине осталось LOW
    // в течение всего цикла 10000 шагов (слишком долго):
   
loopCnt = 10000;
   
while (digitalRead(_pin) == LOW)
        {
       
if (loopCnt == 0)
            {
            
return DHT_ERROR_TIMEOUT;
            }
     
else
            {
            
loopCnt--;
            }
        }

// Аналогичная проверка на значение на слишком долгое значение
HIGH:
loopCnt = 10000;
while (digitalRead(_pin) == HIGH)
        {
       
if (loopCnt == 0)
            {
            
return DHT_ERROR_TIMEOUT;
            }
     
else
            {
           
loopCnt--;
            }
        }

Пока не хочу читать описание. Наверное, так и надо. Дальше, если не случилось выхода (return из функции) по ошибке,  чтение 40 бит данных:
   // Считываем 40 бит

    for (int i = 0; i < 40; i++) { // i – номер бита
        // Проверки на слишком долгие задержки как выше:
        loopCnt = 10000;
        while (digitalRead(_pin) == LOW)
            if (loopCnt-- == 0) return DHT_ERROR_TIMEOUT;
        t = micros();
        loopCnt = 10000;
        while (digitalRead(_pin) == HIGH)
            if (loopCnt-- == 0) return DHT_ERROR_TIMEOUT;
        //
Чтение информации если не было слишком больших задержек:
        if ((micros() - t) > 40) //
Если время HIGH>40 микросекунд, получена 1
            {
             //
Начальное двоичное значение всех данных 0000 0000, потому, при получении 0
             //
ничего менять не надо. А если получено 1, то надо заменить на 1 значение
             // бита с номером
cnt. Это и делается путем выполнения операции ИЛИ  (|)
             // уже собранных данных
bits[idx] и числа maskCnt, в котором 1 уже
             // задвинута на нужное место:
            
mask1 = 1; // В двоичном виде 0000 0001
             
maskCntmask1<< cnt; // Сдвиг ”1” влево, При cnt=3, maskCnt =0000 0100
            
bits[idx]  = bits[idx]  | maskCnt; // Установка в 1 нужного бита
            }
        // следующий байт – изменение значений счётчиков:
       
if (cnt == 0)
          {
           
cnt = 7;  // Видимо, информация передается с последнего бита
           
idx++;
           }
         
else
             {
           
cnt--;
            }

     }
А теперь, все-таки, почитаю описание датчика:
Data consists of decimal and integral parts. A complete data transmission is 40bit, and the sensor sends higher data bit first.
… Старшие биты приедут первыми. Т.е 1 градус – 0000 0001 в той же последовательности и приедет, но если я буду считать биты с нулевого до седьмого, я получу bits[X][0]=0, bits[X][7] = 1 и общее 1000 0000, потому в тексте счётчик с 7 до 0
Data format: 8bit integral RH data + 8bit decimal RH data + 8bit integral T data + 8bit decimal T data + 8bit check sum. If the data transmission is right, the check-sum should be the last 8bit of "8bit integral RH data + 8bit decimal RH data + 8bit integral T data + 8bit decimal T data".
Последовательность байт:
1] Влажность (целое)
2] Влажность (десятичное)
3] Температура (целое)
4] Температура (десятичное)
5] Байт проверки, которые должен быть равен сумме всех предыдущих.
Читаю программный текст дальше, а там так:
    // запись данных

    _humidity    = bits[0];
    _temperatureC = bits[2];
   // проверка контрольной суммы
    sum = bits[0] + bits[2]; // !!!Должно быть sum = bits[0]+ bits[1] + bits[2]+ bits[3]
    if (bits[4] != sum)
        {

        return DHT_ERROR_CHECKSUM;
         }

    else
         {
          return DHT_OK
         }

… т.е не учитываются значения после запятой. Т.е если есть какие-то десятые, то будет ошибка при чтении данных. Наверное, поэтому у меня этот датчик очень редко работал. В драйвере ошибка.
Остальное, вроде так, как и должно быть. Стартовый запрос данных от датчика и его ответ о готовности слать данные:

Общая схема передачи:

Т.е после начального диалога 40 бит информации, при которых 0 это HIGH 26-28 микросекунд, а 1 – 70 микросекунд.

Чёрное в схемах – изменение значений информационного канала (пина)  микроконтроллером, серое – датчиком.

 

Просмотров: 95 | Добавил: akostina76 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Форма входа
Поиск
Календарь
«  Ноябрь 2022  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
282930
Архив записей
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Copyright MyCorp © 2024
    Бесплатный конструктор сайтов - uCoz