Логика в операторе IF

Trigger63rus
Offline
Зарегистрирован: 14.02.2014

Всем привет.

Написал небольшой скетч для приема сигнала шлагбаума CAME, но при изменении длительности в команде IF реакция нулевая. Что то с логикой не так?

int rxPin = 2;  
volatile static unsigned long m=0;
volatile long lastLow=0;
volatile long lastHigh=0;
boolean preambula=0;
  
void setup() {
attachInterrupt(0, grab, CHANGE);
Serial.begin(115200);
}
 
void loop() {
 
if (lastLow>11400){preambula=1;lastLow=0;}
if (lastHigh>0&&lastHigh<250){preambula=0;} //Любые изменения ничего не меняют. Если ставить lastHigh>390, зависает.
if (lastHigh>250&&lastHigh<390&&preambula==1){
preambula=0;
lastHigh=0;
Serial.println();
 
for (int k=0;k<24;){
if (lastLow>0)
{Serial.print(lastLow);
Serial.print(",");
lastLow=0;
k=k+1;}
 
if (lastHigh>0)
{Serial.print(lastHigh);
Serial.print(",");
lastHigh=0;
k=k+1;}
}
}
}
 
void grab()
{
    if (digitalRead(rxPin) == HIGH){lastLow=micros()-m;}
    else{lastHigh=micros()-m;}
    m=micros();
}

 

AS
Offline
Зарегистрирован: 12.03.2014

Во-первых, код бы оформить, как принято.

Во-вторых, я не вижу где переменная m инициализированна, и что такое micros().

Далее, может стоит сначала поглядеть, какие значения принимают lastLow и lastHigh, а потом уже совать их в if?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

AS пишет:

Во-первых, код бы оформить, как принято.

Во-вторых, я не вижу где переменная m инициализированна, и что такое micros().

Далее, может стоит сначала поглядеть, какие значения принимают lastLow и lastHigh, а потом уже совать их в if?

великолепно

Trigger63rus
Offline
Зарегистрирован: 14.02.2014

Код простой, не видел смысла описывать работу.

Инициализация volatile static unsigned long m=0;

micros()-команда среды программирования.

lastLow и lastHigh принимают значения совершено любые значения появляющиеся на ноге 2.

Задача как раз и стоит в том, отфильтровать в принятом сигнале начало кодовой посылки пульта CAME. Она начинается с низкого уровня 11400 и последующего высокого 320. При поступлении высокого отличающегося от промежутка 250-390 микросекунд, необходимо изменить preambula на 0. 

 

AS
Offline
Зарегистрирован: 12.03.2014

Про оформление, это я имел ввиду.

Про значения lastLow и lastHigh. Они могут быть какими-то временем от начала работы программы. Соответсвенно, почему бы в цикле loop не запустить монитор и не поглядеть, что именно прилетает в этот loop, когда вы нажимаете кнопку пульта. Ведь значения могут серьезно выпадать за означеный вами коридор. Просто уберите все условия и поглядите, с чем прилетают lastLow и lastHigh.

Trigger63rus
Offline
Зарегистрирован: 14.02.2014

При коде CAME прилетают с интервалами 320/640 микросекунд +- погрешность. а с учетом помех, принимается все от 12 до бесконечности. Вот в IF и хотел отфильтровать.

AS
Offline
Зарегистрирован: 12.03.2014

Так сначала поглядите что реально прилетает а то +\- на МИКРОсекундах может достигать сказочных значений. Это сопоставимо с тактовой частотой самой адуинки, так что сначала поглядеть, какие значения прилетают. Тем более переделать ваш код - легко.

Trigger63rus
Offline
Зарегистрирован: 14.02.2014

Прилетает все что нужно. Этот скетч это отображает. Именно проблема в том что указанная мною строка не выполняет необходимую функцию по отсечению значений менее 250.

AS
Offline
Зарегистрирован: 12.03.2014

Попробуйте каскадировать условия. Не использовать &&, а вводить условия по очереди. 

if(lastHigh>0){
    if(lastHigh<250){preambula=0;}
}

Хотя мне кажется, что if работает как надо, это значения не соответствуют. 

Trigger63rus
Offline
Зарегистрирован: 14.02.2014

В том то и дело что приходит все что нужно, отключив все условия это видно. 

Попробую каскадом. Hо в этом и все удобство операторов сравнения и или нет.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

