Как повысить стабильность работы программы?
- Войдите на сайт для отправки комментариев
Втр, 05/12/2017 - 21:38
Решил сделать систему отслеживающую наличие людей на кухне и при их отсутствии гасящую свет. Вариантов пробовал много и каждый раз после некоторого количества правильных срабатываний происходили кратковременные сбои.
Вот последний скетч:
#include <avr/sleep.h>
int wakePin2 = 2; // Пин используемый для просыпания (прерывания по входу)
int wakePin3 = 3; // Пин используемый для просыпания (прерывания по выходу)
int sleepStatus = 0; // Переменная для хранения статуса (спим, проснулись) - не используется в коде // Счетчик
int LedPin = 13; // Светодиод для оценки состояния процессора
int chel; //количество народа на кухне
volatile int A; //1 если вход 2
volatile int B; //1 если выход 3
unsigned int times = 250000; //временная задержка
void wakeUpNow2() // Прерывание при входе
{
noInterrupts(); //на всякий случай отключаю остальные прерывания
if (sleepStatus) // Если мы спали,
{
sleep_disable(); // то первое, что нужно сделать после просыпания - выключить спящий режим
digitalWrite(LedPin, HIGH); // Включаем светодиод - проснулись
A = 1; //есть вход
sleepStatus = 0;
delayMicroseconds(times); // В переменную заносим статус бодрствования
interrupts(); //разрешаем прерывания
}
}
void wakeUpNow3() // Прерывание при выходе
{
noInterrupts(); //на всякий случай отключаю остальные прерывания
if (sleepStatus) // Если мы спали,
{
sleep_disable(); // то первое, что нужно сделать после просыпания - выключить спящий режим
digitalWrite(LedPin, HIGH); // Включаем светодиод - проснулись
B = 1; // есть выход
sleepStatus = 0; // В переменную заносим статус бодрствования
delayMicroseconds(times); //задержка
interrupts(); //разрешаем прерывания
}
}
void setup()
{
pinMode(LedPin, OUTPUT);
digitalWrite(LedPin, HIGH); // Включаем светодиод
pinMode(wakePin2, INPUT); //вход для перывания по входу
digitalWrite(wakePin2, HIGH); //подтяжка к 5 в.
pinMode(wakePin3, INPUT); //вход для перывания по выходу
digitalWrite(wakePin3, HIGH); //подтяжка к 5 в.
attachInterrupt(0, wakeUpNow2, FALLING); // Используем прерывание 0 (pin 2) для выполнения функции wakeUpNow2 (прерывание вызывается только при смене значения на порту с HIGH на LOW - подтянуть ногу 2 на 5в.)
attachInterrupt(1, wakeUpNow3, FALLING); // Используем прерывание 1 (pin 3) для выполнения функции wakeUpNow3 (прерывание вызывается только при смене значения на порту с HIGH на LOW - подтянуть ногу 3 на 5в.)
pinMode(4, OUTPUT);//выход
pinMode(5, OUTPUT);//1
pinMode(6, OUTPUT);//2
pinMode(7, OUTPUT);//3
pinMode(8, OUTPUT);//4
pinMode(13, OUTPUT);
chel = 0;
digitalWrite(4, HIGH); //гасим свет
}
void sleepNow() // Функция увода ардуины в спячку.
{
digitalWrite(LedPin, LOW); // Выключаем светодиод, процессор спит
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Здесь устанавливается режим сна
sleep_enable(); // Включаем sleep-бит в регистре mcucr. Теперь возможен слип
sleepStatus = 1; // В переменную заносим статус сна
sleep_mode(); // Здесь устройство перейдет в режим сна!!!
// -----------------------------------------------ПОСЛЕ ПРОСЫПАНИЯ ВЫПОЛНЕНИЕ КОДА ПРОДОЛЖИТСЯ ОТСЮДА!!!
}
void loop()
{
delay(500);
if (A == 1) // есть вход
{
chel++;
digitalWrite(4, LOW); // включаем свет
A = 0;
}
if (B == 1) //есть выход
{
chel--;
if (chel <= 0)
{
chel = 0;
digitalWrite(4, HIGH); //выключаем свет
}
B = 0;
}
// дальше для наладки добавил индикацию работы устройства
if (chel == 0)
{
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
}
if (chel == 1)
{ digitalWrite(5, LOW);//синий многоцветный
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
}
if (chel == 2)
{ digitalWrite(6, LOW);//зеленый многоцветный
digitalWrite(5, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
}
if (chel == 3)
{ digitalWrite(7, LOW);//красный многоцветный
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(8, HIGH);
}
if (chel >= 4)
{ digitalWrite(8, LOW); //другой красный
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
}
sleepNow(); // Вызов функции sleep() для засыпания
}
Десяток -другой входов-выходов отрабатывает отлично, вдруг реле издает двойной щелчок и не включается свет и диод показывает отсутствие человека, хотя он прошел. А самое странное, что иногда одновременно загораются два светодиода на ногах 8 и 5 хотя в программе это не возможно.
Как повысить стабильность работы?
Написать её по-человечески.
А прежде, чем публиковать код на форуме, ознакомиться с его (форума) правилами.
А самое странное, что иногда одновременно загораются два светодиода на ногах 8 и 5 хотя в программе это не возможно.
if (chel == 0) { digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(8, HIGH); }if (chel == 2) { digitalWrite(6, LOW);//зеленый многоцветный digitalWrite(5, HIGH); digitalWrite(7, HIGH); digitalWrite(8, HIGH); } if (chel == 3) { digitalWrite(7, LOW);//красный многоцветный digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(8, HIGH); }???
Светодиоды загораются при низком уровне.
Единственный вариант, это сброс устройства. Может быть тут какая нибудь причина кроме перебоев в питании?
Светодиоды загораются при низком уровне.
И откуда это людям знать? Там у вас черт знает что в железе может наворочено, а люди должны тут сидеть код кривой смотреть. Может датчики затеняются или попугай летает там. С делаями все равно не получится чего-то путнего, особенно с прерываниями в которых делай (который поидее не должен в них вообще срабатывать)
к тому же "А" обнуляется в иф, "В" обнуляется за иф, т.е. каждый цикл. Вот если человек выйдет между "}" и "B=0" что будет? "В" установится в 1 и тут же сбросится в 0.
О задержка.
В документации написано, что задержки в микросекундах работают внутри обработчиков прерываний. Но тоже есть странность. Они предполагались для того, чтобы не было прерывания от второго датчика. Сработал датчик входа -прерывания от выходного отключаются на время и наоборот. Казалось бы, чем она больше, тем меньше шансов, чтто за время прохода сработает второй датчик. Так нет. Наиболее стабильно схема работает при задержке в 200000 микросекунд. если поставить больше 300000 или меньше 150000 счетчик работает очень неустойчиво.
Да и еще, если память не изменяет, то даже при запрещенных прерываниях, само событие прерывания все равно наступает, выставляется флаг и оно будет обработано после того как разрешите прерывания.
Спасибо за совет
Почитаю про флаги. Интересно, можно ли во время обработки прерывания очистить флаги от других прерываний.
Я начинающий ардуинщик. Последний раз программировал на бэйсике и ассемблере 30 лет назад. Приобщаю внуков к этой теме. Спасибо.
Проще для начала в прерывании запоминать "момент" когда наступило прерывание "вход" и "выход" и если между ними меньше чем надо то просто в лупе не выполнять соответствующий if и обнулять A или B.
Убрать все делаи, просто убрать и все и копать дальше.