Ик протокол, декодирование

Deny
Offline
Зарегистрирован: 04.02.2017

Всем доброго времени суток.

Не бейте сразу, понимаю что тема избитая, но как новичек не нашел ответа на просторах интернета.

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


#include <IRremote.h>
int message;
String text;
// выходы, к которым подключены светодиоды
int pins[] = {6, 9, 10, 11};
// уровень сигнала на этих выходах
int signals[] = {0, 0, 0, 0};
int pin = 0;
bool change = false;
IRrecv irrecv(2);
decode_results results;
void setup()
{
Serial.begin(9600);
// при включении мигнем всеми светодиодами, чтобы убедиться что они рабочие
for(int i = 0 ; i < 4; i++){
analogWrite(pins[i], 255);
}
delay(200);
for(int i = 0 ; i < 4; i++){
analogWrite(pins[i], 0);
}
irrecv.enableIRIn();
}
void loop() {
if (irrecv.decode(&results)) {
message = results.value, HEX;
change = false;
switch (message){
// кнопка вверх - увеличиваем сигнал на текущем выходе на 50 до 255
case 0xFF629D: signals[pin]+=50; if(signals[pin] > 255){signals[pin] = 255;} break;
// кнопка вправо - меняем текущий порт прибавляя к нему единицу. Если порты закончились идем заново
case 0xFFC23D: pin++; if(pin > 3){pin = 0;} change = true; break;
// кнопка вверх - уменьшаем сигнал на текущем выходе на 50 до 0
case 0xFFA857: signals[pin]-=50; if(signals[pin] < 0){signals[pin] = 0;} break;
// кнопка вправо - меняем текущий порт уменьшая его на единицу. Если порты закончились идем заново
case 0xFF22DD: pin--; if(pin < 0){pin = 3;} change = true; break;
// кнопки - цифры. задаем цифрой текущий пин
case 0xFF6897: pin = 0; change = true; break;
case 0xFF9867: pin = 1; change = true; break;
case 0xFFB04F: pin = 2; change = true; break;
case 0xFF30CF: pin = 3; change = true; break;
default: change = false;
}
// если текущий порт не был изменен, то меняем мощность на всех диодах
if(!change){
for(int i = 0 ; i < 4; i++){
analogWrite(pins[i], signals[i]);
}
// если был, то мигнем текущим диодом для того чтобы показать на каком именно мы сейчас находимся.
// если уровень ШИМ сигнала больше 150, то мигаем посредством его отключения, если нет, то мигаем посредством включения
} else {
analogWrite(pins[pin], signals[pin] > 150 ? 0 : 255);
delay(200);
analogWrite(pins[pin], signals[pin]);
}
irrecv.resume();
delay(200);
}
}

А теперь вопрос. Как принять и декодировать, а дальше управлять если сигнал не стандартный и имеется только RAW = {5000, 5000, 6000, 8000};

Причем надо принять три таких посылки и тогда выполнится команда и как сделать, чтобы после каждой такой посылк выполнялась своя команда? Заранее спасибо

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Откуда вы такой сигнал получили?

Deny
Offline
Зарегистрирован: 04.02.2017

Это протокол боя! 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Не понял, хрустального шара нету

Deny
Offline
Зарегистрирован: 04.02.2017

ПРотокол инфракрасного  танкового боя, а что от этого как -то меняется  программный код?  Что Вам дает знание откуда такой код?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А зачем его вообще декодировать. Берите прямо raw и сравнивайте. Или я чего-то не понял?

Deny
Offline
Зарегистрирован: 04.02.2017

Привет, Евгений. 

Я в программировании почти ноль.  А мкак произвести сравнение? 

Во всех библиотеках идет сначала декодирование, а потом результат приема сигнала.

Хорошо. допустим  мы получаем данную посылку, как мы поймем, что мы получили именно нужную посылку, а не какую-то левую?

если можно пример кода.

еще раз извините, но я правда тут не очень компетентен.

С уважением.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Нет, Deny, пример кода нужет от Вас, а не от меня. Здесь помогают тем, кто делает сам. Если Вы не может сделать вообще ничего, то запостите Вашу проблему в разделе "Ищу исполнителя", там Вам сделают.

Deny
Offline
Зарегистрирован: 04.02.2017

Выше пример.   а вопрос в том и состоял , что не могупонять как сделать с RAW/  странные Вы люди

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Это не Ваш пример.

Поймите, если Вы будете писать сами - Вам помогут. А писать за Вас ... это в "Ищу исполнителя".

