Errore che non trovo

Ciao a tutti, sto creando un piccolo circuito in pratica tramite un VL530X ed un sensore liquidi non a contatto dovrei riuscire a capire quanto acqua ho ancora nella cisterna, il problema è nei conti sicuramente imposto male le equazioni ma non capisco dove sbaglio.

La cisterna è 1,2m di diametro per 2m di altezza per 2000 litri di acqua.
Ora ho impostato delle variabili sia float che int per ottenere i vari dati ma ottengo dati sbagliati, non so perché, ho convertito di dati del VL530X, che dovrebbe dare i dati in mm, in cm per quando l'altezza dell'acqua è sotto il metro, mentre li converto in metri per quando sono sopra la metro di lettura.

Potete spiegarmi dove sbaglio non lo arrivo a capire.
Ho fatto varie prove, prima inserendo l'aerea della base del cilindro, pensando che fosse li il problema ho inserito la formula del volume ma ho ancora l'errore sia nella sezione cm che nella sezione m

Vi allego anche uno screenshot delle letture che ottengo.

Grazie per il possibile aiuto.

#include <SPI.h>
#include <Wire.h>               // Libreria per sensore laser
#include <VL53L0X.h>            // Libreria per sensore laser

// Costanti varie
char str_CM [7];               // Stringa per scrittura altezza
char Litri[7];                 // Stringa per scrittura litri

// Sezione sensore laser
#define HIGH_ACCURACY   // Accuratezza laser
VL53L0X sensor;         // Sensore laser

// Pin sensore non a contatto
#define sensore_H2O 6


void setup() {
pinMode(sensore_H2O, INPUT_PULLUP);
  Wire.begin();
  sensor.init();
  sensor.setTimeout(500);
  sensor.startContinuous();
  Serial.begin(9600);
}

void loop() {
int A = digitalRead(sensore_H2O);
int distanza = sensor.readRangeSingleMillimeters();
if( A==LOW){
// Sezione calcolo sotto 1 metro di altezza
    if((distanza/10.0)<=99){
      float distanza_CM = (float)(distanza/10.0);  //Distanza in cm
      dtostrf(distanza_CM, 1, 0, str_CM);
      Serial.print(str_CM);
      Serial.println(" cm");
      int L = (((3,14*(60*60))*distanza_CM)/1000);  // Calcolo litri
      int Hy = ((86*L)/2000);       // Calcolo altezza rettangolo
      int y = (117-Hy);  // Calcolo coordinata y rettangolo percentuale
      int Perc = ((L/2000)*100);    // Calcolo percentuale litri
      dtostrf(L, 1, 0, Litri);
      Serial.print(Litri);
      Serial.println("litri");
      Serial.print(Perc);
      Serial.println(" %");
      Serial.print("Hy: ");
      Serial.println(Hy);
      Serial.print("y: ");
      Serial.println(y);
      Serial.println("");  
    }
    else{
      float distanza_M = (float)(distanza/1000);  // Distanza in metri
      dtostrf(distanza_M, 1, 1, str_CM);
      Serial.print(str_CM);
      Serial.println(" m");
      Serial.print(distanza);
      Serial.println(" dist");
      int L = (((3,14*(0,6*0,6))*distanza_M)*1000);  // Calcolo litri
      int Hy = ((86*L)/2000);       // Calcolo altezza rettangolo
      int y = (117-Hy);  // Calcolo coordinata y rettangolo percentuale
      int Perc = ((L/2000)*100);    // Calcolo percentuale litri
      dtostrf(L, 1, 0, Litri);
      Serial.print(Litri);
      Serial.println("litri");
      Serial.print(Perc);
      Serial.println(" %");
      Serial.print("Hy: ");
      Serial.println(Hy);
      Serial.print("y: ");
      Serial.println(y);
      Serial.println("");
    }
}
delay(1500);
}

A parte forse altre cose non ho indagato

Ma 3,14?

Sicuro tu sei?

Nooo la virgola per i decimali, niente non l'avevo completamente notata.

Ok ho controllato tutti i decimali, ho sistemato la parte che calcola la percentuale ma non riesco a capire perché Hy nella parte else, mi da un valore negativo, mentre nella parte if non ho il problema.
Ho risolto solo specificando nella riga di comando di Hy che L è unsigned int.

#include <SPI.h>
#include <Wire.h>               // Libreria per sensore laser
#include <VL53L0X.h>            // Libreria per sensore laser

// Costanti varie
char str_CM [7];               // Stringa per scrittura altezza
char Litri[7];                 // Stringa per scrittura litri

// Sezione sensore laser
#define HIGH_ACCURACY   // Accuratezza laser
VL53L0X sensor;         // Sensore laser

// Pin sensore non a contatto
#define sensore_H2O 6


