DHT22 тормозит работу программы

Тема в разделе "Arduino & Shields", создана пользователем Actimele, 20 ноя 2016.

  1. Actimele

    Actimele Нуб

    Здрасти!

    Есть 3-знаковая 7-сегментная LED панелька.
    Для вывода какого-то числа используется HC595, в нужный момент зажигаю нужный знак (один из трех).
    Все хорошо работает, до тех пор пока не начну получать данные с DHT22. На время опроса датчика, у меня выводится только 1 число.

    Как с этим бороться?

    Код (C++):
    #include <DHT.h>
    #include <DHT_U.h>

    //Пин подключен к ST_CP входу 74HC595
    int HC595_LATCH_PIN = 12;
    //Пин подключен к SH_CP входу 74HC595
    int HC595_CLOCK_PIN = 11;
    //Пин подключен к DS входу 74HC595
    int HC595_DATA_PIN = 10;

    int DHT22_PIN = 2;
    int RELAY_PIN = 3;
    DHT dht(DHT22_PIN, DHT22);
    const int digitPins[3] = {7,8,9}; //Массив пинов.
    int8_t Disp[3]={0};// задается тип int8_t чтобы к нам ничего, кроме набора бит не попало.
    int Value = 0; //значение для отображения на индикаторе
    byte i=0;
    byte segments[10] = { //Массив из 10 значений
    B11111100, //0
    B01100000, //1
    B11011010, //2
    B11110010, //3
    B01100110, //4
    B10110110, //5
    B10111110, //6
    B11100000, //7
    B11111110, //8
    B11110110 //9
    };

    void setup()
    {
      for(byte j=0;j<3;j++)pinMode(digitPins[j],OUTPUT); //цикл - назначаем всем режим выход из нашего массива пинов
      pinMode(HC595_DATA_PIN, OUTPUT);
      pinMode(HC595_CLOCK_PIN, OUTPUT);
      pinMode(HC595_LATCH_PIN, OUTPUT);
      pinMode(DHT22_PIN, INPUT);
      pinMode(RELAY_PIN, OUTPUT);
      Serial.begin(9600);
      dht.begin();
    }
            // Моя функция для работы с индикатором и сдвиговым регистром 74НС595
    void printInd()
    {
      //цифровые выходы из массива в 0 (LOW) - отключаем используем цикл
      for(byte d=0; d<3; d++) digitalWrite(digitPins[d], HIGH);
     
      //Для начала записи в 74HC595 нужно подать 0 на STCP (открыть)
      digitalWrite(HC595_LATCH_PIN, LOW);
      // с данными выпускаем поток битов на DS  синхроннированные с SHCP
      shiftOut(HC595_DATA_PIN, HC595_CLOCK_PIN, LSBFIRST, segments[Disp[i]]);
      // А теперь когда последний бит числа передали закрываем
      digitalWrite(HC595_LATCH_PIN, HIGH);
      digitalWrite(digitPins[i], LOW);
      delayMicroseconds(300); //Частота мирцания и собственно она же яркость индикатора:)
      //delay(1000);// проследить появление
      i++;
      if(i > 2) i=0;
    }
    void loop()
    {
      Serial.println("Loop");
    //Выводим значение отсрочки срабатывания таймера на дисплей
    Disp[0] = (Value/100)%10; //сотни
    Disp[1] = (Value/10)%10; //десятки
    Disp[2] = Value%10; //единицы
    //Функция для отображения на индикаторе

    float h = dht.readHumidity();
    Value = int(h);
    printInd();
    if (isnan(h)) {
      Serial.println("Cannot read data from DHT22");
      return;
    } else {
      if (h > 90) {
        digitalWrite(RELAY_PIN,LOW );
      }
      if (h < 80) {
        digitalWrite(RELAY_PIN, HIGH);
      }
      Serial.print(Value);
    }
    }
     
     
  2. Mestniy

    Mestniy Гуру

    После считывания поставте паузу 10 ms
     
  3. Actimele

    Actimele Нуб

    Не помогло.

    Код (C++):

    float h = dht.readHumidity();
    delay(10);
    Value =int(h);
    printInd();
    Проблема в задержке между считывания с датчика...
     
  4. Vad33

    Vad33 Капитан-оригинал

    Так и должно быть. Индикация то динамическая. Пока идет считывание температуры все замирает.
    Можно считывать температуру не каждый цикл, а раз в 10-20 сек. Перед считыванием индикаторы гасить.
    Либо поменять схему индикации.
     
  5. Igor68

    Igor68 Гуру

    Если лень переделывать схему... то "вырвать" код из библиотеки... и встроить в него кроме чтения ещё и код индикации. Примерно так:
    Код (C++):
    int8_t    iarduino_DHT::readSDA(){
    //        обнуляем массив
            reply[0]=reply[1]=reply[2]=reply[3]=reply[4]=0;
    //        прижимаем шину к земле на 25мс
            pinMode(PinDHT,OUTPUT); digitalWrite(PinDHT,LOW); delay(25);
    //        отпускаем шину
            pinMode(PinDHT,INPUT);
    //        проверяем реакцию датчика на сигнал "старт"
            if(pulseIn(PinDHT,HIGH,600)==0){return -3;}
    //        читаем ответ датчика (40бит данных)
            for(int i=0,j=0; i<40; i++)
            {    j=pulseIn(PinDHT,HIGH,600);
                /*
                *******************************
                где-то тут (в этом коментарии) ваше обращение к индикатору
                вы должны ориентироваться на временные интервалы работы этого цикла "for"
                всё должно быть компактно и оптимально
                *******************************
                */

                if(j)
                {
                    reply[i/8]<<=1;
                    reply[i/8]+=j>45?1:0;
                }
                else{
                    return -2;}
            }
    //        проверяем не отправляет ли датчик в шину больше 40 бит данных
            if(pulseIn(PinDHT,HIGH,600)>0){return -2;}
    //        проверяем контрольную сумму
            if(((reply[0]+reply[1]+reply[2]+reply[3])&0xff)!=reply[4]){return -1;}
    //        определяем модель сенсора
            if(reply[1]||reply[3]||reply[2]&0x80){model=22;}else if(reply[0]>3||reply[2]>4){model=11;}
            return 0;
    }
     
    Другого выхода не видно. Только данные в работе индикации - глобальные.

    Простите если что не так - брал исходники отсюда
    http://iarduino.ru/file/225.html

    Ещё раз простите!
     
  6. Tomasina

    Tomasina Сушитель лампочек Модератор

    другой выход виден - использовать прерывания для индикации. Главное - не переборщить с частотой обновлений.

    А лучше вообще заботы об индикации отдать специальным чипам, хотя бы копеечному TM1637 (жаль, что в Амперке его нет), и забыть об этих проблемах.
     
    Последнее редактирование: 24 ноя 2016
  7. AlexU

    AlexU Гуру

    Если есть свободный таймер, то можно попробовать индикацию повесить на обработчики прерываний таймера. Только желательно всякие 'digitalWrite' заменить на прямую запись в регистры порта.