convertire lettura sensore in Rpm

riciao a tutti
ho un piccolo problema che forse è stupido ma non ci arriverei subito :sweat_smile:
sto completando il primo prototipo di POV Clock con arduino e mi sono imbattuto in un problema di rotazioni del motore
Vorrei in un certo senso sapere quante volte in un minuto il sensore riporta un valore magiore di 60 (è un sensore di luce)
così da calcolare le rotazioni al minuto
più in dettaglio questo sensore viene colpito da un fascio Uv ogni volta che la schedina compie un giro, che fa arrivare il valore del sensore a più di 60.

ho provato a fare uno sketch(ma non penso funzioni bene:

int val=0;
long previousMillis = 0;
void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);      
}

void loop()
{
  unsigned long currentMillis = millis();
if (currentMillis-previousMillis == 1000){
  previousMillis = currentMillis;  
  Serial.println(val);
}
else{
if (analogRead(A1)>60){
  val=val+1;
  digitalWrite(13,HIGH);
}
else{
  val=val;
  digitalWrite(13,LOW);
}
}
}

in particolare la cosa che nn funziona qui è il coneggio delle volte in cui il valore è maggiore di 60
in questo sketch ho provato a vedere le rotazioni per secondo
Grazie a chi mi aiuta :grin:

Prova così.

int RPM = 0;
long previousMillis = 0;

void setup() {
delay(2000); // anti serial brick  
Serial.begin(9600);
  pinMode(13, OUTPUT);      
}

void loop()
{
  int sensore =analogRead(A1); // legge il sensore ad ogni loop
  unsigned long currentMillis = millis();
  if (sensore>60){
    RPM++;
    digitalWrite(13,HIGH);
  } 
  else {
    digitalWrite(13,LOW);
  }

  if (currentMillis-previousMillis > 60000){ // ogni minuto
    previousMillis = currentMillis;  
    Serial.println("RPM: ");
    Serial.println(RPM); // Stampo RMP
    RPM =0; // Azzero RPM per un nuovo conteggio
  }


  // E' possibile calcolare anche le rotazioni con un intervallo minore, ma si perde di precisione
  //  if (currentMillis-previousMillis > 1000){ // ogni secondo
  //    previousMillis = currentMillis;  
  //     Serial.println("RPM: ");
  //    Serial.println(RPM*60); // Stampo RMP*60
  //    RPM =0; // azzero RPM 
  // }
}

A causa della "bassa" velocità di lettura di AnalogRead (10000 volte al secondo) il valore massimo di RPM è limitato a 60'000.

analogRead()

Description
Reads the value from the specified analog pin. The Arduino board contains a 6 channel (8 channels on the Mini and Nano, 16 on the Mega), 10-bit analog to digital converter. This means that it will map input voltages between 0 and 5 volts into integer values between 0 and 1023. This yields a resolution between readings of: 5 volts / 1024 units or, .0049 volts (4.9 mV) per unit. The input range and resolution can be changed using analogReference().
It takes about 100 microseconds (0.0001 s) to read an analog input, so the maximum reading rate is about 10,000 times a second.

PaoloP:
Prova così.

int RPM = 0;

long previousMillis = 0;

void setup() {
delay(2000); // anti serial brick  
Serial.begin(9600);
 pinMode(13, OUTPUT);      
}

void loop()
{
 int sensore =analogRead(A1); // legge il sensore ad ogni loop
 unsigned long currentMillis = millis();
 if (sensore>60){
   RPM++;
   digitalWrite(13,HIGH);
 }
 else {
   digitalWrite(13,LOW);
 }

if (currentMillis-previousMillis > 60000){ // ogni minuto
   previousMillis = currentMillis;  
   Serial.println("RPM: ");
   Serial.println(RPM); // Stampo RMP
   RPM =0; // Azzero RPM per un nuovo conteggio
 }

// E' possibile calcolare anche le rotazioni con un intervallo minore, ma si perde di precisione
 //  if (currentMillis-previousMillis > 1000){ // ogni secondo
 //    previousMillis = currentMillis;  
 //     Serial.println("RPM: ");
 //    Serial.println(RPM60); // Stampo RMP60
 //    RPM =0; // azzero RPM
 // }
}




A causa della "bassa" velocità di lettura di AnalogRead (10000 volte al secondo) il valore massimo di RPM è limitato a 60'000.


> analogRead()
> 
> Description
> Reads the value from the specified analog pin. The Arduino board contains a 6 channel (8 channels on the Mini and Nano, 16 on the Mega), 10-bit analog to digital converter. This means that it will map input voltages between 0 and 5 volts into integer values between 0 and 1023. This yields a resolution between readings of: 5 volts / 1024 units or, .0049 volts (4.9 mV) per unit. The input range and resolution can be changed using analogReference().
> **It takes about 100 microseconds (0.0001 s) to read an analog input, so the maximum reading rate is about 10,000 times a second.**

grazie mille :wink:
però forse c'è lo stesso problema mio del conteggio, nel senso che se immaginiamo che il motore vada lento, quando il sensore arriva verso il fascio, il sensore starà piu tempo sul fascio e sarà proprio quel tempo che farà aumentare il conteggio di molto
cioè se le rotazioni sono una al minuto, non vedrò 1 rpm bensì un centinaio circa perchè il sensore è stato molto tempo sul fascio

EDIT: io volevo fare proprio per questo una cosa tipo:
se sensore > 60 e poi sensore ritorna a < 60 allora rpm +1