void setup() {
pinMode(sensore_H2O, INPUT_PULLUP);
  Wire.begin();
  sensor.init();
  sensor.setTimeout(500);
  sensor.startContinuous();
  Serial.begin(9600);
}

void loop() {
int A = digitalRead(sensore_H2O);
int distanza = sensor.readRangeSingleMillimeters();
if( A==LOW){
// Sezione calcolo sotto 1 metro di altezza
    if((distanza/10.0)<=99){
      float distanza_CM = (float)(distanza/10.0);  //Distanza in cm
      dtostrf(distanza_CM, 1, 0, str_CM);
      Serial.print(str_CM);
      Serial.println(" cm");
      int L = (int)(((3.14*(60*60))*distanza_CM)/1000);  // Calcolo litri
      int Hy = ((86*L)/2000);       // Calcolo altezza rettangolo
      int y = (117-Hy);  // Calcolo coordinata y rettangolo percentuale
      int Perc =((float)L/2000)*100;    // Calcolo percentuale litri
      dtostrf(L, 1, 0, Litri);
      Serial.print(Litri);
      Serial.println("litri");
      Serial.print(Perc);
      Serial.println(" %");
      Serial.print("Hy: ");
      Serial.println(Hy);
      Serial.print("y: ");
      Serial.println(y);
      Serial.println("");  
    }
    else{
      float distanza_M = (float)(distanza/1000.0);  // Distanza in metri
      dtostrf(distanza_M, 1, 2, str_CM);
      Serial.print(str_CM);
      Serial.println(" m");
      Serial.print(distanza);
      Serial.println(" dist");
      int L = (int)(((3.14*(0.6*0.6))*distanza_M)*1000);  // Calcolo litri
      int Hy = ((86*(unsigned int)L)/2000);       // Calcolo altezza rettangolo
      int y = (117-Hy);  // Calcolo coordinata y rettangolo percentuale
      int Perc =((float)L/2000)*100;    // Calcolo percentuale litri
      dtostrf(L, 1, 0, Litri);
      Serial.print(Litri);
      Serial.println(" litri");
      Serial.print(Perc);
      Serial.println(" %");
      Serial.print("Hy: ");
      Serial.println(Hy);
      Serial.print("y: ");
      Serial.println(y);
      Serial.println("");
    }
}
delay(1500);
}

Perche distanza può arrivare a 1000 circa
0.6×0.6×3.14 fa circa 1.2
Ovvero circa 1200
Moltiplicato 86 fa?

Che supera il limite di un int?

Con il sensore non misuri la distanza dalla superficie dell'acqua? Quindi all'aumentare della distanza diminuisce la quantità d'acqua!

Poi A non serve:
if(digitalRead(sensore_H2O) == LOW) {}

e quel gigantesco if/else è inutile: leggi il valore e poi, nella visualizzazione, scrivi i metri o i centimetri.
Il "rettangolo" non capisco a che cosa serva...

int Perc =((float)L/2000)*100;
Perché fai il float di un int per ottenere un risultato int?...

Datman:
int Perc =((float)L/2000)*100;
Perché fai il float di un int per ottenere un risultato int?...

Direi perché se la scrivesse senza il casting, dividere L, che è int, per 2000, altro valore int, significherebbe una divisione intera quindi avendo valori di L che vanno da 0 a 1999 (che suppongo sia il range della variabile L visto che cerca una percentuale) darebbero sempre zero.

docdoc:
Direi perché se la scrivesse senza il casting ...

Difatti .. tipico errore :slight_smile:

Poco tempo fa c'è stato un webinar di Microchip intitolato "How to Write Bad C Code (and Not Realize It)" e, tra i numerosi esempi, ce ne erano vari che portavano ad errori di questo tipo. :smiley:

Guglielmo

Uhmm... Sì, bisognerebbe almeno dividere per 2000.0.
Se moltiplicassi prima per 100, invece, come ho fatto qualche volta, ci sarebbe un overflow quando il valore temporaneo, che può arrivare a 199900, supera 32767?

... se è un int che vale 1999 e lo moltiplichi per 100 ... 0x07CF moltiplicato 0x0064 ti darebbe 0x00030CDC che troncato a 16 bit (visto che stai lavorando con degli int) da 0x0CDC che vale 3292 ... non proprio il valore da te cercato :smiley:

Guglielmo

Sì, chiaro. Anche durante i calcoli parziali usa il tipo di dati che è stato definito.

Il mio post #3 più o meno queste cose voleva significare

Ciao a tutti, cerco di rispondere, o meglio di spiegarvi la mia idea :slight_smile:
Premessa questo sketch per adesso lo uso tramite monitor seriale, ma in futuro verrà modificato per usare un display tft, Gugliemo quello per cui mi hai consigliato di usare un convertitore da 5 a 3.3V per evitare di bruciarlo :wink:

