Тамеры

tatyana_belaya
Offline
Зарегистрирован: 23.02.2014

Здравствуйте. Возникли трудности в написании программы (я новичок в этом деле). Надеюсь получить ответ именно здесь. Суть в следующем: имеется рабочая программа:

 

#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); // гасим красный светодиод
}
}
}

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

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

tatyana_belaya
Offline
Зарегистрирован: 23.02.2014

Здравствуйте. Возникли трудности в написании программы (я новичок в этом деле). Надеюсь получить ответ именно здесь. Суть в следующем: имеется рабочая программа:



#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); // гасим красный светодиод
 }
 }
 }

 

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

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

Garry
Garry аватар
Offline
Зарегистрирован: 07.04.2012

А зависает на Wire.requestFrom(); ?

В twi_readFrom() в twi.c есть 2 цикла:

  // wait until twi is ready, become master receiver
  while(TWI_READY != twi_state){
    continue;
  }

...

  // wait for read operation to complete
  while(TWI_MRX == twi_state){
    continue;
  }

Странно, что если отваливается slave, он что линию не высвобождает? Или зависает в другом месте, а не Wire.requestFrom();?

Гуру, подскажите в чем может быть причина?

 

 

tatyana_belaya
Offline
Зарегистрирован: 23.02.2014

а что вы подразумеваете под TWI_READY, twi_state, TWI_MRX? я же итак использую условие wile(), но программа уже до этого не доходит

Garry
Garry аватар
Offline
Зарегистрирован: 07.04.2012

tatyana_belaya пишет:
а что вы подразумеваете под TWI_READY, twi_state, TWI_MRX? я же итак использую условие wile(), но программа уже до этого не доходит

Хм, вопросм на вопрос, прочтите еще раз мой пост внимательно.

tatyana_belaya
Offline
Зарегистрирован: 23.02.2014

да, зависает именно в этом месте.

Garry
Garry аватар
Offline
Зарегистрирован: 07.04.2012

Что-то не видно помощи девушке...

В общем, можно попробовать переписать эти 2 цикла в неблокирующем виде, с выходом из них по TIMEOUT, который будет передаваться параметром. Странно, что афторы либы не сделали этого сами, но может я чего-то не понимаю в протоколе или либе.