Пауза в скетче.

Тема в разделе "Arduino & Shields", создана пользователем kraus, 16 дек 2019.

  1. kraus

    kraus Нерд

    Весы, Тара. Сыпем в тару песок(или другое сыпучее). При определённом насыпанном весе останавливается программа, а так же включается зуммер и лампа. Освобождаем весы. Устанавливаем новую тару. Нажимаем кнопку (чем запускаем далее скетч ).
    Пробовал с прерываниями - не получилось. Начинающий я...
    Подскажете что не так делаю? Прерывания скетча нет. Не останавливается и кнопка мёртвая. Кнопка с антидребезгом (с резистором).
    Флаги вроде поставил ... как у Алексагайвера в 16 уроке...

    Код (C++):
    // HX711 к Arduino pin 4->CLK  5->DAT 5V->VCC GND->GND
    //дИСПЛЕЙ 1602 и oled  VCC — 5V  GND — GND  SDA — A4  SCL — A5
    // The HX711 board can be powered from 2.7V to 5V so the Arduino 5V power should be fine.

    #include <LiquidCrystal_I2C.h>
    #include "HX711.h" //This library can be obtained here http://librarymanager/All#Avia_HX711

    }
    void dvigatel_1() {}
    void dvigatel_2() {}
     
    Последнее редактирование: 2 янв 2020
  2. Asper Daffy

    Asper Daffy Иксперд

    Ну, тогда понятно.

    А
    тоже от него?
     
    parovoZZ нравится это.
  3. DIYMan

    DIYMan Guest

    Почитайте документацию к attachInterrupt, пожалуйста. И посмотрите, что значит первый параметр, и как надо его правильно использовать. И ответьте на вопрос - какая у вас плата?

    И ещё: в обработчике прерывания - не стоит работать с Serial, да и вообще - делать что-то тяжёлое.
     
    kraus нравится это.
  4. kraus

    kraus Нерд

    Уно.
    А как тогда остановить, чтобы по кнопке опять начинался? У меня ещё там будет порядочно... примерно столько же.
     
    Последнее редактирование: 16 дек 2019
  5. kraus

    kraus Нерд

    Всё правильно у меня - на 3 пин при цифре 1.
    interrupt – номер вызываемого прерывания (стандартно 0 – для 2-го пина, для платы Ардуино Уно 1 – для 3-го пина),
    Но Работало же всё со скетчем блинк (стандартный в примерах)..нажал на кнопку - светодиоды помигали и остановились. ..Нажал кнопку ..помигали и остановились.
     
    Последнее редактирование: 16 дек 2019
  6. kraus

    kraus Нерд

    Здесь-то всё работает!

    Код (C++):
    volatile boolean flag;

    void setup() {
      Serial.begin(9600);
      pinMode(3, INPUT_PULLUP);
      pinMode(7, OUTPUT);
      attachInterrupt(1, oled, FALLING);
    }

    void loop() {
          if (flag) {
            oled();
        Serial.println("Interrupt!");
            flag = 0;
      }          
    }
    void oled(){
      flag = 1;
    digitalWrite(7, HIGH);
      delay(1000);                  
      digitalWrite(7, LOW);
      delay(1000);
      digitalWrite(7, HIGH);
      delay(1000);                  
      digitalWrite(7, LOW);
      delay(1000);      
      digitalWrite(7, HIGH);
      delay(1000);                  
      digitalWrite(7, LOW);
      delay(1000);      
    }
     
  7. DIYMan

    DIYMan Guest

    Ещё раз: Wiring НЕ ГАРАНТИРУЕТ, что номер прерывания 1 - будет для пина номер 3. Именно поэтому в документации описано, что правильно получать номер прерывания вызовом digitalPinToInterrupt.

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

    Пример, приведённый вами выше, как пример вида "здесь-то всё работает" - очень, очень плохой пример того, как надо работать с прерываниями. И который ведёт к неизбежным косякам в мало-мальски приличном по объёму проекте.
     
    kraus нравится это.
  8. asam

    asam Гик

    Это ужасный пример, который, может и работает, но следовать ему абсолютно не стоит.
    - Не надо использовать функцию для преваниния в Loop
    - Не надо использовать библиотеки в прерывании (в вашем случае lcd)
    - Желательно не использовать Serial.print. Иногда допустимо использовать Serial.print в прерывании для отладки с помощью вывода коротких (1-2 символа) собщений, но в окончательном варианте лучше их убрать.
    - Не надо использовать в прерывании delay() или ждать пока изменения millis()
    - И вообще не надо допускать длительных действий в прерывании.
     
  9. Asper Daffy

    Asper Daffy Иксперд

    lcd у тебя через I2C. Ему нужны свои прерывания. Если ты вызываешь его в обработчике, он может просто навечно повиснуть в ожидании прерывания.
     
  10. SergeiL

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

    Странный пример, такое впечатление, что просто недоделанный.
    Мигание и в прерывании, и после, по флагу из loop() запускается.
    А антидребезг за счет delay отрабатывает.
    А так уже не так страшно:
    Код (C++):
    volatile boolean flag;

    void setup() {
      Serial.begin(9600);
      pinMode(3, INPUT_PULLUP);
      pinMode(7, OUTPUT);
      attachInterrupt(1, oled, FALLING);
    }

    void loop() {
          if (flag) {
            blink();
        Serial.println("Interrupt!");
            flag = 0;
      }      
    }
    void oled(){
      flag = 1;
    }
    void blink(){
      digitalWrite(7, HIGH);
      delay(1000);                
      digitalWrite(7, LOW);
      delay(1000);
      digitalWrite(7, HIGH);
      delay(1000);                
      digitalWrite(7, LOW);
      delay(1000);    
      digitalWrite(7, HIGH);
      delay(1000);                
      digitalWrite(7, LOW);
      delay(1000);    
    }
     
    ИгорьК и DIYMan нравится это.
  11. DIYMan

    DIYMan Guest

    (c) уроки Гайвера :D:D:D
     
  12. SergeiL

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

    Из любопытства зашел, посмотрел. Нет у Гайвера этого мигания, а в прерывании - только взведение флага.
    Так что не от Гайвера этот кошмар.
     
  13. kraus

    kraus Нерд

    Абсолютно не стоит..Согласен с Вами. Я пытаться программировать начал только только, может месяц как..
    Это не гайверовский пример, этот кошмар я сам на его примере прерываний накропал с блинком симбиоз.(Уж как получилось).
    Поэтому, пока ещё не понимая как сделать так как в первом посте написал и выложил всё сюда дабы спросить помощи, хоть какой..
    Вот и так ..прошу помочь.. или здесь как на форуме Arduino ru тоже посылают на... "иди учись" (даже ради 2-3 проектов).
    А что надо делать?
     
    Последнее редактирование: 17 дек 2019
  14. SergeiL

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

    Ну я же исправил ваш ужасный вариант, на более приемлемый в посте #10

    Просто то, что Вы хотите получить, нужно делать иначе. То, что у Вас в первом скетче - нужно переписывать полностью.
    Там не просто ошибки, там построение программы абсолютно не соответствует вашей задаче.
    Попробуйте сначала научиться просто измерять вес и выводить его на дисплей в loop(), без всяких прерываний и кнопок, начните с этого.
    Чтобы отображались изменения веса при наполнении тары.
    Дальше научитесь зажигать лампу и включать зуммер при достижении нужного значения.
    Оставьте пока прерывания и кнопку. Это пока не для Вас.
    Как только сможете зажигать лампу и включать зуммер при достижении нужного веса можно будет перейти и к кнопке.
    Начните с исправления этого, тут все просто исправить:
    Код (C++):
      for (int i = 0; i < 3; i ++) // усредняем показания, считав значения датчика 10 раз
      {
        units = + scale.get_units(), 3;                          // суммируем показания 10 замеров
      }
     
     
  15. a1000

    a1000 Гуру

    Если я не ошибаюсь, в прерывании временные функции вообще не работают.
     
  16. vvr

    vvr Инженерище

    Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются. Возможна потеря данных передаваемых по последовательному соединению (Serial data) в момент выполнения функциии обработки прерывания.
     
  17. DetSimen

    DetSimen Guest

    Учиться.
     
    Andrey12, Daniil, parovoZZ и ещё 1-му нравится это.
  18. parovoZZ

    parovoZZ Гуру

    надо юзать delay_ms и delay_us
     
    DetSimen нравится это.
  19. asam

    asam Гик

    Ну что значит не работают. Миллис, например, можно вызывать и сколько угодно раз, просто он всегда будет возвращать одно и то же значение которое было на момент срабатывания прерывания.
    delay() зависнет, но если перед его вызовом разрешить глобальные прерывания (sei), то будет работать, просто это
    1- плохой стиль
    2- ваше прерывание сможет прервать другое прерывание (с другим вектором)
     
    Последнее редактирование: 18 дек 2019
  20. kraus

    kraus Нерд

    Его не было смысла править - это просто дерьмовый вариант за 5 минут склепал чисто для примера что работает.
    Это всё уже давно сделал и прежде чем пост написать игрался неделю. Даже останавливается при достижении нужного веса. но как только снимаю вес с весов - начинает опять работать движок*(светиться светодиод и зуммер орать, поэтому зуммер отключил.)
    Чего тут править можно? Ну вместо 3 замеров сделать 10...ну 20... в результате медленнее стало меняться число на экране...
    Код (C++):
     for (int i = 0; i < 20; i ++) // усредняем показания, считав значения датчика 10 раз
      {
        units = + scale.get_units(), 20;                          // суммируем показания 10 замеров
      }
    .Может формула не та?... так брал её вот здесь в спойлере.
    Или имеете в виду что не там цифру поставил - надо было в скобках? А зачем "+" перед "scale.get_units"?
     
    Последнее редактирование: 18 дек 2019