Проблема с приемом (модуль 433мГц)

dude
Offline
Зарегистрирован: 17.03.2017

Всем привет!

У меня есть две Arduino Nano, передатчик(433мГц) и приемник(433мГц).

К одной ардуине подключен передатчик и загружен вот такой скетч:

#define txPin 13

int var=3000, i;

void SendBit(byte b)
 {
  if (b)
   {
    digitalWrite(txPin, LOW);
    delayMicroseconds(640);
    digitalWrite(txPin, HIGH);
    delayMicroseconds(320);
   }
    else
   {
    digitalWrite(txPin, LOW);
    delayMicroseconds(320);
    digitalWrite(txPin, HIGH);
    delayMicroseconds(640);
   }
 }

void Send_preambula(int preambula)
 {
  digitalWrite(txPin, HIGH);
  delayMicroseconds(preambula);
  digitalWrite(txPin, LOW);
 }

void SendPerebor(long Code, unsigned int preambula, unsigned int pilot)
 {
  for(int i=0; i<8; i++)
   { // посылку посылаем 4 раза подряд.
    Send_preambula(preambula); // время стартового импульса
    
    for(int i=12; i>0 ; i--)
     {
      SendBit(bitRead(Code,i-1)); // побитово перебираем и посылаем код
     }

    digitalWrite(txPin, LOW);
    delayMicroseconds(pilot);
   }
  delay(130);
 }

void setup()
 {
  pinMode(txPin, OUTPUT);
  Serial.begin(9600); 
 }
 
void loop()
 {
  Serial.print("Otpravlyaem kod ");
  Serial.print(var);
  Serial.print(" (");
  Serial.print(var, HEX);
  Serial.println(")");
  SendPerebor(var, 320, 11520);
  Serial.println("Zakonchili");
  delay(5000);
 }

Если вкратце, то каждые 5 секунд 8 раз подряд побитово передается число "3000"(HEX: BB8).

К другой ардуине подключен приемник и загружен вот такой скетч:

#define RX 2 
#define TIMER_DIV 

volatile byte level=255; 
volatile unsigned long last, len; 
byte p_level; 
unsigned long p_len, p_len_prev; 

struct  
{  
  uint8_t state;  
  uint8_t data[3], dat_bit;  
} came;  

void set_bit(uint8_t *data, uint8_t n) 
{ 
  data[n/8]|=1<<(n%8); 
} 


#define CM_MAX_TE 450 
#define CM_MIN_TE 250
#define CM_BITS12 12  
#define CM_BITS24 24  

void process_came()  
{  
  unsigned char b;  

  switch(came.state)  
  {  
    case 0:  
      if(p_level) break;  
      came.state=1;  
      break;  

    case 1: //start  
      if(!p_level) break;  

     else if(p_len>=CM_MIN_TE && p_len<=CM_MAX_TE)  
      {  
        came.state=2;  
        came.dat_bit=0;  
        came.data[0]=0x00;  
        came.data[1]=0x00;  
        came.data[2]=0x00;  
         
      }  
      else came.state=0;  
         
      
    
    case 2: //dat  
      if(p_level)  
      {  
        if(came.dat_bit==CM_BITS24)  
        {  
          came.state=0;  
          break;  
        }  

        if(p_len_prev<=CM_MAX_TE && p_len_prev>=CM_MIN_TE &&  
           p_len<=CM_MAX_TE*2 && p_len>=CM_MIN_TE*2) b=0;  
         else  
        if(p_len_prev<=CM_MAX_TE*2 && p_len_prev>=CM_MIN_TE*2 &&  
           p_len<=CM_MAX_TE && p_len>=CM_MIN_TE) b=1;  
         else  
        {  
          came.state=0;  
          break;  
        }  

        if(b) set_bit(came.data, came.dat_bit);  
        came.dat_bit++;  
        break;  
      }  
       else  
      {  
        if((p_len>5000)&&(came.dat_bit==CM_BITS12 || came.dat_bit==CM_BITS24)) came.state=100;  
      }  
      break;  
  }  
}   

void dump_hex(byte *buf, byte bits) 
{ 
byte b; 

for(b=0; b>(bits+7)/8; b++) 
{ 
if(buf[b]>0x0f) Serial.print('0'); 
Serial.print(buf[b], HEX); 
Serial.print(" "); 
} 
Serial.println(""); 
} 

void rx_int() 
{ 
if(level!=255) return; 

len=micros()-last; 
last=micros(); 

if(digitalRead(RX)==HIGH) level=0; 
else level=1;  
} 

void setup() 
{  
attachInterrupt(0, rx_int, CHANGE); 

Serial.begin(115200);  
while(!Serial); 

Serial.println("PRIEM"); 
Serial.println(""); 

interrupts(); 
}  

byte b; 

void loop() 
{  
if(level!=255) 
{ 
noInterrupts(); 
p_level=level; 
p_len=len; 
len=0; 
level=255; 
interrupts(); 

process_came(); 

p_len_prev = p_len; 
} 


if(came.state==100) 
{  
Serial.print(came.data[0],HEX); 
Serial.print(came.data[1],HEX); 
//Serial.print(came.data[2],HEX);
Serial.print("came["); 
Serial.print(came.dat_bit); 
Serial.print("]: "); 
dump_hex(came.data, came.dat_bit); 
came.state=0; 
} 
}  

