Entender este código control RPM motor

Hola mi muy distinguidos amig@s:

Aquí abajo un código que mira las RPM de un ventilador y que tiene el cable amarillo. Si se fijan en el vídeo de abajo tiene una resistencia en el cable amarillo.

1. ¿Realmente hace falta esa resistencia?

2. ¿No es mejor poner el cable amarillo directamente a Arduino? (Juraría que el cable amarillo suelta pulsos por cada vueltas o dos vueltas cuando el ventilador de 12V está funcionando).

Este es el código de ver las RPM del ventilador.

int NbTopsFan; 
int Calc;

int hallsensor = 2;

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

//Definitions of the fans
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");
}

El código que menos entiendo es este:

//Definitions of the fans
fanspec fanspace[3]={{0,1},{1,2},{2,8}};

3. ¿Para qué es este código y que funciones hace?

Ver vídeo.

Un cordial saludo.

Diria que la resistencia es para limitar el voltaje ,si el ventilador esta alimentado a 12v por logica la señal que envia por el cable amarillo tambien deberia ser de 12v con el consiguiente peligro de cascar la entrada del arduino.en cuanto al codigo parece que define una estructura de datos para varios tipos de ventiladores segun los sensores hall que lleven .en este caso parece que lleva dos,por eso usa el segundo elemento del array de la variable fanspace que es del tipo fanspec (definida por struct).luego usa una interrupcion para captar las señales y calcular las revoluciones.

Hola:

Sería raro lo de la resistencia, ya que suelen proporcionar el cable amarillo del tacómetro 5 V por cada vuelta o cada dos vueltas depende del ventilador.

Aún no entiendo exactamente el array que comenté arriba, esos números. Dijiste tipo de ventilador. Si, ¿Y?

Mirando más el código está cli(); y sei();. ¿Qué son?

Saludos.

Hola.
No tiene mucha lógica la definición de esa estructura, ni ese array, pues no está utilizando prácticamente nada de los mismos. Tan sólo define un parámetro útil, que es el número de pulsos por vuelta (dos para tipo fan=1). Para eso, sencillamente con definir directamente ese número valdría:

static int NbTopsFan; // contador de impulsos.
const int fandiv = 2; // dos pulsos por vuelta
const int hallsensor = 2; // pin 2, que está unido a interrupción 0.

void rpm ()     // se llamará cada vez que se pruduce la interrupción
{ 
 NbTopsFan++; 
} 

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

En cuanto a sei y cli, lo que hacen respectivamente es activar / desactivar las interrupciones. Entonces, establecemos las interrupciones, hacemos un delay de un segundo y desactivamos las interrupciones. Es decir, mientras dura ese delay, cada vez que se produce una interrupción por un tick, se ejecuta rpm(), que suma un pulso. Cuando termina el delay se desactivan las interrupciones para que no siga contando, y se hace el cálculo con los impulsos que hemos contado.

Metaconta:
Hola:

Sería raro lo de la resistencia, ya que suelen proporcionar el cable amarillo del tacómetro 5 V por cada vuelta o cada dos vueltas depende del ventilador.

Aún no entiendo exactamente el array que comenté arriba, esos números. Dijiste tipo de ventilador. Si, ¿Y?

Mirando más el código está cli(); y sei();. ¿Qué son?

Saludos.

