Buenas noches, estoy haciendo un programa que quiero que haga lo siguiente:
- Leer con un sensor de efecto Hall las vueltas que da un rodillo que tiene un imán implantado ( eso lo hace)
- Contar las rpm (eso lo hace con un primer millis) pero lo que quiero es que lo vaya mostrando cada segundo, cuando he puesto el segundo millis no lo hace.
- Guardar en una variable cual es el valor máximo de rpm cada minuto ( eso lo haría con un segundo millis pero aquí llega el problema, se solapa con el primero y solo me muestra los datos una vez ha acabado el segundo millis)
- Haría falta un tercer millis ya que este proceso quiero que dure 2 minutos o 3 pero aun no he podido avanzar hasta este paso sin el anterior.
El título lo he puesto así porque no he encontrado nada parecido y creo que puede valer para algún proyecto que necesite un millis que dependa de otro.
Gracias por vuestra ayuda
int Hall = A0;
int DetectaHall = 0; // Sensor efecto hall
long contadorvueltas = 0; // variable que cuenta las vueltas
long rpmRodillo = 0;
long rpmRueda = 0;
int Detecta = 0;
int DiametroRodillo = 30;
int DiametroRueda = 18;
int rele = 0; // Tengo un relé que activa el giro del rodillo
int rpmMax = 0;
const unsigned long sampleTime = 1000;
const unsigned long sampleTime2 = 5000; // temporizador que no me está funcionando
void setup ()
{
pinMode(rele,OUTPUT);
pinMode (Hall, INPUT) ;
Serial.begin(115200);
}
void loop (){
digitalWrite (rele, HIGH);
unsigned long currentTime = 0;
unsigned long startTime = millis(); // Inicializar las variables del temporizador
unsigned long currentTime2 = 0;
unsigned long startTime2 = millis(); // Inicializar las variables del temporizador 2
contadorvueltas = 0; // En cada retorno del loop reiniciar el contador
while(currentTime <= sampleTime){
DetectaHall = analogRead(Hall) ;
if(DetectaHall< 500 && Detecta == 0){ // El sensor detecta por debajo de 500 y deja de detectar por encima de 513
Detecta = 1;
}
if(DetectaHall> 513 && Detecta == 1){ // En este caso lo que hace el programa es que cuando detecta el imán se activa una variable y cuando deja de detectar significa que ya ha pasado el imán y por tanto cuenta una vuelta
contadorvueltas++;
Detecta = 0;
}
currentTime = millis()-startTime; // Actualiza el tiempo actual
}
rpmRodillo = (contadorvueltas * 60); // Cálculo de las RPM = RPS * 60 segundos
rpmRueda = (rpmRodillo * DiametroRodillo)/ DiametroRueda;
Serial.print(" RPM Rueda:");
Serial.print(rpmRueda);
while(currentTime2 <= sampleTime2){
if (rpmMax < rpmRueda){
rpmMax = rpmRueda;
}
currentTime2 = millis()-startTime2;
}
Serial.print(" RPM MAX:");
Serial.println(rpmMax);
}
Porque lees con analogRead tu sensor de efecto Hall?
La salida es analógica o digital?
Tiene salida digital y analógica, pero haciendo pruebas he visto que es más fiable la analógica ya que la digital me da saltos( pasa de 0 a 1 continuamente y probé con interrupciones y vi que con la analógica lo lee bien
Dime como funciona esto
int Hall = A0;
int DetectaHall = 0; // Sensor efecto hall
long contadorvueltas = 0; // variable que cuenta las vueltas
long rpmRodillo = 0;
long rpmRueda = 0;
int Detecta = 0;
int DiametroRodillo = 30;
int DiametroRueda = 18;
int rele = 0; // Tengo un relé que activa el giro del rodillo
int rpmMax = 0;
const unsigned long sampleTime = 1000;
const unsigned long sampleTime2 = 5000; // temporizador que no me está funcionando
unsigned long currentTime = 0;
unsigned long currentTime2 = 0;
unsigned long startTime; startTime2;
int contador = 0;
void setup () {
pinMode(rele,OUTPUT);
pinMode (Hall, INPUT) ;
Serial.begin(115200);
}
void loop (){
digitalWrite (rele, HIGH);
contadorvueltas = 0; // En cada retorno del loop reiniciar el contador
startTime = millis(); // Inicializar las variables del temporizador
while (currentTime <= sampleTime){
DetectaHall = analogRead(Hall) ;
if (DetectaHall< 500 && Detecta == 0){ // El sensor detecta por debajo de 500 y deja de detectar por encima de 513
Detecta = 1;
}
if (DetectaHall> 513 && Detecta == 1){ // En este caso lo que hace el programa es que cuando detecta el imán se activa una variable y cuando deja de detectar significa que ya ha pasado el imán y por tanto cuenta una vuelta
contadorvueltas++;
Detecta = 0;
}
currentTime = millis()-startTime; // Actualiza el tiempo actual
}
rpmRodillo = (contadorvueltas * 60); // Cálculo de las RPM = RPS * 60 segundos
rpmRueda = (rpmRodillo * DiametroRodillo)/ DiametroRueda;
Serial.print(" RPM Rueda:");
Serial.print(rpmRueda);
if (contador++ =>4) {
if (rpmMax < rpmRueda){
rpmMax = rpmRueda;
}
Serial.print(" RPM MAX:");
Serial.println(rpmMax);
contador = 0;
}
}
has probado a poner el mismo currentTime para las dos rutinas en vez de usar dos currentTime?
o sea una sola rutina de conteo de millis pero incluyendo dentro las dos comprobaciones de tus sampletime
puedes hacerlo con un if anidado dentro de otro en vez de utilizar while.
Hola, gracias por vuestras respuestas.
He encontrado una solución y era por el if del segundo millis.
surbyte ese fragmento de código lo que hace es lo siguiente:
- En primer lugar activa un relé que habilita el movimiento de un rodillo donde tengo colocado un imán que será leído con un sensor de efecto hall.
- Calculo el número de vueltas que da en un segundo el rodillo y las paso de Revoluciones por segundos a RPM. Como lo que quiero saber es la velocidad angular de una rueda que gira solidaria a ese rodillo aplico la segunda fórmula y con eso obtengo el valor en la rueda.
- Lo que me interesa es saber el valor máximo de esas RPM en un instante determinado, en el caso que he puesto son 5 segundos para poder hacer una depuración.
Adjunto el código final en el que hay 3 millis.
- Uno para la lectura de las rpm en el rodillo
- Otro para que guarde el valor máximo de un tiempo establecido
- El último (que abarca todo el programa prácticamente) es para indicar cuanto tiempo va a durar el programa, por ejemplo si queremos leer solo durante 5 minutos se lo indicamos.
int Hall = A0;
int DetectaHall = 0; // Declaración de variables
long contadorvueltas = 0;
long rpmRodillo = 0;
long rpmRueda = 0;
int Detecta = 0;
int DiametroRodillo = 30;
int DiametroRueda = 18;
int rele = 8;
int rpmMax = 0;
const unsigned long sampleTime = 1000;
long previousMillisMinuto = 0;
long Tiempo = 0;
long valorMinuto = 60;
long previousMillisTotal = 0;
long TiempoTotal = 5;
long Minutos = 2;
void setup ()
{
pinMode(rele,OUTPUT);
pinMode (Hall, INPUT) ; // Indicar que el Sensor de Efecto Hall es una entrada y inicializar el puerto serial a 115200
Serial.begin(115200);
}
void loop (){
Tiempo = valorMinuto *1000;
TiempoTotal = Minutos *60*1000;
contadorvueltas = 0; // En cada retorno del loop reiniciar el contador
unsigned long currentMillisTotal = millis();
if(currentMillisTotal - previousMillisTotal < TiempoTotal) { // Con este millis indicamos el tiempo de la simulación
digitalWrite (rele, HIGH);
unsigned long startTime = millis(); // Inicializar las variables del temporizador
unsigned long currentTime = 0;
while(currentTime <= sampleTime){ // Con este while se hace la cuenta de las rpm
DetectaHall = analogRead(Hall) ;
if(DetectaHall< 500 && Detecta == 0){ // El sensor detecta por debajo de 485 y deja de detectar por encima de 513
Detecta = 1;
}
if(DetectaHall> 513 && Detecta == 1){ // En este caso lo que hace el programa es que cuando detecta el imán se activa una variable y cuando deja de detectar significa que ya ha pasado el imán y por tanto cuenta una vuelta
contadorvueltas++;
Detecta = 0;
}
currentTime = millis()-startTime; // Actualiza el tiempo actual
}
rpmRodillo = (contadorvueltas * 60); // Cálculo de las RPM = RPS * 60 segundos (sample time 3000 - 20 segundos) (siempre tiene que estar en 60)
rpmRueda = (rpmRodillo * DiametroRodillo)/ DiametroRueda;
Serial.print(" RPM Motor:");
Serial.println(rpmRueda);
unsigned long currentMillis = millis();
if(currentMillis - previousMillisMinuto < Tiempo) { // Estos dos if guardan el valor máximo de las rpm cada minuto.
if (rpmMax < rpmRueda){
rpmMax = rpmRueda;
}
}
if(currentMillis - previousMillisMinuto > Tiempo) {
previousMillisMinuto = currentMillis;
Serial.print(" RPM MAX:");
Serial.println(rpmMax);
rpmMax = 0;
}
}
if(currentMillisTotal - previousMillisTotal > TiempoTotal) {
digitalWrite (rele, LOW);
}
}
Se que es probable que haya una manera más sencilla pero creo que ésta es válida. Un saludo y gracias