Помогите исправить код.

Тема в разделе "Arduino & Shields", создана пользователем lav522, 18 авг 2016.

  1. lav522

    lav522 Нуб

    Хочу создать примитивнейшую сигнализацию на дверь с помощью зуммера, ультрозвукового дальномера (SR04), переключателя на две позиции, светодиода и собственно ардуино. В программировании полный ноль, но уж очень захотелось сделать самому.

    Что я от нее хочу: при одном положении выключетеля - светодиод не горит, сонар не измеряет, в общем все спит. Как только включаю второе положение - задержка на пару сек, чтобы успел отойти, затем загорается светик и начинает работать SR04. При фиксировании изменения начинает пищать зуммер, при том зуммер у меня без генератора, хотелось бы узнать, возможно ли, чтобы при фиксации движения запускался цикл типа:

    tone(ALARM, 2000);

    delay(100);

    и так бесконечно, до тех пор, пока не изменится положение переключателя.

    Собственно вопрос в том, как переделать код, чтобы зуммер продолжал пищать и после того, как перестанет фиксироваться движение. Пока смог добиться всего, о чем писал выше, только без начальной задержки и главное, зуммер пищит, только пока фиксируется движение, как только человек проходит, он замолкает :(

    Вот код:

    #define ALARM 5
    #define LED 7
    #define SWITCH 8
    int echoPin = 11;
    int trigPin = 12;



    void setup(){
    pinMode(ALARM, OUTPUT);
    pinMode(SWITCH, INPUT_PULLUP);
    pinMode(LED, OUTPUT);
    pinMode(trigPin, OUTPUT);
    Serial.begin(9600);
    }

    void loop (){
    int var = digitalRead(SWITCH);
    switch(var){
    case 1:
    digitalWrite(LED, HIGH);
    int duration, cm;
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);
    cm = duration / 58;
    delay(10);

    /*Serial.println(cm);
    delay(300);*/

    if (cm<45 || cm>60){

    tone(ALARM, 2000);

    delay(100);

    case 0:


    noTone(ALARM);
    digitalWrite(LED, LOW);
    }
    }
    }
     
  2. ostrov

    ostrov Гуру

    Код (C++):
    if (cm<45 || cm>60){
    tone(ALARM, 2000);
    while(1);
    }
    Будет пищать до перезапуска.
     
  3. DIYMan

    DIYMan Guest

    1. Есть кнопочка "Код" на панели инструментов, когда пишете сообщение;
    2. Как только сработал датчик - взводите флаг, что зуммер должен пищать. И если флаг взведён, то зуммер будет продолжать пищать вне зависимости от того, сработал ли датчик в дальнейшем. Вот вам весь алгоритм в псевдокоде:

    Код (C++):
    bool isBuzzerOn; // флаг, что зуммер активен
    bool isWorkGranted; // флаг, что работа разрешена

    void setup()
    {
        isBuzzerOn = false; // зуммер не пищит
        isWorkGranted = false; // работа запрещена
       
    }

    void loop()
    {
        if(isBuzzerOn) // пищим, сработала тревога
            Alarm();
           
        if(!digitalRead(alarmOffPin)) // если нажали кнопку сброса тревоги, выключаем тревогу
            isBuzzerOn = false;
           
        if(!isWorkGranted) // если не работали, то проверяем - можно ли работать
        {
            isWorkGranted = !digitalRead(switchPin); // проверяем, вкл ли выключатель
            if(isWorkGranted)
            {
                // разрешили работу
                delay(2000); // тормозим две секунды, чтобы отойти
               
                // включаем режим работы
            }
        }
           
        if(!isWorkGranted) // работа запрещена, переключатель в положении выкл
            return;
           
        bool isAlarm = digitalRead(sensorPin); // проверяем, есть ли тревога
       
        if(isAlarm) // только если есть тревога - вкл пищалку, не выключаем её
            isBuzzerOn = true;
       

    }
     
  4. vvr

    vvr Инженерище

    введите новую переменную - состояние пищалки
    изначально допустим равна 0, пищалка молчит
    при срабатывании датчика меняется состояние на 1 и начинает орать
    при переключении тумблера состояние обнуляете и пищалка опять молчит
     
  5. vvr

    vvr Инженерище

    пока царапал текст - опередили)))
     
  6. Vetrinus

    Vetrinus Гик

    Код (C++):
    #define ALARM 5
    #define LED 7
    #define SWITCH 8
    #define echoPin  11
    #define trigPin  12
    #define pause 2000

    enum state {OFF, SET_ON, WAIT_FOR_CONTACT, SIGNAL};
    byte system;

    void setup() {
      pinMode(ALARM, OUTPUT);
      pinMode(SWITCH, INPUT_PULLUP);
      pinMode(LED, OUTPUT);
      pinMode(trigPin, OUTPUT);
      Serial.begin(9600);
      system = OFF;
    }

    void loop () {
      switch (system) {
        case OFF:
          if (digitalRead(SWITCH)) system = SET_ON;
          noTone(ALARM);
          digitalWrite(LED, LOW);
          break;
        case SET_ON:
          delay(pause);
          state = WAIT_FOR_CONTACT;
          break;
        case WAIT_FOR_CONTACT:
          digitalWrite(LED, HIGH);
          int duration, cm;
          digitalWrite(trigPin, LOW);
          delayMicroseconds(2);
          digitalWrite(trigPin, HIGH);
          delayMicroseconds(10);
          digitalWrite(trigPin, LOW);
          duration = pulseIn(echoPin, HIGH);
          cm = duration / 58;
          if (cm < 45 || cm > 60) {
            system = SIGNAL;
          }
          if (!digitalRead(SWITCH)) system = OFF;
          break;
        case SIGNAL:
          tone(ALARM, 2000);
          delay(100);
          digitalWrite(LED, HIGH);
          if (!digitalRead(SWITCH)) system = OFF;
          break;
      }
    }
     
     
    lav522 нравится это.
  7. lav522

    lav522 Нуб

    Vetrinus, выдает ошибку
    exit status 1
    expected unqualified-id before '=' token
    Ваделена красным строчка в loop
    state = WAIT_FOR_CONTACT;
     
  8. lav522

    lav522 Нуб

    Ну я уже почти разобрался как через boolean сделать из примера выше))
     
  9. Vetrinus

    Vetrinus Гик

    Код (C++):
    system = WAIT_FOR_CONTACT;
    переименовал переменную и забыл изменить название
     
  10. lav522

    lav522 Нуб

    теперь заработало, спасибо огромное, еще вопрос, возможно ли сделать пищание не статичным, а с задержкой или несколькими. Ну, чтобы не пииииииии, а пи пи пи пи :D
     
  11. lav522

    lav522 Нуб

    например сделать какую-нибудь мелодию в функции где-то вне цикла, а в цикле просто вызывать ее? или так нельзя?
     
  12. Vetrinus

    Vetrinus Гик

    Код (C++):
    case SIGNAL:
          tone(ALARM, 2000, 1000); //пищит секуду, потом пауза в полсекунды
          delay(500);
          digitalWrite(LED, HIGH);
          if (!digitalRead(SWITCH)) system = OFF;
          break;
     
    Последнее редактирование: 18 авг 2016
  13. Tomasina

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

    ну и мой вариант: :)
    Код (C++):
    #define BUZZER    5
    #define LED       7
    #define SWITCH    8
    #define ECHO      11
    #define TRIG      12
    #define TIMEOUT   5
    #define DIST_MIN  45
    #define DIST_MAX  60

    #define SWITCH_ON (!digitalRead(SWITCH)) // макрос для удобства

    enum{DISABLED, READY, ENABLED, ALARM}; // возможные режимы работы
    byte state;  // текущий режим работы


    void setup()
    {
      pinMode(BUZZER, OUTPUT);
      pinMode(LED, OUTPUT);
      pinMode(TRIG, OUTPUT);
      pinMode(ECHO, INPUT);
      pinMode(SWITCH, INPUT_PULLUP);
      state = DISABLED;
    }


    void loop() // основная логика работы
    {
      switch(state)
      {
      case DISABLED: // спящий режим. Все отключено, проверяется только состояние переключателя.
        if(SWITCH_ON) state = READY;
        break;

      case READY:    // режим готовности. Отсчет 5 сек, затем переход в режим охраны.
        for(byte i = 0; i < TIMEOUT; i++)
        {
          digitalWrite(LED, HIGH);
          tone(BUZZER, 1200);
          delay(500);
          digitalWrite(LED, LOW);
          noTone(BUZZER);
          delay(500);
        }
        state = ENABLED;
        break;

      case ENABLED:  // режим охраны. Постоянный опрос сонара и состояния переключателя.
        if(!SWITCH_ON) state = DISABLED;
        else
        {
          int distance = readSensor();
          if (distance < DIST_MIN || distance < DIST_MAX) state = ALARM;
        }
        break;

      case ALARM:    // режим тревоги. Звучит сирена и проверяется только состояние переключателя.
        for(int i = 400; i < 1600; i=+10)
        {
          tone(BUZZER, i);
          delay(20);
          noTone(BUZZER);
        }
        digitalWrite(LED, !digitalRead(LED));
        if(!SWITCH_ON)
        {
          state = DISABLED;    
          digitalWrite(LED, LOW);
        }
        break;

      }
    }


    int readSensor()
    {
      int duration, cm;
      digitalWrite(TRIG, LOW);
      delayMicroseconds(2);
      digitalWrite(TRIG, HIGH);
      delayMicroseconds(10);
      digitalWrite(TRIG, LOW);
      duration = pulseIn(ECHO, HIGH);
      cm = duration / 58;
      return cm;
    }
     
    lav522 и Vetrinus нравится это.
  14. Vetrinus

    Vetrinus Гик

    Можно. Пример можете посмотреть у @Tomasina, только там в функцию не обернуто)
     
  15. lav522

    lav522 Нуб

    спасибо за комментарии к строчкам) но работает странно. При включении идет 5 сек отсчет, затем врубается тревога, хоть показания сонара в норме и не выключается после нажатия на переключатель.
     
  16. Tomasina

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

    Код (C++):
    if (distance < DIST_MIN || distance > DIST_MAX) state = ALARM;
     
  17. lav522

    lav522 Нуб

    теперь все ок, но переключатель отключает сигнализацию только пока она не сработала. Как только начинает орать пищалка, переключатель не работает.
     
  18. Vetrinus

    Vetrinus Гик

    Пищалка циклом выдает звук, похожий на сирену, прислушайтесь.
    Пока цикл не закончен, кнопка считываться не будет
    Вообще, есть в этом недостаток, конечно.
    Стоит вынести сирену в отдельное состояние, либо отказаться от использования циклов, тогда нажатие будет отрабатывать сразу.
     
  19. lav522

    lav522 Нуб

    то есть после выполнения цикла переключатель должен считаться? сейчас запустил сирену, сразу щелкнул переключателем, минуты две слушал - все также орет. Или это такой длинный цикл?
     
  20. Vetrinus

    Vetrinus Гик

    Например, вот так:
    Код (C++):
    #define BUZZER    5
    #define LED       7
    #define SWITCH    8
    #define ECHO      11
    #define TRIG      12
    #define TIMEOUT   5
    #define DIST_MIN  45
    #define DIST_MAX  60

    #define SWITCH_ON (!digitalRead(SWITCH)) // макрос для удобства

    enum{DISABLED, READY, ENABLED, ALARM}; // возможные режимы работы
    byte state;  // текущий режим работы
    int freequency=400;
    bool buzzer_mode=true;


    void setup()
    {
      pinMode(BUZZER, OUTPUT);
      pinMode(LED, OUTPUT);
      pinMode(TRIG, OUTPUT);
      pinMode(ECHO, INPUT);
      pinMode(SWITCH, INPUT_PULLUP);
      state = DISABLED;
    }


    void loop() // основная логика работы
    {
      switch(state)
      {
      case DISABLED: // спящий режим. Все отключено, проверяется только состояние переключателя.
        if(SWITCH_ON) state = READY;
        break;

      case READY:    // режим готовности. Отсчет 5 сек, затем переход в режим охраны.
        for(byte i = 0; i < TIMEOUT; i++)
        {
          digitalWrite(LED, HIGH);
          tone(BUZZER, 1200);
          delay(500);
          digitalWrite(LED, LOW);
          noTone(BUZZER);
          delay(500);
        }
        state = ENABLED;
        break;

      case ENABLED:  // режим охраны. Постоянный опрос сонара и состояния переключателя.
        if(!SWITCH_ON) state = DISABLED;
        else
        {
          int distance = readSensor();
          if (distance < DIST_MIN || distance < DIST_MAX) state = ALARM;
        }
        break;

      case ALARM:    // режим тревоги. Звучит сирена и проверяется только состояние переключателя.
        /*for(int i = 400; i < 1600; i=+10)
        {
          tone(BUZZER, i);
          delay(20);
          noTone(BUZZER);
        }*/

        if(buzzer_mode){
          tone(BUZZER, freequency);
          delay(20);
          noTone(BUZZER);
          freequency=freequency+10;
        } else {
          tone(BUZZER, freequency);
          delay(20);
          noTone(BUZZER);
          freequency=freequency-10;
        }
        if(freequency > 1600 || freequency <400 ) buzzer_mode=!buzzer_mode;
        digitalWrite(LED, !digitalRead(LED));
        if(!SWITCH_ON)
        {
          state = DISABLED;  
          digitalWrite(LED, LOW);
          freequency=400;
          buzzer_mode=true;
        }
        break;

      }
    }


    int readSensor()
    {
      int duration, cm;
      digitalWrite(TRIG, LOW);
      delayMicroseconds(2);
      digitalWrite(TRIG, HIGH);
      delayMicroseconds(10);
      digitalWrite(TRIG, LOW);
      duration = pulseIn(ECHO, HIGH);
      cm = duration / 58;
      return cm;
    }
     
    lav522 нравится это.