Реализация паузы в скетче без delay

Тема в разделе "Arduino & Shields", создана пользователем Vetrinus, 15 авг 2015.

  1. Vetrinus

    Vetrinus Гик

    Здравствуйте! Нужна помощь в реализации паузы. Вот сам скетч, сейчас объясню логику происходящего.
    Код (Text):

    #define PIN13 13
    #define PIN12 12
    #define PIN11 11
    #define PIN10 10
    #define PIN9 9
    #define Control A0
    #define PIN7 7
    #define PIN6 6
    #define PIN5 5
    #define PIN4 4
    #define PIN3 3

    //float V1 = 1.68;
    //float V2 = 2.05;
    //float V3 = 2.79;
    //float V4 = 5.0;

    void setup ()
    {
      pinMode (PIN13, OUTPUT);
      pinMode (PIN12, OUTPUT);
      pinMode (PIN11, OUTPUT);
      pinMode (PIN10, OUTPUT);
      pinMode (PIN9, OUTPUT);
      pinMode (Control, INPUT);
      pinMode (PIN7, OUTPUT);
      pinMode (PIN6, OUTPUT);
      pinMode (PIN5, OUTPUT);
      pinMode (PIN4, OUTPUT);
      pinMode (PIN3, OUTPUT);
    }
    void loop(){
    int SensorValue = analogRead (Control);
    float voltage = SensorValue * (5.0/1024.0);

    if (voltage>4.9 && voltage<5.1)
    {
      digitalWrite (PIN13, LOW);
      delay (1000);
      digitalWrite (PIN12, LOW);
      delay (1000);
      digitalWrite (PIN11, LOW);
      delay (1000);
      digitalWrite (PIN10, LOW);
      delay (1000);
      digitalWrite (PIN9, LOW);
      delay (1000);
      digitalWrite (PIN7, LOW);
      delay (1000);
      digitalWrite (PIN6, LOW);
      delay (1000);
      digitalWrite (PIN5, LOW);
      delay (1000);
      digitalWrite (PIN4, LOW);
      delay (1000);
      digitalWrite (PIN3, LOW);
    }
    if (voltage >2.7 && voltage <2.9) {
        digitalWrite (PIN13, HIGH);
      delay (1000);
      digitalWrite (PIN12, HIGH);
      delay (1000);
      digitalWrite (PIN11, HIGH);
      delay (1000);
      digitalWrite (PIN10, HIGH);
      delay (1000);
      digitalWrite (PIN9, HIGH);
        delay (1000);
      digitalWrite (PIN7, LOW);
      delay (1000);
      digitalWrite (PIN6, LOW);
      delay (1000);
      digitalWrite (PIN5, LOW);
      delay (1000);
      digitalWrite (PIN4, LOW);
      delay (1000);
      digitalWrite (PIN3, LOW);
    }
    if (voltage >=1.9 && voltage <2.2) {
       digitalWrite (PIN13, LOW);
      delay (1000);
      digitalWrite (PIN12, LOW);
      delay (1000);
      digitalWrite (PIN11, LOW);
      delay (1000);
      digitalWrite (PIN10, LOW);
      delay (1000);
      digitalWrite (PIN9, LOW);
      delay (1000);
      digitalWrite (PIN7, HIGH);
      delay (1000);
      digitalWrite (PIN6, HIGH);
      delay (1000);
      digitalWrite (PIN5, HIGH);
      delay (1000);
      digitalWrite (PIN4, HIGH);
      delay (1000);
      digitalWrite (PIN3, HIGH);
    }
    if (voltage >1.5 && voltage <1.8) {
          digitalWrite (PIN13, HIGH);
      delay (1000);
      digitalWrite (PIN12, HIGH);
      delay (1000);
      digitalWrite (PIN11, HIGH);
      delay (1000);
      digitalWrite (PIN10, HIGH);
      delay (1000);
      digitalWrite (PIN9, HIGH);
        delay (1000);
          digitalWrite (PIN7, HIGH);
      delay (1000);
      digitalWrite (PIN6, HIGH);
      delay (1000);
      digitalWrite (PIN5, HIGH);
      delay (1000);
      digitalWrite (PIN4, HIGH);
      delay (1000);
      digitalWrite (PIN3, HIGH);
    }
    }


     
    Есть 1 управляющий канал, подключенный к аналоговому входу.
    С помощью
    Код (Text):
    int SensorValue = analogRead (Control);
    float voltage = SensorValue * (5.0/1024.0);
    Значение напряжения преобразуется в переменную типа float, которые внутри loop() сравниваются в if с заданными промежутками. Всего возможно 4 показателя напряжения, и, вследствие этого, 4 состояния диодов.
    1)
    Код (Text):
      digitalWrite (PIN13, LOW);
      delay (1000);
      digitalWrite (PIN12, LOW);
      delay (1000);
      digitalWrite (PIN11, LOW);
      delay (1000);
      digitalWrite (PIN10, LOW);
      delay (1000);
      digitalWrite (PIN9, LOW);
      delay (1000);
      digitalWrite (PIN7, LOW);
      delay (1000);
      digitalWrite (PIN6, LOW);
      delay (1000);
      digitalWrite (PIN5, LOW);
      delay (1000);
      digitalWrite (PIN4, LOW);
      delay (1000);
      digitalWrite (PIN3, LOW);
    2)
    Код (Text):
    digitalWrite (PIN13, HIGH);
      delay (1000);
      digitalWrite (PIN12, HIGH);
      delay (1000);
      digitalWrite (PIN11, HIGH);
      delay (1000);
      digitalWrite (PIN10, HIGH);
      delay (1000);
      digitalWrite (PIN9, HIGH);
        delay (1000);
      digitalWrite (PIN7, LOW);
      delay (1000);
      digitalWrite (PIN6, LOW);
      delay (1000);
      digitalWrite (PIN5, LOW);
      delay (1000);
      digitalWrite (PIN4, LOW);
      delay (1000);
      digitalWrite (PIN3, LOW);
    3)
    Код (Text):
    digitalWrite (PIN13, LOW);
      delay (1000);
      digitalWrite (PIN12, LOW);
      delay (1000);
      digitalWrite (PIN11, LOW);
      delay (1000);
      digitalWrite (PIN10, LOW);
      delay (1000);
      digitalWrite (PIN9, LOW);
      delay (1000);
      digitalWrite (PIN7, HIGH);
      delay (1000);
      digitalWrite (PIN6, HIGH);
      delay (1000);
      digitalWrite (PIN5, HIGH);
      delay (1000);
      digitalWrite (PIN4, HIGH);
      delay (1000);
      digitalWrite (PIN3, HIGH);
    4)
    Код (Text):
        digitalWrite (PIN13, HIGH);
      delay (1000);
      digitalWrite (PIN12, HIGH);
      delay (1000);
      digitalWrite (PIN11, HIGH);
      delay (1000);
      digitalWrite (PIN10, HIGH);
      delay (1000);
      digitalWrite (PIN9, HIGH);
        delay (1000);
          digitalWrite (PIN7, HIGH);
      delay (1000);
      digitalWrite (PIN6, HIGH);
      delay (1000);
      digitalWrite (PIN5, HIGH);
      delay (1000);
      digitalWrite (PIN4, HIGH);
      delay (1000);
      digitalWrite (PIN3, HIGH);
    В зависимости от того, какой показатель действует сейчас, должна загораться определенная группа диодов.(Как это работает, можете посмотреть далее : https://123d.circuits.io/circuits/949051-the-unnamed-circuit ) Причем загораться не моментально, а с задержкой. И после того, как диоды загорелись или потухли, они не должны менять состояние в течение определенного времени. Мне нужно реализовать именно эти паузы.
    На этом моменте я, честно признаюсь, сильно забуксовал. Единственное, что пришло в голову - попробовать поиграть с millis(). Но я не знаю, будет ли он записывать правильное время, если внутри loop() есть delay.
    Если кто-то может что-либо подсказать, буду очень рад!
     
  2. vvr

    vvr Инженерище

    по вашей ссылке что то не очень понятно, но делеи будут просто тормозить работу дуни.
    нужно от них вообще уйти.
     
  3. DrProg

    DrProg Вечный нерд

    Вот бы еще научиться пользоваться циклами! Программка сразу станет маленькой и удобной.
     
    ИгорьК и Tomasina нравится это.
  4. Vetrinus

    Vetrinus Гик

    С помощью этих операторов делается?
     
  5. DrProg

    DrProg Вечный нерд

    for вполне подойдет.

    И вообще не понятно, так надо чтобы после того как загорается каждый светодиод выдерживалась пауза 1 сек? Или пауза нужна после того как загорятся все светодиоды?
     
    ИгорьК нравится это.
  6. Vetrinus

    Vetrinus Гик

    Обе паузы нужны. Причем как при включении, так и при выключении.
     
  7. Megakoteyka

    Megakoteyka Оракул Модератор

    На циклах придется delay использовать. Без delay можно сделать на конечном автомате.
     
  8. ИгорьК

    ИгорьК Гуру

    Здесь, наверно, класс надо писать. Апдейтить его в зависимости от показаний, а внутри класса - 4 состояния в таблице. Так?
     
  9. Tomasina

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

    Паузы между измерениями? Если во время этой паузы контролируемое напряжение изменится, то что делать?
    Аналогично, если, например, где-то в середине выполнения условия (3) напряжение изменится, то что делать? Завершить до конца последовательное включение светодиодов, или прервать?
     
  10. Megakoteyka

    Megakoteyka Оракул Модератор

    Если программа больше ничего делать не будет, то нет смысла писать класс. Класс хорош в тех случаях, когда нужно отделить работу с некоторой сущностью от остального кода. А тут вполне достаточно автомата на switch.
     
  11. DrProg

    DrProg Вечный нерд

    Я вообще не понял, если все будет включаться и переключаться с задержкой, то почему бы не использовать тот же delay? Все эти millis() хороши для одновременной работы с несколькими задачами, а если все последовательно, то зачем городить огород? Вот например классический Hello World в виде мигающей лампочки можно сделать и через millis() и через прерывания по таймерам, но зачем?
     
    ИгорьК нравится это.
  12. Vetrinus

    Vetrinus Гик

    Завершить до конца, причем гореть они должны не менее минуты, скажем. И в случае выключения тоже самое. Даже если во время выключения подается сигнал на включение, они все равно должны все последовательно выключиться, и не включаться минимум ту же минуту.
     
  13. Vetrinus

    Vetrinus Гик

    Столкнулся с тем, что switch сравнивает числа только в integer, в то время как voltage объявлен как float.
    Можно попробовать изменить формулу расчета (float voltage = SensorValue * (5.0/1024.0);), чтобы был integer
     
  14. Tomasina

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

    Тогда зачем вообще отказ от delay? Программа линейная, паузы жёстко фиксированы, параллельных измерений и других действий не требуется - delay тут идеально подходит.
     
  15. Vetrinus

    Vetrinus Гик

    Вообще, я такого же мнения, но господа Гики выше говорят, что делей ниочень. По сути меня он не устраивает только в одном. Если его просто прописать в конце каждого условия, то выглядеть это будет так. Допустим, все диоды включены, нужно все выключить, тогда: подаем 5 вольт на Control, сначала выключается 1 группа, и минуту ждем. Потом выключается вторая группа, и опять ждем минуту. При включении тоже самое. Все бы ничего, но на практике мне нужна не минута задержки, а 10 минут, причем в обоих случаях... И как это избежать, я хз. Вот, что я сейчас написал через switch case:
    Код (Text):
    #define PIN13 13
    #define PIN12 12
    #define PIN11 11
    #define PIN10 10
    #define PIN9 9
    #define Control A0
    #define PIN7 7
    #define PIN6 6
    #define PIN5 5
    #define PIN4 4
    #define PIN3 3

    //float V1 = 1.68;
    //float V2 = 2.05;
    //float V3 = 2.79;
    //float V4 = 5.0;

    void setup ()
    {
      pinMode (PIN13, OUTPUT);
      pinMode (PIN12, OUTPUT);
      pinMode (PIN11, OUTPUT);
      pinMode (PIN10, OUTPUT);
      pinMode (PIN9, OUTPUT);
      pinMode (Control, INPUT);
      pinMode (PIN7, OUTPUT);
      pinMode (PIN6, OUTPUT);
      pinMode (PIN5, OUTPUT);
      pinMode (PIN4, OUTPUT);
      pinMode (PIN3, OUTPUT);
    }
    void loop(){
    int SensorValue = analogRead (Control);
    float voltage = 10 *SensorValue * (5.0/1024.0);

    switch (voltage) {
      case 5.0:
        digitalWrite (PIN13, LOW);
        delay (1000);
        digitalWrite (PIN12, LOW);
        delay (1000);
        digitalWrite (PIN11, LOW);
        delay (1000);
        digitalWrite (PIN10, LOW);
        delay (1000);
        digitalWrite (PIN9, LOW);
        delay (1000);
        digitalWrite (PIN7, LOW);
        delay (1000);
        digitalWrite (PIN6, LOW);
        delay (1000);
        digitalWrite (PIN5, LOW);
        delay (1000);
        digitalWrite (PIN4, LOW);
        delay (1000);
        digitalWrite (PIN3, LOW);
        break;
      case 2.79:
        digitalWrite (PIN13, HIGH);
        delay (1000);
        digitalWrite (PIN12, HIGH);
        delay (1000);
        digitalWrite (PIN11, HIGH);
        delay (1000);
        digitalWrite (PIN10, HIGH);
        delay (1000);
        digitalWrite (PIN9, HIGH);
          delay (1000);
        digitalWrite (PIN7, LOW);
        delay (1000);
        digitalWrite (PIN6, LOW);
        delay (1000);
        digitalWrite (PIN5, LOW);
        delay (1000);
        digitalWrite (PIN4, LOW);
        delay (1000);
        digitalWrite (PIN3, LOW);
        break;
      case 2.05:
        digitalWrite (PIN13, LOW);
        delay (1000);
        digitalWrite (PIN12, LOW);
        delay (1000);
        digitalWrite (PIN11, LOW);
        delay (1000);
        digitalWrite (PIN10, LOW);
        delay (1000);
        digitalWrite (PIN9, LOW);
        delay (1000);
        digitalWrite (PIN7, HIGH);
        delay (1000);
        digitalWrite (PIN6, HIGH);
        delay (1000);
        digitalWrite (PIN5, HIGH);
        delay (1000);
        digitalWrite (PIN4, HIGH);
        delay (1000);
        digitalWrite (PIN3, HIGH);
        break;
      case 1.68:
        digitalWrite (PIN13, HIGH);
        delay (1000);
        digitalWrite (PIN12, HIGH);
        delay (1000);
        digitalWrite (PIN11, HIGH);
        delay (1000);
        digitalWrite (PIN10, HIGH);
        delay (1000);
        digitalWrite (PIN9, HIGH);
        delay (1000);
        digitalWrite (PIN7, HIGH);
        delay (1000);
        digitalWrite (PIN6, HIGH);
        delay (1000);
        digitalWrite (PIN5, HIGH);
        delay (1000);
        digitalWrite (PIN4, HIGH);
        delay (1000);
        digitalWrite (PIN3, HIGH);
        break;
    }
    }
     
    Но не компилируется с ошибкой
    sketch_aug15a:36: error: switch quantity not an integer
    switch quantity not an integer

    Я пробовал сделать так
    int voltage = 10*sensorValue*(5.0/1024.0),
    компилируется, но в цирквите не работает...
     
  16. Tomasina

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

    в switch может быть только целое число, а не дробное.
    можно так:
    Код (Text):
    switch (voltage * 100) {
      case 500:
      ...
      case 297:
      ...
    Но тут switch мало подходит, ведь он сработает только если, например, voltage будет строго 2,97. А если намеряет 2.96 или 4.99, то условие не сработает. Тебе ведь нужен диапазон, а не строгое соответствие?
     
  17. Unixon

    Unixon Оракул Модератор

    Ну блин, кто ж так делает сравнение неточной величины ...

    Во-первых, напряжение измеряется с некоторой погрешностью и нужно сравнивать с интервалом, а не с константой.
    Во-вторых, switch-case работает только с целыми числами.
     
  18. Vetrinus

    Vetrinus Гик

    Я все это прекрасно понимаю, но считаю, что проблемы нужно решать по мере их поступления. Если в идеальных условиях в цирквите это заработало бы, то дальше я уже стал бы думать на счет интервала значений. А switch case я попробовал только потому, что его мне посоветовали.
     
  19. Vetrinus

    Vetrinus Гик

    если прописать voltage * 100, то при компиляции та же ошибка.
    Если прописать
    Код (Text):
    int voltage = 100 *SensorValue * (5.0/1024.0);

    switch (voltage) {
      case 500:
    и так далее
    то никаких действий не происходит вообще. С ифами медленно, но работало.
     
  20. Tomasina

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

    примерно так:
    Код (Text):
    #define PAUSE_LED 1000      // пауза между зажиганием LED, мсек
    #define PAUSE_MES 10000     // пауза между измерениями, мсек
    #define CONTROL A0

    const byte pinLed[10] = {13,12,11,10,9,7,6,5,4,3};  // массив с адресами пинов для LED

    const bool stateLed[4][10] = {     // маска состояний: ноль-LED выключен, единица-LED включен
      {0,0,0,0,0,0,0,0,0,0},           // для условия №1
      {1,1,1,1,1,0,0,0,0,0},           // для условия №2
      {0,0,0,0,0,1,1,1,1,1},
      {1,1,1,1,1,1,1,1,1,1}
    };


    void setup()
    {
      pinMode (CONTROL, INPUT);
      byte i = 0;
      while(pinLed[i]) pinMode(pinLed[i++], OUTPUT);  // настраиваем все LED-пины на OUTPUT
    }  // конец setup


    void loop()
    {
      int SensorValue = analogRead (CONTROL);
      float voltage = SensorValue * (5.0/1024.0);

      if (voltage>4.9 && voltage<5.1)          ledOperate(1);  // условие №1 - подаем на пины маску №1
      else if (voltage >2.7 && voltage <2.9)   ledOperate(2);
      else if (voltage >=1.9 && voltage <2.2)  ledOperate(3);
      else if (voltage >1.5 && voltage <1.8)   ledOperate(4);

      delay(PAUSE_MES);    // задержка перед следующим измерением
    }  // конец loop


    void ledOperate(byte state)  // функция включения-отключения соответствующих LED по номеру условия
    {
      byte i = 0;
      while(pinLed[i])
      {
        digitalWrite (pinLed[i], stateLed[state-1][i]);
        delay(PAUSE_LED);     // задержка перед зажиганием следующего LED
        i++;
      }
    }  // конец ledOperate
     
     
    DrProg и Vetrinus нравится это.