Прерывания в классе
- Войдите на сайт для отправки комментариев
Нужно отследить сигнал от датчика удара. Во время удара на порты D2 (сильный удар) и D3 (слабый удар) постуавют серии коротких частых импульсов нулевого потенциала. Решил оформить это дело в следующейм объекте:
class Shock {
private:
static volatile byte _st;
static void hi() {
detachInterrupt(0);
_st = 2;
}
static void lo() {
detachInterrupt(1);
_st |= 1;
}
public:
oid reset_() {
_st = 0;
attachInterrupt(0, hi, FALLING);
attachInterrupt(1, lo, FALLING);
}
void disable() {
detachInterrupt(0);
detachInterrupt(1);
}
byte state() {
if (_st == 1)
for (int _t = millis()+100; _t > millis();)
if (_st > 1) return 2;
if (_st > 2) _st = 2;
return _st;
}
};
Shock shock;Что бы не пропустить сигнал повесил на порты прерывания. В main() проверяю не сработал ли датчик вызывая метод shock.state(), затем после обработки (длительное время - десятки секунд) позвращаю объект в мсходное состояние методом shock.reset().
Пробдема 1: Компилятор ругаетсяна "несуществующую переменную shock::_st, которая объявлена вполне себе корректно. Вынес переменную в глобвльные, скомпилилось, по вылезла
Проблема 2: При слабых ударах всё работает коректно, но если удар довольно сильный (много импульсов на обоих портых), цикл main() зависает на в двух вариантах: а) на неопределённое время, риздупляется без внешних воздействий через N-ное количество секунд/минут и б) до следующего (не обязательно первого, бывает и третьего и десятого) сильного удара (длительной серии множественных импульсов на портах).
Кто подскажет решение проблем?
Кто подскажет решение проблем?
Никто, пока не будет полного кода. Как описана _st? Что делается в прерывании? Сколько экземпляров класса создаётся? Всё секретно!
Сделайте короткий, но полный (запускабелтный) код в котором проблема проявляется. Тогда моно будет говорить.
Пока же могу только предположить, что у Вас два эземпляра объекта, так? А переменная _st одна, хотя по логике у каждого экземпляра должна быть совя. Вот экземпляры и гадят друг другу.
И переменная и обработчики прерываний описаны в листинге выше. Экземпляр конечно же один (тоже в листинге).
Зачем вводить прерывание в класс. Сделайте отдельно. Обработчик конкретного прерывания дергает определеный метод определеного класса. И все.
Виноват, не заметил. Но код всё равно нужен, я хочу его запустить и увидеть проблему сам.
Да, кстати, код в строке №24 чреват ошибкой при переходе значения миллис через 0.
//.................................... class Shock { private: static volatile byte _st; // переменная хранения состояния static void hi() { // обработчик сильного удара detachInterrupt(0); _st = 2; } static void lo() { // обработчик слабого удара detachInterrupt(1); _st |= 1; } public: void reset() { // перезапуск слежения за датчиком с обнулением состояния _st = 0; attachInterrupt(0, hi, FALLING); attachInterrupt(1, lo, FALLING); } void disable() { // отключить датчик удара detachInterrupt(0); detachInterrupt(1); } byte state() { // возвращает текеущее состояние if (_st == 1) for (int _t = millis()+100; _t > millis();) // после получения сигнала о слабом ударе if (_st > 1) return 2; // 100мс ждём сигнала о сильном,поскольку в любом случае // сигнал сначала появляется на "слабом" ПИНеif (_st > 2) _st = 2; return _st; } }; Shock shock; //.......................................... void main() { //.......................................... byte shockState = shock.state(); if (shockState != 0) { dispatchAlert("shock", shockState ); shock.reset(); } //.......................................... } // end main //........................................ dispatchAlert(String msg, byte param ) { // позвонить мне на мобилу, сказать что был удар и транслировать // звук с микрофона на объекте, пока я не положу трубку }Зачем вводить прерывание в класс. Сделайте отдельно. Обработчик конкретного прерывания дергает определеный метод определеного класса. И все.
Что бы разгрузить "основной" код программы, ибо там уже сам чорт ногу сломит
Спасибо за совет, но я здесь обратился за другим советом.
class Cl_AAA { public: void bim() {} void bom() {} }; Cl_AAA AAA; void bim() { AAA.bim(); } void bom() { AAA.bom(); } //------------------ void setup() { attachInterrupt(0, bim, CHANGE); attachInterrupt(1, bom, CHANGE); } void loop() { } /**/Через классы код будет похожим, только здесь получится static методы класса
class Cl_AAA { public: static void bim() {} static void bom() {} static void init() { attachInterrupt(0, bim, CHANGE); attachInterrupt(1, bom, CHANGE); } }; Cl_AAA AAA; //------------------ void setup() { AAA.init(); } void loop() { } /**/код в строке №24 чреват ошибкой при переходе значения миллис через 0.
Очень похоже кстати на проблемы с таймером, поскольку тот же диод индикации включенной охранки в основном цикле перстаёт мигать:
void main() { //.............. led.set( armed && ((millis() & 0x3ff) > 0x370) ); //............Можно подробней, что Вы имели в виду?
Можно подробней, что Вы имели в виду?
http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis
Интересное "расследование", положу в копилку )) У меня таких участков кода полно, причём довольно кричичных, например чреватых пожаром. А свою проблему я кажется увидел сам, завтра проверю. Ёмаё, прямо навиду она и никто не обратил внимания. Какой же millis() к чёрту int, это же unsigned long, или dword как я его для себя по привычке переопределяю. И компилятор промолчал же гад.
У вас просто слишком много прерываний возникает, вы об этом не думали? На каждый фронт - прерывание.
В функции обработки прерывание запрещается, см. внимательней скетч.