Standardoil:
Perche distanza può arrivare a 1000 circa
0.6×0.6×3.14 fa circa 1.2
Ovvero circa 1200
Moltiplicato 86 fa?

Che supera il limite di un int?

int L = (int)(((3.14*(0.6*0.6))*distanza_M)*1000);  // Calcolo litri

Con questa formula mi calcolo i litri del recipiente, in pratica la mia idea che mi ha fatto scrivere la riga è questa: (3.14*(0.6*0.6)) mi calcola l'area della base in metri, questa la moltiplico per l'altezza che ottengo dal sensore, convertita in metri (distanza_M) per avere i metri cubi, moltiplico per 1000 ed ottengo i litri.
Quasi sicuramente nello sketch finale tolgo la forumula per l'area della base e metterò direttamente il valore in metri quadrati.

int Hy = ((86*(unsigned int)L)/2000);
int y = (117-Hy);

Da qui tramite una proporzione ottengo l'altezza del rettangolo che dovrebbe indicarmi la percentuale di acqua nel recipiente, sul display tft per leggere i dati non appena mi arriva il convertitore 5V-3.3V, 86 è l'altezza massima in pixel che deve avere il rettangolo (il rettangolo avrà una coordinata y compresa tra 31 e 117). 86:2000=Hy:L
Dove 2000 sono i litri massimi, Hy è l'altezza del rettangolo da trovare, L sono i litri letti dalla precedente forumla.
y ovvero la coordinata da dove iniziare a disegnare il rettangolo la ottengo con la seconda riga, x è fissa, non so come si possano dare le coordinate in altro modo conosco solo la versione "base" quindi con la riga tft.fillRect(x, y , l, h, colore); quindi x ed l sono fissi come valori y la ottengo da 117-Hy e Hy dalla formula detta prima.
Mi verrebbe più comodo capire come dire ad Arduino di disegnare partendo da 117 e salire, ma non ci sono riuscito quindi ho by-passato il problema con questa formula.

Datman:
Con il sensore non misuri la distanza dalla superficie dell'acqua? Quindi all'aumentare della distanza diminuisce la quantità d'acqua!

No farò misurazioni esterne al recipiente per motivi logistici, non mi è facile arrivare alla bocca del recipiente, quindi tramite il sensore VL53... leggerò l'altezza da terra che si bloccherà non appena il sensore per liquidi non a contatto manda un segnale, attualmente per provare lo sketch ho messo un pulsante in pullup per simulare il sensore, poi dovrò cambiare la riga da low e high e la parte setup, questo per capirci è il sensore solo che il mio funziona a 5V:
https://www.amazon.it/Lembeauty-Serbatoio-Contenitore-Interruttore-rilevamento/dp/B07KZT8F6R/ref=pd_day0_2?pd_rd_w=Ph6U7&pf_rd_p=2a4cbc0a-de25-48fb-acfc-b5dc3175ff51&pf_rd_r=15ATNA7VGB9RHTTG7A3V&pd_rd_r=cc410557-8920-48e6-bd68-1aeb21a15d3c&pd_rd_wg=IZv9L&pd_rd_i=B07KZT8F6R&psc=1

Datman:
Poi A non serve:
if(digitalRead(sensore_H2O) == LOW) {}

e quel gigantesco if/else è inutile: leggi il valore e poi, nella visualizzazione, scrivi i metri o i centimetri.
Il "rettangolo" non capisco a che cosa serva...

int Perc =((float)L/2000)*100;
Perché fai il float di un int per ottenere un risultato int?...

sull'if ci devo lavorare per accorciarlo, effettivamente è lungo e manca tutta la parte per comandare il tft e la misurazione della carica della batteria, per adesso ho iniziato a scrivere lo sketch seguendo gli appunti presi su carta, forse sbaglio metodo, ma dopo avere buttato l'idea su carta la sto riportando su Arduino, per provare i vari pezzi prima di andare avanti.
solo che su carta mi è venuto più semplice fare delle misurazioni divise in metri e in cm per quando scenderò sotto il metro di altezza.
Converto in float il Perc perché quando l'ho impostato senza il casting non mi dava risultati mi dava sempre 0%, anche con altezze di 1,5m e più.

Scusate ancora se mi sono dilungato e sempre grazie per i vostri consigli.

Se il pulsante è in pullup, devi usare una resistenza di pulldown; se usi una resistenza di pullup, il pulsante deve chiudere a massa (pull down).

Datman:
Se il pulsante è in pullup, devi usare una resistenza di pulldown; se usi una resistenza di pullup, il pulsante deve chiudere a massa (pull down).

Scusa ho scritto male, ho dichiarato il pulsante come input_pullup usando la resistenza interna di Arduino

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