miercuri, 25 septembrie 2013

Module de transmisie/receptie radio si... Arduino

    Desi am achizitionat de ceva timp o pereche de emitator/receptor pentru frecventa de 433MHz, abia acum am reusit sa fac niste teste.
   Emitatorul are codul MX-FS-03V, iar receptorul MX-05...
   Libraria care se foloseste uzual se numeste VirtualWire.
Eu m-am inspirat din 2 articol despre care unul se gaseste la pjrc.com:
iar celalalt la buildcircuit.com.
   Am folosit 2 placi Arduino, una chinezeasca pe post de receptor si una facuta de mine (Arduiniq sau Arduino de casa), pe post de emitator:
   Schema de conectare este:
   Trebuie retinut ca placa care este conectata cu modul de emisie transmite pe pinul digital 12 (D12), iar cea care este conectata cu modulul receptor primeste datele pe pinul digital 11 (D11).
   In primele teste am costatat ca modulele fara antena pot comunica pe distanta foarte mica (de ordinul centimetrilor), asa ca am improvizat cate o antena din agrafe de birou, distanta de comunicare stabila crescand la cca. 9m:
   Pentru emitator am folosit sketch-ul:
 /*  
 SimpleSend  
 This sketch transmits a short text message using the VirtualWire library  
 connect the Transmitter data pin to Arduino pin 12  
 See more at: http://www.buildcircuit.com/how-to-use-rf-module-with-arduino/#sthash.cUJ8ndxT.dpuf  
 adapted sketch by niq_ro from http://nicuflorica.blogspot.com  
 */  
 #include <VirtualWire.h>  
 const int led_pin = 13;  
 void setup()  
 {  
 // Initialize the IO and ISR  
 vw_setup(2000); // Bits per sec  
 }  
 void loop()  
 {  
 digitalWrite(led_pin, HIGH); // Flash a light to show transmitting  
 send("Salut, Nicu!");  
 delay(1000);  
 }  
 void send (char *message)  
 {  
 vw_send((uint8_t *)message, strlen(message));  
 vw_wait_tx(); // Wait until the whole message is gone  
 digitalWrite(led_pin, LOW); // Flash a light to show transmitting  
 }  

iar pentru receptor:
 /*  
 SimpleReceive  
 This sketch displays text strings received using VirtualWire  
 Connect the Receiver data pin to Arduino pin 11  
 //- See more at: http://www.buildcircuit.com/how-to-use-rf-module-with-arduino/#sthash.cUJ8ndxT.dpuf  
 // modified sketch by niq_ro ( http://nicuflorica.blogspot.com )  
 */  
 #include <VirtualWire.h>  
 byte message[VW_MAX_MESSAGE_LEN]; // a buffer to store the incoming messages  
 byte messageLength = VW_MAX_MESSAGE_LEN; // the size of the message  
 void setup()  
 {  
 Serial.begin(9600);  
 Serial.println("Receptorul e pregatit sa primeasca mesaje...");  
 // Initialize the IO and ISR  
 vw_setup(2000); // Bits per sec  
 vw_rx_start(); // Start the receiver  
 }  
 void loop()  
 {  
 if (vw_get_message(message, &messageLength)) // Non-blocking  
 {  
 Serial.print("Am receptionat mesajul: ");  
 for (int i = 0; i < messageLength; i++)  
 {  
 Serial.write(message[i]);  
 }  
 Serial.println();  
 }  
 }  

