Go Down

Topic: Cuenta más o menos pulsos depende de la velocidad de giro (Read 1 time) previous topic - next topic

davidrummer

Hola a todos.

Me estoy volviendo loco con un proyecto. se trata de un contador de metros lineales de cinta.

Uso un Arduino UNO, una pantalla lcd,un rodillo unido a una rueda dentada con 20 muescas y un optocoplador.

El problema me da al medir los pulsos, si giro la rueda despacio me da una lectura mayor que si la giro a más velocidad*.

HE leído varios foros y paginas web, y no doy con la solución.

No se si el problema sera la velocidad de lectura del arduino, estoy pensando en cambiarlo por otro, pero tengo miedo que el problema persista.

Este es uno de los sketch que utilizo para leer los pulsos.


Code: [Select]
volatile int contador = 0;


// La librería para el LCD 16x2 I2C
#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C lcd(0x3F, 16, 2);
void setup() {
  // put your setup code here, to run once:

 attachInterrupt( 1, ServicioBoton, RISING);   
 lcd.begin();


}

void loop() {

lcd.setCursor(0, 0);
        lcd.print (contador);


}

void ServicioBoton()

 
  { contador++ ;
   
  }




Una vez que los pulsos sean estables a cualquier velocidad, lo intentare pasar a centímetros.

Agradecería cualquier pista o posible solución.

Muchísimas gracias de antemano

tauro0221

Hi,
Tratas de hacer un lcd.clear()  antes de  darle display al counter. Creo que cuando posicionas el curso puede dejar caracteres del display anterior.   No se si estoy en lo correcto pero es buno hacee el clear antes de darle display a la variable.

davidrummer

Hola Tauro0221.

Gracias por responder tan pronto!

Tampoco me funcionó. Ademas en otro sketch sacaba el contador por monitor serial y me daba el mismo error

Soy novatillo y autodidacta en esto, me apunto lo de lcd.clear(); de todos modos

Muchas gracias!

jordi3sk97

Comparándolo con el ejemplo del manual
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

https://www.arduino.cc/reference/en/language/functions/digital-io/pinmode/

El código que muestras es susceptible de mejoras.
Tampoco muestras el esquema de la electrónica.

Y esta frase.....

../..
si giro la rueda despacio me da una lectura mayor que si la giro lentamente.
--/..
Tendrías que revisarla.



tauro0221

Hi,
Otra cosa es si usas un optocoupler tipo interruptor es buena idea de pintar la rueda de negro no brillante.Yo tuve problemas con un projecto y la rueda de diente era de metal con un brillo.  Pintandola se fue el problema. Esto no quire decir que tengas el mismo problema pero que lo tengas en consideracion.

davidrummer

Comparándolo con el ejemplo del manual
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

https://www.arduino.cc/reference/en/language/functions/digital-io/pinmode/

El código que muestras es susceptible de mejoras.
Tampoco muestras el esquema de la electrónica.

Y esta frase.....

Tendrías que revisarla.





Hola jordi3sk97

Tienes razón, voy a intentar adaptarlo el ejemplo al proyecto a ver que tal y subir unas fotos del esquema eléctrico.

No me había dado cuenta de la frase jajaja, ahora lo corrijo. Quería decir que si giro la rueda lentamente mide mas pulsos que si la giro mas rápido, algo así como 70 pulsos girándola lenta y 25 girándola rapido.

Muchas gracias por la orientación!



davidrummer

hola Tauro0221!

Pues mira no lo había oído nunca.

mi rueda es de plástico negro, no tiene mucho brillo, pero a ver si puedo probar con otra rueda mas mate a ver que tal.

Muchas gracias por el consejo!

tauro0221


davidrummer

Hola.

estoy usando  el fc-03 como este

Adjunto una imagen de la rueda con el opto.

Lo tengo conectado a las salida digital 3 alimento la pantalla lcd y el interruptor desde arduino.

Gracias Tauro



davidrummer

Hola tauro0221 y jordi3sk97.

Creo que esto esta empezando a funcionar gracias a vuestra ayuda. llevaba 2 semanas loco con este tema y al fin parece (al menos de momento) que mide lo mismo independientemente de la velocidad en la que lo haga girar.

