Je suis sur un projet de communication entre 2 arduino (maitre/esclave)
Le but est que l'aduino maitre demande à l'arduino esclave de lire l'état de 10 broches de fonctions puis de les renvoyer au maitre pour l'afficher sur un écran lcd.
J'ai une idée avec des variables qui stock l'info reçu sur le port de série
Arduino Maitre :
if(radio.available()){ // Si signal radio
radio.read(&boitier, sizeof(boitier)); // on met la valeur reçu dans la variable "boitier"
if(boitier == 1){ //Si la variable reçu egale 1, mise à jour de la variable "boitier_1"
boitier_1 = 1;
}
if(boitier == 2){ //Si la variable reçu egale 1, mise à jour de la variable "boitier_2"
boitier_2 = 1;
}
if(boitier == 3){ //Si la variable reçu egale 1, mise à jour de la variable "boitier_3"
boitier_3 = 1;
}
if(boitier == 4){ //Si la variable reçu egale 1, mise à jour de la variable "boitier_4"
boitier_4 = 1;
}
}
if(boitier_1 == 1){ // Fonction pour le boitier 1
lcd.setCursor(12, 0);
lcd.write(byte(1)); // affichage de Vrai
}
else{
lcd.setCursor(12, 0);
lcd.write(byte(2)); // affichage d'une croix
}
if(boitier_2 == 1){ // Fonction pour le boitier 2
lcd.setCursor(12, 1);
lcd.write(byte(1)); // affichage de Vrai
}
else{
lcd.setCursor(12, 1);
lcd.write(byte(2)); // affichage d'une croix
}
if(boitier_3 == 1){ // Fonction pour le boitier 3
lcd.setCursor(12, 2);
lcd.write(byte(1)); // affichage de Vrai
}
else{
lcd.setCursor(12, 2);
lcd.write(byte(2)); // affichage d'une croix
}
if(boitier_4 == 1){ // Fonction pour le boitier 4
lcd.setCursor(12, 3);
lcd.write(byte(1)); // affichage de Vrai
}
else{
lcd.setCursor(12, 3);
lcd.write(byte(2)); // affichage d'une croix
}
Mais avec 10 lignes le code est immense !
Comment simplifier le code ?
Pourrait-on le faire avec une variable sur 10 bits "(B1110111010)" par exemple ? et qui chaque byte soit une broche de fonction à l'état haut ou bas ?
Si oui, comment l'appliquer à l'ecran lcd ?
Un moyen comme un autre est d'utiliser l'opérateur d'égalité ==
cet opérateur que tu utilises déjà dans le IF, prend deux opérandes et renvois un booleen.
boitier_1 = (boitier == 1);
Les parentheses sont inutiles mais, permet de rendre plus lisible l'instruction.
Tu peux aussi bien sûre utiliser un champ bit et l'opérateur binaire & ou toujours l'opérateur ==.
L'interet d'un champ bit est surtout si tu peux avoir deux boitiers selectionné en même temps.
uint8_t boitiers[10];
const int nbBoitiers = sizeof boitiers;
Programme:
if (radio.available()) { // Si signal radio
int numBoitier=-1;
radio.read(&numBoitier, sizeof numBoitier);
if (numBoitier >= 1 && numBoitier <= nbBoitiers) { // Vérifie que la valeur reçue est valide
boitiers[numBoitier - 1] = 1; // on soustrait 1 car l'indice dans le tableau commence à 0
}
}
for (int i = 0; i < nbBoitiers; i++) {
lcd.setCursor(12, i);
if (boitiers[i] == 1) {
lcd.write(byte(1)); // affichage de Vrai
} else {
lcd.write(byte(2)); // affichage d'une croix
}
}
Une solution est de traduire le contenu de boitier en chaine de caractère contenant l'état de chaque bit 1 ou 0 et d'afficher cette chaine en une fois sur ton afficheur, ainsi:
word boitier = 0b1110111010; // Valeur reçue de l'Arduino esclave
String boitierBits = "";
void setup()
{
Serial.begin(115200);
boitierBits = wordToBits(boitier);
Serial.println(boitierBits);
lcd.setCursor(12, 0);
lcd.print(boitierBits); // affichage des bits de boitier
}
void loop()
{
}
String wordToBits(word wValue)
{
String wordBits = "";
for (int b = 0; b < 10; b ++)
{
if (bitRead(boitier, b) == 1)
{
wordBits = "1" + wordBits;
}
else
{
wordBits = "0" + wordBits;
}
}
return wordBits;
}
Le résultat de la conversion est dans String boitierBits
Effectivement, peut-on faire en sorte que l'esclave envoi l'état de ses broches sous forme de bit.
Exemple : 10 broches de fonction (état haut = 1 / état bas = 0) sous forme de 10 caractères (1110010110)
Et que le maitre le reçoit, contrôle chaque caractère. Puis suivant le résultat, affiche des symboles (Vrai / Croix) sur l'écran lcd (Si 1 (Vrai) / si 0 (Croix)
Le souci de l'écran lcd, c'est qu'il faut afficher le caractère suivant sur le curseur suivant (de lcd.setCursor(12, 0) à lcd.setCursor(12, 3)) dans mon cas.
Je ne suis pas encore à l'aise avec ses fonctions (String, for, ...)
Pas tout à fait, l'esclave envoie un mot de 16 bits (word) dont chaque bit est le reflet de l'état d'une pin.
J'ai pas bien compris ton affichage, tu affiches l'état des 10 pin de l'esclave ou l'une après l'autre ?
J'ai fais un morceau de code avec 4 broches pour l'arduino esclave.
#include <RF24.h>
const byte CEPin = 8;
const byte CSNPin = 7;
RF24 radio(CEPin, CSNPin);
uint8_t adresse[] = {0xCC, 0xCE, 0xCC, 0xCE, 0xCC};
const int Pinbroche_1 = 2;
const int Pinbroche_2 = 3;
const int Pinbroche_3 = 4;
const int Pinbroche_4 = 5;
/*int broche1 = 0;
int lastbroche1 = 0;
int broche2 = 0;
int lastbroche2 = 0;
int broche3 = 0;
int lastbroche3 = 0;
int broche4 = 0;
int lastbroche4 = 0;*/
int info = 0; // variable reçu
int action = 0; // permet d'entré ou sortie du While
int a; // variable de Pinbroche_1
int b; // variable de Pinbroche_2
int c; // variable de Pinbroche_3
int d; // variable de Pinbroche_4
int Temps_sortie = 5000;
unsigned long Temps_actuel;
unsigned long Temps_precedent = 0;
unsigned long Temps_precedent2 = 0;
void setup() {
Serial.begin(9600);
pinMode(Pinbroche_1, INPUT);
pinMode(Pinbroche_2, INPUT);
pinMode(Pinbroche_3, INPUT);
pinMode(Pinbroche_4, INPUT);
if (!radio.begin()) {
Serial.println(F("radio absente!!")); // contrôle de fonctionnent de la radio
while (true) ; // erreur
}
radio.begin();
radio.setPALevel(RF24_PA_LOW);
radio.openReadingPipe(1, adresse); // Fonction pour écouter
radio.startListening();
Serial.println(F("**** RECEPTEUR PRET ****"));
}
void loop() {
Temps_actuel = millis();
if(radio.available()){ // Si une info sur la radio
radio.read(&info, sizeof(info));
Serial.print("Valeur reçu ");
Serial.println(info);
}
if(info == 50){ // 50 est la valeur pour la demande du contrôle des broches de fonction
Temps_precedent2 = Temps_actuel;
radio.setPALevel(RF24_PA_LOW); // Fonction qui permet d'écrire sur le port de COM
radio.openWritingPipe(adresse);
radio.stopListening();
action = 1;
while (action == 1){
a = digitalRead(2); // a est l'état de la broche 2 (HIGH - 1 / LOW - 0)
b = digitalRead(3); // b est l'état de la broche 3 (HIGH - 1 / LOW - 0)
c = digitalRead(4); // c est l'état de la broche 4 (HIGH - 1 / LOW - 0)
d = digitalRead(5); // d est l'état de la broche 5 (HIGH - 1 / LOW - 0)
radio.write(&a, sizeof(a)); // envoi la variable a
radio.write(&b, sizeof(b)); // envoi la variable b
radio.write(&c, sizeof(c)); // envoi la variable c
radio.write(&d, sizeof(d)); // envoi la variable d
Temps_actuel = millis(); // permet d'actualisé la valeur dans le while
if(Temps_actuel - Temps_precedent2 >= Temps_sortie){ // variable qui permet de sortir du While au bout de "Temps_sortie" 5000 ms
action = 0;
info = 0;
break;
}
}
Temps_precedent = Temps_actuel;
Temps_precedent2 = Temps_actuel;
}
}
J'ai "rectifié" ton programme pour le rendre plus pratique, j'ai laissé, en remarque, les lignes devenues inutiles. J'ai mis des liens pour des explications.
Tu verra que l'état de tout les bits sont envoyés en une fois au moyen de la variable PinBrochesEtats.
Pour recevoir, côté master:
déclarer une variable globale word PinBrochesEtats = 0; // Etat des broches
et lire: radio.read(&PinBrochesEtats, sizeof(PinBrochesEtats));
Pour rendre ces bits affichables, inspires toi du bout de programme du post#4 String wordToBits(word wValue)
Le programme:
#include <RF24.h>
const byte CEPin = 8;
const byte CSNPin = 7;
RF24 radio(CEPin, CSNPin);
uint8_t adresse[] = {0xCC, 0xCE, 0xCC, 0xCE, 0xCC};
//const int Pinbroche_1 = 2;
//const int Pinbroche_2 = 3;
//const int Pinbroche_3 = 4;
//const int Pinbroche_4 = 5;
const int Pinbroche[] {2, 3, 4, 5}; // Tableau des broches https://www.locoduino.org/spip.php?article227
const int PinbrocheNombre = sizeof(Pinbroche) / sizeof(Pinbroche[0]); // Nombre de broches
const int PinbrocheEtatOn = LOW; // Etat OOn de la broche
/*int broche1 = 0;
int lastbroche1 = 0;
int broche2 = 0;
int lastbroche2 = 0;
int broche3 = 0;
int lastbroche3 = 0;
int broche4 = 0;
int lastbroche4 = 0;*/
int info = 0; // variable reçu
int action = 0; // permet d'entré ou sortie du While
word PinBrochesEtats = 0; // Etat des broches
//int a; // variable de Pinbroche_1
//int b; // variable de Pinbroche_2
//int c; // variable de Pinbroche_3
//int d; // variable de Pinbroche_4
int Temps_sortie = 5000;
unsigned long Temps_actuel;
unsigned long Temps_precedent = 0;
unsigned long Temps_precedent2 = 0;
void setup() {
Serial.begin(9600);
for (int p = 0; p < PinbrocheNombre; p ++) // Initialisation des broches
{
pinMode(Pinbroche[p], INPUT);
}
////pinMode(Pinbroche_1, INPUT);
////pinMode(Pinbroche_2, INPUT);
////pinMode(Pinbroche_3, INPUT);
////pinMode(Pinbroche_4, INPUT);
//
//if (!radio.begin()) {
//Serial.println(F("radio absente!!")); // contrôle de fonctionnent de la radio
//while (true) ; // erreur
//}
//
//radio.begin();
//radio.setPALevel(RF24_PA_LOW);
//radio.openReadingPipe(1, adresse); // Fonction pour écouter
//radio.startListening();
Serial.println(F("**** RECEPTEUR PRET ****"));
Serial.print(F("Nombre de broches: "));
Serial.println(PinbrocheNombre);
}
void loop() {
Temps_actuel = millis();
if(radio.available()){ // Si une info sur la radio
radio.read(&info, sizeof(info));
Serial.print("Valeur reçu ");
Serial.println(info);
}
if(info == 50){ // 50 est la valeur pour la demande du contrôle des broches de fonction
PinBrochesEtats = PinBrochesLecture(); // Lecture des broches
Temps_precedent2 = Temps_actuel;
radio.setPALevel(RF24_PA_LOW); // Fonction qui permet d'écrire sur le port de COM
radio.openWritingPipe(adresse);
radio.stopListening();
action = 1;
while (action == 1){
//a = digitalRead(2); // a est l'état de la broche 2 (HIGH - 1 / LOW - 0)
//b = digitalRead(3); // b est l'état de la broche 3 (HIGH - 1 / LOW - 0)
//c = digitalRead(4); // c est l'état de la broche 4 (HIGH - 1 / LOW - 0)
//d = digitalRead(5); // d est l'état de la broche 5 (HIGH - 1 / LOW - 0)
radio.write(&PinBrochesEtats, sizeof(PinBrochesEtats)); // envoi des bit
//radio.write(&a, sizeof(a)); // envoi la variable a
//radio.write(&b, sizeof(b)); // envoi la variable b
//radio.write(&c, sizeof(c)); // envoi la variable c
//radio.write(&d, sizeof(d)); // envoi la variable d
Temps_actuel = millis(); // permet d'actualisé la valeur dans le while
if(Temps_actuel - Temps_precedent2 >= Temps_sortie){ // variable qui permet de sortir du While au bout de "Temps_sortie" 5000 ms
action = 0;
info = 0;
break;
}
}
Temps_precedent = Temps_actuel;
Temps_precedent2 = Temps_actuel;
}
}
word PinBrochesLecture() // Retourne un word où chaque bit est le reflèt de son état
{
word bitsLecture = 0;
for (int p = 0; p < PinbrocheNombre; p ++) // Initialisation des broches
{
if (digitalRead(Pinbroche[p]) == PinbrocheEtatOn)
{
bitsLecture += bitsLecture << p; // https://www.arduino.cc/reference/cs/language/structure/bitwise-operators/bitshiftleft/
}
}
}
Je n'ai pas pu essayer "en vrai" mais reste à ta disposition