Как остановить или временно прервать цикл For

Тема в разделе "Arduino & Shields", создана пользователем Крапивин, 12 апр 2015.

  1. Крапивин

    Крапивин Нерд

    Привет. Кто нибудь может подсказать как прервать цикл For, или временно приостановить, для выполнения другой команды.

    Arduino в цикле считывает температуру с датчиков. надо в процессе работы, послать команду на включение вентилятора, или отключение тенов. Но программа не реагирует ни на какие дополнительные действия, пока идет считывание температуры.
    запуск цикла на считывание 8. а включить вентилятор посылаю с монитор порта 1.
    если нет цикла все работает, когда идет цикл, то отказ.

    ? как мне временно приостановить цикл чтобы выполнить другую команду ?


    while (Serial.available() == 0); //функция Serial.аvailable() проверяет, есть ли в COM порте


    int val = Serial.read() - '0';



    if (val == 1) transmit(RF1ON); //если с COM порта поступил символ (1), вкл вентилятор


    if (val == 8){

    for (int i = 0; i < 25; i++){ // крутим цикл
    ds.requestTemperatures(); // считываем температуру с датчиков


    Serial.print("Temper1 ");
    Serial.print(ds.getTempC(sensor1)); // отправляем температуру
    Serial.println(" *C");

    }
    }
     
  2. geher

    geher Гуру

    Вариантов много разной степени красоты.
    Например, можно перейти к автомату состояний.
    Будет что-то вроде:
    Код (Text):

      // возможные состояния
       #define STATE_NORMAL 0
       #define STATE_TEMPERATURE 1
      //инициализация
      static int state=STATE_NORMAL;
      static int i=0;
      // блок быстрой реакции на события
      if (Serial.available() != 0)
      {
          int val = Serial.read() - '0';
          if (val == 1) transmit(RF1ON); //если с COM порта поступил символ (1), вкл вентилятор
          if (val == 8) { // переключаем состояние на измерение температуры
             state=STATE_TEMPERATURE;
             i=0;  // начинаем цикл измерения с начала
          }
      }
      // обработка состояний
      switch(state) // в данном случае излишество, можно обойтись одним if, но "заразервировано под последующее использование".
      {
          case STATE_NORMAL:
             break;
          case STATE_TEMPERATURE:
             ds.requestTemperatures(); // считываем температуру с датчиков
             Serial.print("Temper1 ");
             Serial.print(ds.getTempC(sensor1)); // отправляем температуру
             Serial.println(" *C");
             i++; // очередное измерение выполнено, учли
             if (i>=25) // все измерения выполнены, пора переключаться обратно
             {
                 state=STATE_NORMAL;
             }
             break;
          default:
             break;
       }
    Естественно, в loop не должно быть других длительных операций. Иначе и их тоже нужно разбивать на элементарные операции, вводить новые состояния и добавлять из в автомат.
    Если параллельно нужно вести несколько сложных операций, то можно либо делать несколько параллельно работающих автоматов - несколько switch по одному на каждый автомат), либо делать сложные состояния - кодировать в состоянии выполнение одной операции или нескольких одновременно (в смысле при обработке конкретного состояния автомата по очереди выполнять элементарные операции, относящиеся к разным сложным операциям, которые должны выполняться для данного состояния).

    Сложнее, если достаточно долго выполняются сами функции считывания температуры (requestTemperatures и getTempC).
    Тогда придется лезть внутрь них, разделять процесс измерения на более короткие операции, каждой из которых сопоставлять отдельную функцию, вводить дополнительные состояния и переходить между ними в нужной последовательности, выполняя за раз в нужном состоянии одну короткую операцию, соответствующую состоянию.
     
    Последнее редактирование: 12 апр 2015
  3. Крапивин

    Крапивин Нерд

    спасибо за совет.
    убрал функцию For.
    все равно ничего не помогает, только пишет об ошибках.
    вставил вункцию как у вас в скетче, тоже не срабатывает а пишет ошибки.

    sketch_apr12a.ino:19:1: error: expected initializer before 'OneWire'
    sketch_apr12a.ino:20:23: error: 'oneWire' was not declared in this scope
    sketch_apr12a.ino: In function 'void loop()':
    sketch_apr12a.ino:53:10: error: 'state' was not declared in this scope
    sketch_apr12a.ino:58:10: error: 'state' was not declared in this scope
    Ошибка компиляции.

    This report would have more information with
    "Отображать вывод во время компиляции"
     
  4. Крапивин

    Крапивин Нерд

    как же обойтись без ds.requestTemperatures() и getTempC
    я думал только они умеют читать температуру с датчиков.
     
  5. Крапивин

    Крапивин Нерд

    :( написал небольшой скетч. который выводит температуру, с 2 датчиков, 1 на улице, 2 в сауне (на даче.)
    выводят данные на экран телефона. необходимо чтоб данные сами изменялись, для постоянного контроля за температурой в сауне. Всё отлично видно как растет температура. При заданной Т. идет звуковой сигнал.
    НО. если идет цикл проверки датчиков. ТО не работают кнопки, включить вытяжку, выключить тены,
    как только цикл останавливается, после 15 прочтения. кнопки работают.
    ели убираю цикл совсем. ТО не знаю какая температура в сауне, надо постоянно, в ручную, делать запрос о температуре.

    вот и появился вопрос как временно приостановить цикл, чтения показаний с датчиков, чтоб можно было нажать кнопку, управления радио розеткой, там цикла нет, посылается 1 маленькая команда.
    после можно опять восстановить чтение температуры, не важно с начала или с середины.
     
  6. Крапивин

    Крапивин Нерд

    break; в теле функции не помогает . останавливается вся программа.
     
  7. Unixon

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

    1) Зачем вообще цикл?
    2) Сколько времени занимает один опрос датчика?
     
  8. Крапивин

    Крапивин Нерд

  9. Крапивин

    Крапивин Нерд

    как можно выводить на дисплей измененные показание датчиков.
    как контролировать изменение температуры без цыкла ?
     
  10. geher

    geher Гуру

    То, что я набросал, скорее иллюстрация, чем готовый код.
    Приведенные ошибки говорят о том, что код был интегрирован в скетч как-то не так.
    Про oneWire не скажу без скетча.
    А про "'state' was not declared in this scope" можно сказать, что получилось употребление переменной state вне области видимости (до объявления или в другом блоке/другой функции). В этом случае определение переменной можно просто вынести в начало скетча, до всех функций. Естественно, определение константы, используемой в объявлении переменной, должно быть еще раньше.
     
  11. Unixon

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

    Выносите опрос датчиков на другой микроконтроллер. Альтернативу в виде слияния вашего главного цикла с алгоритмом OneWire в одном автомате вы вряд ли осилите.

    У вас уже есть бесконечный loop(), зачем вам тут еще один цикл?
     
  12. geher

    geher Гуру

    Если кто-то когда-то написал функцию, то завсегда можно написать другую (или другие), реализующую такие же действия, но чуть по другому.
     
  13. Крапивин

    Крапивин Нерд

    исправил все равно теже ошибки выдает.
     
  14. geher

    geher Гуру

    Без скетча сказать трудно (если вообще возможно).
     
  15. Крапивин

    Крапивин Нерд

    чтобы у него был где то, стоп.
    достаточно считывать данные в течение часа.
    он не должен быть бес конечным.

    как тогда остановить цикл в loop(), через час ?
     
  16. geher

    geher Гуру

    можно просто контролировать время при помощи функции millis и переменных, где фиксируется значение, возвращаемое millis для различных событий (например, начала и завершения какого-то действия, чтобы выполнить противоположное дейтствие спустя какое-то время)
     
  17. Крапивин

    Крапивин Нерд

    в другом варианте цикл считывание показаний с датчиков запускается командой 1.
    останавливается на совсем если нажать , послать любую другую цифру.
    и не продолжает считывать дальше, если не нажата ни одна цифра цикл бесконечный и не останавливается.

    ? возможно ли остановить хотя бы через 1 час ?
     
  18. Крапивин

    Крапивин Нерд

    #include <OneWire.h>
    #include <DallasTemperature.h>
    OneWire oneWire(10); // вход датчиков 18b20
    DallasTemperature ds(&oneWire);

    int x = 0;

    char incomingByte;

    DeviceAddress sensor1 = {0x28, 0x6D, 0x74, 0x23, 0x05, 0x0, 0x0, 0x28};
    DeviceAddress sensor2 = {0x28, 0xB, 0x41, 0x23, 0x05, 0x0, 0x0, 0xF};

    void setup() {
    Serial.begin(38400);
    ds.begin();
    }

    void loop() {

    if (Serial.available() > 0) // управление с телефона
    incomingByte = Serial.read();

    if (incomingByte == '1') { // ждем команды с телефона ( 1 )
    x = 1;
    }


    if (x == 1) {

    ds.requestTemperatures(); // считываем температуру с датчиков




    Serial.print("Temper1 ");
    Serial.print(ds.getTempC(sensor1)); // отправляем температуру
    Serial.println(" *C");

    Serial.println();

    x = 0;

    delay(1000);
    }

    }
     
  19. Unixon

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

    Код (Text):

    #include <OneWire.h>
    #include <DallasTemperature.h>
    OneWire oneWire(10); // вход датчиков 18b20
    DallasTemperature ds(&oneWire);

    DeviceAddress sensor1 = {0x28, 0x6D, 0x74, 0x23, 0x05, 0x0, 0x0, 0x28};
    DeviceAddress sensor2 = {0x28, 0xB, 0x41, 0x23, 0x05, 0x0, 0x0, 0xF};

    #define POLL_INTERVAL 1000
    #define POLL_PERIOD (60*60*1000)

    bool poll_sensor = false;
    unsigned long time_start;
    unsigned long time_poll;

    void setup()
    {
    Serial.begin(38400);
    ds.begin();
    }

    void loop()
    {
    char c = 0;
    if (Serial.available()) c = Serial.read();
    if ('1'==c)
    {
      time_start = millis();
      time_poll = time_start;
      poll_sensor = true;
    }
    else
    {
      if (0!=c) poll_sensor = false;
      if (poll_sensor && ((millis()-time_start)>POLL_PERIOD)) poll_sensor = false;
    }
    if (poll_sensor)
    {
      if ((time_poll==time_start) || ((millis()-time_poll)>POLL_INTERVAL))
      {
       ds.requestTemperatures(); // считываем температуру с датчиков
       Serial.print("Temper1 ");
       Serial.print(ds.getTempC(sensor1)); // отправляем температуру
       Serial.println(" *C");
       Serial.println();
       time_poll = millis();
      }
    }
    }
     
     
  20. Крапивин

    Крапивин Нерд

    sketch_apr12a.ino: In function 'void loop()':
    sketch_apr12a.ino:46:8: error: 'poll_time' was not declared in this scope
    Ошибка компиляции.

    This report would have more information with
    "Отображать вывод во время компиляции"