evg

Здесь попробуем организовать прием данных с RF приемника RF433/315MHz китайского производства. В принципе все они работают по схожим принципам и переделать под любой другой не составляем проблемы.

Данный экземпляр приемника имеет 4 вывода:

  • vcc
  • data
  • data
  • gnd

Подаем на vcc 5V, землю на gnd, оба контакта data соеденены и с них снимаем данные.

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

Результатом работы скетча будет таблица с парами значений длительностей "0" и "1" для высокого и низкого уровня. Временные интервалы могут сильно отличаться для разных пультов. Далее необходимо провести анализ протокола и применить его во вотором скетче, который и будет заниматься определением кода нажатой клавиши. Делать будем без применения изысков в виде использования прерываний по входу, а "в лоб" записывая время изменения сигналов.

На выходе сканера получается табличка:

LOWHIGH
0255
0208
6925
6825
6925
6924
2072
6825
2172
6826
......

В таблице хорошо видно начало и конец пакета, постоянная часть пакета и данные. Снимать данные нужно для каждой кнопки и на разных мощностях передатчика(почему-то влияет на длительность).

Сканер



 const int dataSize = 100;  //количество записываемых пар длительностей(ограниченно свободной памятью Arduino)
 byte storedDataH[dataSize];  //массив для значений времени HIGH 
 byte storedDataL[dataSize];  //Массив для значений времени LOW

 int maxSignalLength = 255;   //ограничение на максимальную длительность сигнала(записываем byte поэтому 255)
 int dataCounter = 0;    
 
//используемые для приемника пины
int RFgnd=10; // gnd
int RFvcc=13; // vcc
int RFdata=11;// data


 void setup(){
  Serial.begin(9600);
  
  pinMode(RFgnd,OUTPUT); digitalWrite(RFgnd,LOW);
  pinMode(RFvcc,OUTPUT); digitalWrite(RFvcc,HIGH);
 // pinMode(RFdata+1,INPUT); digitalWrite(RFdata+1,LOW);
  pinMode(RFdata,INPUT); digitalWrite(RFdata,LOW);
  
  while(digitalRead(RFdata)==HIGH){
      //Wait here until a LOW signal is received
  }

cli();// запретим прерываения
  //читаем данные с вывода data и длительности сохраняем в storedDataX

  for(int i=0; i<dataSize; i=i+1){

    //HIGH part
    dataCounter=0; 
    while(digitalRead(RFdata)==HIGH && dataCounter<maxSignalLength){
      dataCounter++;
    }
    storedDataH[i]=dataCounter;

    //LOW part
    dataCounter=0;//reset the counter
    while(digitalRead(RFdata)==LOW && dataCounter<maxSignalLength){
      dataCounter++;
    }
    storedDataL[i]=dataCounter;
  }

sei();//разрешим прерывания

  //Выводим все что приняли в Serial Monitor
  Serial.println("=====================");
  Serial.println("LOW, HIGH");

  for(int i=0; i<dataSize; i=i+2){
    Serial.print(storedDataL[i]);
    Serial.print(",");
    Serial.println(storedDataH[i]);
  }
 }

 void loop(){
   //Do nothing here
 }
  

Второй частью будет написание скетча принимающего команды пульта(передатчика).

Функция listenForSignal считывает dataSize пар значений и собирает их в массиве storedData

Далее последовательно просматривая массив ищем начало пакета. Длительности нулей и единиц определяются эксперементально и определяются функциями getL и getH. Нужно заметить, что при отсутствии несущей частоты передатчика, приемник будет принимать дикий шум :), поэтому необходимо принять меры к четкому определению пакета данных. В данном случае я не анализирую весь пакет, т.к. особого смысла не имеет, а выделяю начало и несколько реперных точек. В моем случае сам пакет состоит из 27 бит. 19 бит постоянная часть, и 8 бит код кнопки.

Берем 8 бит данных кода кнопки, точнее её HIGH часть, и упаковываем в 1 байт. Получаем чистый код кнопки, который и обрабатываем в основном цикле.


const int dataSize = 100;  
 byte storedData[dataSize];  


 int maxSignalLength = 255;   
 int dataCounter = 0;    


int pr = 20;
 #define ERR 100


int RFgnd=10;
int RFvcc=13;
int RFdata=11;

int led = 13;

//////////////////////////////////////////////////////////////////
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);


  pinMode(RFgnd,OUTPUT); digitalWrite(RFgnd,LOW);
  pinMode(RFvcc,OUTPUT); digitalWrite(RFvcc,HIGH);
 // pinMode(RFdata+1,INPUT); digitalWrite(RFdata+1,LOW);
  pinMode(RFdata,INPUT); digitalWrite(RFdata,LOW);

}


 
void loop() {
  const byte num[8]={63,207,15,243,51,195,3,252};
  byte scode;
  // put your main code here, to run repeatedly:
   listenForSignal();
   scode = GetCode();

   if(scode != ERR)  
   {
// Serial.println(scode);    
     switch(scode){
       case 15: Serial.println("[3]");
       delay(10);
       break;
       case 243: Serial.println("[4]"); 
       delay(10);
       break;
       case 51:  Serial.println("[5]");
       delay(10);
       break;
       case 195:  Serial.println("[6]");
       delay(10);
       break;
       case 63:  Serial.println("[1]");
       delay(10);
       break;
       case 207: Serial.println("[2]");
       delay(10);
       break;
       case 3:
         Serial.Serial.println("[7]");
       delay(10);
       break;
       case 252: Serial.print("[8]");         
         delay(500);
       break;
     }

   }

}

  void listenForSignal(){  
cli();
   for(int i=0; i<dataSize; i=i+2){     
      //HIGH
    dataCounter=0;
    while(digitalRead(rfReceivePin)==HIGH && dataCounter<maxSignalLength){
      dataCounter++;
    }
    storedData[i]=dataCounter;

    //LOW part
    dataCounter=0;
    while(digitalRead(rfReceivePin)==LOW && dataCounter<maxSignalLength){
      dataCounter++;
    }
      storedData[i+1]=dataCounter;  
   }
   sei();
  
 }

byte getL(byte n)
{
 return (n==0)?0:((n>=10 && n<=25)?1:((n>=60 && n<=70)?2:ERR));
}

byte getH(byte n){
  return (n>=20 && n<=40)?0:((n>=70 && n<=80)?1:((n>=200)?2:ERR));
}

 byte GetCode(){
   byte ret = 0,l,h;
   int n=0;
   while(n<dataSize){
     if(storedData[n]==0 && storedData[n+1]>=200 && storedData[n+2]==0 && storedData[n+3]>=200) break;
     n++;
   }
   if(n > dataSize-27*2-1) return ERR;
   if(getL(storedData[n+26*2])!=1 || getH(storedData[n+26*2+1])!=2) return ERR;
   n+=18*2;
   for(int i=0;i<8;i++){
     //Serial.print("n1=");Serial.print(storedData[n]);Serial.print(" n2=");Serial.println(storedData[n+1]);
     l = getL(storedData[n]);
     h = getH(storedData[n+1]);
    // Serial.print("l=");Serial.print(l);Serial.print(" h=");Serial.println(h);
     if(l==ERR || h==ERR) return ERR;
     n+=2;
     ret += h<<(7-i);
   }
   return ret;
 }

Коментарии