Считывание посылок от брелка сигнализации

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

 Имеется код, просьба ГУРУ - подсказать где ошибка.

// (c) 2012 tahion
#define rxd     3    // rx data pin
#define rxe     4    // rx enable pin
#define delta   100  // max time delta
#define mintime 100  // min time pulse
unsigned int time,oldtime,count,log0,log1;
byte data[8];
void setup(){
  pinMode(rxd,INPUT);
  pinMode(rxe,OUTPUT);
  digitalWrite(rxe,LOW);
  attachInterrupt(rxd,pinint,CHANGE);
  Serial.begin(115200);
  Serial.println("Starline 64 bit receiver started");
  interrupts();
}
void pinint(){
  if(digitalRead(rxd)==HIGH)oldtime=micros();
  else{
    time=micros()-oldtime;
    if(time<mintime)return;
    if(constrain(time,log0-delta,log0+delta)==time)savebit(false);
    else if(constrain(time,log1-delta,log1+delta)==time)savebit(true);
    else{
      log0=time/2;
      log1=time/4;
      count=0;
    }
  }
}
void savebit(boolean val){
  for(int i=1;i<=8;i++){
    data[i]=data[i]<<1;
    if(i<8)if(bitRead(data[i+1],7))bitSet(data[i],0);
  }
  if(val)bitSet(data[8],0);
  count++;
  if(count==64){
    Serial.print("STARLINE ");
    for(int i=1;i<=8;i++)printhex(data[i]);
    Serial.println("");
  }
}
void printhex(byte val){
  if(val<=0x0F)Serial.print("0");
  Serial.print(val,HEX);
}
void loop(){}

 

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

Nikelbak пишет:

 Имеется код, просьба ГУРУ - подсказать где ошибка.

А с чего вы взяли, что здесь ошибка?

Она себя как-то проявила?

Ну так расскажите обществу - какие симптомы наблюдаются.

 

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

 Да дело тут вот в чем. Не я автор кода. Автор в шапке некий tahion. Устройство предназначено для анализа пакетов отправляемых брелками сигнализации. Вот ссылка на более подробную информацию

http://phreakerclub.com/forum/showthread.php?t=377&highlight=%D0%B0%D1%8...

Автор выкладывает код и говорит что прога рабочая но есть ошибка (сделанная специально), при этом ошибка оч простая и элементарная, нужно только прочесть мануал по программированию ардуины. 

Я вот долго всматривался и разбирал код. По мне так он написан в безобразной стилистике, ну это простимо. Устройства у меня нет чтоб все проверить на деле, но с первого взгляда мне не понятно (исходя из мануала) следущее.

В "attachInterrupt(rxd,pinint,CHANGE);" где rxd задает номер прерывания присваевается номер 3, что соответствует как я понимаю 20 пину на "ардуиноМЕГА", в проекте используется не "мега", это раз. Второе что мне совсем не понятно - переменные объявлены как "unsigned", а исходя из мануала должны быть "volatile". Возможно я просто не вкуриваю. И если не в этом ошибка то в чем она еще может быть.

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

 А, так это квест! ;)

Уже интересно... Бум посмотреть.

Цитата:

присваевается номер 3

=Слушаем поступающую информацию, используя внешнее прерывание INT1.

А есть образчик этой самой поступающей информации? Может там просто-напросто ширина импульса другая?

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

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

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

Nikelbak пишет:

Ну да ))) можно и так сказать))

У девайсов с ATmega328 - это пин 3, у тех, что 1280/2560 - пин 20. Тут все по-честному

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

 хмм значит не в этом проблема, а что с volatile. Хотя нет стоп. В мануале написано что если interupt в функции "attachInterrupt(interrupt, function, mode)" имеет номер 1 то соответственно прерывание будет по пину 3, но тут судя по коду, номер прерывания стоит 3 что соответствует 20 пину в меге. Или все же не так.

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

 Не обязательно, возможно один из if-ов в ISR с подковыркой.

Тут можно действовать методом исключения. Например, сразу исключить из рассмотрения функцию printhex() - все, что в ней делается, это добавляется ведущий 0 для значений<16.

Следующий кандидат на исключение - savebit.

Но тут главное не слишком увлекаться и не выплеснуть в запале такую подлость, как timing:

может быть время обработки отдельного события настолько велико, что вновь поступающие события начинают накладываться на обрабатываемые? Неплохо было бы знать, как часто меняется состояние на входе и сравнить с временем отработки одного бита.  Плюс время отработки одного байта.

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

 Не думаю что все настолько сложно как мне написал автор цитирую

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

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

Nikelbak пишет:

 хмм значит не в этом проблема, а что с volatile. Хотя нет стоп. В мануале написано что если interupt в функции "attachInterrupt(interrupt, function, mode)" имеет номер 1 то соответственно прерывание будет по пину 3, но тут судя по коду, номер прерывания стоит 3 что соответствует 20 пину в меге. Или все же не так.

