los arduino llevan módulos pwm dedicados, ¿por que no los usas?
En tu programa yo desarrollaria el bucle principal con arreglo a lo siguiente:
void loop () {
- Lee el potenciometro ponderando varias mediciones para estabilizar.
-Adapta el valor del adc del potenciometro 0-1023 y relaciónalo a las rpm. Entiendo que el potenciometro es para elegir las rpm, y conocerás el máximo y el mínimo de rpm.
.....
Es la única forma de hacerlo seguro y eficiente. Hacerlo por fuerza bruta manejando manualmente el pin que genera el pulso es ineficiente y siempre te va a ser inestable.
gracias por tus respuesta..
Entiendo lo que me explicas pero no he podido encontrar un ejemplo con los timmer para leer el sensor hall.
realice el siguiente código pero el motor me arranca o se mueve por pulsos muy cortos, asumo que es por la interrupción.( en el código aun no relaciono las mediciones del sensor con el potenciometro, ya que trato de visualizar primero las lecturas antes de seguir adelante)
volatile int contador = 0; // Variable entera que se almacena en la RAM del Micro
volatile int suma = 0;
int pwm = 9; // asigna el pin 12 a la variable pwm
int led = 10;
int pot = A0; // asigna la entrada analógica A0 a la variable pot
int t1 = 0; // declara la variable t1
int t2 = 0; // declara variable t2
void setup () // setup loop
{
Serial.begin(9600);
attachInterrupt(0,interrupcion0,RISING); // Interrupcion 0 (pin2)
pinMode (pwm, OUTPUT); // declara el pin 12 como salida
pinMode (pot, INPUT); // declara el pin A0 como entrada
}
void loop ()
{
delay(999); // retardo de casi 1 segundo
for (int i=0; i<20;i++)
{
suma = contador +suma;
Serial.println(suma);
}
suma=suma/20;
// Serial.print(suma); // Como son dos interrupciones por vuelta (contador * (60/2))
// Serial.println(" RPM"); // El numero 2 depende del numero aspas de la helise del motor en prueba
contador = 0;
suma = 0;
t2 = analogRead (pot); // lee el voltaje en A0 y guarda en t2
t2=map(t2,0,1023,1500,3000);
digitalWrite (pwm, HIGH); // establece el pin 12 HIGH
digitalWrite (led, HIGH);
delayMicroseconds (t2); // espera t1 uS (hora alta)
digitalWrite (pwm, LOW); // establece el pin 12 BAJO
digitalWrite (led, LOW);
delayMicroseconds (t1); // espera t2 uS (poco tiempo)
delay(20); //Detenemos el programa 25 milisegundos
//Serial.println(t1);
//Serial.println(t2);
}
void interrupcion0() // Funcion que se ejecuta durante cada interrupion
{
contador++; // Se incrementa en uno el contador
}
Este código te permite determinar la frecuencia de una señal cuadrada cualquiera. Tú sensor hall sería esa señal cuadrada.
Pruébalo aparte tal cual está y luego ve introduciéndolo en tu código como librería o directamente.
Este código usa el timer1. Debes tenerlo en cuenta por que el pwm hardware también necesita usar un timer, simplemente asegúrate que el pwm no quiera usar el timer1. Por que ese conflicto hará que todo se vaya a la mierda. Busca un pwm hardware que no use el timer1.
Ten en cuenta que este código usa 115200 bps de velocidad del puerto serie.
Por último, el sensor hall lo tiene que poner en cualquier pin de la tarjeta arduino con interrupción hardware por flanco de subida. Con resistencia pullup si es un hall de colector abierto, OpenDrain.
Yo empezaría por ahí. Cuando tengas el motor girando y puedas ver sus revoluciones por segundo (Hz) entonces empiezas con el pwm hardware.
/ Frequency timer
// Author: Nick Gammon
// Date: 10th February 2012
volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;
// here on rising edge
void isr ()
{
unsigned int counter = TCNT1; // quickly save it
// wait until we noticed last one
if (triggered)
return;
if (first)
{
startTime = (overflowCount << 16) + counter;
first = false;
return;
}
finishTime = (overflowCount << 16) + counter;
triggered = true;
detachInterrupt(0);
} // end of isr
// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect)
{
overflowCount++;
} // end of TIMER1_OVF_vect
void prepareForInterrupts ()
{
// get ready for next time
EIFR = _BV (INTF0); // clear flag for interrupt 0
first = true;
triggered = false; // re-arm for next time
attachInterrupt(0, isr, RISING);
} // end of prepareForInterrupts
void setup () {
Serial.begin(115200);
Serial.println("Frequency Counter");
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
// Timer 1 - interrupt on overflow
TIMSK1 = _BV (TOIE1); // enable Timer1 Interrupt
// zero it
TCNT1 = 0;
// start Timer 1
TCCR1B = _BV (CS10); // no prescaling
// set up for interrupts
prepareForInterrupts ();
} // end of setup
void loop ()
{
if (!triggered)
return;
unsigned long elapsedTime = finishTime - startTime;
float freq = 1.0 / ((float (elapsedTime) * 62.5e-9)); // each tick is 62.5 nS
Serial.print ("Took: ");
Serial.print (elapsedTime);
Serial.print (" counts. ");
Serial.print ("Frequency: ");
Serial.print (freq);
Serial.println (" Hz. ");
// so we can read it
delay (500);
prepareForInterrupts ();
} // end of loop
Las rpm es muy fácil sacarlas a partir de la frecuencia que te dé. Multiplicas por 60 y listo. Aunque yo no lo haría. Lo trabajaría directamente en hz. Solo multiplicaria para enviar el valor en rpm a la terminal.
Una vez tengas esto, prueba al generar una señal PWM, Debes usar cualquier pin que te dé PWM que usen el timer0 o el timer2. El timer2 tiene una opción mas de preescalador que el timer0 (dividir la freuencia del pwm). Para el timer2 los PWM en el arduino Nano, Uno, mini y Mega serían los PWM 3 y 11. Cualquiera de los dos te vale (Localiza en tu placa arduino cual es el pin de salida de cada uno de estos dos pwm).
la siguiente linea te permite activar el pwm en el pin elegido. En "analogOutPin" pones el pin del pwm que elijas de tu placa arduino. En "OutputValue" pones el valor del dutty cicle, de 0 a 255 siendo 0, la señal entera a nivel bajo y 255 la señal entera a nivel alto. Un valor de 128 por ejemplo te daría una onda cuadrada simétrica.
En resumen, duty a cero, el motor no anda, y cuando empiezas a subir el dutty el motor girará mas rápido cuanto más subas el dutty.
analogWrite(analogOutPin, outputValue);
Ya con todo esto, conjugandolo en tu sketch creo que podrías implementarlo todo. Solo te queda hacer el feedback si como dice KillerJC quieres un control en lazo cerrado, bien por los metodos mas simples hasta hacerlo por PID como ya te expliqué.
Un saludo.