Доброго времени суток Уважаемые Форумчане.
Пишу программу (сигнализатор событий, а проще говоря простенькую сигнализацию) под Arduino PRO mini.
На борту платы модем и датчик на размыкание.
Пока плата питается от LiIon, далее сделаю нормальное питание. (Но питание от батареи должно быть предусмотрено).
У контроллера есть 2 режима работы
1) нормальный, при возникновении события происходит звонок
2) режим глубокого сна, контроллер принимает только команды от модема
Реализовать такой режим работы я попытался отключением прерывания INT1 (на которое приходит сигнал о разрыве цепи )
так вот проблема с которой я столкнулся: контроллер при отключении прерывания INT1 и уходе в сон все равно просыпается при изменении состояния на ноге D3 (INT0) но подпрограмму обработки прерывания алгоритм не заходит. Скорее всего это прерывание (пробуждение) вызвано прерываниями "PCINT" (которые мало известны в среде IDE) попытки отключить прерывания "PCINT" не увенчались успехом.
В примере сделана вырезка отвечающая за работу режима Sleep
Я пытался использовать стандартные библиотеки IDE и библиотеку GyverPower.h, результат один и тот же.
помогите разобраться что я делаю не так. где моя ошибка?
необходимо чтобы при отключенном прерывании INT1 и изменению состоянии ноги D3 контроллер спал.
Пишу программу (сигнализатор событий, а проще говоря простенькую сигнализацию) под Arduino PRO mini.
На борту платы модем и датчик на размыкание.
Пока плата питается от LiIon, далее сделаю нормальное питание. (Но питание от батареи должно быть предусмотрено).
У контроллера есть 2 режима работы
1) нормальный, при возникновении события происходит звонок
2) режим глубокого сна, контроллер принимает только команды от модема
Реализовать такой режим работы я попытался отключением прерывания INT1 (на которое приходит сигнал о разрыве цепи )
так вот проблема с которой я столкнулся: контроллер при отключении прерывания INT1 и уходе в сон все равно просыпается при изменении состояния на ноге D3 (INT0) но подпрограмму обработки прерывания алгоритм не заходит. Скорее всего это прерывание (пробуждение) вызвано прерываниями "PCINT" (которые мало известны в среде IDE) попытки отключить прерывания "PCINT" не увенчались успехом.
В примере сделана вырезка отвечающая за работу режима Sleep
Я пытался использовать стандартные библиотеки IDE и библиотеку GyverPower.h, результат один и тот же.
помогите разобраться что я делаю не так. где моя ошибка?
необходимо чтобы при отключенном прерывании INT1 и изменению состоянии ноги D3 контроллер спал.
режим SLEEP:
#include <SoftwareSerial.h>
#include <GyverPower.h>
//#include <avr/sleep.h>
//#include <avr/power.h>
#define RINGPIN 2
#define DTRPIN 6
#define RSTPIN 9
#define DETECTPIN 3
#define RX_PIN 4
#define TX_PIN 5
#define DETECTLEVELDP CHANGE // уровень детекции пина 3 рост/падение RISING
//RISING (рост) – срабатывает при изменении сигнала на пине с LOW на HIGH
//FALLING (падение) – срабатывает при изменении сигнала на пине с HIGH на LOW
#define DETECTLEVEL HIGH // настраиваем с чем сравнимать детекцию идет в комплекте с предыдущим параметром DETECTLEVELDP CHANGE
//#define TIME_COUNT_BEFORE_SLEEP 55000 // 55 сек
#define TIME_COUNT_BEFORE_SLEEP 10000 // 10 сек
volatile boolean intFlagRing = false; // флаг входящего сообщения от модема
volatile boolean intFlagDetect = false; // Флаг сообщения на RINGPIN (2 нога)
volatile unsigned long interputPINtime; // время для иключения дребезга на входе DETECTPIN
volatile unsigned long TimeCountBeforeSleep; // время покоя модуля преред переходом в спящий режим (сон)
char inSerial[40];
int i = 0;
SoftwareSerial SerialModem(RX_PIN, TX_PIN); // RX, TX
void setup() {
pinMode(DETECTPIN, INPUT_PULLUP); // 3 нога внешнее прерывание INPUT
pinMode(RINGPIN, INPUT); // GSM Ring
pinMode(LED_BUILTIN, OUTPUT); // диод
digitalWrite(RINGPIN, HIGH); // RING включили подтягивающий резистор
digitalWrite(LED_BUILTIN, HIGH); // зажигаем светодиод
//set_sleep_mode(SLEEP_MODE_STANDBY); // Определяем режим сна SLEEP_MODE_STANDBY
//set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Определяем режим сна SLEEP_MODE_PWR_DOWN
power.hardwareDisable(PWR_ADC | PWR_TIMER1); // см раздел константы в GyverPower.h, разделяющий знак " | "
power.setSleepMode(POWERDOWN_SLEEP);
power.bodInSleep(false); // рекомендуется выключить bod во сне для сохранения энергии (по умолчанию false - выключен!!)
// открываем последовательный порт для мониторинга действий в программе
Serial.begin(9600);
while (!Serial) {
}
SerialModem.begin(9600);
while (!SerialModem) {
}
Serial.print("Serial all init OK\r\n");
PCICR |= (0 << PCIE2) | (0 << PCIE1) | (0 << PCIE0); // отключение периваний Pin Change Interrupts, PCINT
PCMSK0 |= (0 << PCINT7) | (0 << PCINT6) | (0 << PCINT5) | (0 << PCINT4) | (0 << PCINT3) | (0 << PCINT2) | (0 << PCINT1) | (0 << PCINT0);
PCMSK1 |= (0 << PCINT14) | (0 << PCINT13) | (0 << PCINT12) | (0 << PCINT11) | (0 << PCINT10) | (0 << PCINT9) | (0 << PCINT8);
PCMSK2 |= (0 << PCINT23) | (0 << PCINT22) | (0 << PCINT21) | (0 << PCINT20) | (0 << PCINT19) | (0 << PCINT18) | (0 << PCINT17) | (0 << PCINT16);
printReg();
delay(50);
EnableDisableWork(true);
interputPINtime = millis();
TimeCountBeforeSleep = millis();
}
void printReg() {
Serial.print(F("wakeUp PCIFR - "));
Serial.print(PCIFR, BIN);
Serial.print(F("; PCICR - "));
Serial.print(PCICR, BIN);
Serial.print(F("; PCMSK0 - "));
Serial.print(PCMSK0, BIN);
Serial.print(F("; PCMSK1 - "));
Serial.print(PCMSK1, BIN);
Serial.print(F("; PCMSK2- "));
Serial.print(PCMSK2, BIN);
Serial.println(F("; "));
}
void wakeUpM() { //пришло прерывание отключаем прерываня от модема, назбудить надо дальше
detachInterrupt(digitalPinToInterrupt(RINGPIN)); //Отключаем прерывания от модема
// проверяем что сработало и ставим флаг
if (digitalRead(RINGPIN) == HIGH) intFlagRing = true;
if (digitalRead(DETECTPIN) == DETECTLEVEL) intFlagDetect = true ;
}
void EnableDisableWork(bool in)
{ //включение выключение прерывание, для включения и выключения радочего режима
Serial.print(F("EnableDisableWork "));
if (in == true) {//wakeUpM
attachInterrupt(digitalPinToInterrupt(DETECTPIN), wakeUpM, DETECTLEVELDP); //Если на 1-вом прерываниии - DETECTLEVELDP, то событие.
//attachInterrupt(digitalPinToInterrupt(DETECTPIN), interputPin, DETECTLEVELDP); //Если на 1-вом прерываниии - DETECTLEVELDP, то событие.
interputPINtime = millis(); // сохранили время для исключения дребезга
Serial.println(F(" true. "));
} else {
detachInterrupt(digitalPinToInterrupt(DETECTPIN)); //Отключаем прерывания
PCICR |= (0 << PCIE2) | (0 << PCIE1) | (0 << PCIE0); // отключение периваний Pin Change Interrupts, PCINT
Serial.println(F(" false. "));
}
}
void EnterSleep() {
intFlagRing = false;
Serial.println(F("\r\nEnterSleep"));
digitalWrite(LED_BUILTIN, LOW); // гасим светодиод
attachInterrupt(digitalPinToInterrupt(RINGPIN), wakeUpM, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
delay(100);
// sleep_enable(); //Разрешаем спящий режим
// sleep_mode(); //Спим (Прерывания продолжают работать.) Программа останавливается.
// sleep_disable(); //Запрещаем спящий режим
power.sleep(SLEEP_FOREVER);
// сюды придет программа после рбработки прерывания wakeUp()
printReg();
delay(50);
digitalWrite(LED_BUILTIN, HIGH); // включаем светодиод
if (intFlagRing == true) {
Serial.print(F("RING PIN, "));
}
if (intFlagDetect == true) {
Serial.print(F("DETECT PIN, "));
}
}
void loop() {
if (intFlagDetect == true) {
intFlagDetect = false;
Serial.print(F("*"));
}
if (millis() - TimeCountBeforeSleep > TIME_COUNT_BEFORE_SLEEP) {
// проверяем сколько счетчик стоит, если долго то уходим в SEEP
EnterSleep();
TimeCountBeforeSleep = millis();// могли долго спать, нужно обновить счетчик
}
// считываем данные с компьютера и записываем их в GPRS Shield
serialPCread();
// считываем данные с GPRS Shield и выводим их в Serial-порт
serialGPRSread();
}
void serialPCread()
{
i = 0;
if (Serial.available() > 0) {
char c;
// если приходят данные по USB
while (Serial.available() > 0) {
inSerial[i] = (Serial.read());
delay(10);
i++;
}
inSerial[i] = '\0';
if (!strcmp(inSerial, "/ENABLE\r\n")) {
Serial.println("_EN");
EnableDisableWork(true);
TimeCountBeforeSleep = millis();
inSerial[0] = '\0';
} else if (!strcmp(inSerial, "/DISABLE\r\n")) {
Serial.println("_DI");
EnableDisableWork(false);
TimeCountBeforeSleep = millis();
inSerial[0] = '\0';
} else SerialModem.print(inSerial);
}
}
void serialGPRSread()
{
if (SerialModem.available() > 0) {
// если приходят данные с GPRS Shield
while (SerialModem.available() > 0) {
// передаём их в терминал
Serial.write(SerialModem.read());
}
}
}