Pages: [1] 2   Go Down
Author Topic: Leggere il numero di giri di una vetola PC Nexus  (Read 1206 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
God Member
*****
Karma: 2
Posts: 544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti..
Mi so imbattutto in un strano problema, ho comprato una ventola per pc Nexus D12SL-12 (http://www.nexustek.nl/NXS-120mm-pwm-fan-ultra-quiet.htm). Questa ha un filo per regolare la velocità (PWM) e un filo per leggere il numero di giri. Come tante altre ventole.
Questa ha un minimo di 500 RPM a un massimo di 2000 RPM.
Avevo già fatto questo con molte altre e leggevo regolarmente il numero corretto RPM, ma con questa ho dei problemi.
Più precisamente, dal minimo al massimo leggo solo una differenza di 300 RPM invece dovrebbero essere 1500 RPM e inoltre non riesco mai a leggere un numero corretto... MIN 3500 massimo 3800.
E' una ventola che ha 4 step al giro.. e il circuito con cui la leggo ha una resistenza pull-up di 10K.
Mi potete dire dove sbaglio ? Tenete presente che con altre ventole più piccole non ho mai avuto problemi.
Questo è il codice con cui leggo i dati tramite un pin analogico dell' arduino.
int fanPulse = A2;
unsigned long pulseDuration;

void setup()
{
Serial.begin(9600);
pinMode(fanPulse, INPUT);
digitalWrite(fanPulse,HIGH);
}

void readPulse() {
pulseDuration = pulseIn(fanPulse, LOW);
double frequency = 1000000/pulseDuration;

Serial.print("pulse duration:");
Serial.println(pulseDuration);

Serial.print("time for full rev. (microsec.):");
Serial.println(pulseDuration*4);
Serial.print("freq. (Hz):");
Serial.println(frequency/4);
Serial.print("RPM:");
Serial.println(frequency/4*60);

}

void loop()
{
analogWrite(3,0);
delay(15000);
readPulse();
analogWrite(3,255);
delay(15000);
readPulse();
}


Grazie
Logged

0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10465
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

al posto della pulseIn fai:
Code:
unsigned long time;
while (digitalRead(fanPulse) == LOW){
   continue;//wait to be HIGH
}

while (digitalRead(fanPulse) == HIGH){
   continue;//wait to be LOW
}
time = micros();
while (digitalRead(fanPulse) == LOW){
   continue;//wait to be HIGH
}
pulseDuration = micros()-time;

in pratica conm questo codice sei sicuro di posizionarti ALL'INIZIO del segnale basso, e non magari di iniziare a leggerlo da metà (non ricordo se la puilseIn lo faccia, ma non sarebbe la prima volta che la pulseIn sfasa) che versione di IDE hai?

poi al posto di 1000000 scrivi 1000000.0 (se non forzi la divisione ad essere in double perdi i decimali!)
« Last Edit: September 16, 2012, 04:38:07 pm by lesto » Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 2
Posts: 544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie, questa sera provo.
Ho la 1.0.1 praticamente appena scaricata dal sito :-)
Tu hai esperienza con la lettura rpm delle ventole ?
Logged

0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10465
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

nessuna esperienza di ventole, mi spiace, ma solo di arduino smiley
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 2
Posts: 544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao... ho fatto un po' di prove e il tuo codice va molto bene, ma ha un difetto... se la ventola è spenta il sistema si ferma perchè aspetta sempre un valore che non arriva.
Sarebbe da mettere un timeout... della serie ... se non arriva niente entro 1/2 secondo... salta...
Che dici ?
Logged

0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10465
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

devi modificare le condizioni nel while in modo che se supera un certo tempo dentro il while esce in automatico.
Poi quando esce in automatico potresti memorizzarti il fatto ed evitare i while fino a quando per caso non rilevi una differenza facendo una digitalRead ogni tanto.

oppure fai il passo successivo e usi gli interrupt
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 2
Posts: 544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

gli interupt li ho già provati, ma mi danno dei vincoli e non sono precisi.
Se intendi per leggere gli impulsi.
Logged

0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10465
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

veramente gli interrupt son proprio il contrario;
precisi e meno limitanti, in quanto non bloccano il codice se non effettivamente quando avviene qualcosa..
in cambio sono un poco più complessi da usare, ma basta ricordarsi che le variabili tra loop e interrupt vanno dichiarate volatile e quasi tutto è ok.
Posta il codice degli interrupt che vediamo.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 327
Posts: 22645
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@lesto:
l'ultima versione della pulseIn permette anche di iniziare a leggere mentre il pin ha uno stato diverso da quello atteso.
pulseIn(pin, value, timeout)
"value" è lo stato atteso, se lo stato è differente, la pulseIn attende che si verifichi lo stato atteso e poi inizia a cronometrare la durata dell'impulso.
Logged


Offline Offline
God Member
*****
Karma: 2
Posts: 544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao.. questo è il codice... che usavo... ma con queste ventole non ho la lettura corretta.
Code:
cli();               
 sei();               
                                 
int NbTopsFan;
int Calc;

                                 
int hallsensor = 2;

                       
typedef struct{                 
  char fantype;
  unsigned int fandiv;
}fanspec;


fanspec fanspace[3]={{0,1},{1,2},{2,8}};

char fan = 1;

void rpm ()     
{
 NbTopsFan++;
}

 
void setup()
{
 pinMode(hallsensor, INPUT);
 Serial.begin(9600);
 attachInterrupt(0, rpm, RISING);
}
void loop ()
{
   NbTopsFan = 0;
   sei();
   delay (1000);
   cli();
   Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv);
   Serial.print (Calc, DEC);
   Serial.print (" rpm\r\n");
}

Scusa Leo ma non è come lo utilizzavo io ? Pulsein intendo...
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 327
Posts: 22645
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Rispondevo a lesto, che ti aveva consigliato un codice dove metteva in attesa il micro dell'avvento del segnale low, mi pare. La nuova pulseIn permette di fare tutto in automatico
Logged


0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10465
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

uh questo è il codice con gli interrupt.
allora
int NbTopsFan;

deve essere volatile se no ci sono casini con il modo in cui viene otimizzato il codice quindi
volatile int NbTopsFan;

poi inizializzala a 0
voaltile int NbTopsFan = 0;

sei() e cli() toglie, ance perdi un valore chissene. Piuttosto alza il delay a 10 secondi, che diminuisci l'errore, e anche elimina l'uso dell'array che non capisco perchè lo usi, tanto vale che metti direttamente 2, che velocizzi il codice.


sa questo punto il numero di rpm deve essere corretto per forza!
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 2
Posts: 544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Scusami Lesto...
Ma la penultima riga non sono riuscito a capirla molto..
"sei() e cli() toglie, ance perdi un valore chissene" volevi dire di togliere quei 2 comandi ?
Logged

0
Offline Offline
Shannon Member
****
Karma: 130
Posts: 10465
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
God Member
*****
Karma: 2
Posts: 544
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Certo che però 10 sec per ventola = 20 sec. per ciclo... mi sembrano tanti.
Comunque provo lo stesso.
Se non sbaglio, bisogna collegare le ventole a dei pin particolari dell' ardudino uno/mega per usare gli interrupt, vero ?
Logged

Pages: [1] 2   Go Up
Jump to: