Помогите с дребезгом кнопки :)

Тема в разделе "Arduino & Shields", создана пользователем Djvan, 10 май 2014.

  1. Djvan

    Djvan Нерд

    Здравствуйте товарищи. В общем делаю контроллер для аквариума, ну часть уже сделал - но нужно, чтобы кнопкой была возможность отключения системы (т.е. кнопке должен даваться флаг 0,1 или 2) - пока значение флага выводится на экран 16х2 - флаг записывается в переменную svet. Попробовал сделать задержку в 400 миллисекунд, но кнопка работает нестабильно - т.е. не всегда срабатывает - в общем случае переключается и выдает на экран значения 0,1,2 - но иногда требуется несколько раз нажать кнопку - хотелось бы решить проблему, но вот с библиотекой дебоунс совсем не знаком - только учусь - помогите разобраться - как сделать, чтобы кнопка меняла флаг нормально, с первого раза :) Буду очень благодарен за ответы :)

    Код (Text):
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>


    #define ONE_WIRE_BUS 2 //на 2 пин подключаем датчик температуры

    // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    OneWire oneWire(ONE_WIRE_BUS);

    // Pass our oneWire reference to Dallas Temperature.
    DallasTemperature sensors(&oneWire);
    LiquidCrystal_I2C lcd(0x27,16,2);  // устанавливаем адрес 0x27, и дисплей 16 символов в 2 строки (16х2)


    int Relay1 = 3; //реле на нагреватель
    int Relay2 = 4; // реле на кулеры      
    int ButPin = 5; // пин на кнопку  
    int  theat=25;  //температура при которой включается нагреватель
    int  tcool=29;  //температура при которой включается кулер
    int svet = 0;  //флаг по умолчанию равен нулю



    void setup(void)
    {
        pinMode(Relay1, OUTPUT);
        pinMode(Relay2, OUTPUT);
      // pinMode(ButPin, INPUT);
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
     
      lcd.init();                    // инициализация LCD
      lcd.backlight();                // включаем подсветку
      lcd.clear();                    // очистка дисплея
     
     
      // start serial port
      Serial.begin(9600);
      Serial.println("Dallas Temperature IC Control Library Demo");

      // Start up the library
      sensors.begin();
     
     
        lcd.setCursor(0, 0);            // устанавливаем курсор на 1 строку, 1 символ
      lcd.print("H:");            // вывод надписи
     
      lcd.setCursor(4, 0);            // устанавливаем курсор на 1 строку, 9 символ
      lcd.print("C:");

      lcd.setCursor(8, 0);            // устанавливаем курсор на 1 строку, 9 символ
      lcd.print("F:");

      lcd.setCursor(12, 0);            // устанавливаем курсор на 1 строку, 9 символ
      lcd.print("S:");

      lcd.setCursor(8, 1);            // устанавливаем курсор на 1 строку, 9 символ
      lcd.print("t:");
     
        lcd.setCursor(0, 1);            // устанавливаем курсор на 1 строку, 9 символ
      lcd.print("S:");
     
        lcd.setCursor(4, 1);            // устанавливаем курсор на 1 строку, 9 символ
      lcd.print("O:");
    }

    void loop()
    {

    {
      if(digitalRead(ButPin) == LOW && svet == 0)    
        {                                            
       
          svet = 1;
          Serial.print("1");
    lcd.setCursor(2, 1);          
      lcd.print("1");
          delay(400);
        }
     
      if(digitalRead(ButPin) == LOW && svet == 1)
        {
              svet = 2;
          Serial.print("2");
      lcd.setCursor(2, 1);          
      lcd.print("2");
          delay(400);
        }
        if(digitalRead(ButPin) == LOW && svet == 2)
        {
              svet = 0;
          Serial.print("0");
    lcd.setCursor(2, 1);          
      lcd.print("0");
          delay(400);
        }
       
    }
      sensors.requestTemperatures(); // Send the command to get temperatures

      //Serial.print("Temperature for the device 1 (index 0) is: ");
      //Serial.println(sensors.getTempCByIndex(0));
      float temp = sensors.getTempCByIndex(0);
      lcd.setCursor(10, 1);
      lcd.print(temp,1);
      lcd.print((char)223);
      lcd.print("C ");
     
      if (temp < theat)
      {
        digitalWrite(3, LOW);
        lcd.setCursor(2, 0);          
      lcd.print("1");
        }        
        else
        { digitalWrite(3, HIGH);
          lcd.setCursor(2, 0);          
      lcd.print("0");
      }
      if (temp > tcool)  //
      {
        digitalWrite(4, LOW);
          lcd.setCursor(6, 0);          
      lcd.print("1");
        }        
        else
        { digitalWrite(4, HIGH);
          lcd.setCursor(6, 0);          
      lcd.print("0");
     
      }
    }
     
  2. Djvan

    Djvan Нерд

    И еще - подскажите - какое питание нужно подать на ардуино - будет использоваться ардуино про мини. Вообще хочу сделать, чтобы в коробку подавалось 220в - далее пойдет развязка на реле - чтобы управлять 3 устройствами 220 и 1 устройством 12в + питание самой ардуины. Я так понимаю нужно взять драйвер или что то похожее - подскажите что заказать - желательно на али или ебее. И еще такой вопрос - достаточно будет подать например 5в на ардуино с юсб - потянет для питания шилда 4 реле + экрана, блютуф и датчика температуры? Или на реле лучше отдельно питание подать? В общем подскажите нубу как все правильно сделать. Заранее всем спасибо за помощь :) И извините за глупые вопросы :)
     
  3. Airbus

    Airbus Радиохулиган Модератор

    Всё просмотрел не увидел где у Вас "дребезг". Нет непосредственной команды от кнопки ButPin = 5? Тогда и антидребезг не нужен (дребезг идёт только от кнопки от других датчиков-нет)код на Си тем более в "обвёртке" от Ардуино выполняется медленно но если будет такая необходимость добавьте строку Delay (100); этого вполне хватит. Теперь про питание:подойдёт любое 5-12 в Ардуино есть стабилизатор-поэтому можно и от USB смотря какие релюхи у Вас стоят если на 5 вольт то можно и не париться если на 12 то смело подавайте 12 на всех шилдах есть встроенные стабилизаторы.Реле шилд можно заказать на Ебае придёт за 2 недели но я делал сам с релюхами на 5 вольт чтоб питать по USB.
     
  4. lerik2703

    lerik2703 Гик

    вы не верно обрабатываете не только "анти дребезг" но и обработку переменной svet!поэтому вам как новичку лучше будет все-же с библиотекой Bounce
    PHP:
    #include <Bounce.h>
    #define ButPin 5 // пин на кнопку
    int svet = 0;  //флаг по умолчанию равен нулю
    Bounce bouncer = Bounce(ButPin, 50); //создаем экземпляр класса Bounce для ButPin
    void setup()
    {
      pinMode(ButPin, INPUT);  //переключаем ButPin (5) вывод в режим входа
      digitalWrite(ButPin, 1);  //включаем на нем подтягивающий резистор

    }

    void loop()
    {
      if (bouncer.update()) {    //если произошло событие
        if (bouncer.read()==LOW) {    //если кнопка нажата
          switch (svet) {
          case 0:
            svet = 1;
            // здесь любой код для svet=0
            break;
          case 1:
            // по аналогии case 0:
            break;
          }
        }
      }
      // дальше трудимся
    }
     
    библиотеку можно поискать здесь на форуме
     
    Megakoteyka и Djvan нравится это.
  5. Djvan

    Djvan Нерд

    Пробовал с этой библиотекой - но как то не получилось - но Ваш пример мне очень понравился - нафиг делать кучу условий, если можно поставить выбор :) Блин как же я про case забыл то :) Спасибки - буду копать. Вообще понял - надо наверно будет полностью переделать программку - начать с общего скелета, а то пытался все последовательно делать, но в результате код очень некрасивый и путанный получался - попробую переделать.

    Ну вроде делей поставил - лучше всего кнопка срабатывала при 600 - на черновом варианте так и оставил - но буду переделывать под библиотеку дебоунс, как советовали ниже. реле у меня шилдом идет блок на 4 реле (питание 5в). Если питаю от ардуино (подключена к ПК) - то при включении реле экран 16х2 заметно темнеет - при отключении реле - ярче загорается. Т.е. как понимаю - лучше запитать от 5 в - отдельно каждое устройство - чтобы не грузить МК. В идеале хочу чтобы в коробку со всеми устройствами приходило 220в, далее шла микросхема(ну как назвать - преобразователь 220-5, драйвер или еще как это называется) которая из 220 делает 5в (ну в общем чтобы отдельный блок питания не использовать - можно конечно просто разобрать БП на 5в 2А - но наверняка есть вариант поинтереснее - где то на ебее видел что то типа dc-dc 220 - (5-15) - но не могу найти :(
    PS - а вот сейчас нашел - вот это подойдет? http://www.ebay.com/itm/AC-to-DC-Po...357?pt=LH_DefaultDomain_0&hash=item3a86c22815 - я так понимаю, что подаю 220в - на выходе получаю 5в 1а ???? - и от этого уже параллельно запитать ардуино, экран, реле?
     
    Последнее редактирование: 12 май 2014
  6. Djvan

    Djvan Нерд

    Вот поморочился сегодня - переделал программу - правда времени мало было - хоккей все таки. В общем получилось вот что
    Код (Text):
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    #include <DS1307new.h>
    #include <Bounce.h>

    #define ButPin 5 // пин на кнопку 1
    #define ButPin2 8 // пин на кнопку 2
    #define ONE_WIRE_BUS 2 //на 2 пин подключаем датчик температуры

    // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    OneWire oneWire(ONE_WIRE_BUS);

    // Pass our oneWire reference to Dallas Temperature.
    DallasTemperature sensors(&oneWire);
    LiquidCrystal_I2C lcd(0x27,16,2);  // устанавливаем адрес 0x27, и дисплей 16 символов в 2 строки (16х2)

    //для часиков
    uint16_t startAddr = 0x0000;            // Начальный адрес для хранения в NV-RAM
    uint16_t lastAddr;                      // новый адрес для хранения в NV-RAM
    uint16_t TimeIsSet = 0xaa55;            // По этой переменной проверяется то, что время не нужно устанавливать заново

    int Relay1 = 3; //реле на нагреватель
    int Relay2 = 4; // реле на кулеры
    int Relay3 = 6; // реле на фильтр
    int Relay4 = 7; // реле на свет    
    int  theat=25;  //температура при которой включается нагреватель
    int  tcool=29;  //температура при которой включается кулер
    int svet = 0;  //флаг по умолчанию равен нулю - свет
    int oborud = 0;  //флаг по умолчанию равен нулю - все остальное оборудование
    int vkl = 10;
    int vykl = 22;
    Bounce bouncer = Bounce(ButPin, 50); //создаем экземпляр класса Bounce для ButPin
    Bounce bouncer2 = Bounce(ButPin2, 50); //создаем экземпляр класса Bounce для ButPin2
    void setup(void)
    {
        pinMode(Relay1, OUTPUT);
        pinMode(Relay2, OUTPUT);
        pinMode(Relay3, OUTPUT);
        pinMode(Relay4, OUTPUT);
        pinMode(ButPin, INPUT);  //переключаем ButPin (5) вывод в режим входа
        pinMode(ButPin2, INPUT);  //переключаем ButPin2 (8) вывод в режим входа
      digitalWrite(ButPin, 1);  //включаем на нем подтягивающий резистор
      digitalWrite(ButPin2, 1);  //включаем на нем подтягивающий резистор
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
     
     
      lcd.init();                    // инициализация LCD
      lcd.backlight();                // включаем подсветку
      lcd.clear();                    // очистка дисплея
      Serial.begin(9600);
      RTC.setRAM(0, (uint8_t *)&startAddr, sizeof(uint16_t));
      RTC.getRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
      if (TimeIsSet != 0xaa55)
      {
        RTC.stopClock();
           
        RTC.fillByYMD(2014,5,11); //устанавливаем дату
        RTC.fillByHMS(15,23,0); //устанавливаем время
        RTC.setTime();
        TimeIsSet = 0xaa55;
        RTC.setRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
        RTC.startClock();
      }
      else
      {
        RTC.getTime();
      }
      RTC.setCTRL();
      sensors.begin();
      lcd.setCursor(0, 0);          
      lcd.print("H:");          
      lcd.setCursor(4, 0);        
      lcd.print("C:");
      lcd.setCursor(8, 0);          
      lcd.print("F:");
      lcd.setCursor(12, 0);        
      lcd.print("S:");
      lcd.setCursor(8, 1);          
      lcd.print("t:");
      lcd.setCursor(0, 1);        
      lcd.print("S:");
      lcd.setCursor(4, 1);        
      lcd.print("O:");
    }

    void loop()
    {
      sensors.requestTemperatures();
      float temp = sensors.getTempCByIndex(0);
      lcd.setCursor(10, 1);
      lcd.print(temp,1);
      lcd.print((char)223);
      lcd.print("C ");
     
      if (bouncer.update()) {    //если произошло событие
        if (bouncer.read()==LOW) {    //если кнопка нажата
          switch (svet) {
          case 0:// здесь любой код для svet=0
            svet = 1;
            Serial.print("1");
            lcd.setCursor(2, 1);          
            lcd.print("1");
            digitalWrite(7, LOW);
            lcd.setCursor(14, 0);          
            lcd.print("1");
            break;
          case 1:
            svet = 2;
            Serial.print("A");
            lcd.setCursor(2, 1);          
            lcd.print("A");
            RTC.getTime();
            if (vkl < RTC.hour & RTC.hour < vykl)  // если время больше времени включения и меньше времени выключения (в часах), включаем свет
            {digitalWrite(7, LOW);
            lcd.setCursor(14, 0);          
            lcd.print("1");}
          else
          {digitalWrite(7, HIGH);
            lcd.setCursor(14, 0);          
            lcd.print("0");}
            break;
            case 2:
            svet = 0;
            Serial.print("0");
            lcd.setCursor(2, 1);          
            lcd.print("0");
            digitalWrite(7, HIGH);
            lcd.setCursor(14, 0);          
            lcd.print("0");
            break;
          }
        }
      }

      if (bouncer2.update()) {  
        if (bouncer2.read()==LOW) {
          switch (oborud) {
          case 0:
            oborud = 1;
            Serial.print("1");
            lcd.setCursor(6, 1);          
            lcd.print("1");
            break;
          case 1:
            oborud = 2;
            Serial.print("A");
            lcd.setCursor(6, 1);          
            lcd.print("A");
            break;
          case 2:
            oborud = 0;
            Serial.print("0");
            lcd.setCursor(6, 1);          
            lcd.print("0");
            break;
          }
        }
      }
      switch (oborud){
        case 0:
            digitalWrite(3, HIGH);
            lcd.setCursor(2, 0);          
            lcd.print("0");
            digitalWrite(4, HIGH);
            lcd.setCursor(6, 0);          
            lcd.print("0");
            break;
        case 1:
            digitalWrite(3, LOW);
            lcd.setCursor(2, 0);          
            lcd.print("1");
            digitalWrite(4, LOW);
            lcd.setCursor(6, 0);          
            lcd.print("1");
          break;
        case 2:
        if (temp < theat)  // если температура воды меньше theat, включаем нагреватель
        {digitalWrite(3, LOW);
        lcd.setCursor(2, 0);          
        lcd.print("1");}        
        else
        {digitalWrite(3, HIGH);
        lcd.setCursor(2, 0);          
        lcd.print("0");}
        if (temp > tcool)  // если температура воды больше tcool, включаем кулеры
        {digitalWrite(4, LOW);
        lcd.setCursor(6, 0);          
        lcd.print("1");}        
          else
        {digitalWrite(4, HIGH);
        lcd.setCursor(6, 0);          
        lcd.print("0");}
        break;}

    }
    Теперь одна проблема - строка sensors.requestTemperatures();
    В общем она тормозит программу - т.е. дребезг кнопок перестает работать - вернее кнопки вообще стали редко переключаться - можно 10-15 раз нажать чтобы переключилась - если ее закомментировать - то все работает быстро и без проблем - дребезг кнопки решается - но как только идет опрос датчика температуры - начинается затык программы - тормозит - и из-за этого вероятно плохое срабатывание кнопок - может эту функцию куда в другое место вынести? Моих мозгов и опыта пока не хватает :(
     
  7. lerik2703

    lerik2703 Гик

    здесь я вам могу посоветовать обратное , наоборот отказаться от библиотеке DallasTemperature.h и обращаться к датчику на прямую через OneWire.h,примеров здесь предостаточно!