Вопрос про внешние прерывания

b612
Offline
Зарегистрирован: 12.03.2017

Подскажите, уважаемые.

Пытаюсь доделать под свои нужды проект.

https://ongroup.ru/energoeffektivnaya_gsm-signalizaciya_na_osnove_arduino_sborka_proshivka_test.html

У него есть большой недостаток - нет обратной связи, т.е. модем не может разбудить ардуину.
Я не долго думая подключил датчик к INT0, а INT1 к TX-у модема, задействовал 0-е и 1-е) прерывание.

...
void wakeUp0(){//обработчик прерывания  
  waked0=true;
  }                          
void wakeUp1(){//обработчик прерывания
  waked1=true;  
  }                          
....
....
   attachInterrupt(0, wakeUp0, CHANGE  );/     // включить прерывание 0
   attachInterrupt(1, wakeUp1, CHANGE  );      // включить прерывание 1

НО
Почему-то при любом дёргании за любую из двух ног ардуины, срабатывают ОБА обработчика прерываний.

Что не так ?

 

 

b707
Offline
Зарегистрирован: 26.05.2017

а дергаете за какие ноги? Вы в курсе, что цифра 0 в коде

attachInterrupt(0, wakeUp0, CHANGE  );

это номер прерывания, а не номер ноги ардуино?

b612
Offline
Зарегистрирован: 12.03.2017

b707 пишет:

а дергаете за какие ноги? Вы в курсе, что цифра 0 в коде

attachInterrupt(0, wakeUp0, CHANGE  );

это номер прерывания, а не номер ноги ардуино?

Да, конечно в курсе.

Ноги D2 = INT0 и D3 = INT1

nik182
Offline
Зарегистрирован: 04.05.2015

Кто ж знает что у вас там в коде? Скажем датчик будит, ардуина обменивается , срабатывает ТХ. Или наоборот - ТХ будит , ардуина опрашивает датчик и.т.д. 

Попробуйте отключить все прерывания внутри прерываний ( не запретить ), перед засыпанием опять проинициализируйте прерывания. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Код секретный? Тогда разбирайтесь с ним сами. Хрустальные шары здесь запрещены. И что за датчик Вы тоже забыли написать.

b612
Offline
Зарегистрирован: 12.03.2017

Ок. благодаря вашим советам была найдена ошибка.
при пробуждении, я выключал подтяжки и из за этого срабатывало второе прерывание.
Теперь другой вопрос.
Если во время бодрствования (прерывания выключены), была активность модема, то после ухода в сон и пробуждения по прерыванию от датчика, срабатывает и обработчик активности модема.
Т.е похоже, что при бодрствовании устанавливается какой-то флаг, который обрабатывается только после ухода в сон и последующего пробуждения.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Код по-прежнему секретный? Ну, тогда по-прежнему разбирайтесь сами.

ven-til
Offline
Зарегистрирован: 13.02.2018

ЕвгенийП пишет:

Код по-прежнему секретный? Ну, тогда по-прежнему разбирайтесь сами.

Ну почему бы не помочь.

b612, похоже, что при бодрствовании устанавливается какой-то флаг, который обрабатывается только после ухода в сон и последующего пробуждения.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ven-til пишет:

Ну почему бы не помочь.

Потому что хрустальные шары запрещены. И нарушая запрет Вы рискуете.

ven-til
Offline
Зарегистрирован: 13.02.2018

Google, как удалить запись на форуме Arduino.ru?

sadman41
Offline
Зарегистрирован: 19.10.2016

Гугл активируется через "OKay, Google. <сюда пишите что надо>"

b612
Offline
Зарегистрирован: 12.03.2017
Никакого секрета, просто не хотел утомлять вас чтением моих каракулей
#include <avr/sleep.h>
#include <SoftwareSerial.h>              // библиотека программного UART
SoftwareSerial gsm(7, 6);                // RX(7), TX(6)

volatile bool waked0=false;
volatile bool waked1=false;
volatile bool tosleep=false;
volatile bool doDial=false;
volatile int8_t incomingByte = 0;
volatile int8_t rejim = 0;
#define _Rejim0 0  // исходный режим
#define _ATcommand 1  // режим прямого ввода AT-команд
#define _SetPinTo 2
#define _SetLEDTo 3

/*ISR (INT0_vect)
  {waked0=true;}
ISR (INT1_vect)
  {waked1=true;}*/
  
void wakeUp0(){//обработчик прерывания  
  waked0=true;
  }                          
void wakeUp1(){//обработчик прерывания
  waked1=true;  
  }                          

///////////////////////////////////////////
void toRejim0(){
  rejim = _Rejim0;  
  Serial.println("");
  Serial.print(">");  
}

