Stazione meteo con 3 slave AT85

Buongiorno a tutti, sto cercando di sviluppare una stazione meteo che dovrà visualizzare i dati di temperatura, umidità e pressione (in seguito anche l'orario) utilizzando un sensore BMP + AHT. Il programma funziona e sulla seriale mi dà i dati corretti; questi vengono inviati via I2C a 3 AT85 che comandano dei display TM1637; qui scatta il problema di cui non sono riuscito a scoprire la causa, infatti i dati rilevati sulla seriale sono:

IMG_1585

Mentre sui singoli TM mi vengono visualizzati:

IMG_1584
dove il solo dato corretto è quello della pressione.

Il programma master (ancora da rifinire) è:

#include <Wire.h>
#include <BMx280I2C.h>
#include <SparkFun_Qwiic_Humidity_AHT20.h>

#define I2C_ADDRESS 0x77

AHT20 aht;
BMx280I2C bmx280(I2C_ADDRESS);

double prex_cum, temp_cum, humd_cum;
double prex_old, temp_old, humd_old;
double prex, temp, humd;
int prex1, temp1, humd1;
int cont = 0;
byte dato1[4]; //dato da inviare - pressione
byte dato2[4]; //dato da inviare - temperatura
byte dato3[4]; //dato da inviare - umidità

int el = 0;
int u_s, d_s, u_m, d_m, u_h, d_h, f, u_t, d_t, t, vuoto;

byte digits[11] = {
  B01111110,  // 0
  B00110000,  // 1
  B01101101,  // 2
  B01111001,  // 3
  B00110011,  // 4
  B01011011,  // 5
  B01011111,  // 6
  B01110000,  // 7
  B01111111,  // 8
  B01111011,  // 9
  B00000001   // "-"
};

void setup() {
  Serial.begin(9600);
  Wire.begin();

  bmx280.begin();
  bmx280.resetToDefaults();

  bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
  bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
  bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);

  if (aht.begin() == false)
  {
    Serial.println("AHT20 non trovato. Controllare collegamenti.");
    while (1);
  }
  Serial.println("AHT20 attivato.");

}

void loop() {
  richiestaDati();

  prex1 =  (prex / 100) ;
  dato1[3] = (prex1 % 10);
  dato1[2] = ((prex1 / 10 ) % 10 );
  dato1[1] = ((prex1 / 100) % 10 );
  dato1[0] = ((prex1 / 1000) % 10 );
  delay(200);

  temp1 = (temp * 100);

  dato2[3] = (temp1 % 10);
  dato2[2] = ((temp1 / 10 ) % 10 );
  dato2[1] = ((temp1 / 100) % 10 );
  dato2[0] = ((temp1 / 1000) % 10 );
  delay(200);

  humd1 = (humd * 100);

  dato3[3] = (humd1 % 10);
  dato3[2] = ((humd1 / 10) % 10);
  dato3[1] = ((humd1 / 100) % 10);
  dato3[0] = ((humd1 / 1000) % 10);
  delay(200);

  // Trasmette i dati
  if (cont > 0) {
    Wire.beginTransmission(0x08);

    Serial.print("Pressione: ");
    Wire.write(dato1[0]);  // BLU
    Serial.print(dato1[0]);
    Wire.write(dato1[1]);
    Serial.print(dato1[1]);
    Wire.write(dato1[2]);
    Serial.print(dato1[2]);
    Wire.write(dato1[3]);
    Serial.println(dato1[3]);
    Wire.endTransmission(0x08);
    delay(200);
    Wire.beginTransmission(0x09);

    Serial.print("Temperatura: ");
    Wire.write(dato2[0]);  // GIALLO
    Serial.print(dato2[0]);
    Wire.write(dato2[1]);
    Serial.print(dato2[1]);
    Wire.write(dato2[2]);
    Serial.print(dato2[2]);
    Wire.write(dato2[3]);
    Serial.println(dato2[3]);
    Wire.endTransmission(0x09);
    delay(200);

    Wire.beginTransmission(0x0A);

    Serial.print("Umidità: ");
    Wire.write(dato3[0]);  // VERDE
    Serial.print(dato3[0]);
    Wire.write(dato3[1]);
    Serial.print(dato3[1]);
    Wire.write(dato3[2]);
    Serial.print(dato3[2]);
    Wire.write(dato3[3]);
    Serial.println(dato3[3]);
    Wire.endTransmission(0x0A);

    cont = 0;
    delay(1000);
  }

  cont ++;
  Serial.println("");
}