dejo aquí el sketch por si le puede ayudar a alguien más.

Code: [Select]

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);

const byte interruptPin = 3;
volatile  long contador = 0;
long T0 = 0; // variable anti rebote
int centimetros = 0;


void setup() {
  // pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
  lcd.begin();
  Serial.begin(9600);
}

void loop() {
  centimetros = contador / 20 * 6.5; /*(((contador * 0.107 * 3.141592) * (19.01 / 2) / 10));*/

  // lcd.clear();
  lcd.setCursor(5, 0);
  lcd.print (centimetros);




}

void blink() {
  //state = !state;
  //contador++;
  {
    if ( millis() > T0  + 2)   //2 es el tiempo en millis  para evitar rebotes
    { contador++ ;
      T0 = millis();
    }
  }
}


Muchisimas gracias a los dos!!!


tauro0221

Hi,
Yo estaba mirando tu sketch y en el  no declaraba el pin del interrupt como input. Otra cosa que noto es que las abertura esta muy grande. Yo las cambiaria por un disco que tenga las abertura mas pequena o un agujero para hacrlo mas facil. Esto te garantiza un pulso mas limpio. Se que ya esta trabajando pero debes de mejorar las aberturas.
Otra cosa que puedes hacer para no tener que usar delays es de ejecutar la instruccion  "noInterrupts() " imediatamente que entre en la rutina que lleva la cuenta y cuando regresas imediatamente haces nterrupts() asi no tienes que usar delays.


PeterKantTropus

En el sketch original estabas utilizando una interrupción sobre el pin 1 , pero el Arduino UNO solo tiene interrupción en los pines 2 y 3 , por eso el último sketch te funciona.

Saludos
"Si no entra como tornillo, entra como clavo"

davidrummer

Buenas Tauro.

Creo que declara la entrada como input en esta linea
Code: [Select]
pinMode(interruptPin, INPUT_PULLUP);.

Lo de las muescas mas pequeñas, lo voy a intentar, porque creo que así también tendría más definición , no? o eso me pareció entender en algún foro.

El "noInterrupts() " iría justo cuando acabara la función de la interrupción, voy a ver si encuentro algún ejemplo.

Gracias  otra vez Tauro!


surbyte

No hace falta declarar una entrada como entrada para que luego trabaje como interrupción.

Entradas son entradas e interrupciones son las que dispone el Arduino en uso tal como dice @PeterKanTropus.

INT0 es pin 2
INT1 es pin 3.

Esta línea puede mejorarse aunque sea correcta, debes simplificar operaciones, porque toda matemática es lenta. 
Code: [Select]
centimetros = contador / 20 * 6.5;

6.5/20 = 0.325 entonces

Code: [Select]
centimetros = contador * 0.325;

hará lo mismo de modo mas rápido.

Bueno, ahora que revisé todo tu código en su contexto me pregunto para que usas interrupciones? No creo que una rueda gire tan rápido como para no leer cambios.
Pero... debes probarlo, asi que te voy a sugerir un código que no usa interrupciones pero si mira los cambios en un pin y lo presenta en el LCD.

Prueba a ver, es el mismo pin okay?

Code: [Select]
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);

const byte ruedaPin = 3;
long contador = 0;
int centimetros = 0;
bool status, statusAnt = false;

void setup() {
  // pinMode(ledPin, OUTPUT);
  pinMode(ruedaPin, INPUT_PULLUP);
  lcd.begin();
  Serial.begin(9600);
}

void loop() {
 
  status = digitalRead(ruedaPin):
 
  if (status && !statusAnt) {
      contador++; 
      centimetros = contador 0.325;
      // lcd.clear();
      lcd.setCursor(5, 0);
      lcd.print (centimetros);
  }
  statusAnt = status;
}

davidrummer

En el sketch original estabas utilizando una interrupción sobre el pin 1 , pero el Arduino UNO solo tiene interrupción en los pines 2 y 3 , por eso el último sketch te funciona.

Saludos
Hola PeterKantTropus.

Pues pensaba  que con el 1 se refería al INT3 y con el 0 a INT2 o algo así leí en algunos ejemplos.

el sensor leer lee, pero claro lee mal.


Gracia por la ayuda!

Go Up