26.09.2013
   Am gasit un articol frantuzesc bun la skyduino.wordpress.com despre transmisia care foloseste aceeasi librarie.
   Dupa ce am inceput sa ma joc cu textul de transmis, pana la maximul din documentatie (27 caractere), am constatat ca apar probleme de transmisie... aparand erori, de fapt trunchieri ale mesajului.

 

 
 
 
   Am conectat si direct modulele prin fire (masa si firul de transmisie/receptie) pentru a depista problema...
   Am ajuns la concluzia ca textele de 5-8 caractere sunt transmise si receptionate bine, dar din cand in cand e bine sa opresc partea de receptie si s-o repornesc dupa 25 de mesaje, asa cam sketch-ul arata cam asa:
 /*  
 SimpleReceive  
 This sketch displays text strings received using VirtualWire  
 Connect the Receiver data pin to Arduino pin 11  
 //- See more at: http://www.buildcircuit.com/how-to-use-rf-module-with-arduino/#sthash.cUJ8ndxT.dpuf  
 // modified sketch by niq_ro ( http://nicuflorica.blogspot.com )  
 */  
 #include <VirtualWire.h>  
 uint8_t message[VW_MAX_MESSAGE_LEN]; // a buffer to store the incoming messages  
 // byte message[VW_MAX_MESSAGE_LEN]; // a buffer to store the incoming messages  
 uint8_t messageLength = VW_MAX_MESSAGE_LEN; // the size of the message  
 //byte messageLength = VW_MAX_MESSAGE_LEN; // the size of the message  
 int led = 13;  
 int j=0; // count received message;  
   
 void setup()  
 {  
 pinMode(led, OUTPUT);   
 Serial.begin(9600);  
 Serial.println("Receptorul e pregatit sa primeasca mesaje...");  
 // Initialize the IO and ISR  
 vw_setup(2000); // Bits per sec  
 vw_rx_start(); // Start the receiver  
 }  
 void(* resetFunc) (void) = 0; //declare reset function @ address 0  
      
 void loop()  
 {  
 if (vw_wait_rx_max(200)) // Si un message est reçu dans les 200ms qui viennent  
   {  
 if (vw_get_message(message, &messageLength)) // Non-blocking  
 {  
 vw_wait_rx();  
 digitalWrite(led, HIGH);    
 j=j++;  
 Serial.print("Am receptionat mesajul, ");  
 Serial.print(j);  
 Serial.print(" din ");  
 Serial.print(messageLength);  
 Serial.print("/");  
 Serial.print(VW_MAX_MESSAGE_LEN);  
 Serial.print(" caractere: ");  
 for (int i = 0; i < messageLength; i++)  
 {  
 Serial.write(message[i]);  
 }  
 Serial.println();  
 digitalWrite(led, LOW);  
   
 if (j>25) // if received 25 messages, stop the receiver  
 {  
 vw_rx_stop(); // Stop the receiver  
 //delay (500);  
 //Serial.end();  
 //Serial.begin(9600);  
 Serial.println("Receptorul e pregatit iar sa primeasca mesaje...");  
 vw_setup(2000); // Bits per sec  
 vw_rx_start(); // Start the receiver  
 
 j=0;  
    }  
   }  
  }  
 }  
   

 
   Am adaugat si o resetare automanata dupa 150 de mesaje pentru a elimina cat mai mult posibilitatea primirii de mesaje false:
 /*  
 SimpleReceive  
 This sketch displays text strings received using VirtualWire  
 Connect the Receiver data pin to Arduino pin 11  
 //- See more at: http://www.buildcircuit.com/how-to-use-rf-module-with-arduino/#sthash.cUJ8ndxT.dpuf  
 // modified sketch by niq_ro ( http://nicuflorica.blogspot.com )  
 */  
 #include <VirtualWire.h>  
 uint8_t message[VW_MAX_MESSAGE_LEN]; // a buffer to store the incoming messages  
 // byte message[VW_MAX_MESSAGE_LEN]; // a buffer to store the incoming messages  
 uint8_t messageLength = VW_MAX_MESSAGE_LEN; // the size of the message  
 //byte messageLength = VW_MAX_MESSAGE_LEN; // the size of the message  
 int led = 13;  
 int j=0; // count received message;  
 int k=0; // count received message for master reset;  
   
 void setup()  
 {  
 pinMode(led, OUTPUT);   
 Serial.begin(9600);  
 Serial.println("Receptorul e pregatit sa primeasca mesaje...");  
 // Initialize the IO and ISR  
 vw_setup(2000); // Bits per sec  
 vw_rx_start(); // Start the receiver  
 }  
 void(* resetFunc) (void) = 0; //declare reset function @ address 0  
   
   
 void loop()  
 {  
 if (vw_wait_rx_max(200)) // Si un message est reçu dans les 200ms qui viennent  
   {  
 if (vw_get_message(message, &messageLength)) // Non-blocking  
 {  
 vw_wait_rx();  
 digitalWrite(led, HIGH);    
 j=j++;  
 k=k++;  
 Serial.print("Am receptionat mesajul, ");  
 Serial.print(k);  
 Serial.print(" din ");  
 Serial.print(messageLength);  
 Serial.print("/");  
 Serial.print(VW_MAX_MESSAGE_LEN);  
 Serial.print(" caractere: ");  
 for (int i = 0; i < messageLength; i++)  
 {  
 Serial.write(message[i]);  
 }  
 Serial.println();  
 digitalWrite(led, LOW);  
   
 if (j>25) // if received 25 messages, stop the receiver  
 {  
 vw_rx_stop(); // Stop the receiver  
 //delay (500);  
 //Serial.end();  
 //Serial.begin(9600);  
 Serial.println("Receptorul e pregatit iar sa primeasca mesaje...");  
 vw_setup(2000); // Bits per sec  
 vw_rx_start(); // Start the receiver  
   
 j=0;  
 }  
 if (k>150)  
 {  
 Serial.println("resetting");  
  resetFunc(); //call reset  
  /*  
  http://www.instructables.com/id/two-ways-to-reset-arduino-in-software/step2/using-just-software/  
  */  
 }  
   
 }  
   }  
 }  
   
   Distanta maxima de comunicare este de cca. 16m, pentru transmisia la 2000 bps intr-o cladire pe structura metalica si pereti din rigips si BCA... destul de putin fata de cat se prezinta pe net... 

   Trebuie sa incerc si varianta transmisiei seriale cum e prezentat la hobby robotics:
sau la Sparkfun...
 /*  
 * Simple Transmitter Code  
 * This code simply counts up to 255  
 * over and over  
 * (TX out of Arduino is Digital Pin 1)  
 */  
 byte counter;  
 void setup(){  
 //2400 baud for the 434 model  
 Serial.begin(2400);  
 counter = 0;  
 }  
 void loop(){  
 //send out to transmitter  
 Serial.print(counter);  
 counter++;  
 delay(10);  
 }  
respectiv:
 /*  
 * Simple Receiver Code  
 * (TX out of Arduino is Digital Pin 1)  
 * (RX into Arduino is Digital Pin 0)  
 */  
 int incomingByte = 0;  
 void setup(){  
 //2400 baud for the 434 model  
 Serial.begin(2400);  
 }  
 void loop(){  
 // read in values, debug to computer  
 if (Serial.available() > 0) {  
 incomingByte = Serial.read();  
 Serial.println(incomingByte, DEC);  
 }  
 incomingByte = 0;  
 }  
    Am testat aceste 2 sketch-uri, prin care Arduino de casa transmite necodat numere de la 0 la 255 din cand in cand pe Tx (am modificat sa transmita mai rar), iar Arduino Uno primeste pe pinul Rx si am constatat ca primesc numere mereau, am deconectat emitatorul meu si numerele aleatoare sunt primite, asa am realizat ca si ce am testat eu intial este influentat de "celalalt" emitatorul... care nu-i al meu... 

