Arduino nano,display oled , water flow meter

Ciao a tutti,
ho un progetto di un controllo quantita' acqua gestito con Nano, sensore ys-f201 .
Il tutto funziona mandandomi del serial i ml al secondo e il volume erogato.

Ho inserito un display oled e funziona anche questo fino al Void Setup.

Non riesco a mettere a display i 2 dati che visualizzo nel serial monitor.

In realta' funzionavam poi ho ripreso lo sketch dopo 2 anni e ho modificato qualcosa non riesco a capire lo sbaglio .

potete aiutarmi ?

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Creo istanza del display
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT);


byte sensorInterrupt = 0;  // 0 = digital pin 2
int sensorPin       = 2;
volatile int pulse;
//volatile byte pulseCount;

float flowRate;
float volume = 0;
float calibrationFactor =10.5 ;
long dt =0; 
long t0=0;

unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long mlprecedenti;
unsigned long lttotali;
unsigned long oldTime;

int i = 0 ;
int o = 7;

void setup() {
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C);
  Serial.begin(9600);
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);
  attachInterrupt(digitalPinToInterrupt(sensorPin), increase, RISING);
  t0=millis();
  //Provo ad inizializzare il display all'indirizzo 0x3C (il tuo potrebbe essere diverso)
  

  // Pulisco il buffer
  display.clearDisplay();
  //Setto il colore del testo invertito
  display.setTextColor(WHITE, BLACK);
  display.setTextSize(1);
  display.setCursor(50, 20);
  display.fillRect(0, 16, SCREEN_WIDTH, 1, WHITE);
  display.fillRect(0, 48, SCREEN_WIDTH, 1, WHITE);
  display.print("LITRI ");
  display.setCursor(65, 50);
  display.print("mL");
  display.setTextSize(2);
  display.setCursor(100, 30);
  display.fillRect(79, 29, SCREEN_WIDTH, 17, WHITE);
  display.display();
}

void loop() 
  {
  if  ( Serial . available ( ) )  { 
    if ( Serial . read ( ) == 'r' ) volume = 0 ; //reset the volume if we receive 'r' 
  } 
  float  frequency = GetFrequency ( ) ;  //we obtain the frequency of the pulses in Hz 
  float  flow_L_m = frequency / calibrationFactor ; //calculate the flow in L/m 
  dt = millis ( ) - t0 ;  //calculate the time variation 
  t0 = millis ( ) ; 
  volume = volume + ( flow_L_m / 60 ) * ( dt / 1000 ) ;  // volume(L)=flow(L/s)*time(s)
  Serial.print("Flow: ");  
  Serial.print(flow_L_m,3);  
  Serial.print("L/min\tVolume: ");  
  Serial.print(volume,3) ;  
  Serial.println( "L" ) ; 
  
  }



void increase (){
  pulse ++ ;

}

//---Function to obtain pulse frequency-------- 
int  GetFrequency ( )  
{ 
  int  frequency ; 
  pulse  =  0 ;    //We set the number of pulses to 0 
  interrupts ( ) ;     // We enable the interruptions 
  delay ( 1000 ) ;    //sample for 1 second 
  noInterrupts ( ) ;  // We disable the interruptions 
  frequency = pulse ;  //Hz(pulses per second) 
  return  frequency ; 
}



Ciao, forse "funziona" fino al setup perché non fai nulla nel loop per stampare sul display....

Spiegati meglio. intendi che il codice che c'e' dentro alla setup viene eseguito tutto ??

Comunque:

  1. metti la display.begin prima di display.clearDisplay
  2. metti un pò di Serial.println("") nel setup, ad esempio una subito dopo la Serial.begin(9600) , una prima di display.begin e una prima di display.clearDisplay
void setup() {
  Serial.begin(9600);
  Serial.println("1.")
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);
  attachInterrupt(digitalPinToInterrupt(sensorPin), increase, RISING);
  t0=millis();
  //Provo ad inizializzare il display all'indirizzo 0x3C (il tuo potrebbe essere diverso)
  Serial.println("2.");
  display.begin( SSD1306_SWITCHCAPVCC, 0x3C);
  Serial.println("3.");
  // Pulisco il buffer
  display.clearDisplay();  ...

Ciao, si nel setup viene eseguito tutto , infatti ho modificato come mi hai detto e nel Serial ora in partenza vedo 1,2,3 e poi inizia a leggere i valori della portata.

il mio problema e' che non mi visualizza i valori nel display, appena inserisco un display print e un display.display nel Loop si blocca anche il codice

appena inserisco le funzioni per stampare nel display si blocca il ciclo loop.
Non riesco a risolvere

Sei tu che hai bloccato il loop che gira alla velocità 1 ciclo ogni secondo. Nel loop chiami questa funzione GetFrequency() al cui interno c'è un delay(1000).

Poi la cosa non ha senso, gli interrupt su arduino sono abilitati e nella funzione tu li riabiliti, allora attendi 1 secondo con delay() e disabiliti gli interrupt e li lasci disabilitati.

Con gli interrupt disabilitati non funge più nulla neanche la seriale.

Per non parlare delle altre stranezze che sono davvero troppe.

Devi ripensare tutto evitando di usare delay() e al suo posto usare la funzione millis.

uint32_t millis1s;
void setup() {
     // qui copiaci il tuo codice e alla fine
     millis1s = millis();
]

void loop() {
    if (millis() - millis1s >= 1000) {
        millis1s = millis();
        // il codice tra queste graffe sarà eseguito ogni 1 secondi
       // quindi qui accedi al valore di pulse e lo salvi in una variabile locale
       int lpulse = pulse;
       pulse = 0;
       // fai i tuoi calcoli qui usando la variabile *lpulse*, salvi i risultati dei 
       tuoi calcoli in variabili globali e poi fuori da queste graffe li stampi sul
       display.
    }
    
}

PS: sarebbe bene non stampare a raffica sul display ma temporizzando
sempre con millis.

Ciao.

D'accordo grazie.

La cosa strana è che in qualche modo funzionava . Poi in questi giorni ho fatto modifiche e boh. Sicuramente devo studiare .

Ci provo

Con certezza il codice che hai pubblicato non può funzionare. Nel codice che scriverai in futuro fai attenzione con noInterrupt().

Con il codice che ho scritto non ti serve più noInterrupt().
Lascia da parte l'azzeramento tramite seriale e concentrati sul calcolo e la visualizzazione. Imperativo non usare delay() e vedrai che tutto funzionerà.

Questo che segue è un esempio:

Nota che alla fine dell'articolo c'è link alla simulazione

Dove viene impiegato millis allo stesso modo, cioè millis() sottratto il tempo di millis salvato in precedenza se è maggiore o uguale l'intervallo stabilito. Ad esempio millis1s vale 1000 allora quando
millis() vale 2000 = (2000 - 1000) >= 1000 si lo è quindi esegue il codice tra le graffe.

Ciao.

penso di avere capito. Ora provo subito a riscrivere il codice .

Ringrazio molto per la pazienza .

Faccio sapere

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