Он побитово принимает код и выводит в 16-ной системе счисления.

Теперь сама проблема: почему-то код принимается неправильно(или выводится). То есть отправляется "BB8", а приходит "DD1". И так со всеми кодами.

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

Правильный код приходит только тогда, когда отправляешь код "4095"(HEX: FFF).

И есть еще одна проблема: почему-то не принимаются коды от 1 до 2047. Ну это пока что не важно, так как для начала нужно сделать, чтобы правильно принимался(или отображался) код.

Вообщем, помогите, пожалуйста, исправить мою проблему, а то у меня уже мыслей не осталось, все уже перепробовал.

Только не предлагайте использовать библиотеки - они не подходят для реализации задуманного.

Заранее спасибо!

dude
Offline
Зарегистрирован: 17.03.2017

arDubino
Offline
Зарегистрирован: 12.01.2017

может просто надо передавать строку и примать строку. т.е. типы данных должны быть одни и теже

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

У вас криво организован МАнчестер 2 https://youtu.be/NaaG90--n4E?t=517

dude
Offline
Зарегистрирован: 17.03.2017

Не очень понял. Передается последовательность нулей и единиц, и принимается тоже последовательность.

Если имеется ввиду "тип переменной"(типа integer, double, char), то нет, так как приемник каждый импульс по отдельности принимает, а как я хранить буду принятые данные(в переменной какого типа) - это уже не важно.

dude
Offline
Зарегистрирован: 17.03.2017

Довольно-таки интересная лекция, спасибо.

Но вопрос остался, так как там все завязано на напряжение: то есть если напряжение не равно 1/2, то следовательно параллельно пришел еще какой-то пакет. А как проверять на это самое напряжение?

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Блин вот у вас передатчик и приемник . Вкл выкл.   Пусть посылка будет в 1 бит /=\     длительность 640 это 1  320 это 0    если больше это ошибка или начало пакета . Ясно!?   Передаем посылку в 2, 3 бита  /=\=/=\    где  /1\2/3\ последовательность . Если 2 бита в посылке то 3 бит в последовательности  это 0 . Надо же выключить передатчик в конце посылки , а не ждать след пакета .   Передача байта (8 бит)  /1\2/3\4/5\6/7\8/=\    Где = это стоповый бит, пусть будет 0 , ноль короче 1 . Ну а дальше  если длительность больше 640 это или ошибка или ждать начало нового пакета.  Вот такой принцип легче программировать на прием и на передачу.

dude
Offline
Зарегистрирован: 17.03.2017

Да, я себе это так и представлял. Так 640(320) - это же задержка. И получается, что она не всегда будет равна этим значениям, так как что-то может повлиять на время передачи, или же приемник или передатчик будут двигаться.

Правильно я понимаю, что нужно взять границу побольше на всякий случай?(то есть вместо 640 взять, допустим, 740. А вместо 320 - 420)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Скорее 640+-64 это 1  а 320+- 32 это 0  . А иначе это помехи, и принятый пакет в отбой.  У вас же канал в одну сторону . отправляйте 4 раза одно и тоже . Приемник пусть анализирует это повтор старого или новая посылка.  

dude
Offline
Зарегистрирован: 17.03.2017

Спасибо большое. Вроде бы разобрался.

Попробуй сам написать, а то в этом разбираться не очень хочется)

201bazza
Offline
Зарегистрирован: 04.02.2020

Здравствуйте, товарищи! Сижу уже неделю с такой же проблемой. Не могу понять что не так с кодом. У меня в передатчике немного другой код:

#include <VirtualWire.h>
 
#define txPin 3 // цифра 3 - это номер ноги, к которой подключается контакт data передатчика.
#define Te 320 
const int led_pin = 13;//сигнальный светодиод
 
void setup(){
  pinMode(txPin, OUTPUT); // настраиваем ногу txPin, т.е. ногу №3 как выход
}
 
void loop()
{
 SendCame(0b101010101010101010101010);
}
void SendCameBit(byte b) // 0 передается 2-мя высокими интервалами, 1-м низким интервалом
{
  delayMicroseconds(Te);
  if (!b) digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,LOW);
}
 
void SendCame(long Code)
{  
  digitalWrite(led_pin, HIGH); // Зажигаем светодиод в начале передачи   
  for (int j=0;j<4;j++) // посылку посылаем как и брелок - 4 раза подряд.
  {
    digitalWrite(txPin,HIGH);
    delayMicroseconds(Te);
    digitalWrite(txPin,LOW);// посылаем стартовый импульс
    for (byte i=24;i>0;i--)
    {
      SendCameBit(bitRead(Code, i-1)); // побитово перебираем и посылаем код
    }
    delay(10); //здесь большое значение времени >300 вообше не дает пройти сигналу. Почему?
  }
  vw_wait_tx(); // Ожидаем окончания отправки сообщения
  digitalWrite(led_pin, LOW); // Гасим светодиод в конце передачи
  delay(1500); // сделать паузу после посылки на 0,05 с
}