Deny
Offline
Зарегистрирован: 04.02.2017

ВОт мой код, что это меняет! Суть в том что декодеровка RAW не происходит, а значит или надо в библиотеке что-то менять или каким-то образом переделывать луп.

При этом send  работает без проблем



#include <IRremote.h>

IRsend irsend;
int switchPin = 4;
int ledPin = 13;
int RECV_PIN = 1; //пин подключения IR приёмника
IRrecv irrecv(RECV_PIN);
decode_results results;

bool LampState = false;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup()
{
  pinMode(switchPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

void loop()
{
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledOn = !ledOn;
    {
      
     
      int khz = 38; // 38kHz carrier frequency for the NEC protocol


  // ir - Tank
unsigned int irSignal[] =  {5000, 5000, 6000, 8000}; //AnalysIR Batch Export (IRremote) - RAW

irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); //Note the approach used to automatically calculate the size of the array.
delay (30);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
irsend.sendRaw(irSignal2, sizeof(irSignal2) / sizeof(irSignal2[0]), khz); //Note the approach used to automatically calculate the size of the array.
delay (7);
irsend.sendRaw(irSignal3, sizeof(irSignal3) / sizeof(irSignal3[0]), khz); //Note the approach used to automatically calculate the size of the array.
delay (7);
irsend.sendRaw(irSignal4, sizeof(irSignal4) / sizeof(irSignal4[0]), khz); //Note the approach used to automatically calculate the size of the array.
delay (5);
    }
    return lastButton = LOW;
  }
  {
  if (irrecv.decode(&results)) 
  {
    if (results.value == irSignal) //Код кнопки
    {
      LampState = !LampState;
      if (LampState)
      {
        digitalWrite(RELAY_PIN,LOW);
      }
      else
      {
        digitalWrite(RELAY_PIN,HIGH);
      }
    }
    irrecv.resume(); // Получаем следующее значение
  }
}
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Мы с Вами говорим на разных языках. Я Вам говорю, начните делать и Вам помогут. Вы же мне опять стандартынй пример суёте. Что Вы сделали в этом примере, чтобы раскодировать свой пакет? Ничего!

Вы не знаете с чего начинать? Хорошо, я расскажу.

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

Ну и отлично, значит Вам нужно добавить свой декодер. Давайте. Начните с исследования своего протокола. Для этого посмотрите на текст библиотеки. В файле IRRemote.h Вы легко найдёте описание функции decode, оно выглядит так

int   decode     (decode_results *results) ;
 
Прекрасно. Добавьте рядом свою
 
int   decode1     (decode_results *results) ;

Теперь лезем в файл IRRecv.cpp и смотрим как устроена эта самая decode. А устроена она просто. 

int  IRrecv::decode (decode_results *results)
{
	results->rawbuf   = irparams.rawbuf;
	results->rawlen   = irparams.rawlen;

	results->overflow = irparams.overflow;

	if (irparams.rcvstate != STATE_STOP)  return false ;
//..... дальше вызовы декодеров

Отлично. Пишете свою функцию decode1, которая начинается точно также, но не вызывает никаких декодеров, а просто возвращает инстину, если сообщение получено и ложь - если не получено. Примерно вот так:

int  IRrecv::decode1 (decode_results *results)
{
	results->rawbuf   = irparams.rawbuf;
	results->rawlen   = irparams.rawlen;

	results->overflow = irparams.overflow;

	return irparams.rcvstate == STATE_STOP ;
   }  

Теперь всё это сохраняете и в свою 65 строку ставите вызов своеё функции decode1.

Если функция вернула истину, значит results->rawbuf лежит полученная информация, а длина этой информации лежит в results->rawlen.

Отлично, печатаете эту информацию и смотрите на неё при одном входном сигнале, потом при другом. Стараетесь понять что именно приходит при том или ином входном сигнале. Когда поймёте, считайте, что дело сделано - Вы можете распознать пришедшие сигналы и спокойно ими пользоваться.

Вот как-то так. Пробуйте.

Deny
Offline
Зарегистрирован: 04.02.2017

Евгений, вот за это спасибо. Теперь попробую, я же писал что не программер, и естественно тренеруюсь на кошках. Т.е. на стандартных примерах. И с ними проблем нет, а вот когда взялся делать свое и попался не стандартный код начились танцы с бубном. То что надо было лезть в библиотеку я понял, но куда именно ? Теперь, спасибо Вам попытаюсь
сориентироваться.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кстати, Вы навели меня на мысль. У внука есть танки, которые друг по другу стреляют, завтра придёт ко мне заниматься, предложу ему сделать штуковину с батарейкой, чтобы она реагировала на попадание из танка тем. что свигала бы что-нибудь актуатором. Тогда можно будет строить всякие ДОТы, укрытия и т.п., которые будут разрушаться от попадания ИК-снаряда.

Deny
Offline
Зарегистрирован: 04.02.2017

Евгений, именно этим я и занимаюсь сейчас. Доты и прочее.   Мы увлекаемся танками  в 16 масштабе tankspb.com, вот  и решили реализовать укреп район. Полся нестандартный код .

Logik
Offline
Зарегистрирован: 05.08.2014

ЕвгенийП пишет:

А зачем его вообще декодировать. Берите прямо raw и сравнивайте. Или я чего-то не понял?

Как обычно. Нихрена не поняли (и зачем кичится тупостью?! Ну не понял пройди мимо или спроси ..). Восстановить протокол обмена или, что лучше, отождествить его с одним из стандартных принципиально важно. Тогда есть возможность полноценно управлять устройством,  а не слепо повторять принятое, к тому же принятое с ошибками.

Для опознания протокола четырех цифр мало. Даффайте лог всей команды, тогда опознать можна. Учитывайте что полученные длительности всегда с существенной ошибкой.

Deny
Offline
Зарегистрирован: 04.02.2017

Доброго времени суток! Дело в том, что именно это и есть вся команда raw = {5000,5000, 6000,8000}    повторяется она три раза, delay  между повторами где-то 10 .  Вот такая аказия. Эта посылка выверена, так, когда ее отправляешь


51
irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); //Note the approach used to automatically calculate the size of the array.
52
delay (30);      

танк точно распознает и отсчитывает попадания, до полного уничтожения. 

С уважением

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Logik пишет:

Ну не понял пройди мимо или спроси ..)

