Buongiorno a tutti
sto realizzando un progettino di comando tra vari arduino,
controllo valvole riscaldamento, termostati,
ho 1 arduino mega, 3 arduino nano, collegati con rs485
fino a che si tratta di inviare e ricevere comandi e segnali di un byte, tutto bene.
per ricevere il dato temperatura (numero "int") che occupa due byte la seriale (trasmettendo un byte alla volta)
non riesce a trasferire il numero.
Domanda c'è un modo semplice per trasmette un array di numeri interi (due byte) su seriale?
Grazie anticipatamente
Manca qualche informazione per poterti dare dei consigli sensati.
Per la comunicazione RS485 stai usando qualche libreria? Hai implementato un minimo di protocollo?
Probabilmente se posti anche il codice facciamo prima..
P.S. Ricorda di metterlo all'interno dei tag ``
Ti ringrazio per la risposta,
per comunicare tra i vari arduino uso un array di risposta rx[10]
dove rx[0] è il numero della scheda master che deve leggere
e da rx[1] a rx[10] sono i dati
Uso libreria SoftSerial per usare pin diversi da 0-1
il problema sorge quando devo ricevere sul master la temperatura che un numero intero e non un byte
in seguito allego codice dello Slave
#include <EEPROM.h>
#include <SoftwareSerial.h>
SoftwareSerial rs485(4, 3); // TX, RX
#include <OneWire.h>
#include <DallasTemperature.h>
OneWire onewire(14);
DallasTemperature sensors(&onewire);
DeviceAddress sensore1 = { 0x28, 0xFF, 0x79, 0xBF, 0x83, 0x16, 0x03, 0xFF };
DeviceAddress sensore2 = { 0x28, 0xFF, 0x31, 0x2F, 0x84, 0x16, 0x04, 0x30 };
byte PU[5] = {15, 16, 17, 18, 19}; //pulsanti comando luci
byte PS[5]; //lettura stato pulsante
byte PSV[5];
//stato vecchio pulsante
byte VAL1 = 10; //stabilisce i pin vlvole con array
byte VAL2 = 11;
byte VAL3 = 12;
byte VALS1; //valvole stato
byte VALS2;
byte VALS3;
byte VALON1; //comando accensione valvole
byte VALON2;
byte VAEON1;
byte VAEON2;
float TEMP1; //temperatura
float TEMP2;
unsigned long TIME; //time pausa
byte rx[3]; //array ricezione
int tx[10]; //array trasmissione
int TI1; //temperatura impostata per TR1
int TR1; //temperatura rilevata per TR1
int TI2;
int TR2;
int TIE1;
int TIE2;
void setup(){
rs485.begin(9600); // inizializza seriale 485
delay(1000);
pinMode (2, OUTPUT); // pin comando RS485
digitalWrite (2, LOW);
tx[0] = 1; //nr. scheda master a cui trasmettere
for (byte com = 0; com < 5; com++){
pinMode(PU[com], INPUT); // dichiara il pulsante come input
digitalWrite(PU[com], INPUT_PULLUP); // abilita la resistenza di pull-up
PS[com] = HIGH;
PSV[com] = HIGH;
} //fine for
pinMode(VAL1, OUTPUT); //dichiara il Pin valvole come output
pinMode(VAL2, OUTPUT);
pinMode(VAL3, OUTPUT);
VALS1 = HIGH; //mette a alto lo stato valvole
VALS2 = HIGH;
VALS3 = HIGH;
digitalWrite(VAL1, VALS1); //mette a alto le uscite perchè i relè lavorano a negativo
digitalWrite(VAL2, VALS2);
digitalWrite(VAL3, VALS3);
sensors.begin(); //Inizializzo comunicazione
TIME = 0;
//EEPROM.put(0, 2050); //metodo per memorizzare interi
//EEPROM.put(4, 1950);
EEPROM.get(0, TIE1); //metodo per leggere interi
EEPROM.get(4, TIE2);
TI1 = TIE1;
TI2 = TIE2;
EEPROM.get(6, VAEON1);
EEPROM.get(8, VAEON2);
VALON1 = VAEON1;
VALON2 = VAEON2;
Serial.begin(9600);
Serial.print("EEprom ");
Serial.print(TI1);
Serial.print(" ");
Serial.println(TI2);
} //fine setup
void loop(){
rx[0]= 0;
rx[1]= 0;
rx[2]= 0;
//lavoro in loco
if( millis() - TIME > 5000 ){
sensors.requestTemperatures(); //Invio comando per leggere temperatura di tutti i sensori connessi
delay(20);
TEMP1 = sensors.getTempC(sensore1); //leggo temperatura
TEMP2 = sensors.getTempC(sensore2);
TR1 = TEMP1 * 100;
TR2 = TEMP2 * 100;
Serial.print("lettura ");
Serial.print(TR1);
Serial.print(" ");
Serial.println(TR2);
TIME = millis();
}
for (byte com = 0; com < 5; com++){
PS[com] = digitalRead(PU[com]); //legge i pin pulsanti
} //fine for
delay (20);
for (byte com = 0; com < 5; com++){
if (PS[com] != PSV[com] && PS[com] == LOW){
// da decidere cosa fanno i pulsanti
}
PSV[com] = PS[com]; //assegna lo stato pulsante al valore pulsante vecchio
} //Fine for
// se c'è una comunicazione aspetto che arrivino tutti
if (rs485.available()){
delay(10);
}
//legge i caratteri nel buffer e li mette nell'array
if (rs485.available() > 2 && rs485.available() < 4){
Serial.println("ricezione");
for (byte i = 0; i < 3; i++){
rx[i] = rs485.read();
Serial.print(rx[i]);
Serial.print(" ");
}
Serial.println();
} //fine for lettura ricevuto
else if (rs485.available()){ //svuota gli eventuali dati nel buffer
byte prov = rs485.read();
}
if (rx[0] == 5){ //RICONOSCE IL NR DELLA SCHEDA SLAVE -DA CAMBIARE IN BASE ALLA SCHEDA-
if (rx[2] == 11){VALON1 = !VALON1;}
if (rx[2] == 12){TI1 = TI1+100;}
if (rx[2] == 13){TI1 = TI1+50;}
if (rx[2] == 14){TI1 = TI1-100;}
if (rx[2] == 15){TI1 = TI1-50;}
if (rx[2] == 21){VALON2 = !VALON2;}
if (rx[2] == 22){TI2 = TI2+100;}
if (rx[2] == 23){TI2 = TI2+50;}
if (rx[2] == 24){TI2 = TI2-100;}
if (rx[2] == 25){TI2 = TI2-50;}
}
if(VALON1){ //controllo accensione prima valvola
VALS1 = HIGH;
tx[1] = 0;
tx[2] = 0;
}
if(!VALON1){
tx[2] = TI1; //comando accensione valvola accesa
if((TI1 == TR1) || (TR1 > TI1)){ //controllo temperature
VALS1 = HIGH;
tx[1] = 0;
}
if(TI1 - TR1 > 30 ){
VALS1 = LOW;
tx[1] = 1;
}
} //fine prima valvola
if(VALON2){
VALS2 = HIGH;
tx[4] = 0;
tx[5] = 0;
}
if(!VALON2){
tx[5] = TI2;
if((TI2 == TR2) || (TR2 > TI2)){
VALS2 = HIGH;
tx[4] = 0;
}
if(TI2 - TR2 > 30 ){
VALS2 = LOW;
tx[4] = 1;
}
}
if(VALS1 && VALS2) VALS3 = HIGH;
if(!VALS1 || !VALS2) VALS3 = LOW;
if (rx[0] == 5){
tx[3] = TR1;
tx[6] = TR2;
tx[7] = 0;
tx[8] = 0;
tx[9] = 0;
digitalWrite (2, HIGH); //trasmissione
Serial.println("trasmissione");
tx[0] = 1;
for (byte com = 0; com < 10; com++){
rs485.write (tx[com]);
Serial.print(tx[com]);
Serial.print(" ");
}
Serial.println();
digitalWrite (2, LOW); //fine trasmissione
delay(5);
}
for (byte i = 0; i < 3; i++){ //azzera array ricevuto per nuova lettura
rx[i] = 0;
}
//Fine for comanda luci
digitalWrite (VAL1, VALS1); // comanda le valvole
digitalWrite (VAL2, VALS2);
digitalWrite (VAL3, VALS3);
//if( millis() - TIME > 1800000){
//if(TIE1 != TI1){
//EEPROM.put(0, TI1); //metodo per memorizzare interi
//TIE1 = TI1;
//}
//if(TIE2 != TI2){
//EEPROM.put(4, TI2); //metodo per memorizzare interi
//TIE2 = TI2;
//}
//if(VAEON1 != VALON1){
//EEPROM.put(6, VALON1);
//VAEON1 = VALON1;
//}
//if(VAEON2 != VALON2){
//EEPROM.put(8, VALON2);
//VAEON2 = VALON2;
//}
//TIME = millis();
//}
} //fine LOOP
troverai dei Serial.print solo per trovare traccia del lavoro di arduino poi saranno cancellati
Grazie
ciao
non ho guardato il programma però...attenzione..un array di 10 elementi ha posizione da 0 a 9...non da 0 a 10 (che farebbero 11).
di solito in uno scambio dati si implementa un minimo di "controllo" dei dati trasmessi...un CRC, un check sum, un carattere di inizio e fine messaggio etc.
la seriale riceve un byte alla volta...sta a te gestire questi byte sapendo che dovrebbero essere "inseriti" in un char ( un byte) un int (due byte) un float (4 byte) etc.
Se t'interessa in QUESTA discussione si è trattato di come salvare dati, byte a byte, su variabili complesse come le struct.
diversamente potresti usare il protocollo modbus, ci sono molte librerie, che di per se ti fa già tutto...controllo del dato trasmesso, dati inviati e ricevuto sono int, ti assegna l'ID della scheda...e puoi decidere quale fa da master e quale fa da slave etc...
il master è supervisionato tramite scheda ethernet,
non mi servono eventuali controlli di invio dati,
mi servirebbe un modo semplice da trasmettere un numero intero superiore a 255 dallo slave al master
all'interno di un array di 10
Un intero, su Arduino, è composto da DUE bytes (16 bit) ... quindi, prendi l'intero, ti ricavi il byte più significativo e quello meno significativo e li trasmetti. Quando li ricevi, li rimetti assieme e ricostruisci l'intero.
Guglielmo
Grazie per le risposte.
il modo più semplice che ho trovato è dividere il numero intero con "highByte" e "lowByte",
di conseguenza aumentare l'array di trasmissione per i byte necessari, e sul secondo arduino,
ricompattare il numero con byte alto*256 + byte basso.
funziona alla perfezione, ancora grazie
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.