На счет отладки могу сказать одно, я бы завел массив, элементов на 100 (если памяти хватает), заполнил бы его lastHigh, lastLow, а когда бы он заполнился, выплюнул бы его в Serial, вот тогда и начнется отладка, а так сложно сказать, где лыжи не едут, текст как текст. Вполне вероятно, что значения в lastLow & lastHigh не те, что Вы ожидаете.

И текст лучше отформатировать (Ctrl-T в среде), иначе Вы точно ничего не найдете в коде.

Я бы на Вашем месте не парился, взял бы какой нибудь готовый декодер (программный), например, такой. Но это по желанию.

toc
Offline
Зарегистрирован: 09.02.2013

триггер63, 

добавьте счётчики подходов к.. и входов в if. 

добавьте вывод отладочной информации (в месте где дополнительная задержка некритична).

Trigger63rus
Offline
Зарегистрирован: 14.02.2014

Всем спасибо. Воспользуюсь советами.

leshak
Offline
Зарегистрирован: 29.09.2011

На таких интервалах, пока между тем как вы сделали проверку if, и добрались до serial.print ваши lastLow и lastHigh имееют более чем не призрачные шансы поменятся. И не один раз.

Так что либо, как советовали "в массив", либо запрещать прерывание на момент анализа значений, либо в начале loop(), копируете текущие значение lastLow, lastHigh в какие-то две времененные переменые, которые потом не может изменить прерывание и все if/print пишите с использованием этих двух переменных.

Вообщем держите в уме, что переменные lastXXX в любой момент могут изменить значение.

Trigger63rus
Offline
Зарегистрирован: 14.02.2014

Всем привет.

Спасибо за ответы. Проблема была решена путем помещения всех данных в массив и по окончании вывода его в порт. Заработали все логические связки.

Не думал что Serial.print так медленно работает, что за это время уже значения поменялись.

Иметь бы описание времязотратных команд....

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

http://arduino.ru/forum/obshchii/vremya-na-ispolnenie-raznykh-funktsii

тестировал некоторые функции. может пригодится

leshak
Offline
Зарегистрирован: 29.09.2011

Trigger63rus пишет:

Не думал что Serial.print так медленно работает, что за это время уже значения поменялись.

Медленно. Но в данном случае это не важно. Влияет только на то, насколько быстро вы заметите проблему и насколько легко ее "воспроизвести".

Если у вас есть код, и он может прерватся в ЛЮБОЙ момент (на то он и прерывание), то не важно насколько быстро он выполняется.  Если код не предусматривает подобного развития проблем - жди беды.

Представте что вы красите стену и есть какой-то "шустрик", который в любой момент может подменить вам банку с краской. Играет роль насколько быстро вы красите? За час вы можете покрасить стену или за день? Вам нужно либо запереть дверь, что-бы шустрик не пролез, либо перелить краску в какой-то флакон и не выпускать его из рук. Тогда стена будет одноцветной.

И, кстати, само время выполенения Serial.println - вообще не важно. Раз были проблемы, то значит переменная уже успела испортится на момент его вызова. "Шустрик" успел поработать МЕЖДУ if и println

Trigger63rus пишет:

Иметь бы описание времязотратных команд....

Нет особого смысла. Даже если оно бы и было, то время выполнения одной команды, в реальном коде - не интерестно. А более менее "осмысленного куска" - слишком муторно вычислять, даже если бы была "табличка" для каждой отдельной команды. Гораздо проще взять и померять этот кусок (или переписать код так, что-бы снизить чувствительность к времени его исполнения).

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а можно просто добавить флаг

если флаг 1 шустрик может менять краску, если поменял меняет флаг на 0. маляр просто ждет изменения флага на 0

если флаг 0 маляр красит, покрасил изменил флаг на 1. шустрик ждет изменения флага на 1

никто никому не мешает, просто ждут своей очереди

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

О том leshak и говорил, запретить прерывания в начале loop, считать lastHight, lastLow в локальные переменные, затем снова разрешить прерывания, тем самым запретив изменения между чтением lastHigh, а потом lastLow. Потом в сравнениях использовать только локальные переменные, а не lastHigh, lastLow.

 

ank-sw
Offline
Зарегистрирован: 20.03.2014

Сталкивался с проблеммой длинных чисел. Не корректно обрабатывались, если не указывать явно признак L в присвоении значения.

Попробуйте декларировать так:

volatile static unsigned long m = 0L;
volatile long lastLow = 0L;
volatile long lastHigh = 0L;
 
 
PS
Мой IDE 1.5.5 Mac версия