void richiestaDati() {

  bmx280.measure();
  do {
    delay(50);
  } while (!bmx280.hasValue());

  prex = bmx280.getPressure();

  if (aht.available() == true){
    //Get the new temperature and humidity value
    temp = aht.getTemperature();
    humd = aht.getHumidity();
  }
  delay(2000);
}

mentre gli slave utilizzano:

/* Slave Receive
 *  Modello per lo slave su AT85
 */

#include "Wire.h"
#include <TM1637Display.h>
#include <Arduino.h>

#define CLK 3
#define DIO 4

int tem[4] ;
int temperatura = 0;

TM1637Display display(CLK, DIO);

void setup() {
  display.setBrightness(2);
  Wire.begin(0x09);
  Wire.onReceive(riceviDati);
  delay(100);
}

void loop() {

}

void riceviDati() {
  byte temp1 = Wire.read();
  byte temp2 = Wire.read();
  byte temp3 = Wire.read();
  byte temp4 = Wire.read();

  tem[0] = temp1;
  tem[1] = temp2;
  tem[2] = temp3;
  tem[3] = temp4;

  temperatura = ((tem[0] * 1000) + (tem[1] * 100) + (tem[2] * 10) + tem[3])- 500;
  display.showNumberDecEx(temperatura, (0x80 >> 1), false);
}

Qualcuno mi saprebbe indirizzare su come risolvere le discrepanze? Dove sbaglio?

Saluti + grazie

Enrico

Comunque dubito che i centesimi potranno avere un'utilità, sia per le caratteristiche dei sensori che per gli errori di misura!

Hm, non ho ancora provato il tuo codice (non ho sottomano dei display 7seg) ma mi chiedevo intanto perché qui sottrai 500:

  temperatura = ((tem[0] * 1000) + (tem[1] * 100) + (tem[2] * 10) + tem[3])- 500;

E poi se ti serve mandare un dato che non supera mai 10.000 perché mandare 4 byte che rappresentano le 4 cifre che poi devi "ricomporre" invece di mandare (e leggere) direttamente i soli 2 byte che rappresentano l'intero (es. "tem[0]*256+tem[1]"), o al limite i 4 caratteri come stringa (da convertire con "atoi()")?

Chiedo venia a tutti, mi sono accorto solo adesso che per gli slave utilizzavo un programma con una correzzione dei valori (5 ° di temperatura e 10% per l'umidità) ricavata da controlli con termometro a mercurio e da un igrometro per compensare i valori di un precedente progetto con altri microcontrollori.

D'accordo con Datman sui centesimi.

Pe docdoc, mi era sembrato più semplice (vista la mia inesperienza) utilizzare 4 valori e poi inserire lam virgola.

Grazie a tutti

Enrico

Ok, per il "-500" ora è chiaro, ma il problema sarebbe stato più evidente se tu avessi catturato le letture (mostrate nella seriale) che corrispondevano esattamente alla foto dei display. Infatti non sembra essere quello perché se tu rilevavi 24,02 gradi anche sottraendo 500 avresti dovuto vedere 19,02 e non 18,93 per cui non capivo bene la correlazione. Vedendo invece la seriale con 2402 ed il display con 19.02 sarebbe stato immediato capirlo, non trovi?..:wink:
Per questo dico (chiedo) sempre di postare tutti i dati di qualche test (output seriale del programma se disponibile, ed esattamente cosa c'è in input e cosa si ottiene).

Con i display a 7 segmenti di quel tipo si fa anche così (sebbene la funzione richieda un valore intero, poi il discorso virgola è solo di visualizzazione), ma in genere è opportuno cercare di ottimizzare le comunicazioni soprattutto se tra due programmi, come in questo caso: se tu hai un valore intero (ok, a parte la pressione sono float ma a 2 decimali che, moltiplicandoli per 100, diventano di fatto degli "int") è meglio passare il valore intero che mettersi a "farlo a pezzi", mandarlo e poi "ricostruirlo"... :sunglasses: Come dico sempre, se devono "parlare" tra loro due programmi facciamoli "parlare la loro lingua".

Concordo su tutto.

GRAZIE a tutti.

Enrico

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.