[RISOLTO] Trasmettere e ricevere un array di numeri interi su rs485

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.