a me non serve molta precisione mi va bene anche un errore di +-50

int RPM = 0;
long previousMillis = 0;
boolean Ready = true;

void setup() {
  delay(2000); // anti serial brick  
  Serial.begin(9600);
  pinMode(13, OUTPUT);      
}

void loop()
{
  int sensore =analogRead(A1); // legge il sensore ad ogni loop
  unsigned long currentMillis = millis();
  if (sensore>60){
    if (Ready == true){
      RPM++;
      digitalWrite(13,HIGH);
      Ready = false;
    }
  } 
  else {
    digitalWrite(13,LOW);
    Ready = true;
  }

  if (currentMillis-previousMillis > 60000){ // ogni minuto
    previousMillis = currentMillis;  
    Serial.println("RPM: ");
    Serial.println(RPM); // Stampo RMP
    RPM =0; // Azzero RPM per un nuovo conteggio
  }


  // E' possibile calcolare anche le rotazioni con un intervallo minore, ma si perde di precisione
  //  if (currentMillis-previousMillis > 1000){ // ogni secondo
  //    previousMillis = currentMillis;  
  //     Serial.println("RPM: ");
  //    Serial.println(RPM*60); // Stampo RMP*60
  //    RPM =0; // azzero RPM 
  // }
}

Ho inserito la variabile booleana Ready.
All'inizio del ciclo la variabile è true; appena il sensore supera la soglia di 60 diventa false e quindi non incrementa più RPM.
Se il valore del sensore si abbassa, Ready diventa true ed è pronto per una nuova lettura.

Non è meglio aumentare rpm usando gli interrupt piuttosto che leggerli nel loop ?

Faccina ha ragione però non so se esiste qualcosa di già scritto col comparatore adc..

lesto:
Faccina ha ragione però non so se esiste qualcosa di già scritto col comparatore adc..

Non credo funzioni.
Bisognerebbe creare un piccolo circuito esterno che trasformi il segnale analogico del sensore luminoso in digitale con soglia regolabile; con quell'accorgimento sarebbe possibile leggere gli impulsi.
Tanto vale usare l'ADC e il codice scritto sopra. :wink:

Bisognerebbe creare un piccolo circuito esterno che trasformi il segnale analogico del sensore luminoso in digitale con soglia regolabile;

tipo un opamp con 1 r e un trimmer per regolarlo ?

PaoloP:

lesto:
Faccina ha ragione però non so se esiste qualcosa di già scritto col comparatore adc..

Non credo funzioni.
Bisognerebbe creare un piccolo circuito esterno che trasformi il segnale analogico del sensore luminoso in digitale con soglia regolabile; con quell'accorgimento sarebbe possibile leggere gli impulsi.
Tanto vale usare l'ADC e il codice scritto sopra. :wink:

Nono, se non erro é proprio questo che fa il comparatore, lancia un interruppe se un valore analogico e maggiore o minore di un altro. E una cosa collegata dall'adc perché è presente anche su micro sprovvisti. Però mai usato o letto attentamente, quindi potrei anche sbagliarmi alla grande

Ok. Ma perché andarsi a complicare la vita quando per scrivere il codice così com'è chi o messo si e no 4 minuti.

ragazzi noon ho potuto rispondere che è saltata la luce a casa per 5-6 ore :0
allora anche io avevo pensato ad un circuito esterno così usavo l'interrupt e mi facilitavo a vita ma il pcb deve contenere pochissimi elementi ovvero: cpu, quarzo , 8 resistenze, 7 led, il sensore e basta!

prciò opto per il convertitore sw
in effetti ora funziona ed ha un piccolissimo margine d'errore circa il 10% che per me va benissimo
ovviamente non si puo ottenere il valore preciso facendo in questa maniera ma va bene :slight_smile:
grazie a tutti per l'interesamento e un grazie speciale a Paolo che mi ha scritto quel pezzo di codice (quello col boolean) al quale non ci sono arrivato :grin: :grin:
ciao

edit: ah paolo mi ha scritto anche tutto il resto :sweat_smile: :sweat_smile: pardon

Lieto di essere stato utile. :smiley:
Mi raccomando, se puoi, pubblica le foto del pcb e relativi schemi. Potrebbero essere utili a qualcun'altro.

Se hai problemi con il chip in stand-alone chiedi pure. Io non sono molto ferrato sull'hardware, ma di sicuro altri ti sapranno rispondere.

PaoloP:
Lieto di essere stato utile. :Dnon
Mi raccomando, se puoi, pubblica le foto del pcb e relativi schemi. Potrebbero essere utili a qualcun'altro.

Se hai problemi con il chip in stand-alone chiedi pure. Io non sono molto ferrato sull'hardware, ma di sicuro altri ti sapranno rispondere.

ci mancherebbe :wink: ma se ti racconto come ho fatto il primoi pcb prototipo ti metti le mani tra i capelli :stuck_out_tongue_closed_eyes:
praticamente le piste le ho dovuto disegnare a mano perchè la stampante laser non funziona (punto 1)
(punto 2) sul software per disegno ho disegnato i componenti sul chip al contrario e praticamente è venuto alla fine tutto a specchio
tolgo lo zoccolo ci saldo uno zoccolo per aria modificando il lato a spechio
e altro ahahaha
vabbè appena faccio un pcb serio lo pubblico intanto se volete metto lo schema; lo sketch non è ancora pronto per un vero e proprio orologio
quando mi arriva tutto (compreso penso sicuramente l'rtc) meto tutto XD