Помогите с кодом

Тема в разделе "Arduino & Shields", создана пользователем arssev1, 6 дек 2017.

  1. arssev1

    arssev1 Гик

    Господа, подскажите пожалуйста как программно реализовать следующую задумку:
    Есть: DHT11, QuadDisplay
    Нужно: по нажатию на кнопку менять на дисплее температуру или влажность, а при нажатии на кнопку нужно еще и моргнуть светодиодом на 150мс. Вроде бы все очень просто, но никак не могу придумать, как это правильно реализовать. Либо через прерывания (что плохо т.к. кнопку с прерываниями использовать вроде-бы как не хорошо, т.к. любой дребезг будет портить картину), либо еще как.
     
    Последнее редактирование: 6 дек 2017
  2. arssev1

    arssev1 Гик

    Вот, с кнопкой разобрался, теперь бы еще понять, как моргать светодиодом при нажатии кнопки:
    Код (C++):
    #include "DHT.h" //библиотека для термометра
    #include "QuadDisplay2.h" //библиотека для дисплея

    #define BUTTONPIN 2 //кнопка подключена через подягивающий резистор к 2 пину
    #define DHTPIN 4 //DHT11 подключен к 4 пину
    #define DHTTYPE DHT11 //да-да, DHT11, никакой другой

    DHT dht(DHTPIN, DHTTYPE); //ну вы поняли, DHT11 к 4 пину подключили
    QuadDisplay qd(9); //А дисплей к 9 пину и к аппаратному SPI

    int buttonState; //сюда мы будем записывать состояние кнопки (нажата или нет)
    int previous; //предыдущее состояние кнопки
    bool whatToDisplay; //если true - отображаем температуру, если false - влажность
    long deltaTime; //разница во времени (нужна для подавления дребезга)
    long debounce = 200; //время на подавление дребезга

    float humidity; //сюда пишем влажность
    float temperature; //сюда - температуру

    void setup() {
      qd.begin(); //инициализация дисплея
      dht.begin(); //инициализация датчика
      pinMode(BUTTONPIN, INPUT); //кнопка на вход
    }

    void loop() {
      humidity = dht.readHumidity(); //читаем влажность
      temperature = dht.readTemperature(); //читаем температуру
      buttonState = digitalRead(BUTTONPIN); //проверяем нажата ли кнопка
     
      if (buttonState == HIGH && previous == LOW && millis() - deltaTime > debounce) { //если нажали кнопку, и в прошлом цикле ее не нажимали, и прошло 200мс
        if (whatToDisplay == false) { //если до этого показывали влажность, то
        whatToDisplay = true; //показываем температуру
        }
        else { //иначе
        whatToDisplay = false; //показываем влажность
        }
        deltaTime = millis(); //фиксируем разницу во времени
      }
      if (whatToDisplay == true) { //если нужно показать температуру, то
      qd.displayTemperatureC(temperature); //берем и показываем
      }
      else if (whatToDisplay == false) { //если нужно показать влажность, то
      qd.displayHumidity(humidity); //тож показываем, чо нет?
      }
      previous = buttonState; //фиксируем положение кнопки
    }
     
  3. qwone

    qwone Гик

    ИгорьК нравится это.
  4. arssev1

    arssev1 Гик

    Это очень здорово, спасибо, я долго вникал, и думаю вникать буду еще долго. Правда здорово! Но, хотелось бы понять, как можно сделать это на Wiring, неужели нельзя сделать это обычной средой Arduino IDE. Буду сверх благодарен, если Вы найдете решение. Заранее спасибо
     
  5. qwone

    qwone Гик

    Ну все в обычной среде Ардуино. Вот только этот рецепт не афишируется
    Код (C++):
    //**/
    unsigned long mill;// переменная для millis()
    typedef void (*pDo)() ;// тип -функция обработчик
    //------Cl_Led----------------------
    // класс светодиод
    class Cl_Led {
      protected:
        const byte pin;
        bool led;
        unsigned long past, time;
        byte state; //0 выкл/ 1 вкл / 2 мигать
        /*установить в состояние*/
        void stand(byte state_) {
          past = mill;
          state = state_;
          switch (state) {
            case 0: // выкл
              digitalWrite(pin, led = LOW);
              break;
            case 1: // вкл
              digitalWrite(pin, led = HIGH);
              break;
            case 2:// мигать
              digitalWrite(pin, led = !led);
              break;
            case 3:// короткое выключение
              digitalWrite(pin, led = LOW);
              break;
            case 4:// короткое включение
              digitalWrite(pin, led = HIGH);
              break;
          }
        }
      public:
        /*конструктор*/
        Cl_Led(byte pin_): pin(pin_) {}
        /*инициализация-вставить в setup()*/
        void init() {
          pinMode(pin, OUTPUT);
          OFF();
        }
        /*работа-вставить в loop()*/
        void run() {
          if (state == 2 && mill - past >= time)stand(2);
          if (state == 3 && mill - past >= time)stand(1);
          if (state == 4 && mill - past >= time)stand(0);
        }
        /*включить*/
        void ON() {
          stand(1);
        }
        /*коротко включить*/
        void ON(unsigned long time_) {
          time = time_;
          stand(4);
        }
        /*выключить*/
        void OFF() {
          stand(0);
        }
        /*коротко выключить*/
        void OFF(unsigned long time_) {
          time = time_;
          stand(3);
        }
        /*мигать*/
        void blink(unsigned long time_ = 200) {
          time = time_;
          stand(2);
        }
    };
    //------Cl_Btn----------------------
    // класс кнопка
    class Cl_Btn {
      protected:
        const byte pin;
        pDo Do;//обработчик
        bool bounce = 0;
        bool btn = 1, oldBtn;
        unsigned long past;
      public:
        /*конструктор*/
        Cl_Btn(byte pin_, pDo Do_): pin(pin_), Do(Do_) {}
        /*инициализация-вставить в setup()*/
        void init() {
          pinMode(pin, INPUT_PULLUP);
        }
        /*работа-вставить в loop()*/
        void run() {
          bool newBtn = digitalRead(pin);
          if (!bounce && newBtn != btn) {
            bounce = 1;
            past = mill;
          }
          if (bounce && mill - past >= 10) {
            bounce = 0 ;
            oldBtn = btn;
            btn = newBtn;
            if (!btn && oldBtn) Do();
          }
        }
    };
    //-----компоновка----------------------
    Cl_Led Led(/*пин*/13);
    void DoBtn1() {
      Led.ON(200);
      Serial.println("DoBtn1");
    }
    void DoBtn2() {
      Led.OFF(200);
      Serial.println("DoBtn2");
    }
    void DoBtn3() {
      Led.blink();
      Serial.println("DoBtn3");
    }
    Cl_Btn Btn1(/*пин*/2,/*обработчик*/DoBtn1);
    Cl_Btn Btn2(/*пин*/3,/*обработчик*/DoBtn2);
    Cl_Btn Btn3(/*пин*/4,/*обработчик*/DoBtn3);
    //-----main-----------------------
    int main() {
      init();
      // setup()
      Serial.begin(9600);
      Led.init();
      Btn1.init();
      Btn2.init();
      Btn3.init();
      for (;;) {
        // loop()
        mill = millis();
        Led.run();
        Btn1.run();
        Btn2.run();
        Btn3.run();
      }
      return 0;
    }
    /*Скетч использует 2814 байт (9%) памяти устройства. Всего доступно 30720 байт.
      Глобальные переменные используют 251 байт (12%) динамической памяти, оставляя 1797 байт для локальных переменных. Максимум: 2048 байт.
    */
    ПС: Это обычный Wiring в отличии от "честного Си" (деалект недалеких новичков Ардунистов)
     
  6. arssev1

    arssev1 Гик

    Спасибо, решил проблему значительно проще, боюсь, что сильно на кривокодил, но работает...
    Код (C++):
    #include "DHT.h" //библиотека для термометра
    #include "QuadDisplay2.h" //библиотека для дисплея

    #define BUTTONPIN 2 //кнопка подключена через подягивающий резистор к 2 пину
    #define LEDPIN 10 //светодиод к 10 пину
    #define BUZZERPIN 3 //пищалка к 3 пину
    #define DHTPIN 4 //цифровой пин DHT11 подключен к 4 пину
    #define DHTTYPE DHT11 //да-да, DHT11, никакой другой

    DHT dht(DHTPIN, DHTTYPE); //ну вы поняли, DHT11 к 4 пину подключили
    QuadDisplay qd(9); //а дисплей к 9 пину и к аппаратному SPI

    int buttonState; //сюда мы будем записывать состояние кнопки (нажата или нет)
    int previous; //предыдущее состояние кнопки
    bool whatToDisplay; //если true - отображаем температуру, если false - влажность
    long deltaTime; //разница во времени (нужна для подавления дребезга)
    long debounce = 200; //время на подавление дребезга

    float humidity; //сюда пишем влажность
    float temperature; //сюда - температуру

    void setup() {
      qd.begin(); //инициализация дисплея
      dht.begin(); //инициализация датчика
     
      pinMode(BUTTONPIN, INPUT); //кнопка на вход
      pinMode(LEDPIN, OUTPUT); //светодиод на выход (хотя хз зачем, там же дальше analogWrite);
      pinMode(BUZZERPIN, OUTPUT); //тоже не выход (опять хз нужно ли для tone)
    }

    void loop() {
      humidity = dht.readHumidity(); //читаем влажность
      temperature = dht.readTemperature(); //читаем температуру
      buttonState = digitalRead(BUTTONPIN); //проверяем нажата ли кнопка
     
      if (buttonState == HIGH && previous == LOW && millis() - deltaTime > debounce) { //если нажали кнопку, и в прошлом цикле ее не нажимали, и прошло 200мс
        if (whatToDisplay == false) { //если до этого показывали влажность, то
        whatToDisplay = true; //показываем температуру
        }
        else { //иначе
        whatToDisplay = false; //показываем влажность
        }
        deltaTime = millis(); //фиксируем разницу во времени
        blinkSqueak(); //мигаем-пищим, че нет то?
      }
      if (whatToDisplay == true) { //если нужно показать температуру, то
      qd.displayTemperatureC(temperature); //берем и показываем
      }
      else if (whatToDisplay == false) { //если нужно показать влажность, то
      qd.displayHumidity(humidity); //тож показываем, чо нет?
      }
      previous = buttonState; //фиксируем положение кнопки
    }

    void blinkSqueak() { //мигалка-пищалка
      analogWrite(LEDPIN, 40); //светодиод на 16 процентов яроксти
      tone(BUZZERPIN, 4500); //пищим с частотой 4500
      delay(50); //продолжаем пищать и светить 50мс
      analogWrite(LEDPIN, 0); //не светим
      noTone(BUZZERPIN); //и не пищим
    }
     
  7. DetSimen

    DetSimen Guest

    нельзя так часто опрашивать DHT11
     
  8. arssev1

    arssev1 Гик

    Почему? В даташите ничего про это не написано.
    И как это исправить в коде?
    Код (C++):
    #include "DHT.h" //библиотека для термометра
    #include "QuadDisplay2.h" //библиотека для дисплея

    #define BUTTONPIN 2 //кнопка подключена через подягивающий резистор к 2 пину
    #define LEDPIN 10 //светодиод к 10 пину
    #define BUZZERPIN 3 //пищалка к 3 пину
    #define DHTPIN 4 //цифровой пин DHT11 подключен к 4 пину
    #define DHTTYPE DHT11 //да-да, DHT11, никакой другой

    DHT dht(DHTPIN, DHTTYPE); //ну вы поняли, DHT11 к 4 пину подключили
    QuadDisplay qd(9); //а дисплей к 9 пину и к аппаратному SPI

    int buttonState; //сюда мы будем записывать состояние кнопки (нажата или нет)
    int previous; //предыдущее состояние кнопки
    bool whatToDisplay; //если true - отображаем температуру, если false - влажность
    long deltaTime1; //разница во времени (нужна для подавления дребезга)
    long deltaTime2; //для того, чтобы опрашивать датчик реже
    long debounce = 200; //время на подавление дребезга

    float humidity; //сюда пишем влажность
    float temperature; //сюда - температуру

    void setup() {
      qd.begin(); //инициализация дисплея
      dht.begin(); //инициализация датчика
      Serial.begin(9600);

      pinMode(BUTTONPIN, INPUT); //кнопка на вход
      pinMode(LEDPIN, OUTPUT); //светодиод на выход (хотя хз зачем, там же дальше analogWrite);
      pinMode(BUZZERPIN, OUTPUT); //тоже не выход (опять хз нужно ли для tone)
    }

    void loop() {
      if (millis() - deltaTime2 > 3000) { //если читали данные из датчика больше 3 секунд назад
        humidity = dht.readHumidity(); //читаем влажность
        temperature = dht.readTemperature(); //читаем температуру
        Serial.print(temperature);
        Serial.print(" ");
        Serial.println(humidity);
        deltaTime2 = millis(); //фиксируем разницу во времени
      }
      buttonState = digitalRead(BUTTONPIN); //проверяем нажата ли кнопка

      if (buttonState == HIGH && previous == LOW && millis() - deltaTime1 > debounce) { //если нажали кнопку, и в прошлом цикле ее не нажимали, и прошло 200мс
        if (whatToDisplay == false) { //если до этого показывали влажность, то
          whatToDisplay = true; //показываем температуру
        }
        else { //иначе
          whatToDisplay = false; //показываем влажность
        }
        deltaTime1 = millis(); //фиксируем разницу во времени
        blinkSqueak(); //мигаем-пищим, че нет то?
      }
      if (whatToDisplay == true) { //если нужно показать температуру, то
        qd.displayTemperatureC(temperature); //берем и показываем
      }
      else if (whatToDisplay == false) { //если нужно показать влажность, то
        qd.displayHumidity(humidity); //тож показываем, чо нет?
      }
      previous = buttonState; //фиксируем положение кнопки
    }

    void blinkSqueak() { //мигалка-пищалка
      analogWrite(LEDPIN, 40); //светодиод на 16 процентов яроксти
      tone(BUZZERPIN, 4500); //пищим с частотой 4500
      delay(50); //продолжаем пищать и светить 50мс
      analogWrite(LEDPIN, 0); //не светим
      noTone(BUZZERPIN); //и не пищим
    }
    Теперь кнопка тупит, может быть это из-за Serial?
     
    Последнее редактирование: 7 дек 2017
  9. DetSimen

    DetSimen Guest

    открываем datasheet, там родным по белому написано

    3. Each read out the temperature and humidity values are the results of the last measurement For real-time data, sequential read twice, but is not recommended to repeatedly read the sensors, each read sensor interval is greater than 5 seconds can be obtainedaccurate data.
     
    arkadyf нравится это.
  10. DetSimen

    DetSimen Guest

    Код (C++):
    void loop(void)
    {
    static long prevTime = 0;
    long now = millis();

    if ((now - prevTime)>5000)
    {
    ReadDHT11();
    doSomeThing();
    prevTime = now;
    }
    }
     
    arkadyf нравится это.
  11. YeS

    YeS Гик

    Я бы даже раз в пол минуты-минуту опрашивал датчик. Врятли значение влажности и температуры в помещении существенно меняется за такое время.
     
    arkadyf нравится это.
  12. DetSimen

    DetSimen Guest

    я с Вами категорически согласен. Мои уличные температурные датчики (BMP, правда) опрашиваюца раз в 10 минут, вапще. Никакой рояли там это не играет. А в ванной, где от влажности должна включаться вытяжка, то раз в 10 секунд. Всё зависит от задачи.
     
    arkadyf нравится это.