void gsmOFF(){                           //
  Serial.println("gsm OFF");
  PORTD|=B00010000;                      // ВЫКЛЮЧЕНИЕ МОДУЛЯ (поднимаем DTR)
  _delay_ms(10);                         //
//  gsm.println("AT+CPWROFF");             // ПЕЧАТАЕМ КОМАНДУ OFF
  gsm.println("AT+CSCLK=2");             // усыпляем модем
  while(1){                              //
    if (gsm.find("OK"))
      {
        Serial.println("AT+CSCLK=2 ok");
        break;          //выходим из цикла
      }
  }  
  PORTB &=~ B00100000;                      // выключить LED 13 
}                                        //
//=========================================
void gsmON(){                            //
  //PORTD|=B01000000;                       // 6-му порту (TX) назначить 1
  PORTD &= ~(B00010000);                  // ЗАПУСК МОДУЛЯ (опускаем DTR)
  _delay_ms(110);                         //
  PORTB |= B00100000;                     // включить LED 13 !!!
  Serial.println(F("gsm ON"));
//  while(!gsm.find("+PBREADY"));         // ждём прочтения тел. книги
//  Serial.println("PBREADY");
  gsm.println(F("AT+CSCLK=0"));             // устанавливаем управление питанием через без DTR
  while(1){                              //
    if (gsm.find("OK"))
      {
        Serial.println(F("AT+CSCLK=0 ok"));
        break;          //выходим из цикла
      }
  }  

  while(1){                              //
    gsm.println(F("AT+CREG?"));             // проверяем в сети ли модуль
    if (gsm.find("0,1"))
      { Serial.println(F("on line? Ok."));
        break;          // если сеть есть, выходим из цикла
      }
    _delay_ms(400);                      // проверка раз в 0,4 сек
    Serial.println(F("off line"));
  }                                      //
}                                        //
///////////////////////////////////////////
                                         //
void sleepNow(){                         // функция засыпания
   Serial.println("sleep");  
   _delay_ms(100);                       //
   Serial.end();
   ADCSRA = 0x00;                        // отключить подсистему АЦП (экономия 140 мкА)
   //UCR = 0x00;                         // отключить UART
   //PORTD &=~ B01000000;                // в вывод TX поставить 0
   PORTD = 0;                            // в вывод TX поставить 0
   DDRD |= B00010000;                    // 4-й вывод - выход на DTR модема), 6-й софтварный TX   
   //digitalWrite(2, HIGH);//включим подтяжку
   //digitalWrite(3, HIGH);//включим подтяжку
   PORTB &=~ B00100000;                      // выключить LED 13 
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // режим сна PWR_DOWN
   attachInterrupt(0, wakeUp0, CHANGE  );// FALLING ); // включить прерывание 0
   attachInterrupt(1, wakeUp1, CHANGE  );      // включить прерывание 1
   sleep_enable();                       // включение возможности сна 
   sleep_mode();                         // сон

   //проснулись
   sleep_disable();                      //
   detachInterrupt(0);                   // отключить прерывания
   detachInterrupt(1);                   // отключить прерывания   
   //digitalWrite(2, LOW);//вЫключим подтяжку
   //digitalWrite(3, LOW);//вЫключим подтяжку
   PORTB |= B00100000;                       // включить LED 13 !!!
   Serial.begin(9600);
   gsm.begin(9600);                        // скорость работы UART   
   Serial.println("Wake");
} 

void setup(){
 gsm.begin(9600);                        // скорость работы UART
 Serial.begin(9600);
 DDRD |= B01010000;                      // 4-й выводы на выход (DTR модема) 6-й софтварный TX
 PORTD &= ~(B00010000);                  // ЗАПУСК МОДУЛЯ (опускаем DTR)
 PORTB |= B00100000;                     // включить LED 13 !!!
 //pinMode(2, INPUT_PULLUP);
 //pinMode(3, INPUT_PULLUP);
 digitalWrite(2, HIGH);//включим подтяжку
 digitalWrite(3, HIGH);//включим подтяжку
 DDRB |= B00100010;                      // вывод 13 на выход (светик) и на звук
 //pinMode(9, OUTPUT);                      //звук
 //gsmON();                                // запуск модуля для теста
 //gsmOFF();                               // выключаем модуль
 }

