consigli per Contagiri a lancetta

volevo modificare questo codice per eliminare il doppio rilevamento ad ogni giro.
http://www.arduino.cc/playground/Main/ReadingRPM

a primo acchitto, vedendo quel 30 nel calcolo, pensavo che inserendo 60 avrei risolto, ma mi ritornano valori dell'ordine dei 20000!! e soprattutto molto ma molto istabili!

suppongo sia un'errore nei calcoli e nelle variabili, nelle quali commetto sempre errori!

ci gioco da pochissimo, abbiate pietà!

ciao e grazie!

io non ho capito bene:
quel codice ad ogni passare sul sensore della ventola aumenta una variabile di uno (questo grazie all'interrupt) poi quando vede nel loop che la variabile è a 20 calcola i millisecondi impiegati e fa 20/millisecondi, il tutto per 1000 così avrai i giri al secondo, non capisco la difficoltà :roll_eyes:

anzi leggendo i commenti al codice ci sono 2 sensori quindi ogni giro genera 2 interrupt

giri al secondo dici?

io ho connesso un'aggeggino che usavo tempo fà per testare alcune CDI, un semplice disco con un sensore di hall e una calamita. un'impulso per giro!

a quello che dovrebbe essere una rotazione di circa 1000-1500 giri minuto il programma ne restituisce circa 500. poi, al massimo l'aggeggino raggiunge circa 15.000 RPM, ma mi segna massimo 5000 giri!

strano dico io!

niente, alla fine ho cancellato tutto, foglio bianco e ho riscritto tutto da me. Non sarà ottimizzato e perfetto, ma funziona e restituisce il giusto conteggio!

bhe, almeno ci si avvicina. perche ho deciso di eseguire i calcoli sotto interrupt, pertanto una lieve imperfezione ci sarà. Ma il progetto è di sola visualizzazione, pertanto va bene!

ho attaccato un LCD e buttato su il risultato. regolato il tutto, è abbastanza reattivo.

ora il prossimo step che mi è venuto in mente è.....visualizzare il tutto in "analogico", cioè a dire, a lancetta!

l'idea sarebbe di prendere un piccolo servo, il più veloce che trovo ( ne ho visto uno a 0.07 sec.) e porlo dietro un quadrante con una lancetta attaccata!

però, al momento non ho idea di come arrivare dai giri ai gradi! consigliate un map()? o che altro?

Ciao,

l'idea sarebbe di prendere un piccolo servo, il più veloce che trovo ( ne ho visto uno a 0.07 sec.) e porlo dietro un quadrante con una lancetta attaccata!

ora, non so come funzionino i contagiri delle auto, ma penso siano elettronici.
Perchè non usare uno di quelli?
Oppure un vu-meter analogico a cui cambi solo la scala?

bhe, perche i Vu-meter andrebbero in crisi con un minimo di vibrazioni del mezzo, e quelli delle auto sono.....un po grossini!

poi suppongo che quelli delle auto o moto, siano a servo, fanno pure il check iniziale per regolare il tutto!

i Vu-meter andrebbero in crisi con un minimo di vibrazioni del mezzo,

non hai spiegato dove andrebbero montati.. :roll_eyes:

poi suppongo che quelli delle auto o moto, siano a servo,

che siano a servo o meno, son già assemblati e pure l'enclosure è tosta.
Penso che da un rottamaro non ti costi poi molto..

NUlla vieta naturalmente di farsi il contagiri partendo da 0 XD

si hai ragione, scusa. non ho ben spiegato il progetto!

si parla di un tentativo di creazione di strumentazione per la mia Vespa da gara.

vedrò di andare per step, ma alla fine vorrei qualcosa che abbia: contagiri, sensore temperatura liquido, voltmetro batteria, e controllare un servo che in base ad una tabella e al numero di giri mi apra la valvola di scarico. poi chi sa, se ci si riesce ci metto pure la sonda K!

progetto arduo? forse si, per le mie nozioni di programmazione, ma non demordo!

poi se mi date anche una mano....ce la posso fare! :slight_smile:

Scusate l' OT....
valvola di scarico ???
vuol dire che monti un cilindro rotax 123 ??? ne ho venduto uno qualche mese fà....
se hai quel cilindro ti do un consiglio... procurati una rave pneumatica.... sviluppare una mappatura variabile non è cosa da poco... e se dovessi gestire solo quella metti che si può anche fare anche se ci vogliono giorni sul banco di prova ma puoi il micro deve gestire anche gli altri sensori e lo schermo... devi fare un codice più che perfetto :wink:

contattami via msn o mail e ti faccio vedere il mezzo. qui mi sembra un po OT.

bhe, di certo non voglio fare tutto e subito. parto con il conta giri, e temperatura, poi pian piano....si vedrà!

ho dato un'occhiata alla libreria servo, sembra semplice da usare. bastano i gradi o i millisecondi da dare in pasto al servo!

vedremo se riesco a fare qualcosa! provo a reperire un servo nel pomeriggio!

Basta che gli dai i gradi al servo... è il metodo più semplice per fare una mappatura ti serve una roba di questo tipo....
o una funzione che a seconda dei giri rilevati apre più o meno il servo, oppure memorizzi tutti i giri in un vettore e per ogni giro dai l'apertura della valvola......
è una cosa molto sperimentale.... :wink:

però scusa ma non capisco che centrava la ventola sensored dei pc allora, quello che vuoi fare tu è con la ruota della moto :fearful:

guardati le discussioni in rilievo, quelle smepre in cima c'è un contagiri della bici che potrebbe interessarti 8)

no bhe, volevo capire come effettuare il calcolo!

il conteggio dei giri verrà poi fatto con un sensore IR o Hall direttamente sull'albero motore!

darò comunque un'occhiata a quel post di cui parli!

lo scarno e inutile codice attuale! vedrò di postare gli sviluppi man mano!

//Costanti*******************************

//Variabili******************************
volatile unsigned int rpm = 0;
volatile unsigned long timeold = 0;
volatile byte cycle = 0;

//include********************************
#include <LiquidCrystal.h>

//inizializza display********************
LiquidCrystal lcd(8, 7, 6, 5, 4, 3);


 void setup()
 {
   Serial.begin(9600);
   attachInterrupt(0, rpm_fun, FALLING);
   digitalWrite(2, HIGH);
   lcd.begin(16, 2);
 }

 void loop()
 {
   lcd.clear();
   lcd.setCursor(0, 1);
   lcd.print("Valve |");
   lcd.setCursor(15, 1);
   lcd.print("|");
   lcd.setCursor(0, 0);
   lcd.print("RPM ");
   lcd.print(rpm);
   lcd.print(" T=   ");
   lcd.write(223);
   delay(100);
   
  
 }

 void rpm_fun()
 {
  cycle++;
  if(cycle == 10) {
    rpm = 0;
    rpm = (60000/(millis()-timeold)*10);
    Serial.println(rpm);
    timeold = millis();
    cycle = 0 ;
    }
 }

non fate caso all'accozzaglia di cose inutili che ho scritto sul display, è solo per vedere gli ingombri delle varie cose da visualizzare!

ho avuto modo di lavorarci un po su. ma ancora la strada è lontana!

//Costanti*******************************
#defineTermostatoA0
#defineVentola13
#defineCassa9
#defineDivisor5

//Variabili******************************
volatileunsigned int rpm = 0;
volatileunsigned long timeold = 0;
volatilebyte cycle = 0;
int analogValue =0;
int temp1 =0;

//include********************************
#include<LiquidCrystal.h>
#include<Servo.h>

//inizializzadisplay********************
LiquidCrystal lcd(8, 7, 6, 5, 4, 3);

//inizializzaservo**********************
Servo lancetta;
Servo Valve;

void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, FALLING);
digitalWrite(2, HIGH);
pinMode(Ventola, OUTPUT);
lcd.begin(16, 2);
lancetta.attach(11);
Valve.attach(10);
}

