Таймеры в ардуино (работа с I2C)

Тема в разделе "Проводная и беспроводная связь", создана пользователем Tatyana, 27 фев 2014.

  1. Tatyana

    Tatyana Нуб

    Здравствуйте. Возникли трудности в написании программы (я новичок в этом деле). Надеюсь получить ответ именно здесь. Суть в следующем: Идет сообщение по интерфейсу I2C. Имеется 1 MASTER (М) и 2 SLAVEа (S1, S2). М делает запрос к S1 и S2 по порядку, получает ответ и в зависимости от их состояния совершает определенные действия. Загвоздка в том, что в момент отправки запроса мастером, слейв может отключиться (по некоторым обстоятельствам), т.е. мастер ждет ответа, но ответ не приходит, и он зависает. Вопрос в следующем: можно ли каким-то образом, перед тем как делать запрос к слэйву, включить таймер на время равное максимальному времени прохождения функции по опросу состояния S1, по истечении которого программа продолжалась с проверки S2 (в случае зависания). И остановить таймер при нормальной работе после выполнения мастером действия, соответствующего ответу опрошенного слэйва.
    имеется рабочая программа:

    #include <Wire.h>

    // ----------------НАЗНАЧЕНИЕ ВЫВОДОВ-------------------------------

    int led_fail_1=3; // красный светодиод стенда 1
    int led_ok_1=8; // зеленый светодиод стенда 1
    int led_fail_2=9; // красный светодиод стенда 2
    int led_ok_2=10; // зеленый светодиод стенда 2
    int st_1=4; // работает стенд 1
    int st_2=5; // работает стенд 2
    int TWI_adr_1=3; // адрес опрашиваемого устройства 1
    int TWI_adr_2=3; // адрес опрашиваемого устройства 2
    char now_status;

    void setup()
    {
    // -----------------НАСТРОЙКА ВЫВОДОВ-----------------------------
    pinMode(led_fail_1, OUTPUT);
    digitalWrite(led_fail_1, LOW);
    pinMode(led_ok_1, OUTPUT);
    digitalWrite(led_ok_1, LOW);
    pinMode(led_fail_2, OUTPUT);
    digitalWrite(led_fail_2, LOW);
    pinMode(led_ok_2, OUTPUT);
    digitalWrite(led_ok_2, LOW);
    pinMode(st_1, INPUT_PULLUP);
    pinMode(st_2, INPUT_PULLUP);

    Wire.begin(); // подключаемся по I2C к ведомому устройству
    Serial.begin(9600); // start serial for output
    }

    void loop()
    {
    // ----------------------ОПРОС ПЕРВОГО СТЕНДА---------------------------------------------
    {
    if (digitalRead(st_1)==LOW) // если стенд 1 включен
    {
    Wire.requestFrom(3, 1); // request 1 bytes from slave device #3
    while(Wire.available()) // slave may send less than requested
    {
    char now_status = Wire.read(); // receive a byte as character
    switch(now_status)
    {
    case 0: // если статус ОК
    digitalWrite(led_fail_1,LOW); // гасим красный светодиод
    digitalWrite(led_ok_1,HIGH); // зажигаем зеленый светодиод
    break;
    case 1: // если СДУ<<
    digitalWrite(led_ok_1,LOW);
    digitalWrite(led_fail_1,HIGH);
    delay(250);
    digitalWrite(led_fail_1,LOW);
    delay(250); // мигаем красным светодиодом
    break;
    case 2: // если СДУ>>
    digitalWrite(led_ok_1,LOW); // гасим зеленый светодиод
    digitalWrite(led_fail_1,HIGH);
    delay(250);
    digitalWrite(led_fail_1,LOW);
    delay(250); // мигаем красным светодиодом
    break;
    case 3: // ошибка
    digitalWrite(led_ok_1,LOW); // гасим зеленый светодиод
    digitalWrite(led_fail_1,HIGH); // зажигаем красный светодиод
    break;
    }
    }
    }
    else {
    digitalWrite(led_ok_1,LOW); // гасим зеленый светодиод
    digitalWrite(led_fail_1,LOW); // гасим красный светодиод
    }
    }

    // ----------------------ОПРОС ВТОРОГО СТЕНДА---------------------------------------------
    {
    if (digitalRead(st_2)==LOW) // если стенд 1 включен
    {
    Wire.requestFrom(3, 1); // request 1 bytes from slave device #3
    while(Wire.available()) // slave may send less than requested
    {
    char now_status = Wire.read(); // receive a byte as character
    switch(now_status)
    {
    case 0: // если статус ОК
    digitalWrite(led_fail_2,LOW); // гасим красный светодиод
    digitalWrite(led_ok_2,HIGH); // зажигаем зеленый светодиод
    break;
    case 1: // если СДУ<<
    digitalWrite(led_ok_2,LOW);
    digitalWrite(led_fail_2,HIGH);
    delay(250);
    digitalWrite(led_fail_2,LOW);
    delay(250); // мигаем красным светодиодом
    break;
    case 2: // если СДУ>>
    digitalWrite(led_ok_2,LOW); // гасим зеленый светодиод
    digitalWrite(led_fail_2,HIGH);
    delay(250);
    digitalWrite(led_fail_2,LOW);
    delay(250); // мигаем красным светодиодом
    break;
    case 3: // ошибка
    digitalWrite(led_ok_2,LOW); // гасим зеленый светодиод
    digitalWrite(led_fail_2,HIGH); // зажигаем красный светодиод
    break;
    }
    }
    }
    else {
    digitalWrite(led_ok_2,LOW); // гасим зеленый светодиод
    digitalWrite(led_fail_2,LOW); // гасим красный светодиод
    }
    }
    }

    Заранее спасибо.
     
  2. Unixon

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

  3. alexxx86

    alexxx86 Гик

    Watchdog тут совсем не к месту, в случае зависания он просто перезагрузит дуину.
     
  4. Корней

    Корней Гик

    Существует как минимум одна альтернативная библиотека, "лишенная" такой проблемы
    https://github.com/rambo/I2C
    https://github.com/DSSCircuits/I2C-Master-Library
    Но вот соберется ли она под современной IDE - не знаю.
    Как минимум можно использовать как образец, что бы вправить мозг текущему
    Код (Text):
     // wait for read operation to complete
      while(TWI_MRX == twi_state){
        continue;
      }
    в twi_readFrom https://code.google.com/p/arduino/source/browse/trunk/libraries/Wire/utility/twi.c?r=1092
     
  5. lerik2703

    lerik2703 Гик

    может по аналогии?
    HTML:
    const int ledPin =  13;
    long previousMillis = 0;
    long interval = 10000;

    void setup() {
      pinMode(ledPin, OUTPUT);    
      Serial.begin(9600);

                }

    void loop()
    {
      unsigned long currentMillis = millis();
      while  (!Serial.available())
      {
        if  (millis()-currentMillis > interval)
            break;
      }

      digitalWrite(ledPin, 1);
    }
     
     
  6. Корней

    Корней Гик

    Wire.requestFrom() вызывает twi_readFrom(), который и залипает. Снаружи это не разлепить без манипуляций с указателями стека и инструкции.
    А внутри приведенной библиотеки выполняется "разлипание" как раз показанным вами способом .
     
  7. Корней

    Корней Гик