Команда PulseIn

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

Всем доброго вечера.

Решил попробовать наисать небольшой скетч для приема сигнала радиобрелков. Скетч работает, но как то на половину. Т.е. не принимает часть сигнала (пример принятого ниже), как будто через раз. Куда копать? Сама команда PulseIn тормозит или Serial.Print?

Скетч:
unsigned long durationh;
unsigned long durationl;
int pin = 2;
void setup()
{
Serial.begin(115200);
}
void loop()
{
durationh = pulseIn(pin, HIGH);
durationl = pulseIn(pin, LOW);
Serial.print("^"); // Сигнал высокого уровня
Serial.print(durationh);
Serial.print("v"); // Сигнал низкого уровня
Serial.print(durationl);
 
}
 
Результат:
Брелок CAME1
v15720^340v263^344v284^327v279^321v291^361v253^631v260^615v287^607v301^596v547^617v568^598v570^613v565^595
v15707^359v251^335v275^330v284^318v292^368v262^625v271^621v283^598v298^592v537^627v550^611v568^600v570^599
 
Брелок CAME2
v16245^646v574^636v592^631v606^616v301^385v270^348v298^338v606^339v604^617v277^669v288^653v301^335v310^327
v16249^642v590^638v600^629v598^631v301^365v281^355v295^339v624^348v620^607v260^661v289^648v295^338v314^339
 

 

step962
Offline
Зарегистрирован: 23.05.2011

Если бы вы, прежде чем пользоваться функцией PulseIn, прочитали ее описание, то узнали, что:

"Например, если задано считывание HIGH функцией pulseIn(), функция ожидает пока на заданном порту не появиться HIGH. Когда HIGH получен, включается таймер, который будет остановлен когда на порту вход/выхода будет LOW."

То есть с ее помощью вы можете в лучшем случае узнать длину импульса в первой последовательности LOW-HIGH и длину паузы - в третьей. А это значит, что собрать удастся лишь 25% информации.

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

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

Здравствуйте.

Так я же меряю время LOW-HIGH-LOW и HIGH-LOW-HIGH двумя командама Pulsein High и Pulsein Low.

Т.е. при прохождении сигнала ___/--\ должент возврат быть времени импулься высокого уровня, а при наступлении \__/-- должен быть возврат времени низкого уровня.

Или что то я не так понимаю?

 

step962
Offline
Зарегистрирован: 23.05.2011

В первом вызове функции pulseIn(...,HIGH) вы можете замерить продолжительность импульса, который еще не начался к моменту обработки команды. Запущенная функция будет ждать перехода LOW-HIGH, после чего обнулит/запустит таймер и начнет ждать перехода HIGH-LOW, чтобы по значению в таймере рассчитать длительность импульса.

Вторая функция pulseIn(...,LOW) будет запущена лишь после завершения первой, то есть сразу после момента перехода HIGH-LOW (когда необходимый для старта таймерапереход HIGH-LOW - пусть и только-только - уже завершился). И что произойдет в первой фазе исполнения этого нового вызова? Правильно - ожидание момента перехода HIGH-LOW, который наступит только после того, как завершится текущая пауза, сигнал перейдет из состояния LOW в HIGH и наконец-то определится ниспадающий фронт (переход HIGH-LOW). То есть практически полный цикл изменения состояния согнала - псу (коту/козе.слону) под хвост.

 

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

Спасибо, более менее доступно.

Почему то считал что фронты спада, подъема во времени размазаные и должно все успеть сработать.

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

А как вариант digitalRead() использовать? При наступлении значения HIGH включаем счетчик1, при наступлении LOW выключаем счетчик1, включаем счетчик2 и т.д. Не будет таких проблем как с PulseIn?

step962
Offline
Зарегистрирован: 23.05.2011

Trigger63rus пишет:

 При наступлении значения HIGH включаем счетчик1, при наступлении LOW выключаем счетчик1, включаем счетчик2 и т.д. Не будет таких проблем как с PulseIn?

digitalRead подойдет. Необходимо лишь помнить, что на время считывания последовательности мк ничем иным заняться не сможет. Ну и точность пострадает: в случае с прерываниями можно считать с точностью до такта (т.е. 1/16 мкс), то здесь могут быть погрешности в пределах десятков-сотен мкс. Поэтому, может быть, стоит попытаться ознакомится с прямым чтением состояний портов мк.

В общих чертах:

По какому-либо событию обнуляем и запускаем счетчик, присваиваем индексу значение 0. В момент перехода HIGH-LOW считываем значение счетчика в массив результатов (пусть он называется arr) и увеличиваем значение индекса на 1. В момент перехода LOW-HIGH считываем значение счетчика в массив результатов и увеличиваем значение индекса на 1. 

...

Крутимся в этом цикле, пока не надоест / не кончится память, выделенная под массив / не будет получен признак конца последовательности.

После этого начинаем рассчитывать длины импульсов пауз:

Длина n-й паузы/импульса = arr[n+1]-arr[n]

 

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

Здравствуйте.

Всех с наступающим.

Написал скетч:

 
int pin = 2;
long Time1 = 0;
long Time2 = 0;
unsigned long dTime =0;  
 
void setup() {
Serial.begin(9600);
attachInterrupt(0, print, CHANGE);
}
 
void loop() {
Time1 = micros();
dTime=Time1-Time2;
}
 
void print()
{
Time2 = micros();
Serial.println (dTime);
}
 
Отображает время между изменениями. Но только при изменении состояния ноги 2 относительно земли, а относительно +5 вольт реакции нет, что может быть?
Trigger63rus
Offline
Зарегистрирован: 14.02.2014

Соответсвенно на данные с приемника ни как не реагирует.

Trigger63rus
Offline
Зарегистрирован: 14.02.2014
Добавил volatile как это рекомендуется в руководстве и вынес Serial.print, стало срабатывать от приемника, но теперь в порт успевает повторить несколько значений, пока не изменится уровень на входе.
 
int pin = 2;
long Time1 = 0;
volatile long Time2 = 0;
volatile long dTime0 = 0;
unsigned long dTime =0;  
  
void setup() {
Serial.begin(115200);
attachInterrupt(0, print, CHANGE);
}
 
void loop() {
int state=digitalRead(pin);
Time1 = micros();
dTime=Time1-Time2;
if (state==HIGH){
Serial.print("V"); Serial.print (dTime0);
}
if (state==LOW){
Serial.print("^"); Serial.print (dTime0);
}
}
 
void print()
{
Time2 = micros();
dTime0=dTime;
}
 
Trigger63rus
Offline
Зарегистрирован: 14.02.2014

Как привязать вывод serial.print к прерыванию?

anri77
Offline
Зарегистрирован: 01.08.2016

Trigger63rus пишет:

Как привязать вывод serial.print к прерыванию?

так же интересен этот момент...

Если переменная успевает прокидывать в порт несколько одинаковых значение, означает ли это то, что при использовании этой переменной так же будет и в других моментах , например при передачи значений высокого, выдаст несколько раз подряд высокий а потом несколько раз низкий(так же как и залетает в ком порт)?

Подскажите кто сталкивался