Je remets ce sujet car je me heurte (après avoir utilisé une carte mega + stripled + module HC-06 bluetooth) a un problème de liaison série associé à la carte Nano.
Je n'arrive pas en effet à faire fonctionner SoftwareSerial et ma carte Nano dans le but de stocker les données de mon module bluetooth HC-06 et les transmettre ensuite en I2C vers ma carte Mega.
Mon soft fonctionne bien avec une carte mega mais impossible ( en ayant essayé d'autres I/O ) avec la carte Nano ?
Je souhaite utiliser une deuxième liaison série pour pouvoir débugger un minimum avec moniteur série et l'UART physique présente sur la Nano.
Si quelqu'un a une idée ou déjà utilisé une deuxième UART qui fonctionne sur une Nano , je suis preneur.
Merci
/*Carte arduino nano de lecture données série via module HC-06 bluetooth
et retransmission sur demande maitre ( carte arduino mega) via I2C */
#include <Wire.h>
#include <SoftwareSerial.h>
//
//
// Variables liaison série
char serial_char;// stockage des chaines de caractères avant envoi I2C
byte indice = 0;
//
SoftwareSerial mySerial(10,11); // pin10 = D6 = RX, pin11 = D7 = TX
//
void setup()
{
//Serial.begin(38400); // opens serial port, sets data rate to 9600 bps
//while (!Serial);
//Serial.print("Hello ");
mySerial.begin(9600);
delay(500);
/*mySerial.print("AT+BAUD3");
/delay(2000);
while (mySerial.available())
{
char str = mySerial.read();
Serial.print(str);
}*/
Wire.begin(2); // Joindre le bus i2c avec l'adresse #2
Wire.onRequest(requestEvent); // enregistrer l'événement (lorsqu'une demande arrive)*/
}
void loop()
{
while (mySerial.available())
{
//read the incoming byte:
serial_char = mySerial.read();
//delay(500);
//Serial.print("Char ");
//Serial.println(serial_char);
//delay(500);
indice = indice+1;
}
bonjour fm, moi j'utilise actuellement les librairies Wire et SoftwareSerial sur un nano "esclave" sans aucun soucis.
je récupéré la teleinfo de mon compteur EDF via SoftwareSerial , et la renvoie "décodé" via le bus I2C vers un arduino maitre.
J'ai gardé la liaison série classique pour le debug.
#include <SoftwareSerial.h>
#include <Wire.h>
SoftwareSerial Serial_Teleinfo(3, 4);
// Créé une liason série sur les pins 3 et 4
// Seulement Pin 3 sur l'optocoupleur
long top1 = 0;
long top2 = 0;
long obtention = 0;
long Index_HC = 0;
long Index_HP = 0;
byte I_A = 0;
int P_W = 0;
char PERIODE = ' ';
byte compteurOK = 0;
unsigned long temps_d_acquisition = 0;
int go = 0;
volatile byte* Long1ArrayPtr;
volatile byte* Long2ArrayPtr;
volatile byte* Long3ArrayPtr;
volatile byte* Int1ArrayPtr;
void setup() {
pinMode(13, OUTPUT);
Wire.begin(8);
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
Serial.begin(9600); // Port série pour liasion Arduino <-> PC
Serial_Teleinfo.begin(1200); // Port SoftwareSerial pour liasion Arduino <-> Teleinfo
}
void loop() {
if (go == 1) {
recup_teleinfo();
}
}
void requestEvent()
{
byte Data[16];
if (compteurOK == 1) {
digitalWrite(13, HIGH);
Long1ArrayPtr = (byte*) &obtention;
Data[0] = Long1ArrayPtr[0];
Data[1] = Long1ArrayPtr[1];
Data[2] = Long1ArrayPtr[2];
Data[3] = Long1ArrayPtr[3];
Long2ArrayPtr = (byte*) &Index_HC;
Data[4] = Long2ArrayPtr[0];
Data[5] = Long2ArrayPtr[1];
Data[6] = Long2ArrayPtr[2];
Data[7] = Long2ArrayPtr[3];
Long3ArrayPtr = (byte*) &Index_HP;
Data[8] = Long3ArrayPtr[0];
Data[9] = Long3ArrayPtr[1];
Data[10] = Long3ArrayPtr[2];
Data[11] = Long3ArrayPtr[3];
Int1ArrayPtr = (byte*) &P_W;
Data[12] = Int1ArrayPtr[0];
Data[13] = Int1ArrayPtr[1];
Data[14] = I_A;
Data[15] = byte(PERIODE);
Data[16] = compteurOK;
}
else {
Data[0] = 0;
Data[1] = 0;
Data[2] = 0;
Data[3] = 0;
Data[4] = 0;
Data[5] = 0;
Data[6] = 0;
Data[7] = 0;
Data[8] = 0;
Data[9] = 0;
Data[10] = 0;
Data[11] = 0;
Data[12] = 0;
Data[13] = 0;
Data[14] = 0;
Data[15] = 0;
Data[16] = 0;
}
Wire.write(Data, 17);
}
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
go = Wire.read(); // receive byte as an integer
Serial.println(go); // print the integer
top1 = millis();
temps_d_acquisition = millis();
compteurOK = 0;
}
void recup_teleinfo() {
digitalWrite(13, LOW);
go = 0;
char charIn_Trame_Teleinfo = 0; // stock chaque charactère recu de la trame teleinfo
String Ligne; // stock la ligne complette (entre LF(0x0A) et CR(0x0D))
String Etiquette; // stock l'intitulé
String Valeur; // stock la valeur apres l'intitulé
char Checksum;
/*
Trame recu par la teleinfo (Expliquations ! non recu par la teleinfo)
ADCO 040422040644 5 (N° d'identification du compteur : ADCO (12 caractères))
OPTARIF HC.. < (Option tarifaire (type d'abonnement) : OPTARIF (4 car.))
ISOUSC 45 ? (Intensité souscrite : ISOUSC ( 2 car. unité = ampères))
HCHC 077089461 0 (Index heures creuses si option = heures creuses : HCHC ( 9 car. unité = Wh))
HCHP 096066754 > (Index heures pleines si option = heures creuses : HCHP ( 9 car. unité = Wh))
PTEC HP.. (Période tarifaire en cours : PTEC ( 4 car.))
IINST 002 Y (Intensité instantanée : IINST ( 3 car. unité = ampères))
IMAX 044 G (Intensité maximale : IMAX ( 3 car. unité = ampères))
PAPP 00460 + (Puissance apparente : PAPP ( 5 car. unité = Volt.ampères))
HHPHC E 0 (Groupe horaire si option = heures creuses ou tempo : HHPHC (1 car.))
MOTDETAT 000000 B (Mot d'état (autocontrôle) : MOTDETAT (6 car.))
*/
//RAZ des valeurs
Index_HC = Index_HP = 0;
I_A = 250;
P_W = 32000;
PERIODE = 'A';
obtention = 0;
while ( Index_HC == 0 || Index_HP == 0 || I_A == 250 || P_W == 32000 || PERIODE == 'A' ) { // recommence tant que l'on a pas recu tous les élément voulus
//Attend un début de ligne (0x0A)
charIn_Trame_Teleinfo = Serial_Teleinfo.read() & 0x7F ;
while (charIn_Trame_Teleinfo != 0x0A) { // reste dans cette boucle tant qu'on ne recoit pas le Charactere de début de ligne 0x0A
if ((millis() - temps_d_acquisition) > 1000 ) {
Serial.println("Teleinfo Inaccesible"); // Affiche un erreur si la teleinfo est inaccesible et retourne à Loop
loop();
}
if (Serial_Teleinfo.available()) { // Tant qu'il y a des caractères disponibles
charIn_Trame_Teleinfo = Serial_Teleinfo.read() & 0x7F ; // Stock 1 caractere recu
}
}
//Vide Ligne
Ligne = "";
//Vide Etiquette
Etiquette = "";
//Concatene les carateres recus jusqu'a l'espace suivant (0x20)
charIn_Trame_Teleinfo = Serial_Teleinfo.read() & 0x7F ;
while (charIn_Trame_Teleinfo != 0x20) { // reste dans cette boucle tant qu'on ne recoit pas le Charactere Espace
if (Serial_Teleinfo.available()) { // Tant qu'il y a des caractères disponibles
charIn_Trame_Teleinfo = Serial_Teleinfo.read() & 0x7F ; // Stock 1 caractere recu
if (charIn_Trame_Teleinfo != 0x20) {
Etiquette += charIn_Trame_Teleinfo; // concatene les caractères reçus sauf les espaces
}
Ligne += charIn_Trame_Teleinfo;
}
}
//Vide Valeur
Valeur = "";
//Concatene les carateres recus jusqu'a l'espace suivant (0x20)
charIn_Trame_Teleinfo = Serial_Teleinfo.read() & 0x7F ;
while (charIn_Trame_Teleinfo != 0x20) { // reste dans cette boucle tant qu'on ne recoit pas le Charactere Espace
if (Serial_Teleinfo.available()) { // Tant qu'il y a des caractères disponibles
charIn_Trame_Teleinfo = Serial_Teleinfo.read() & 0x7F ; // Stock 1 caractere recu
if (charIn_Trame_Teleinfo != 0x20) {
Valeur += charIn_Trame_Teleinfo; // concatene les caractères reçus sauf les espaces
}
Ligne += charIn_Trame_Teleinfo;
}
}
//Concatene les carateres recus jusqu'a la fin de ligne (0x0D)
charIn_Trame_Teleinfo = Serial_Teleinfo.read() & 0x7F ;
while (charIn_Trame_Teleinfo != 0x0D) { // reste dans cette boucle tant qu'on ne recoit pas le Charactere de fin de ligne
if (Serial_Teleinfo.available()) { // Tant qu'il y a des caractères disponibles
charIn_Trame_Teleinfo = Serial_Teleinfo.read() & 0x7F ; // Stock 1 caractere recu
if (charIn_Trame_Teleinfo != 0x0D) {
Ligne += charIn_Trame_Teleinfo; // concatene les caractères reçus sauf le Charactere de fin de ligne (0x0D)
}
if (charIn_Trame_Teleinfo != 0x0D) {
Checksum = charIn_Trame_Teleinfo;
}
}
}
//Controle du Checksum (Le dernier caractere de la ligne et un caractere de controle)
char Controle = 0;
String trame = Etiquette + " " + Valeur;
for (byte i = 0; i < (trame.length()); i++) {
Controle += trame[i];
}
Controle = (Controle & 0x3F) + 0x20;
if (Controle == Checksum) { // Si le checksum correspond bien au code controlé
//Associe la valeur lue à son etiquette
if (Etiquette.substring (0, 4) == "HCHC") {
Index_HC = Valeur.toInt();
}
if (Etiquette.substring (0, 4) == "HCHP") {
Index_HP = Valeur.toInt();
}
if (Etiquette.substring (0, 4) == "PTEC") {
PERIODE = Valeur[1];
}
if (Etiquette.substring (0, 4) == "IINS") {
I_A = Valeur.toInt();
}
if (Etiquette.substring (0, 4) == "PAPP") {
P_W = Valeur.toInt();
}
}
}
if (( Index_HC != 0) && (Index_HP != 0) && (I_A != 250) && (P_W != 32000) && (PERIODE != 'A' )) {
compteurOK = 1;
Serial.print("Temps d'aquisition : "); Serial.print(millis() - temps_d_acquisition); Serial.println(" Millisecondes");
Serial.print(" => Index HC : "); Serial.print(Index_HC); Serial.println(" Wh");
Serial.print(" => Index HP : "); Serial.print(Index_HP); Serial.println(" Wh");
Serial.print(" => PERIODE : H") ; Serial.println(PERIODE);
Serial.print(" => Intensite instantanee : "); Serial.print(I_A); Serial.println(" A");
Serial.print(" => Puissance apparente : "); Serial.print(P_W); Serial.println(" W");
top2 = millis();
obtention = top2 - top1;
Serial.print("Temps obtention : "); Serial.print(obtention); Serial.println(" Millisecondes");
}
}
Merci pour la réponse. Je vais essayer de voir la différence entre ton code et le mien.
J'ai essayé plusieurs pin pour Softwareserial avec mon arduino nano pour finir avec la 10 et 11 ( en fait celles que j'ai testées avec ma carte mega et ça fonctionne bien avec la mega ?)
Actuellement je continue avec le serial Hardware de la nano mais sans debug du coup ( plutôt pénible en aveugle )
Récupérer les infos de télétransmission au compteur, intéressant mais pour quel projet ? Est ce que la vitesse de ton Softwareserial fonctionne aussi à 9600 bauds ( vitesse idem moniteur ) ?
Je viens de percuter sur l'info des pins de Software: D10 et D11 ! Venant du hardware j'étais persuadé que le paramètre passé était le numéro de pin ! Erreur bête, merci pour la réponse !
Salut ptitnitro62000 !
Ton projet de lecture conso eau elec est très intéressant ( à étudier de plus près ) et tu le maitrise bien. De mon côté j'avance sur le mien mais mon expérience en soft est un peu limite ( De l'assembleur mais il y a plus de 20 ans maintenant ! ).
Je me bats encore pas mal avec mon I2C pour récupérer les infos provenant de ma carte nano de manière synchrone !
La question est comment récupérer le bon nombre de caractères provenant de la nano qui elle, remplie un buffer de manière asynchrone ( provenance bluetooth ).
J'aavais essayé de récupérer et envoyer le nbre de caractères au début du transfert mais pas terrible encore ( pb requestform ? )
J'ai ensuite modifié et simplifié pour envoyer sans le nbre de caractères mais celà pose problème côté Réception carte Mega
Je mets mon code ( nano + mega ) pour aide éventuelle ?
CARTE NANO
/*Carte arduino nano de lecture données série via module HC-06 bluetooth
et retransmission sur demande maitre ( carte arduino mega) via I2C */
#include <Wire.h>
#include <SoftwareSerial.h>
//
SoftwareSerial mySerial(10,11); // D10 = RX, D11 = TX
//
// Variables liaison série
char serial_char[255];// stockage des chaines de caractères avant envoi I2C
byte index = 0;//nbre de caractères à envoyer I2C
byte index_precedent = 0;
boolean initial = false;//init envoi nbre de caractères à récupérer via I2C
boolean myserie = false;// données série bluetooth acquises
boolean envoi = false;// envoi I2C terminé
byte ack;
//
void setup()
{
Serial.begin(9600); // opens serial port, sets data rate to 38400 bps
while (!Serial);
mySerial.begin(9600);
/*mySerial.print("AT+BAUD3");
/delay(2000);
while (mySerial.available())
{
char str = mySerial.read();
Serial.print(str);
}*/
Wire.begin(2); // Joindre le bus i2c avec l'adresse #2
Wire.onRequest(requestEvent); // enregistrer l'événement (lorsqu'une demande arrive)
//Wire.onReceive(receiveEvent);// ack du maitre
//for (byte i=0; i<=255; i++){serial_char[i]= 'A';}
index_precedent = 0;
}
void loop()
{
while (mySerial.available())
{
index = index+1;
serial_char[index] = mySerial.read();
Serial.print("serie_index ");
Serial.println(index);
Serial.print("Char ");
Serial.println(serial_char[index]);
}
}
// Fonction qui est exécutée lorsque des données sont demandées par le Maître envoi données I2C
// Cette fonction est enregistrée comme un événement ("event" en anglais), voir la fonction setup()
void requestEvent()
{
if ( index > index_precedent )
{
for ( byte i = index_precedent+1; i <= index ; i++)
{
Serial.print("ok_nano ");
Serial.println(serial_char[i]);
Wire.write(serial_char[i]); // renvoi des caractères stockés
}
index_precedent = index;
}
}
CARTE MEGA
#include <Wire.h>
byte ack = 0;
byte indice = 0;
//
void setup()
{
Wire.begin(2); // joindre le bus i2c (adresse est optionnelle pour un maître)
Serial.begin(9600); // démarré une communication série
Serial.println("hello");
}
void loop()
{
Wire.requestFrom(2,1);// récupérer le nbre de caractères à lire
indice = Wire.read(); // réception des caractères stockés
//Serial.print("indice ");
//Serial.println(indice);
//Wire.write(ack);
if (indice >= 1)
{
Serial.print("indice ");
Serial.println(indice);
Wire.requestFrom(2,indice); // lecture du nbre de caractères stockés
for (int j = 1 ; j <= indice ; j++)
{
char c = Wire.read(); // réception des caractères stockés
Serial.println(c);
}
indice =0;// raz indice après réception*/
}
}
Wire.begin(2); // joindre le bus i2c (adresse est optionnelle pour un maître)
NON, c 'est: Wire.begin(); qu'il faut noté,
Ta nano est déjà sur l'adresse #2, ta mega est maitre t'es pas obligé de mettre d’adresse, où si tu veux mettre une adresse à ta mega met pas la même que la nano !!!!
regarde l'exemple en image: L'architecture Bus I2C:
Oui c'est vrai, pas d'adresse pour le maitre, merci.
En fait celà ne change rien. J'essai actuellement de renvoyer un accusé réception de ma carte maitre après avoir reçu le nbre de caractères à lire et de l'autre côté récupérer ce flag accusé réception côté esclave pour renvoyer les caractères correspondants.
Je ne sais pas si c'est la bonne solution mais je me heurte tjs au problème de lire le bon nbre de caractères via requestfrom( adresse, nbre de caractères ? ).
Représente sur un petit dessin les échanges I2C que tu souhaite avoir entre le maitre et l'esclave, ainsi que les échanges Bleutooth. Çà sera + clair pour tous.
J'ai réussi à synchroniser le nombre de lecture et écriture entre le maitre et l'esclave en dépilant mon buffer lu via serial.
ça fonctionne bien du côté de ma carte nano ( slave ) par contre je ne lis que le dernier carcatères du côté de ma carte mega ( master ) !?
Et là je ne comprends pas ? Surement encore une "coquille" qui traine !?
Le code à suivre
Carte Nano
{
while (mySerial.available())
{
index = index+1;
serial_char[index] = mySerial.read();
Serial.print("serie_index ");
Serial.println(index);
Serial.print("Char ");
Serial.println(serial_char[index]);
}
}
// Fonction qui est exécutée lorsque des données sont demandées par le Maître envoi données I2C
// Cette fonction est enregistrée comme un événement ("event" en anglais), voir la fonction setup()
void requestEvent()
{
if (!ack && ((index-index_precedent)>=1))
{
Wire.write(index-index_precedent);
Serial.print("index ");
Serial.println(index-index_precedent);
}
else
{
if ( index > index_precedent )
{
for ( byte i = index_precedent+1; i <= index ; i++)
{
Serial.print("ok_nano ");
Serial.println(serial_char[i]);
Wire.write(serial_char[i]); // renvoi des caractères stockés
}
index_precedent = index;
ack = false;
}
}
}
void receiveEvent(int howMany)
{
ack = Wire.read(); // receive byte as a character
Serial.print("ack "); // print the character
Serial.println(ack); // print the character
}
Carte mega
#include <Wire.h>
boolean ack = false;
byte index = 0;
//
void setup()
{
Wire.begin(); // joindre le bus i2c (adresse est optionnelle pour un maître)
Serial.begin(9600); // démarré une communication série
Serial.println("hello");
}
void loop()
{
delay(2000);
if (index < 1)
{
Wire.requestFrom(2,1); // lecture du nbre de caractères stockés
index = Wire.read();
Serial.print("index ");
Serial.println(index);
}
else
{
ack = true;
Serial.print("index_suite ");
Serial.println(index);
Wire.beginTransmission(2);
Wire.write(ack); // sends instruction byte
Wire.endTransmission(); // stop transmitting
delay(200);
Wire.requestFrom(2,index);// récupérer le nbre de caractères à lire
for (int j = 1 ; j <= index ; j++)
// while(Wire.available() > 1)
{
char c = Wire.read(); // réception des caractères stockés
Serial.print("char ");
Serial.println(c);
}
ack = false;
index = 0;
}
}
Salut, oui j'avais finalement réussi par comprendre , Mais pas évident pour ceux qui n'ont pas suivi le sujet du début.
Ce soir vu que j'aurai un peu de temps et que j'ai tout le matos pour le faire, je vais mettre dans les mêmes conditions.
j'ai réalise le montage, et mis tes codes.... c'est une usine à gaz...
je vais tenter de réécrire un code ... et commencer par des échanges simple
Il faudra que tu renseigne sur les caractéristiques de la librairie wire (qui gère l'I2C)!!!
parce que vouloir faire passer d'un coup 255 char, alors que les échanges I2C sont limité à 30 octets !!!!
Concernant la librairie Softserial, elle intégré un buffer de 64 bytes (-2) soit 62 caractères.
char c;
#include <Wire.h>
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
Serial.print("Hello demanrrage MEGA");
}
void loop() {
Wire.requestFrom(8, 1);
while (Wire.available()) { // slave may send less than requested
c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(50);
Wire.beginTransmission(8); // transmit to device #8
Wire.write("char is "); // sends five bytes
Wire.write(c); // sends one byte
Wire.endTransmission(); // stop transmitting
delay(50);
}
code carte nano: (esclave)
#include <Wire.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 4);
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(requestEvent); // register event
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
Serial.print("Hello demanrrage du nano");
mySerial.begin(9600);
}
void loop() {
delay(100);
}
void requestEvent() {
byte c;
if (mySerial.available())
{
c = mySerial.read();
}
else {
c = 0; //(Null char.)
}
Serial.print("Char :");
Serial.println((char)(c));
Wire.write(c);
}
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
char d = Wire.read(); // receive byte as a character
Serial.print(d); // print the character
}
char e = Wire.read(); // receive byte as an integer
Serial.println(e); // print the integer
}