S mètre pour nRF24L01
Bonjour,
Voici un petit programme destiné à mesurer la qualité de réception d'un signal reçu par le nRF24L01.
Pourquoi:
il n'y a pas de S-mètre d'origine sur ce transmetteur. (Il y a bien un membre de la classe RF24 bool testRPD(void) sensée indiquer si le signal dépasse le seuil de -64dbm, mais il renvoie systématiquement false avec mes nRF24L01).
Comment:
Sur le nRF24L01 on peut faire varier la puissance d'émission de 0dbm à -18dbm par pas de 6db.
On vas envoyer des série de 4 trames, toutes les 100ms, à des puissances d'émission différentes et vérifier lesquelles on vas recevoir.
On allumera de 0 à 4 leds suivant la qualité de réception (chaque led correspond à une trame).
On obtiendra ainsi 5 solutions possibles allant de S0 (absence de signal) à S4 (réception des 4 trames) par pas de 6db.
Réalisation:
le montage est des plus simples. On prend 4 leds avec une résistance série dont la catode est reliée à la masse et l'anode aux broches choisies au début du programme avec la macro #define LED[X] [pin]. On peut rajouter une cinquième led rouge facultative (LED0) pour indiquer l'absence de signal (toutes les autres leds sont éteintes).
Test:
après vérification il s'est avéré que l'écart de puissance réel de mes nRF24L01 ne correspondait pas à celui indiqué dans le datasheet.
portée: S4 ~30m, S3 ~45m, S2-S1 ~60m, soit un écart d'environ 3db pour les puissances faibles et 0db pour les puissances fortes.
Il s'agit de nRF24L01 d'import à bas coût (clone?) .
Si quelqu'un peut confirmer si cette anomalie est également présente sur des modèles connus pour être d'origine.
Autre point: sur les cartes génériques, je recommande l'ajout d'un condensateur d'appoint de 47µF, pour épauler l'alimentation 3,3V de la carte, souvent insuffisante pour encaisser les pics de courants.
signal_tx.ino:
/*
* Signal mètre pour nRF24L01 coté TX. Auteur Christophe JUILLET. Usage libre.
* Pour plus d'info sur ce programme, voir le sujet "Signal mètre pour nRF24L01" sur la page: http://forum.arduino.cc/index.php?board=75.0
*/
#include <SPI.h>
#include <RF24.cpp> // URL des librairies: https://github.com/TMRh20/RF24
// Il faut installer les fichiers: RF24_config.h RF24.h RF24.cpp nRF24L01.h dans le répertoire "include" par défaut.
// Attention! Il existe plusieurs variantes de librairies du même nom qui ne sont pas toujours totalement compatibles entre-elles.
// pour plus d'info sur l'usage du nRF24L01 et le brochage voir la page: http://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo
#define CE 9 // CE nRF24L01
#define CS 10 // CS nRF24L01
const byte canal = 120; // choisir un canal d'émission radio (entre 100 et 125, au dessus des canaux wifi)
const byte pipe[5] = {0xE8,0xE8,0x12,0x34,0x56}; // choisir un canal logique unique (remplacer "123456" par des chiffres au hasard).
RF24 radio(CE, CS);
void setup() {
radio.begin();
radio.setChannel(canal);
radio.setDataRate(RF24_250KBPS); // On réduit le débit pour doubler la portée. Attention! ne fonctionne qu'avec la version "+" du nRF24L01+. Sinon on met la ligne en commentaire.
radio.openWritingPipe(pipe);
}
void loop() {
static byte puissance[4] = { 0, 1, 2, 3};
radio.setPALevel(RF24_PA_MAX); // RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX. On règle à la puissance maxi (1mW).
radio.enableDynamicAck();
radio.write(&puissance[0], 1, 1); // pas d'ACK
delay(10);
radio.setPALevel(RF24_PA_HIGH); // -6dbm
radio.enableDynamicAck();
radio.write(&puissance[1], 1, 1);
delay(10);
radio.setPALevel(RF24_PA_LOW); // -12dbm
radio.enableDynamicAck();
radio.write(&puissance[2], 1, 1);
delay(10);
radio.setPALevel(RF24_PA_MIN); // -18dbm
radio.enableDynamicAck();
radio.write(&puissance[3], 1, 1);
delay(70);
}
signal_rx.ino:
/*
* Signal mètre pour nRF24L01 coté RX. Auteur Christophe JUILLET. Usage libre.
* Pour plus d'info sur ce programme, voir le sujet "Signal mètre pour nRF24L01" sur la page: http://forum.arduino.cc/index.php?board=75.0
*/
#include <SPI.h>
#include <RF24.cpp> // URL des librairies: https://github.com/TMRh20/RF24
// Il faut installer les fichiers: RF24_config.h RF24.h RF24.cpp nRF24L01.h dans le répertoire "include" par défaut.
// Attention! Il existe plusieurs variantes de librairies du même nom qui ne sont pas toujours totalement compatibles entre-elles.
// pour plus d'info sur l'usage du nRF24L01 et le brochage voir la page: http://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo
#define CE 9
#define CS 10
#define LED0 3 // led absence de signal (facultative)
#define LED1 7 // led signal 1
#define LED2 6 // led signal 2
#define LED3 5 // led signal 3
#define LED4 4 // led signal 4
const bool parler = true; // true: retour console (pour contrôle), false: silencieux (plus rapide)
const byte canal = 120; // prendre le même canal de réception radio que celui de l'émetteur (voir fichier signal_tx.ino)
const byte pipe[5] = {0xE8,0xE8,0x12,0x34,0x56}; // prendre le même canal logique que celui de l'émetteur (voir fichier signal_tx.ino)
RF24 radio(CE,CS);
void setup() {
if (parler)
Serial.begin(250000);
pinMode(LED0, OUTPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
digitalWrite(LED0, HIGH);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
digitalWrite(LED4, LOW);
radio.begin();
radio.setChannel(canal);
radio.setDataRate(RF24_250KBPS); // On utilise le même débit que pour l'émetteur. Attention! ne fonctionne qu'avec la version "+" du nRF24L01+. Sinon on met la ligne en commentaire.
radio.openReadingPipe(1,pipe);
radio.startListening();
}
void loop() {
static unsigned long t1 = millis(), t2, tempsMort; // tempsMort: temps entre deux trames
static byte RFdata = 0, RFsignal = 0;
static bool maj = false, RFok = false;
t2 = millis();
tempsMort = t2 - t1;
if (radio.available()) {
radio.read(&RFdata, 1);
t1 = t2;
tempsMort = 0;
maj = false;
RFok = true;
RFsignal |= 1 << RFdata;
}
if (tempsMort > 40 && RFsignal && !maj) {
maj = true;
if (parler) {
Serial.print(RFsignal & 1 << 0 ? "Signal: 1 " : "Signal: ");
Serial.print(RFsignal & 1 << 1 ? "2 " : " ");
Serial.print(RFsignal & 1 << 2 ? "3 " : " ");
Serial.println(RFsignal & 1 << 3 ? "4 " : " ");
}
digitalWrite(LED0, LOW);
digitalWrite(LED1, RFsignal & 1 << 0 ? HIGH : LOW);
digitalWrite(LED2, RFsignal & 1 << 1 ? HIGH : LOW);
digitalWrite(LED3, RFsignal & 1 << 2 ? HIGH : LOW);
digitalWrite(LED4, RFsignal & 1 << 3 ? HIGH : LOW);
RFsignal = 0;
}
if (tempsMort > 120 && RFok) {
RFok = false;
if (parler)
Serial.println("pas de signal");
digitalWrite(LED0, HIGH);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
digitalWrite(LED4, LOW);
}
}
Les fichiers sont également en pièces jointes.
signal_tx.ino (1.93 KB)
signal_rx.ino (3.17 KB)