Aide Emetteur Récepteur 433mhz

Bonsoir,

Je commence à être autonome niveau programmation mais, j'aurais besoin d'aide pour un petit bout de code.

Voici le code que j'ai :

#include <VirtualWire.h>
 
const char *msg = "23574617";
 
void setup()
{
    Serial.begin(9600); 
    vw_setup(2000);
}
 
void loop()
{
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx();
    Serial.println("Fin de la transmission.");
    delay(2000);
}

Comment envoyer deux informations différentes et faire en sorte que le récepteur puisse les lire toutes les deux?

Merci par avance.

#include <VirtualWire.h>
 
const char *msg1 = "23574617";
const char *msg2 = "76543210";
char msg3[10];
 
void setup()
{
    Serial.begin(9600); 
    vw_setup(2000);
}
 
void loop()
{
    vw_send((uint8_t *)msg1, strlen(msg1)+1); // le +1 pour envoyer le '\0' de fin de chaîne si vous voulez
    vw_wait_tx();

    vw_send((uint8_t *)msg2, strlen(msg2)+1); // le +1 pour envoyer le '\0' de fin de chaîne si vous voulez
    vw_wait_tx();

   itoa((int) (millis()/1000), msg3, 10); // nombre de secondes depuis le début du sketch
    vw_send((uint8_t *)msg3, strlen(msg3)+1); // le +1 pour envoyer le '\0' de fin de chaîne si vous voulez
    vw_wait_tx();

    Serial.println("Fin de la transmission.");
    delay(2000);
}

bien sûr il faut que de l'autre côté il y ait du code qui écoute..

Merci, cela te générait il de m'envoyer le code du récepteur ?

Je l'ai pour une réception simple mais, ne le connais pas pour plusieurs...

il n'y a rien à changer si c'est bien fait - il suffit de boucler...

au premier passage dans la boucle votre code lira le premier message au second passage le second message etc...

postez votre code

Ce code marche :

// ==== Recepteur 433 MHz ===============================
//
// Source : http://skyduino.wordpress.com/2011/12/29/tutoriel-arduino-et-emetteurrecepteur-433mhz-virtualwire/
//
//=======================================================

#include <VirtualWire.h> // inclusion de la librairie VirtualWire
 
uint8_t buf[VW_MAX_MESSAGE_LEN]; // Tableau qui va contenir le message reçu (de taille maximum VW_MAX_MESSAGE_LEN)
uint8_t buflen = VW_MAX_MESSAGE_LEN; // Taille maximum de notre tableau
 
void setup() // Fonction setup()
{
    Serial.begin(9600); // Initialisation du port série pour avoir un retour sur le serial monitor
    Serial.println("Tuto VirtualWire"); // Petit message de bienvenue
 
    vw_setup(2000); // initialisation de la librairie VirtualWire à 2000 bauds (note: je n'utilise pas la broche PTT)
    vw_rx_start();  // Activation de la partie réception de la librairie VirtualWire
}
 
void loop() // Fonction loop()
{
    if (vw_wait_rx_max(200)) // Si un message est reçu dans les 200ms qui viennent
    {
        if (vw_get_message(buf, &buflen)) // On copie le message, qu'il soit corrompu ou non
        {
            Serial.print("RX : ");
            for (byte i = 0; i < buflen; i++) // Si il n'est pas corrompu on l'affiche via Serial
             //Serial.print(buf[i]);   //Conversion ASCII
             {Serial.print(buf[i]- '0');   //Conversion ASCII des chiffres 0-9
             }
             Serial.println("");
        }
    }
}