Una estructura es un conjunto de variables agrupadas en un mismo nombre a las que se accede por la notacion de punto ,como en las propiedades o metodos de los objetos.se define una estructura llamada fanspec ,que como veras ,esta compuesta por dos vaiables ,una tipo char llamada fantype y otra tipo unsigned int llamada fandiv.para usar esta estructura ,se define una variable que es de tipo fanspec ,en este caso la llama fanspace ,esta variable,recuerda que tiene dos elementos y accederiamos a ellos por notacion de punto,con fanspace.fantype accedemos a la variable char y con fanspace.fandiv a la unsigned int ,es decir cada variable tiene a su vez dos valores.pero ademas se puede crear un array de este tipo ,como es el caso .si creamos un array de tres variables del tipo fanspec tendremos en total 2*3 = 6 elementos,que son los que ves entre llaves.como dice noter en este caso es del todo inutil.en cuanto al tipo de ventilador ,lo que dije exactamente es tipo de ventilador segun sensores ,porque me imagino que habra ventiladores de 2 ,4 o 8 sensores,no lo se.en cuanto a la resistencia no se me ocurre otro motivo que el comentado,pero a ver si alguien mas puesto en electronica nos alumbra.

Buenas:

Si alguien sabe hacer un pequeño código más simplificado, menos engorroso y ameno, mejor que mejor. No digo optimizado ya que si hay que actualizarlo, se complica.

Voy a coger un ventilador con tacómetro que tengo y me pongo hacer pruebas, si funciona, subo un vídeo.

Muchas gracias por las explicaciones, ahora lo pillo mejor.

Edito:
Buscando más información he encontrado estas cosas.
attachInterrupt

Por lo que veo en las LCD no cuenta los RPM en tiempo real, sino que cada cierto tiempo te lo muestra de forma lenta como algo más d eun segundo.

Si has visto el código que he puesto yo, creo que poco más se puede simplificar.

¡¡¡Dios mio, se me pasó!!!

Gracias por el código, lo has hasta explicado con líneas de textos. Voy a probarlo con ansias, antes a ver si realmente da pulso de 5 V el tacómetro.

Esta parte del código.

attachInterrupt(0, rpm, RISING);

Presisamente donde dice RISING. ¿Qué significa?

Saludos.

Metaconta:
¡¡¡Dios mio, se me pasó!!!

Gracias por el código, lo has hasta explicado con líneas de textos. Voy a probarlo con ansias, antes a ver si realmente da pulso de 5 V el tacómetro.

Esta parte del código.

attachInterrupt(0, rpm, RISING);

Presisamente donde dice RISING. ¿Qué significa?

Saludos.

Esta explicado en el enlace que pones a prometec y en la referencia a atachinterrupt.tienes varias maneras de disparar la interrupcion ,con RISING la interrupcion se produce cuando la entrada que recibe el impulso pasa de LOW a HIGH.

RISING flanco de subida.
La interrupción se dispara cuando la tensión en el pin 2 del arduino pasa de LOW a HIGH.

Buenas:

¿No es lo mismo dejarlo en HIGH?

Ya que en este caso lo que importa es cuando detecte el HIGH o alto o 1 ó 5 V. Dice que el RISING es cuando detecta el LOW al HIGH. Detecta cambio de flanco, pero si soloen HIGH también lo detecta.

¿O es qué al volver a LOW y luego cuando se pone en HIGH no hace nada?

Si es así, para eso si que se usa RISING.

Saludos.

Tienes cuatro posibles disparos
LOW
Low to High o RISING
HIGH
High to Low o FALLING

Cada vez que pase de 0->1 tienes sun flanco de subida y un disparo de la interrupcción.
No hay mucho mas que decir. Si eso no se ajusta a tu necesidad usas otra opción.

Entendido.

En este trozo de código:

void loop ()
{
   NbTopsFan = 0;
   sei();   
   delay (1000); 
   cli();
   int Calc = ((NbTopsFan * 60)/fandiv);
   Serial.print (Calc, DEC);
   Serial.print (" rpm\r\n");
}

Precisamente donde pone:

delay (1000);

Lo que equivale 1 seg. ¿Hal algún problema si lo pones en menos tiempo?

Se acerca más en tiempo real los datos del RPM. Lo que no se si Arduino UNO no es capaz, pero un DUE lo hará de perlas y un Raspberry ni te cuento, como solo me interesa el UNO me quedo con él.

¿Alguna opinión al respecto?