27.09.2013
   Rasfoind forumul Arduino am regatit o discutie despre transmiterea, respectiv receptia mai multor valori pe unde radio, iar de acolo se facea trimitere la Control Robotics... mentionez ca se foloseste tot libraria Wirtualwire.
 
   Am adaptat un pic sketch-urile de acolo pentru a aprinde LED-urile de la D13 cand transmit, respectiv primesc date, iar datele de transmitere sunt alese aleator de mine (0, 1023, 255, 725).

 /*.............................................................  
 Sending Multiple Variables Using VirtualWire. Transmitter  
 Author: Rodrigo Mompo Redoli  
 For controlrobotics.rodrigomompo.com  
 ..............................................................*/  
 #include <VirtualWire.h>  
 int Sensor1Pin = A1;// The pins were sensor are attached  
 int Sensor2Pin = A2;  
 int Sensor3Pin = A3;  
 int Sensor4Pin = A4;   
 int ledPin = 13;  
 int Sensor1Data;// The variable were the data from each sensor  
 int Sensor2Data;// will be stored   
 int Sensor3Data;  
 int Sensor4Data;  
 char Sensor1CharMsg[21];// The string that we are going to send trought rf   
 void setup() {  
  // LED   
  pinMode(ledPin,OUTPUT);  
  // Sensor(s)  
  pinMode(Sensor1Pin,INPUT);  
  pinMode(Sensor2Pin,INPUT);  
  pinMode(Sensor3Pin,INPUT);  
  pinMode(Sensor4Pin,INPUT);  
  // VirtualWire setup  
  vw_setup(2000); // Bits per sec  
  vw_set_tx_pin(12);// Set the Tx pin. Default is 12  
 }  
 void loop() {  
  // Read and store Sensor Data or put a predefined values (min=0, max=1023, 255, 725)
  /*  
  Sensor1Data = analogRead(Sensor1Pin);  
  Sensor2Data = analogRead(Sensor2Pin);  
  Sensor3Data = analogRead(Sensor3Pin);  
  Sensor4Data = analogRead(Sensor4Pin);  
  */  
  Sensor1Data = 0;  
  Sensor2Data = 1023;  
  Sensor3Data = 255;  
  Sensor4Data = 725;  
  sprintf(Sensor1CharMsg, "%d,%d,%d,%d,", Sensor1Data, Sensor2Data, Sensor3Data, Sensor4Data);  
  // Turn on a light to show transmitting  
  digitalWrite(ledPin, HIGH);  
  vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));  
  vw_wait_tx(); // Wait until the whole message is gone  
  // Turn off a light after transmission  
  delay(200);  
  digitalWrite(ledPin, LOW);  
  delay(2000);  
 }  
respectiv
 /*.............................................................  
 Sending Multiple Variables Using VirtualWire. Receiver  
 Author: Rodrigo Mompo Redoli  
 For http://controlrobotics.rodrigomompo.com  
 adapted sketch by niq_ro (Nicu FLORICA) from http://nicuflorica.blogspot.com  
 ..............................................................*/  
 #include <VirtualWire.h>  
 // Sensors   
 int Sensor1Data;  
 int Sensor2Data;  
 int Sensor3Data;  
 int Sensor4Data;  
 char StringReceived[22];   
 int led = 13;   
 void setup() {  
 pinMode(led, OUTPUT);   
 Serial.begin(9600);  
 Serial.println("Receptorul lui niq_ro e pregatit sa primeasca mesaje...");   
  // VirtualWire   
   // Initialise the IO and ISR  
   // Required for DR3100  
   // Bits per sec  
   vw_setup(2000);  
   vw_set_rx_pin(11);   
   // Start the receiver PLL running  
   vw_rx_start();      
 } // END void setup  
 void loop(){  
   uint8_t buf[VW_MAX_MESSAGE_LEN];  
   uint8_t buflen = VW_MAX_MESSAGE_LEN;  
 //Taking the data from the control base  
   if (vw_get_message(buf, &buflen))   
   {  
    digitalWrite(led, HIGH);    
  int i;  
     // Message with a good checksum received, dump it.   
     for (i = 0; i < buflen; i++)  
  {        
      // Fill Sensor1CharMsg Char array with corresponding   
      // chars from buffer.    
      StringReceived[i] = char(buf[i]);  
      Serial.print(StringReceived[i]);  
  }  
    sscanf(StringReceived, "%d,%d,%d,%d,%d,%d",&Sensor1Data, &Sensor2Data,&Sensor3Data,&Sensor4Data); // Converts a string to an array  
 Serial.println();  
 digitalWrite(led, LOW);      
     // Turn off light to and await next message   
   }  
  memset( StringReceived, 0, sizeof( StringReceived));// This line is for reset the StringReceived  
 }  