attachInterrupt - "плохая" функция. На ATMega328 она способна настраивать лишь 2 вектора прерывания из 25 (у 1280/2560 этих векторов побольше и векторов INTx - тоже). Вектор 3 на ATMega328 она не настроит, да и смысла в этом нет, поскольку сигнал приходит на третью ногу, а это - в терминах AVR - пин PD2, отвечающий за внешнее прерывание INT0.

Поэтому для чтения с пина 3 необходимо активировать обработчик прерывания с номером 1.

Вполне приличный кандидат для проверки на ловушки (их таки может быть чуть больше одной). 

ЗЫ: ну да, похоже, действительно, не одна: нога 3 Arduino - это PD3 AVR. или внешнее прерывание INT1, имеющее номер 2. Стало быть:

attachInterrupt(2,pinint,CHANGE);

Или все же 1 (потому что INT1)? Тут надо с обоими вариантами поэкспериментировать или английский вариант описания функции читать, а не русский. Т.е. выяснить, задают для функции в первом параметре номер вектора прерывания (от 1 до 25) или номер внешнего прерывания (0, 1)

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

 Ну, а тройка в любом случае (для UNO/Duemilanove/Nano/...) не подходит.

ЗЫ: почитал английское описание (мутно - тоже говорится о номере прерывания, без акцента на то, вектор прерывания это или номер внешнего прерывания), посмотрел примеры. После примеров ясно/понятно:

нога 2 - прерывание 0 (таки внешнее), соответственно

нога 3 - прерывание 1

 

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

 Значит можно счтитать присвоение прерывания 3 по значению переменной rxd неверно, нужно соответственно заменить в строчке attachInterrupt(rxd,pinint,CHANGE); rxd на цифру 1. Так ведь.

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

Nikelbak пишет:

 Значит можно счтитать присвоение прерывания 3 по значению переменной rxd

константы

Цитата:

неверно, нужно соответственно заменить в строчке attachInterrupt(rxd,pinint,CHANGE); rxd на цифру 1. Так ведь.

Похоже, так.

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

 Да, извиняюсь, константы.  Ладно попробую опубликовать эту версию.

Он там писал что дальше будет загадка помощнее. Итак - наше предположение оказалось верным, программа работает но данные не выводятся, в чем может быть проблема?

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

 Ну во первых, не совсем понятно какой-же мануал читать нужно. Вы уверены что именно на ардуину? Как минимум может подразумеватся "на приемник" и "на передачик", на протокол.

Во вторых, на совсем понятно зачем фнукцаия interrupts(); вызывается (сторка 15).

в мануале про нее написанно "Re-enables interrupts (after they've been disabled by noInterrupts()).", то есть разрешает прерывания ранее запрещенные с помощью noInterrupts(). А его мы выше не видим.  Скорее всего  "обыкновенная перестраховка" и ни на что это не влияет, но....

ewgeniy12
Offline
Зарегистрирован: 12.09.2016

мммнда.... мыслители  всё просто void Loop пустой нет цикла я вроде не спец но видно сразу

negavoid
Offline
Зарегистрирован: 09.07.2016

loop здесь не нужен, всё делает pinint()

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015
// (c) 2012 tahion
#define rxd     3    // rx data pin
#define rxe     4    // rx enable pin
#define delta   100  // max time delta
#define mintime 100  // min time pulse
unsigned int time,oldtime,count,log0,log1;
byte data[8];
void setup(){
  pinMode(rxd,INPUT);
  pinMode(rxe,OUTPUT);
  digitalWrite(rxe,LOW);
  attachInterrupt(1,pinint,CHANGE); //тут надо заменить, потому что прерывания нужно вызывать на  INT1 а мы лезем в INT3
  Serial.begin(115200);
  Serial.println("Starline 64 bit receiver started");
  interrupts();
}
void pinint(){
  if(digitalRead(rxd)==HIGH)oldtime=micros();
  else{
    time=micros()-oldtime;
    if(time<mintime)return;
    if(constrain(time,log0-delta,log0+delta)==time)savebit(false);
    else if(constrain(time,log1-delta,log1+delta)==time)savebit(true);
    else{
      log0=time/2;
      log1=time/4;
      count=0;
    }
  }
}
void savebit(boolean val){
  for(int i=1;i<=8;i++){
    data[i]=data[i]<<1;
    if(i<8)if(bitRead(data[i+1],7))bitSet(data[i],0);
  }
  if(val)bitSet(data[8],0);
  count++;
  if(count==64){
    Serial.print("STARLINE ");
    for(int i=1;i<=8;i++)printhex(data[i]);
    Serial.println("");
  }
}
void printhex(byte val){
  if(val<=0x0F)Serial.print("0");
  Serial.print(val,HEX);
}
void loop(){}