Saludo.

Claro que lo hay, son las lecturas en 1 segundo que luego te dan esta expresión

int Calc = ((NbTopsFan * 60)/fandiv);

Si disminuyes a 100 mseg x ejemplo la ecuación cambia a

int Calc = ((NbTopsFan * 60 * 10)/fandiv);

Buenas:

Mirando el serial. Se presenta los datos en cada segundo y lo quiero en tiempo real o menos tiempo posible el refrezco, que luego quiero pasarlo al LCD.

Con Arduino UNO a lo mejor no se puede porque es muy lento con Arduino DUE es potente y no se si se puede hacer, tal como pasa con los tacómetros de los coches y con Raspberry Pi 2 se peude hacer si o si.

Cambiando de tema y haciendo pruebas. El resultado sin tener un tacómetro, en realidad estoy con un pulsador pulsándolo, en este caso sin pulsar e incluso pulsado me aparece esto.

2150 rpm
29938 rpm
24508 rpm
26968 rpm
26068 rpm
26278 rpm
27178 rpm
26458 rpm
25888 rpm
23698 rpm
28498 rpm
27838 rpm
24328 rpm
25948 rpm

Supuestamente tiene que dar 0 RPM si no hace nada en la entrada del tacómetro, pin 2. Cuando empiece a pulsar el pulsador, tiene que pontar los pulsos, incluido los rebotes.

¿Qué es lo que ocurre?

Saludos.

PD: ¿No habrá al final Ardiuno TRE? ¿El proyecto se ha abandonado?

¿Tienes el pulsador con su resistencia pull down correspondiente?
El código no está probado, pero no es muy complicado y creo que debería funcionar.

Hola:

He usado el Pull-Up y Down, hasta con interruptor, luego ondas cuadradas de 1 Hz, 10 Hz, 100 Hz y 1 KHz generadas por un PIC12F508. Se coporta igual haga lo qu ehaga, está conectada al pin 2 de Arduino UNO rv3. También he cambiado de 9600 baudios a 115200 y sigue con lo mismo. He probado hasta el pin 3 por si acaso, el mismo comportamiento de siempre.

Ver imagen.

Espero que no esté roto el pobre Arduino. Quizás hay qu eprobar mejor código, a parte en vez de usar delay un mili que es más preciso y no deja en ningún momento el microcontrolador esclavo.

Saludos.

Simulado en proteus con un pulsador funciona bien. Me da 0 cuando no pulso y sube dependiendo de mi frecuencia de pulsación.
¿Tienen tierra masa común el arduino y el generador de pulsos?

Buenas:

Sigo investigando y he probado un ventilador de 12 V. / 0.10 A. con tacómetro y su salida del cable amarillo de es 5 V.

El comportamiento es el mismo, hasta con tacómetro, probando otro ventilador ocurre lo mismo.

Estoy buscando como loco un ejemplo sencillo sobre leer RPM de un ventilador de PC precisamente por aquí.

Si encuentran algunos interesantes antes que yo, los probaré todos, me quedo con el más efizaz. Sigo pensando mejor ponerlo a 115200 baudios com proyecto final, ya que trabaja más rápido en la lectura de datos y sin problemas. Por ahroa nos centramos en el famoso 9600 baudios.

El generador si tiene masa. también he hecho pruebas de lo que preguntas.

Lo queno entiendo que hace sin RPM conectado en el serial contando RPM como si lo tuviera así sin más. Debería poner 0 RPM. Conectando el ventilador lo he detenido quitándo la alimentación, debería poner 0 RPM y sigue con la misma.

Un cordial saludo.

Haz la siguiente prueba:
Sin nada conectado al pin2, prueba el programa, pero iniciando el pin en el setup así:

 pinMode(hallsensor, INPUT_PULLUP);

Debería darte cero. Si es así, pon un pulsador entre pin2 y GND y prueba pulsando a ver.