Vorrei costruire un misuratore di giri al minuto e distanza percorsa utilizzando un sensore a infrarossi TCRT5000 collegato al pin 2 (interrupt 0). I dati sono aggiornati una volta al secondo.
Fino a quando i dati sono inviati via Serial tutto funziona senza problemi ininterrottamente per ore. Se modifico il file per inviare gli stessi dati al display, parte tutto regolarmente ma, arrivati a un valore di distanza di circa 1400-1500 metri, i valori restano fissi.
Ho provato a riavviare, a scollegare e ricollegare, ad alimentare da una fonte esterna o solo dal pc ma il risultato è sempre lo stesso.
Ho utilizzato due sensori collegandone uno ad un arduino con il display e relativo programma e l'altro ad un arduino collegato al pc che trasmette i dati via serial. All'avvio tutto come dovrebbe fornendo anche gli stessi valori di giri al minuto (massima differenza di 0,2%). Alla distanza critica di circa 1500 m i valori sullo schermo si bloccano mentre il terminale del pc continua a riceverli (ho interrotto a una distanza di 200.000 metri).
Per il funzionamento del display ho utilizzato la libreria LCD5110_Basic. Ho provato anche altre librerie, compresa quella di adafruit, ma la sola differenza è un peggioramento, probabilmente dovuto al peso delle librerie stesse.
Questo è il codice che invia i dati via Serial:
volatile unsigned long timer1 = 0;
volatile unsigned long result = 0;
volatile long giri = 0;
unsigned long microsRPM;
unsigned long lastmillis = 0;
int diametro = 120; //mm del diametro
int circonferenza = diametro*3.14;
long distanza = 0;
void setup() {
Serial.begin(9600);
attachInterrupt(0, rpm_fan, FALLING);
}
void loop() {
if (millis() - lastmillis == 1000) {
detachInterrupt(0);//Disable interrupt when calculating
microsRPM = 60000000 / result;
distanza = (giri*circonferenza)/1000;
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
//invia i dati a serial
Serial.print(" micros RPM: ");
Serial.print(microsRPM);
Serial.print(" distanza: ");
Serial.println(distanza);
lastmillis = millis();
}
}
void rpm_fan() {
giri++;
result = micros() - timer1;
timer1 = micros();
}
Questo è quello per l'LCD5110:
#include <LCD5110_Basic.h>
/*
* Arduino UNO
LCD5510: RST - CE - DC - Dim - Clk - Vcc - BL -Gnd
Pin: 6 7 5 11 13 5V GND GND
Hard SPI? MOSI SCK
* Arduino Leonardo
LCD5510: RST - CE - DC - Dim - Clk - Vcc - BL -Gnd
Pin: 6 7 5 MOSI SCK 5V GND GND
Hard SPI? MOSI SCK
*/
LCD5110 lcd(13,11,5,6,7);
extern unsigned char SmallFont[]; //dimensioni font caratteri
extern unsigned char MediumNumbers[]; //dimensioni font numeri
extern unsigned char BigNumbers[];
volatile unsigned long timer1 = 0;
volatile unsigned long result = 0;
volatile long giri = 0;
unsigned long microsRPM;
unsigned long lastmillis = 0;
int diametro = 120; //mm del diametro
int circonferenza = diametro*3.14;
long distanza = 0;
void setup() {
attachInterrupt(0, rpm_fan, FALLING);
lcd.InitLCD(58);
}
void loop() {
if (millis() - lastmillis == 1000) {
noInterrupts();//Disable interrupt when calculating
microsRPM = 60000000 / result;
distanza = (giri*circonferenza)/1000;
interrupts(); //enable interrupt
//dati con LCD 5510
lcd.clrScr();
printDati();
//lcd.update();
lastmillis = millis(); // Uptade lasmillis
}
}
void rpm_fan() {
//half_revolutions++;
giri++;
result = micros() - timer1;
timer1 = micros();
}
void printDati() {
lcd.setFont(SmallFont);
lcd.print("Distanza",0,0);
lcd.print("RPM",0,32);
lcd.setFont(MediumNumbers);
lcd.printNumI(distanza,0,8);
lcd.setFont(BigNumbers);
lcd.printNumI(microsRPM,24,24);
}
Le uniche differenze sono l'inserimento della libreria supplementare e le parti per visualizzare i dati in sostituzione di quelle con serial.
Ho letto e seguito le indicazioni in vari forum riguardo gli interrupt e l'LCD5110, compresi i collegamenti consigliati e come e quando interrompere l'interrupt ma non ho risolto il problema.
Sapreste aiutarmi?