void loop()
{
analogValue=analogRead(Termostato);
temp1=map(analogValue, 0, 1023, 0, 130);

lancetta.write(rpm/100);
lcd.clear();
lcd.noBlink();
lcd.setCursor(0, 1);
lcd.print("Valve |");
lcd.setCursor(0, 0);
lcd.print("RPM ");
if(rpm >= 500){
lcd.print(rpm); }
else {
lcd.print("0"); }
//lcd.setCursor(9, 0);
lcd.print(" T=");
lcd.print(temp1);
lcd.write(223);
if(temp1 >= 95) {
digitalWrite(Ventola, HIGH);
tone(Cassa, 4186, 50); }
else if(temp1 <=90) {
digitalWrite(Ventola, LOW); }
//Serial.println(rpm/100);

if(rpm <= 1000) {
lcd.setCursor(7, 1);
lcd.print(" |");
Valve.write(0);
}
if(rpm > 1000) {
lcd.setCursor(7, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(20);
}
if(rpm > 2500) {
lcd.setCursor(8, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(30);
}
if(rpm > 4000) {
lcd.setCursor(9, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(50);
}
if(rpm > 5500) {
lcd.setCursor(10, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(70);
}
if(rpm > 6500) {
lcd.setCursor(11, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(100);
}
if(rpm > 8000) {
lcd.setCursor(12, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(120);
}
if(rpm > 9500) {
lcd.setCursor(13, 1);
lcd.write(255);
lcd.print(" |");
}
if(rpm > 10000) {
lcd.setCursor(14, 1);
lcd.write(255);
lcd.print("|");
}
delay(100);

}

void rpm_fun()
{
cycle++;
if(cycle == Divisor) {
rpm=0;
rpm=(60000/(millis()-timeold)*Divisor);
timeold=millis();
cycle=0;
}
}

ancora è tutto in abozzo, e molte cose sono da rifinire!

adesso mi servono un paio di aiuti.

per creare la visualizzazione a barre sull'LCD che indica il movimento del servo per la valvola, ho usato una serie di IF. Ma ho subito capito che il sistema non può essere usato, perche ogni volta invia i comandi di tutti gli IF.
idem per il servo che viene controllato. Si incasina con le troppe informazioni che riceve!

di contro, il contagiri funziona bene, e il sensore di temperatura pure. poi verrà modificato per leggere un termistore.

avete consigli su modifiche da apportare? snellimenti del programma? urla per incompetenza? :cold_sweat:

grazie!

rileggendo il tutto, mi rendo conto che è un po incasinato.

se riesco stasera riscrivo tutto con più calma e magari con qualche foto esplicativa di tutto il sistema!

scusate!

invece di tutti quegli if usa la funzione map tra 180°-0° e le tacchette dell'LCD :wink:

non afferro come.

hai da farmi un mini esempio?

Come promesso, cercherò di spiegare meglio il progetto.

sto cercando di realizzare uno strumentino da applicare alla mia vespa da gara, che mi dia qualche informazione su ciò che accade al mezzo.
attualmente le idee sono concentrate nello gestire:
-un contagiri, su display e se riesco a lancetta (con servo o usando un indicatore commerciale);
-sensore temperatura liquido di raffreddamento. suppongo mi dovrò cimentare nell'usare i termistori, in quanto vengono usati di base per queste applicazioni;
-Sensore temperatura gas di scarico. Credo di implementarlo più in là, con un chip che legga una termocoppia e poi in pasto all'Arduino.
-tentativo di gestione di un servo, che si muova di pari-passo all'aumento dei giri, tirandomi su poi, la valvola di scarico.
-monitoraggio temperatura liquido, attivando quando serve una ventola al radiatore che rinfreschi il tutto.
-il tutto visualizzato su un lcd. attualmente uso un 16x2, ma ho in arrivo un 20x4.
-ho al momento inserito un cicalino che suona al raggiungimento di una data temperatura, ma se mi servirà il piedino, lo abolirò.
-Lettura dei giri motore tramite sensore di hall+magnate o sensore IR con apposito elemento rotante.

il codice abbozzato e un po commentato lo riporto di seguito. è quello attuale, e qualcosa funziona!

//Costanti*******************************
#define Termostato A0
#define Ventola 12
#define Cassa 9
#define Divisor 5

//Variabili******************************
volatile unsigned int rpm = 0;
volatile unsigned long timeold = 0;
volatile byte cycle = 0;
int analogValue =0;
int temp1 =0;

//include********************************
#include <LiquidCrystal.h>
#include <Servo.h>

//inizializza display********************
LiquidCrystal lcd(8, 7, 6, 5, 4, 3); //RS PIN6 - E PIN8 - D4 - D5 - D6 - D7

//inizializza servo**********************
Servo lancetta;
Servo Valve;

void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, FALLING);
digitalWrite(2, HIGH);
pinMode(Ventola, OUTPUT);
lcd.begin(16, 2);
lancetta.attach(11);
Valve.attach(10);
}

void loop()
{
analogValue = analogRead(Termostato); //lettura del sensore di temperatura
temp1 = map(analogValue, 0, 1023, 0, 130); //mappa provvisoria per leggere da 0° a 130°

lancetta.write(rpm/100); // tentativo di movimento servo-lancetta sembra funzionare!
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Valve |");
lcd.setCursor(0, 0);
lcd.print("RPM ");
if(rpm >= 500){ //scrive i giri solo se superano 500RPM
lcd.print(rpm); }
else {
lcd.print("0"); } //altrimenti scrive solo 0
lcd.print(" T=");
lcd.print(temp1);
lcd.write(223); //il pallino dei gradi
if(temp1 >= 95) { //questo aziona un relè che comanda una ventola, attivo al raggiungimento dei 95° fino ai 90°
digitalWrite(Ventola, HIGH);
tone(Cassa, 4186, 50); }
else if(temp1 <=90) {
digitalWrite(Ventola, LOW); }

//bloccone If in attesa di soluzione migliore
//fa comparire la barra quadratini sul display e comanda il servo (ma per il servo non và, userò un map)

if(rpm <= 1000) {
lcd.setCursor(7, 1);
lcd.print(" |");
Valve.write(0);
}
if(rpm > 1000) {
lcd.setCursor(7, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(20);
}
if(rpm > 2500) {
lcd.setCursor(8, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(30);
}
if(rpm > 4000) {
lcd.setCursor(9, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(50);
}
if(rpm > 5500) {
lcd.setCursor(10, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(70);
}
if(rpm > 6500) {
lcd.setCursor(11, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(100);
}
if(rpm > 8000) {
lcd.setCursor(12, 1);
lcd.write(255);
lcd.print(" |");
Valve.write(120);
}
if(rpm > 9500) {
lcd.setCursor(13, 1);
lcd.write(255);
lcd.print(" |");
}
if(rpm > 10000) {
lcd.setCursor(14, 1);
lcd.write(255);
lcd.print("|");
}
delay(100);

}

void rpm_fun() //interrupt che calcola i giri. non è precisissimo, ma per il suo scopo, va più che bene
{
cycle++;
if(cycle == Divisor) {
rpm = 0;
rpm = (60000/(millis()-timeold)*Divisor);
timeold = millis();
cycle = 0 ;
}
}

devo perfezionare il servo per la valvola, e trovare un modo pratico di gestire quello che segnerà i giri.
al momento ho un micro servo preso in germania un "Power D65 HB" della www.chd.hk

molto veloce, ma assorbe forse un po tantino. l'arduino si riavvia se lo alimento con lui! strano!vero?

vi passo una foto:

-a sinistra l'arduino :stuck_out_tongue:
-in basso al centro, il potenziometro che simula il sensore di temperatura
-il led rosso al centro simula la ventola
-il cicalino a sinistra del led
-il servo appoggiato al connettore giallo, a destra della bredboard
-in alto a sinistra l'LCD con visualizzati alcuni dati (notare i quadratini neri)
-non visibile nell'immagine, la ruota con il sensore di hall che simula gli RPM.

che ve ne pare al momento?

vi ringrazio per tutto!
Giuseppe

Ho riguardato tutto il codice e non si può fare come dico io...Con il Map intendo....
prova a dividere il codice in due ... nel loop matti tutto tranne il blocco degli if che li metti dentro ad una funzione