void loop(){
  if (waked0){                   // если сработало прерывание
      waked0=false;
      Serial.println("INT0");
      //gsmON();//будим модем
      for (uint8_t i=0;i<10;i++)
        {
        digitalWrite(9, HIGH);
        delay(50);
        digitalWrite(9, LOW);
        delay(50);
        }
    }
  else if (waked1)
    {                   // если сработало прерывание
      waked1=false;
      Serial.println("INT1");
      //пискнем
      digitalWrite(9, HIGH);
      delay(100);
      digitalWrite(9, LOW);
    }
  else if (doDial){      
      doDial=false;
      Serial.println("Dial");
      //gsmON(); 
      gsm.println("ATD+79514558448;");   // отзваниваемся, в ответ приходит OK и CONNECT
      _delay_ms(100);
      if (gsm.find("OK")) 
          while(1){                      // ожидание сброса вызова
          gsm.println("AT+CPAS");        // при каждой итерации опрашиваем модуль
          if (gsm.find("0")) break;      // если 0, то выходим из цикла while
          _delay_ms(100);                // проверка раз в 0,1 сек
          }   
      for (char i=0; i<14; i++){
          PORTB|=B00100000;                 // LED 13 ON
          _delay_ms(200);
          PORTB&=~(B00100000);                // LED 13 OFF
          _delay_ms(200);
        }
      //gsmOFF();                          // выключить модуль 
      _delay_ms(10);
      //while(1);                          // блокируем программу*/
  }
  else if (tosleep){
      tosleep=false;
      //gsmOFF(); //усыпляем модем
      sleepNow();                        // укладываем контроллер спать
    }
  else {
  if (gsm.available())           // Ожидаем прихода данных (ответа) от модема...
    {Serial.write(gsm.read());}    // ...и выводим их в Serial    
  if (Serial.available())           // Ожидаем команды по Serial...
    {incomingByte=Serial.read();
    switch (rejim) 
      {
      case _Rejim0: 
        {switch (incomingByte) 
          {case 's': 
            {tosleep=true;
            toRejim0();
            break;
            }
           case 'f': //"f"
            {Serial.println(F("gsm to sleep"));
            gsmOFF();
            break;
            }
           case 'g': //"g"
            {Serial.println(F("gsm to wake"));
            gsmON();
            break;
            }
           case 'a': 
            {rejim=_ATcommand; 
            Serial.print(F("AT>"));
            break;
            }
           case 'd': 
            {rejim=_SetPinTo;
            Serial.print(F("set pin 4 to>"));
            break;
            }
           case 'l': //"L"
            {rejim=_SetLEDTo;
            Serial.print(F("set LED 13 to>"));
            break;
            }
           case 'R': //"R"
            {doDial=true;
            break;
            }
           case 'q': //"q"
            {
            Serial.print(F("portD2 = "));
            Serial.println(digitalRead(2));
            break;
            }
           case 'w': //"w"
            {
            Serial.print(F("portD3 = "));
            Serial.println(digitalRead(3));
            break;
            }
           case 'h': //"h"
            {
            Serial.println(F("a - at commands"));
            Serial.println(F("s - arduino to sleep"));
            Serial.println(F("R - do dial"));
            Serial.println(F("f - gsm to sleep"));
            Serial.println(F("g - gsm to wake"));
            Serial.println(F("f - gsm to sleep"));
            Serial.println(F("l(L) - set LED 13 to .."));
            Serial.println(F("q - read POTTd2"));
            Serial.println(F("w - read POTTd3"));
            break;
            }
           default:      
            {break;}          
          }
         break;
         }
      case _ATcommand: 
        {
        gsm.write(incomingByte);    // ...и отправляем полученную команду модему          
        //Serial.write(incomingByte);
        if (incomingByte == 0x0D)
          {
            toRejim0();
          }
        break;
        }
      case _SetPinTo: 
        {
        if (incomingByte == '1')
          {
            digitalWrite(4, HIGH);
             toRejim0();
          }
        else if (incomingByte == '0')
          {
            digitalWrite(4, LOW);
            toRejim0();
          }
        else 
          {
            toRejim0();            
          }
        break;
        }
      case _SetLEDTo: 
        {
        if (incomingByte == '1')
          {
            digitalWrite(13, HIGH);
             toRejim0();
          }
        else if (incomingByte == '0')
          {
            digitalWrite(13, LOW);
            toRejim0();
          }
        else 
          {
            toRejim0();            
          }
        break;
        }
      default:      
        {break;}    
      }
    }//switch (rejim) 
  }//if (Serial.available())
}

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b612 пишет:

Никакого секрета, просто не хотел утомлять вас чтением моих каракулей

Так все и не надо.

КОгда вопрос нормально готовится, из кода выбрасывается всё лишнее, оставляется только то, что работает и демонстрирует проблему.

В коротком коде люди разберутся и подскажут.

Как-то так.

b612
Offline
Зарегистрирован: 12.03.2017

ЕвгенийП пишет:
Так все и не надо.
похоже attachinterupt как-то замудрёно работает. Надо как-то "вручную" включать прерывания.