Mais je ne sais pas comment il peut lire deux messages différents (et qu'il sache: celui ci c'est le msg un et celui c'est le msg deux). Pouvez vous m'aider ?

Soit vous comptez à chaque tour de boucle 1, 2 ,3 puis 1, 2 ,3 mais c'est pas très robuste si vous ratez un message, soit vous mettez comme premier octet du message envoyé le No ou le type de ce message. Par exemple si vous envoyez 5 valeurs, envoyez
A214
B125
C32
D177
E112

Puis ça recommence
A233
B144
....

Au décodage vous regardez le premier octet et ça vous dit quel message c'est

Et dans mon code je dois rajouter quoi pour faire un "décodage en octet" ?

Quand vous faites vw_get_message(buf, &buflen, si ça ne retourne pas 0 (c'est pour cela qu'il y a le if avant sinon c'est que le message est corrompu) vous avez dans buf le message reçu. Donc vous pouvez faire un switch (cf example) sur le premier caractère du buffer et lire la valeur à partir du second caractère avec la fonction de décodage d'entiers à partir de leur représentation en ASCII atoi (const char * str);

int valA, valB, valC;

// ...

switch(buf[0]) { // on regarde le premier caractère 
   case 'A':
       valA = atoi((const char *) &buf[1]); // &buf[1] est l'adresse en mémoire de la chaîne  partir du second caractère, donc le début du nombre entier envoyé
       break;
   case 'B':
        valB = atoi((const char *) &buf[1]);
        break;
   case 'C':
        //... etc
}

Merci beaucoup.

Comment dans le code émetteur je dis que msg1 prend la valeur, par exemple, du potentiomètre ?
Ici, je voudrais dire msg1 prend la valeur de A0 et msg2 celle de A1.

#include <VirtualWire.h>

const char *msg1;
const char *msg2;

void setup()
{
pinMode (A0, INPUT);
pinMode (A1, INPUT);
Serial.begin(9600); 
vw_setup(2000);
}

void loop()
{
vw_send((uint8_t *)msg1, strlen(msg1)+1); // le +1 pour envoyer le '\0' de fin de chaîne si vous voulez
vw_wait_tx();

vw_send((uint8_t *)msg2, strlen(msg2)+1); // le +1 pour envoyer le '\0' de fin de chaîne si vous voulez
vw_wait_tx();

Serial.println("Fin de la transmission.");
delay(2000);
}

Il faut réserver un peu de mémoire pour msg1 et pour msg2. Comme vous lisez les valeurs sur A0 et A1 vous aurez un chiffre entre 0 et 1023 - donc 4 caractères max. Il faut le '\0' de fin de chaîne et donc comme on a dit un caractère en début de message pour dire si on envoie A0 (A) ou A1 (B).

Donc 1+4+1=6 characteres pour les buffers:

char msg1[6]; // pour lire A0
char msg2[6]; // pour lire A1

Dans les setup() on peut pré-remplir le premier caractère, on l'écrasera jamais

void setup()
{
    // .... diverses initialisations
    msg1[0] = 'A';
    msg2[0] = 'B';
}

Ensuite dans la boucle il faut lire A0 et A1 et traduire leur valeur en ASCII et la mettre dans le buffer au bon endroit. on pourrait utiliser sprintf pour tout cela mais inclure cette fonction ça rajoute bcp de code et donc prend de la mémoire. Il existe la fonction [

char *  itoa ( int value, char * str, int base );

](http://www.cplusplus.com/reference/cstdlib/itoa/) qui peut nous aider et qui est plus compacte et qui met un '\0' en fin de chaîne - tout ce que l'on veut donc:

    ....
    itoa(analogRead(A0), &msg1[1], 10); // &msg[1] --> le pointeur à partir du second caractère 
    itoa(analogRead(A1), &msg2[1], 10); // idem pour le second message
    ...

Voilà ça devrait le faire (tapé sur mon iPad donc pas testé)

Voilà le code que j'ai mis sur mon récepteur mais, il ne marche pas. Pouvez - vous m'aider ?

#include <VirtualWire.h>

uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

int valA, valB, valC;

void setup()
{
Serial.begin(9600);
vw_setup(2000);
vw_rx_start();
}

void loop() // Fonction loop()
{
switch(buf[0]) { // on regarde le premier caractère 

case 'A':
valA = atoi((const char *) &buf[1]);
break;

case 'B':
valB = atoi((const char *) &buf[1]);
break;
}

Serial.println(valA);
Serial.println(valB);
delay (1000);

}

Et celui de l'émetteur ?

#include <VirtualWire.h>

char msg1[6]; // pour lire A4
char msg2[6]; // pour lire A5

void setup()
{
pinMode (A4, INPUT);
pinMode (A5, INPUT);
Serial.begin(9600); 
vw_setup(2000);
msg1[0] = 'A';
msg2[0] = 'B';
}

void loop()
{
  
itoa(analogRead(A4), &msg1[1], 10); // &msg[1] --> le pointeur à partir du second caractère 
itoa(analogRead(A5), &msg2[1], 10); // idem pour le second message

vw_send((uint8_t *)msg1, strlen(msg1)+1); // le +1 pour envoyer le '\0' de fin de chaîne si vous voulez
vw_wait_tx();

vw_send((uint8_t *)msg2, strlen(msg2)+1); // le +1 pour envoyer le '\0' de fin de chaîne si vous voulez
vw_wait_tx();

Serial.println(msg1);
Serial.println(msg2);

Serial.println("Fin de la transmission.");
delay(200);
}

Mais, je crois que celui ci marche. Vois tu une erreur ?

Ou est passé tout le code de réception qui remplit le buffer??

Je pensais qu'il n'était plus utile ...
Je dois le mettre ou ?

Ben faut bien écouter les messages qui arriven quand même :slight_smile:

(Dans mon exemple de code j'avais mis ... pour montrer qu'il y avait du vide avant)

donc vous attendrez de recevoir un message, quand il est la vous remplissez le buffer et ensuite vous allez regarder si c'est A ou B (valC vous sert à rien au fait)

Voici mon code REC :

#include <VirtualWire.h>

uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

int valA, valB ;

void setup()
{
Serial.begin(9600);
vw_setup(2000);
vw_rx_start();
}

void loop() // Fonction loop()
{

if (vw_wait_rx_max(200)) // Si un message est reçu dans les 200ms qui viennent
{
  if (vw_get_message(buf, &buflen)) // On copie le message, qu'il soit corrompu ou non
  {
    switch(buf[0]) { // on regarde le premier caractère 
      case 'A':
     valA = atoi((const char *) &buf[1]);
     break;

      case 'B':
     valB = atoi((const char *) &buf[1]);
     break;
    }
  }
}

Serial.println(valA);
Serial.println(valB);
delay (100);
}

Et je ne comprends pas pourquoi les valeurs varient entre 0 et 9999 (ou 0 et 100 la première fois que je lance le programme). Pouvez - vous m'expliquer ?

C'est bizarre

Mais bon - Il ne faut afficher les valeurs que quand vous avez reçu un message et uniquement pour la valeur reçue - sinon les variables ne sont pas initialisées (enfin comme elles sont globales la première fois elles sont à 0)

Mettez le Print de valA ou valB dans leur case respectif avant le break

Sinon

  • Pas besoin de délai 100ms à la fin, vous risquez de perdre des messages vaut mieux boucler vite

  • passez le port série à 115200 bauds au lieu de 9600 pour le moment - pas la peine de ralentir inutilement les Serial.print()

  • Au lieu d'attendre 200ms un message au début utilisez plutôt la fonction vw_have_message() qui est similaire à available() sur le port série

En gros on fait:

Si qque chose de dispo
Si le message est reçu non corrompu
Décoder en fonction de la première lettre
Lire la valeur
Afficher la valeur

Avez vous un lien qui référencie toutes les commandes de cette librairie ?