Zenders en ontvangers
Soorten zenders
Er zijn verschillende soorten zenders/ontvangers beschikbaar voor de Arduino. Deze pagina gaat alleen over 433 MHz zender en ontvangers. Voor Bluetooth is er een aparte pagina. De simpele, zeer goedkope 433 MHz zenders kunnen bij veel projecten worden ingezet. Ze kunnen echter gemakkelijk gestoord en afgeluisterd worden, maar dat zal bij de meeste Arduino projecten geen probleem zijn. Om de modules betrouwbaar te maken is een speciale softwarebibliotheek nodig. Ik testte er drie: VirtualWire.h, RH_ASK.h en RFRecieve.h/RFTransmitter.h. De laatste bibliotheek heeft ook nog PinChangeInterruptBoards.h nodig. Verder ontlopen deze bibliotheken elkaar niet veel.
433 MHz modules: aparte zender en ontvanger
Links de kleine zender; rechts de ontvanger
Deze 433 MHz zender/ontvangers zijn uitstekend te gebruiken als je vanuit de ene Arduino naar de andere Arduino wilt gaan. Het bereik is 10 tot 100 meter. Zodra je met meerdere Arduino's wilt communiceren of heen en weer tussen twee Arduino's dan heb je problemen. Ik testte de set FS1000A XY-MK-5V TX/RX en de veel kleinere H34A/H5V4D (zie foto). Het laatste setje vind ik net iets beter, maar beide voldoen goed. Als je er geen antenne bij hebt gekregen soldeer er dan een 17,4 cm lange koperdraad aan als antenne. Deze antenne mag je eventueel tot een spiraal wikkelen. Hoewel je kunt communiceren met een gewone seriële verbinding, is dat niet aan te raden, omdat de ontvanger heel veel ruis oppikt. Er zijn goed bruikbare softwarebibliotheken, die hier een oplossing voor hebben en ook nog extra functies hebben. Hieronder zie je een voorbeeld met de oudere bibliotheek VirtualWire en een met de nieuwere RH_ASK. In beide gevallen moet je de datapin aansluiten op pin 12 bij de zender en pin 11 bij de ontvanger. Hoewel deze bibliotheken veel met elkaar te maken hebben kun je niet de zender met de ene en de ontvanger met de andere bibliotheek maken. Als je de twee Arduino's tegelijk op je computer hebt aangeloten start de IDE dan twee keer op: een keer met alleen de zender-sketch en een keer met alleen de ontvanger-sketch.
Klik hier om de vier sketches te zien!
Hier volgt het voorbeeld met de VirtualWire bibliotheek
// Zender
#include "VirtualWire.h"
void setup() {
vw_set_tx_pin(12); // Stel pin D12 in als TX pin
vw_setup(4000); // Stel het aantal bits per seconde in
}
void loop() {
const char *msg = "Arduino 1 meldt zich!"; // Deze boodschap wordt verzonden
vw_send((uint8_t *)msg, strlen(msg));
vw_wait_tx(); // Wacht tot de booschap is verzonden
delay(500);
}
----------------------------------------------------------------------------------
// Ontvanger
#include "VirtualWire.h"
void setup() {
Serial.begin(9600);
Serial.println("Ik wacht op ontvangst\n");
vw_set_rx_pin(11); // Stel pin D11 in als RX Pin
vw_setup(4000); // Stel het aantal bits per seconde in
vw_rx_start();
}
void loop() {
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN; // = 30
if (vw_get_message(buf, &buflen)) {
Serial.print("Ontvangen: ");
for (int i = 0; i < buflen; i++) Serial.write(buf[i]);
Serial.println();
}
}
Hier volgt het voorbeeld met de ASK bibliotheek
// Zender
#include <RH_ASK.h>
RH_ASK driver; // data gaat naar pin 12
void setup() {
if (!driver.init()) Serial.println("Er is iets fout");
}
void loop() {
const char *msg = "Bericht voor de andere Arduino";
driver.send((char *)msg, strlen(msg));
driver.waitPacketSent();
delay(1000);
}
----------------------------------------------------------------------------------
// Ontvanger
#include <RH_ASK.h>
RH_ASK driver; // data gaat naar pin 11
void setup() {
Serial.begin(9600);
if (driver.init()) Serial.println("Ontvanger actief");
}
void loop() {
uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
uint8_t buflen = sizeof(buf);
if (driver.recv(buf, &buflen)) {
driver.printBuffer("Ontvangen bytes met daaronder de betekenis", buf, buflen);
for (int i = 0; i < buflen; i++) Serial.write(buf[i]);
Serial.println("\n");
}
}
Communicatie naar twee kanten
Voor communicatie heen en weer tussen twee Arduino's raad ik aan de bluetooth modules te gebruiken of de HC-12 tranceiver, die ik hierna beschrijf.
De gewone 433 MHz zenders kùnnen wel gebruikt worden om tussen twee Arduino's beide kanten op te communiceren, maar dan moet je er wel voor zorgen dat er altijd maar een van beide Arduino's "aan het woord is". In het voorbeeldprogramma gaat dat automatisch goed doordat je zelf een tekst moet intypen en verzenden. Als je echter een programma hebt waarbij de Arduino's zelfstandig communiceren dan is dat nogal tricky. Wat je kunt doen is als een Arduino gezonden heeft, deze pas opnieuw laten zenden als hij zelf iets ontvangen heeft. Dit werkt een tijdje, totdat een verzonden boodschap niet ontvangen wordt. Dan zit het systeem vast. Je moet dus een delay inbouwen, waarna een boodschap eventueel nog een keer wordt verzonden.
Ga als volgt te werk: sluit op beide zenders zowel een zender als ontvanger aan. De datapin ("ADAT") van de zender gaat naar pin 12 van de Arduino en de datapin van de ontvanger naar pin 11 van de Arduino. Upload onderstaand programma in beide Arduino's. Ik gebruikte twee Arduino nano's. Open nu de Arduino onwikkelomgeving (IDE) nog een keer en verbind beide Arduino IDE's met een andere Arduino (dus met een andere poort). Nu kun je twee verschillende Seriële monitors openen. Zodra de begintekst in de beide vensters te zien is kun je een tekst invoeren en verzenden. Heel even later zie je de verzonden tekst aankomen bij de andere Arduino en kun je controleren of de communicatie inderdaad beide kanten op werkt.
Klik hier om het testprogramma te zien!
// Programma voor communicatie tussen twee Arduino's die beide een 433 MHZ zender EN ontvanger hebben
#include <RH_ASK.h>
RH_ASK zender; // gebruik pin 11 voor de ontvanger en pin 12 voor de zender
void setup() {
Serial.begin(9600);
zender.init();
Serial.print("Let op: een opdracht mag uit maximaal ");
Serial.print(RH_ASK_MAX_MESSAGE_LEN - 1); Serial.println(" letters bestaan");
}
void loop() {
if ( Serial.available() ) {
String bericht = Serial.readString();
if ( bericht.length() >= RH_ASK_MAX_MESSAGE_LEN ) {
Serial.println("Bericht is te lang: niets verzonden"); return;
}
uint8_t buffer[bericht.length() + 1]; // Declareer buffer van de juiste lengte
bericht.toCharArray(buffer, sizeof(buffer));
zender.send( (char *) buffer, sizeof(buffer) );
zender.waitPacketSent();
Serial.println("Zojuist verzonden:"); Serial.println(bericht);
}
else {
uint8_t inPost[RH_ASK_MAX_MESSAGE_LEN];
uint8_t inPostlengte = sizeof(inPost);
if ( zender.recv(inPost, &inPostlengte) ) {
Serial.println("Ontvangen:");
for ( int i = 0; i < inPostlengte; i++) Serial.print((char)inPost[i]);
Serial.println();
}
}
}
Hier zie je hoe je Arduino's berichten van elkaar kunnen lezen en verzenden
433 MHz gecombineerde zender/ontvanger combinatie ("transceiver") HC-12
Deze zender-ontvanger combinatie heeft een bereik van meer dan een kilometer en hij kan tot 100 verschillende kanalen gebruiken. Hij is dus veel beter bruikbaar dan de eerder genoemde 433 MHz set, maar ook een stuk duurder (ongeveer 10 euro). In werkelijkheid ligt de frequentie - afhankelijk van het gekozen kanaal - tussen de 433 en 473 MHz. Ik moet nog veel testen, met name het instellen van de frequentie. Ook zonder de frequentie te veranderen kun je heen en weer communiceren tussen twee Arduino's. Dit werkt veel eenvoudiger dan met de gewone 433 MHz zender/ontvanger. Een voorbeeld hiervan kun je zien in het Duo Toverfles project (nog niet helemaal klaar; testprogramma werkt al wel. De link komt hopelijk zeer snel.)
De communicatie is eenvoudig te testen via de seriële monitor. Hiertoe moet de Arduino ontwikkelomgeving twee keer worden opgestart (dus NIET twee programma's binnen één Arduino sessie). De twee monitors horen in mijn geval bij de Arduino's die op COM13 en COM17 aangesloten zijn. Je typt in de ene monitor een tekst in en deze wordt op de andere weergegeven. Als dit werkt dan kun je er zeker van zijn dat de draadloze communicatie in orde is.
Klik hier om het testprogramma te zien!
#include <SoftwareSerial.h>
SoftwareSerial HC_12(2, 3); // Sluit TX aan op poort 2 en RX op poort 3
void setup() {
Serial.begin(9600);
HC_12.begin(9600);
}
void loop() {
if (Serial.available() > 0) { // Er is iets ingetikt op de seriële monitor
String input = Serial.readString();
HC_12.println(input); // Verzend dit over de HC-12
}
if (HC_12.available() > 1) { // Er zijn twee of meer karakters binnengekomen op de HC_12
String input = HC_12.readString();
Serial.println(input); // Laat dit zien op de seriële monitor
}
delay(20); // Voorkom storingen
}
Je typt een tekst in, in de Seriële monitor van (in dit geval) Arduino 17 en vezendt dat.
En dit is de uitvoer. Je ziet dat het bericht dat via COM17 is verstuurd, correct wordt ontvangen op COM13 (en omgekeerd).
Nog doen: mijn testprogramma met de RFReceive/RFTramsmitter bibliotheek