Schema de conexiune, pentru citirea a 4 valori analogice este:
si trebuie scoase ghilimele de le-am pus eu la citirea intrarilor analogice si mutate la cele predefinite:

void loop() {  
  // Read and store Sensor Data or put a predefined values (min=0, max=1023, 255, 725)
  /*  
  Sensor1Data = analogRead(Sensor1Pin);  
  Sensor2Data = analogRead(Sensor2Pin);  
  Sensor3Data = analogRead(Sensor3Pin);  
  Sensor4Data = analogRead(Sensor4Pin);  
  */  
  Sensor1Data = 0;  
  Sensor2Data = 1023;  
  Sensor3Data = 255;  
  Sensor4Data = 725;  

si trebuie scoase ghilimele de le-am pus eu la citirea intrarilor analogice si mutate la cele predefinite:

void loop() {  
  // Read and store Sensor Data or put a predefined values (min=0, max=1023, 255, 725)
  
  Sensor1Data = analogRead(Sensor1Pin);  
  Sensor2Data = analogRead(Sensor2Pin);  
  Sensor3Data = analogRead(Sensor3Pin);  
  Sensor4Data = analogRead(Sensor4Pin);  
  /*  
  Sensor1Data = 0;  
  Sensor2Data = 1023;  
  Sensor3Data = 255;  
  Sensor4Data = 725;  
  */

14 comentarii:

  1. Salut!
    E un tutorial foarte bun. de curand mi-am achizitionat modulele (receiver si transmiter). Dar vreau sa folosesc si un encoder ht12e si un encoder ht12d. Te rog ai putea face un tutorial, sau sa-l adaugi la acesta?

    Multumesc anticipat!

    RăspundețiȘtergere
  2. salut,

    mi-au venit si mie module din astea, se pare ca-s chiar cele folosite de tine in primul exemplu si functioneaza!
    mersi

    RăspundețiȘtergere
  3. https://www.robofun.ro/transmitator_radio?search=Transmitator%20radio
    Salut, stiti cumva daca pot transmite date in interiorul masinii (de la motor - la habitaclu) cu un astfel de transmitator, avand in calcul interferentele, din interiorul masinii.

    RăspundețiȘtergere
  4. Buna ziua,
    Folosesc aceasta pereche tx/rx pentru un proiect, dar am si eu probleme cu distanta. Imi puteti explica mai exact unde atasati antena? Banuiesc ca doar la transmitator, sau puneti una si la receptor? Transmitatorul meu are o singura gaura unde as putea prinde antena, si din ce observ eu, e legata cu una dintre acele antene care vin deja cu transmitatorul, acolo se lipeste?. Va multumesc.

    RăspundețiȘtergere
    Răspunsuri
    1. eu am lipit doar la emitator.. acolo, in acea "gaura" se pune firul, a carui lungime depinde si de frecventa de emisie, dar pt 433MHz poti ncerca cu 17cm, vezi http://www.robertoinzerillo.com/wordpress/?p=74

      Ștergere
    2. Vreau sa fac o antena elicoidala, daca nu merge, incerc pur si simplu cu un cablu de 17cm. Dar mai am o intrebare pentru dvs. daca se poate, conteaza cum e cablul? Izolat sau nu? Vreau sa folosesc un fir dintr-un cablu UTP. Nu cred ca acest aspect este important, doar totusi...
      Va multumesc pentru timpul acordat! :)

      Ștergere
    3. interesant este ca comunica doar pe o distanta de maxima de 40 cm... cu toate ca le-am pus antena ( 17 cm elicoidal)...ar mai fi o probabilitate calitatea device-ului?

      Ștergere
    4. dar fir simplu nu puteti incerca ?

      Ștergere
    5. am gasit si https://www.instructables.com/id/433-MHz-Coil-loaded-antenna/ dar oricum ceva e dubios, ar trebui sa "bata" macar 10m, daca nu 20m

      Ștergere
    6. eu consider ca nu deranjeaza izolatia, dar au fost fost discutii aprinse pe tema asta, pe diverse forumuri si grupuri de fb... si mai ca era sa iau bataie ca am zis asta, ca ar trebui dezizolate... eu nuj cred, dar asta e alta treaba

      Ștergere
  5. salut,am si eu o intrebare, ai incercat , sau ai idee daca se poate sa comanzi o priza telecomandata printr-un astfel de emitator ? de obicei se folosesc telecomenzi radio , dar sunt curios daca se poate si prin acest emitator doar.
    Mersi anticipat

    RăspundețiȘtergere
  6. Domule Florica am tot citit pe blogul Dvs. diverse articole faceti un lucru bun mai ales pentru incepatori.
    Am si eu doua intrebari legate de aceste module:
    1- ce valoare are rezistenta aceea de 0,5W (parca)? Cea lipita pe receptor privind fata PCB-ului cu smd-urile plantate, pe modulul meu lipseste si cihar nu am gasit o fotografie buna ca sa pot citi codul de culori de pe ea.
    si la reglajul receptorului, mentionati Dvs. ca trebuie rotit surubul de alama al inductorului variabil. De unde se pornesc acele ture ? cu surubul jos adica in invers acelor de ceasornic sau cu surubul la suprafata bobinei variabin le in cazul acesta fiind in sensul acelor de ceasornic.
    Am incercat doua perechi de emitatoare receptoare, ambele cu rezistenta aceea lipsa la receptor si bobina de trei spire la emitator. Pe ardushop am vazut ca acea bobina are 5 spire, asa apare si la dvs,pe alte site-uri are 3 spire.
    In orice caz modulele mele de receptie au un zgomot foarte mare, am incercat sa decuplez si emitatorul si receptorul, mentionez ca nu le-am cumparat de pe ardushop

    RăspundețiȘtergere
  7. tinand cont ca articolul e de acum vreo 6 ani, nu pot s ava dau informatii foarte exacte, dar in mare: unele module au 3 sau 5 spire pentru ca unele lucreaza pe 433MHz, altele pe 315MHz... nu cred ca am recomandat sa se umble la reglajul bobinelor, asta se feca, oricum, cu o surubelnita din material nemetalic, gen textolit, plastic, etc... montajele astea sunt de calitate slaba si pentru comunicatii digitale, daca vreti ceva mai ok, cumparati de la TME, dar nu mai umblati in bobine... schema se gaseste pe net... http://www.hobbycomponents.com/images/forum/HCMODU0087_Schematic.gif

    RăspundețiȘtergere
    Răspunsuri
    1. per ansamblu aceste module emitator-receptor sunt f slabe calitativ. in ceea ce priveste TME probabil au o calitate mai mare dar pretul le face indizerabile.
      La pretul de acolo se poate cumpara o pereche de NRF20L01+ subiect pe care l-ati acoperit deaja intr-un alt articol.
      Am vazut pe cineva care a intrebat daca se pot folosi modulele de 433 MHz direct la o telecomanda.
      Raspunsul este NU. ori se folosesc cu HT12E si HT12D asa cum ati aratat in alt post, ori se folosesc doua arduino cu bibliotecile aferente aka VirtualWire sau RadioHead ca in aceasta postare.

      Ștergere