А я и спросил, если Вы не заметили.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Deny,

у меня для Вас хорошие новости. Если Ваши танки такие же, как у моего внука, то у Вас вообще нет никаких проблем от слова "совсем".

Сейчас он приходил и мы попробовали с ним.

Скетч взяли из примера библиотеки IRremote, ничего в нём не меняли, кроме скорости сериала. Вот он.

#include <IRremote.h>

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(115200);
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Ready ...");
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
  delay(100);
}

В библиотеке тоже ничего не меняли.

Датчик взяли самый обыкновенный - копеечный.

Стали стрелять из танка по датчику. У танка есть два режима огня: одиночный и очередями. Результат:

1. На каждый одиночный выстрел в мониторе порта появлялось число A25313D1

2. При стрельбе очередью в мониторе постоянно лезли числа EC8BD05

Вывод: датчик со стандартной библиотекой вполне вроспринимает обстрел и отличает вид огня. Значит, на этом датчике можно хоть сейчас делать мишень - никаких дополнительных усилий не нужно.

Deny
Offline
Зарегистрирован: 04.02.2017

Евгений, не все так просто. 

Попробуйте этим кодом обстрелять танк, и Вы приятно удивитесь, танк код не поймет. Для обстрела возьмите обчный ИК диод, частота от 36-40 кГц.

Этот метод уже опробован, почему возник вопрос.  Поверьте не все так просто. 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А, так Вам ещё и обстрелять надо. А раньше Вы писали, что только декодировать и я так понял, что нужно только принять выстрел. Нам то как раз нужно именно принять, чтобы сделать мишень, поэтому у нас всё здорово :)

Что касается "обстрелять", попробуйте переставить местами байты. Здесь ведь они печатаются в формате MSBF, попробуйте LSBF

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Deny пишет:

Евгений, не все так просто. 

Попробуйте этим кодом обстрелять танк, и Вы приятно удивитесь, танк код не поймет. Для обстрела возьмите обчный ИК диод, частота от 36-40 кГц.

Этот метод уже опробован, почему возник вопрос.  Поверьте не все так просто. 

А стреляете из чего, пушка, ДШК, СГМТ?

Deny
Offline
Зарегистрирован: 04.02.2017

Пушка,  ик-диод в стволе!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Порядок байтов попробовали?

Deny
Offline
Зарегистрирован: 04.02.2017

Нет, еще не пробовал

Deny
Offline
Зарегистрирован: 04.02.2017

Господа, кто сталкивался с библиотекой IRLib2?

Замечательная библиотека, мне очень понравилась, только на Меге не могу подружить передачу и прием