surbyte:
Y pretendes detectar el paso de cruce x cero usando una simple instrucción digitalRead?
Eso si es tarea para las interrupciones xq debes detectar el cruce e inmediatamente tomar el tiempo para tu acción de control de brillo.
ok ok, por eso veia en los ejemplos todos que usaban la interrupcion.
¿pero por algun motivo? ¿por la rapidez de lectura?
No usaba la interrupcion por miedo a que interfiriese en el resto de sketch, pues este que puse aqui es solo para el control del motor.
Justamente una interrupcion lo que no hace es insterferir siempre que respetes el hecho que debe ser veloz.
Eso significa, nada de enviar Serial.print o cosas por BT o cuestiones lentas. No poner delay().
Es ir, leer, sumar algo, cambiar un pin y salir
Se puede hacer mucho mas, solo generalizo.
cuando veas el ejemplo que te dije, verás todo lo que se hace.
Ese ejemplo puede resultar complejo, pero puedes buscar lo mismo en google y encontrarás cosas mucho mas fáciles de usar.
Aqui ando de nuevo peleando.
He estado mirando Arduino Phase control, pero me cuesta entender el codigo.. mis conocimietos son bastante limitados.
He seguido peleandome con el mio.
const byte ZCP = 2;
unsigned long previousMillis = 0;
unsigned long currentMillis;
unsigned long tiempo = 5; //brillo al 50%
int contador;
void setup() {
Serial.begin(9600);
pinMode(ZCP, INPUT_PULLUP);
pinMode(3, OUTPUT);
digitalWrite(3, LOW);
attachInterrupt(0,Zero_Cross,FALLING);
}
void Zero_Cross() {
contador++;
}
void loop() {
if (contador >0){
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= tiempo){
Serial.println("HIGH");
previousMillis = currentMillis;
contador=0;
}
}else{
Serial.println("LOW");
}
}
Tengo que decir que en el monitor serial me aparece bien un HIGH y un LOW (mas bien un HIGH y dos LOW).... pero vaya... que si meto la salida a la bombilla esta esta siempre al 100% de luminosidad.
¿Acaso es complicado hacer Phase control con millis?
No entiendes como funciona esto.
Primero has verificado que tienes un puslo cada 10 mseg?
El zero cross interrupt esta disparando la interrupción cada 10 mseg.
Entonces tu contador se incrementa pero para hacerlo antes hay que ponerlo a 0.
Y cuando lo pongo a 0, cuando cumplo lo que quiero hacer, o sea a los 5 mseg.
void Zero_Cross() {
contador++;
}
Pero para que eso ocurra contador tiene que ser una variable que tenga la etiqueta
Hola;
Pues aqui estoy de nuevo.. y no para bien.
Pues no tengo manera de hacer el control de fase con un millis(), y hay que reconocer el codigo no parece demasiado complejo.
Consigo monitorizar la fase y sus correspondientes pasos por cero, es decir que eso funciona correcto.
Pero el problema es que a partir de ahi quiero regular la intensidad de una bombilla y no hay manera.
O brilla al 100% o parpadea como una loca.
El codigo se base en detectar el pase por cero y sumar a un contador.
A partir de ahi temporizo para dar señal.
const byte ZCP = 2;
unsigned long currentMillis;
unsigned long previosMillis;
unsigned long tiempo;
volatile int contador;
void setup() {
Serial.begin(9600);
pinMode(ZCP, INPUT_PULLUP);
pinMode(3, OUTPUT);
digitalWrite(3, LOW);
attachInterrupt(0,Zero_Cross,FALLING);
contador=0;
}
void Zero_Cross(){
contador++;
}
void loop() {
tiempo=currentMillis-previosMillis;
Serial.println(tiempo);
if (contador==1){ //detecto el pase por cero
currentMillis=millis();
if (currentMillis-previosMillis>= 5){ // Puesto que la onda completa son 10ms, doy señal en la mital de la onda.. Esto quiere decir que el brillo de la bombilla sera al 50%
Serial.println("HIGH");
}else{
Serial.println("LOW"); //simpre que no este en HIGH estara en LOW
}
}
if (contador >= 2){ //cuando completa una onda completa, volvermos empezar repitiendo el ciclo
previosMillis = currentMillis; //resetamos el conometro
contador=1; //volvemos a la "if" de arriba
}
}
He visto alguna que otra libreria por ahi, pero desconozco si usan delay en sus rutinas...pues es justo lo que no quiero. En el proyecto este tengo que usar millis() o micros().
Para comenzar tu código esta mal enfocado.
Si usas interrupciones, la idea esque estas hagan la tarea.
Bueno desempolvé un código que tenia de demostración para mis alumnos donde iba y volvía haciendo un dimmer
#include <TimerOne.h> // http://www.arduino.cc/playground/Code/Timer1
volatile int i = 0; // Variable contador volatile porque se usa con la interrupción
volatile boolean zero_cross=0; // Esto nos dice si estamos o no en crossed zero
int AC_pin = 3; // Salida al Triac
int dim = 64; // Nivel de Dimming (0-128) 0 = on, 128 = 0ff
int inc = 1; // Contador up o down, 1=up/ascendente, -1=down/descendente
int freqStep = 75; // Estes es el retardo para el paso del brillo en microsegundos.
// Calculado en función de la frecuencia de la red (50Hz) para 60 hz se debe usar otro valor
//
// Hay que entender que hay dos cruces x cero por ciclo, lo que significa
// que el curce ocurre a 100Hz para una alimentación de 50Hz o 20 mseg de períoodo.
// Para calcula la freqStep dividir la longitud de una onda senoidal en useg x el numero de pasos de brillo
// 100Hz = 10000uSeg 10000 uSeg/ 128 steps = 75uS/step
void setup() {
pinMode(AC_pin, OUTPUT); // Configuro el pin del Triac
attachInterrupt(0, zero_cross_detect, RISING); // La interupcion en el pin 2 para detectar el cruce x cero
Timer1.initialize(freqStep); // Inicializo TimerOne library para la frecuencia que usaremos
Timer1.attachInterrupt(dim_check, freqStep);
// La libreria TimerOne usa el TIMER1 de modo que generará una interrupción (dim_check) que apunta a la función
// que usaremos para chequear si es el momento adecuado para disparar el triac
// Esto ocurre cada 75 useg en 50hz.
void zero_cross_detect() {
zero_cross = true; // pone en 1 cuando hay un cruce x cero
i=0;
digitalWrite(AC_pin, LOW); // apago el TRIAC
}
// Disparo el TRIAC en el momento adecuado
void dim_check() {
if (zero_cross) { // si esta en 1 entonces
if (i>=dim) {
digitalWrite(AC_pin, HIGH); // Enciendo las luces
i = 0; // reseteo el contado de tiempo
zero_cross = false; // reseteo el detector de cruce x cero
}
else {
i++; // incremento el contador de tiempo
}
}
}
void loop() {
dim = 64; // 64 es 128/2 o sea 50% del brillo.
}
En mi loop tenia esto
dim += inc;
if ((dim>=128) || (dim<=0))
inc*=-1;
delay(18);
No me preguntes porque delay(18) solo debes ser un retardo para poder apreciar el cambio de brillos de mi demo de dimmer.
El código que te puse debería mostrar el 50% de brillo. Verifica que los pines usados para el triac coincide con el tuyo.
Hola:
Siento mucho mi ignorancia, pero me cuesta a veces ver esto claro.
Resulta que no daba con la solucion, segun tu me comentabas la interrupcion tenia que estar colocada en un lugar determinado. La coloque en todos los sitios posibles pero no funcionaba.
Resulta que al final lo que era es que en el codigo que me pasaste faltaba la llave "}" de cierre en void setup.. que cosas.. lo que no entiendo es porque marcaba ese error.
Copio y pego aqui el codigo corregido.
#include <TimerOne.h> // http://www.arduino.cc/playground/Code/Timer1
volatile int i = 0; // Variable contador volatile porque se usa con la interrupción
volatile boolean zero_cross=0; // Esto nos dice si estamos o no en crossed zero
int AC_pin = 3; // Salida al Triac
int dim = 64; // Nivel de Dimming (0-128) 0 = on, 128 = 0ff
int inc = 1; // Contador up o down, 1=up/ascendente, -1=down/descendente
int freqStep = 75; // Estes es el retardo para el paso del brillo en microsegundos.
// Calculado en función de la frecuencia de la red (50Hz) para 60 hz se debe usar otro valor
//
// Hay que entender que hay dos cruces x cero por ciclo, lo que significa
// que el curce ocurre a 100Hz para una alimentación de 50Hz o 20 mseg de períoodo.
// Para calcula la freqStep dividir la longitud de una onda senoidal en useg x el numero de pasos de brillo
// 100Hz = 10000uSeg 10000 uSeg/ 128 steps = 75uS/step
void setup() {
pinMode(AC_pin, OUTPUT); // Configuro el pin del Triac
attachInterrupt(0, zero_cross_detect, RISING); // La interupcion en el pin 2 para detectar el cruce x cero
Timer1.initialize(freqStep); // Inicializo TimerOne library para la frecuencia que usaremos
Timer1.attachInterrupt(dim_check, freqStep);
// La libreria TimerOne usa el TIMER1 de modo que generará una interrupción (dim_check) que apunta a la función
// que usaremos para chequear si es el momento adecuado para disparar el triac
// Esto ocurre cada 75 useg en 50hz.
}
void zero_cross_detect() {
zero_cross = true; // pone en 1 cuando hay un cruce x cero
i=0;
digitalWrite(AC_pin, LOW); // apago el TRIAC
}
// Disparo el TRIAC en el momento adecuado
void dim_check() {
if (zero_cross) { // si esta en 1 entonces
if (i>=dim) {
digitalWrite(AC_pin, HIGH); // Enciendo las luces
i = 0; // reseteo el contado de tiempo
zero_cross = false; // reseteo el detector de cruce x cero
}
else {
i++; // incremento el contador de tiempo
}
}
}
void loop() {
dim = 64; // 64 es 128/2 o sea 50% del brillo.
}