TODOPIC
Microcontroladores PIC => RTOS => Mensaje iniciado por: john_freddy en 19 de Abril de 2012, 16:00:19
-
Buenas tardes compañeros del foro, soy nuevo en esta cuestión de programas en micros, actualmente estoy desarrollando un proyecto el cual por medio de dos pulsadores debo aumentar o disminuir el angulo de disparo que se va a producir para disparar 3 scr que van conectados a una red trifásica, cuando presiono el pulsador de incremento este angulo de disparo se debe ver en la fase de 0°, en la de 120° y en la de 240° y debe incrementarse igualmente a medida que presiono nuevamente el pulsador y así mismo debe suceder cuando disminuyo por medio del otro pulsador. Lo he intentado por interrupciones y por rtos peor no he logrado tener control de los pulsos de disparo. Adjunto los dos programas realizados si es posible alguien me ayude se lo agradezco de antemano.
Este programa es por interrupciones: el problema aquí son los tiempos que se emplean para producir los disparos ya que no hay simetría y el pulso no permanece estático.
#include <18f4550.h>
#fuses HS, NOWDT, NOBROWNOUT, NOMCLR, NOPROTECT, NOWRT
#use fast_io(B)
#use delay(clock=20000000)
#priority RB,EXT
float ret = 0;
float ret1 = 5.55;
//float disp = 0.231;
#int_EXT
void EXT_isr(){
delay_ms(ret);
output_D (0b0000000001);
delay_ms(1);
output_D (0b0000000000);
delay_ms(ret1);
output_D (0b0000000010);
delay_ms(1);
output_D (0b0000000000);
}
#int_RB
void RB_isr(void){
if (input(pin_B6)==0){
ret += 0.231;
ret1 += 0.231;
}
}
void main(void)
{
port_b_pullups(true);
setup_adc_ports(no_analogs);
set_tris_B(0b11111111);
set_tris_D(0b00000000);
enable_interrupts(global);
enable_interrupts(INT_EXT);
ext_int_edge(L_to_H);
enable_interrupts(INT_RB);
ext_int_edge(H_to_L);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
while(TRUE);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
}
Por medio de RTOS: en este segundo caso se generan los pulsos pero no puedo incluir los pulsadores ya que cuando lo hago y coloco la variable ret se detiene la generación de pulsos y no hay ningún control sobre esto, pero si cambio la variable ret y ret1 a numeros por ejemplo 1ms o algo por el estilo se produce un tren de pulsos.
#include <18f4550.h>
#fuses HS, NOWDT, NOBROWNOUT, NOMCLR, NOPROTECT, NOWRT
#use fast_io(B)
#use delay(clock=20000000)
#use rtos(timer=0,minor_cycle=1us)//8330us) //8330us
float ret = 0;
float ret1 = 5.55;
float disp = 0.231;
#task(rate=16ms,max=1us)
void incremento(){
delay_ms(ret);
output_D (0b0000000001);
delay_ms(0.1);
output_low(PIN_D0);
delay_ms(ret1);
output_D (0b0000000010);
delay_ms(0.1);
output_low(PIN_D1);
}
//#task(rate=2ms,max=1us)
//void decremento();
void main(void)
{
port_b_pullups(true);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_adc_ports(no_analogs);
set_tris_B(0b11111111);
set_tris_D(0b00000000);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
rtos_run();
}
les pido disculpas por el mensaje tan largo y de nuevo muchas gracias a quien me pueda orientar
-
¿Cuál es el problema?
Saludos
-
Gracias Picuino, el asunto es: en el código que manejo por interrupciones cuando doy a los pulsadores los tiempo no los puedo medir en la simulación por tal motivo no se si se están produciendo a los intervalo deseados. en el código que maneja RTOs cuando coloco condicionales para manejar a los pulsadores ya no se producen los pulsos pero si no coloco estos condicionales si hay un tren de pulsos. Y por ultimo no estoy totalmente seguro si el código como esta escrito este bien encaminado para la solución del problema. Gracias
-
No estoy seguro de entender el problema.
¿Qué hace este código que has posteado?
#include <18f4550.h>
#fuses HS, NOWDT, NOBROWNOUT, NOMCLR, NOPROTECT, NOWRT
#use fast_io(B)
#use delay(clock=20000000)
#priority RB,EXT
float ret = 0;
float ret1 = 5.55;
#int_EXT
void EXT_isr(){
delay_ms(ret);
output_D (0b0000000001);
delay_ms(1);
output_D (0b0000000000);
delay_ms(ret1);
output_D (0b0000000010);
delay_ms(1);
output_D (0b0000000000);
}
#int_RB
void RB_isr(void){
if (input(pin_B6)==0){
ret += 0.231;
ret1 += 0.231;
}
}
void main(void) {
port_b_pullups(true);
setup_adc_ports(no_analogs);
set_tris_B(0b11111111);
set_tris_D(0b00000000);
enable_interrupts(global);
enable_interrupts(INT_EXT);
ext_int_edge(L_to_H);
enable_interrupts(INT_RB);
ext_int_edge(H_to_L);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
while(TRUE);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
}
Si lo comentas un poco se entenderá mejor.
Me llama la atención la instrucción while(TRUE); que detiene la ejecución del programa.
Saludos
-
Gracias por responder. No soy muy hábil en lo de la programación pero voy a tratar de explicarlo lo mejor posible y efectivamente faltaron los comentarios y me disculpo por eso. el montaje físico esta compuesto por un circuito de cruce por cero y un pic18f4550 para manejar tres SCR conectados a una red trifasica. cuando presiono el pulsador conectado el pin B6 se habilita la interrupción por cambio de flanco y realiza el incremento del tiempo de disparo el cual es manejado por ret(fase a 0°) y ret1(fase a 120°), cuando el ckto de cruce por cero hace el cambio de bajo a alto se habilita la interrupción ext y saca al puerto D los pulsos en los tiempos establecidos por ret y ret1. En la simulación lo que se debe ver es un tren de pulsos al cual logro desplazar a medida que incremento o decremento el tiempo de disparo y estos pulsos se deben ver reflejados en las ondas a 0°, 120° y 240°. La instrucción while(true) lo que hace es un ciclo infinito para que el programa corra infinitamente.
-
¿Qué frecuencia de red utilizas?
La variable ret ya desplaza el primer pulso. No hace falta ret1, porque estás desplazando el segundo pulso dos veces.
Ret1 debería valer siempre el tiempo de 0º a 120º
Otra cosa es que los delay creo que no aceptan valores reales.
Saludos.
-
La frecuencia de red es 60hz, pero el ret retarda la fase a cero grados y ret1 retrasa el disparo para la de 120 grados, aun así no seria necesario y solo con uno bastara?
-
Sólo uno bastaría.
El retardo máximo debería ser de 1/(2*60) = 8'333ms
El retardo entre el primer disparo y el segundo debe ser exactamente 8.333ms
Los retardos debes aumentarles poco a poco. En tu código se aumenta el retardo continuamente con la pulsación de la tecla. Se debería aumentar con el flanco para ir paso a paso.
Saludos.
-
Picuino, muchas gracias por sus respuestas pero me surgen dos dudas, primero los disparos que menciona a 8.33ms esos serian para la onda a 0°, pero y para las ondas a 120° y a 240° no debería realizar una especia de desfase de tiempo por ejemplo la onda a 120° su desfase seria de 5.55ms, y la segunda que esto no se sinceramente como hacerlo es como incrementar con los flancos de subida y esta segunda es la que mas me interesa. De nuevo muchas gracias por su ayuda.
-
1. Cruce por cero de onda 0º
2. Desfase de x ms
3. Disparo de onda de 0º
4. Desfase de 8.33ms
3. Disparo de onda de 120º
4. Desfase de 8.33ms
3. Disparo de onda de 240º
Edito:
Tienes razón con el desfase. Debe ser de 5.55 ms, no de 8.33ms
1. Cruce por cero de onda 0º
2. Desfase de x ms
3. Disparo de onda de 0º
4. Desfase de 5.55 ms
3. Disparo de onda de 120º
4. Desfase de 5.55 ms
3. Disparo de onda de 240º
-
lo modifique de la siguiente forma:
#int_EXT //esta interrupción es la del cruce por cero, cuando cambia de bajo a alto ejecuta el proceso
void EXT_isr(){ // no estoy muy seguro a los 8.33ms que seria el equivalente a 180°, creo que deberia ser 5.55ms que seria
delay_ms(ret); //desface a 120° que es el desface de las otras dos ondas.
output_D (0b0000000001);
delay_ms(0.1);
output_D (0b0000000000);
delay_ms(8.33);
output_D (0b0000000010);
delay_ms(0.1);
output_D (0b0000000000);
delay_ms(8.33);
output_D (0b0000000100);
delay_ms(0.1);
output_D (0b0000000000);
}
#int_RB //esta interrupcion es por cambio de estado en el puerto B4 a B7 en este caso el pulsador de incremento
void RB_isr(void){ //esta conectado al pin B6, cuando ocurre el cambio de estado de alto a bajo y el contador de retardo (ret)
if (input(pin_B6)==0 && ret <= 8.33){ //es menor de 8.33, incrementa ret en 0.231 que seria el equivalente a 5°
ret += 0.231;
}
}
cuando simulo con proteus me aparecen los pulsos pero si doy click en el pulsador de incremento los pulsos desaparecen. De nuevo agradezco la ayuda brindada.
-
Picuino como podría hacer sin el uso de la interrupción ext que los tiempos sean manejados con el flanco de subida. Gracias
-
ufff...
Te cuento el método más sencillo (sin rtos):
main() {
char keyb1;
while(1) {
if (input(pin_B6)==0 && keyb1==1) {
keyb1 == 0;
ret += 0.231;
}
if (input(pin_B6)==1 and keyb1==0) {
keyb1 = 1;
}
}
}
-
pero me surgió una duda mayor y quien es keyb1, es algún teclado externo o algo así?, lo he estado manejando con RTOs ya tengo las tareas pero no logro cuadrar los tiempo, le adjunto el código por RTOs:
#include <18f4550.h>
#fuses HS, NOWDT, NOBROWNOUT, NOMCLR, NOPROTECT, NOWRT
#use fast_io(B)
#use delay(clock=20000000)
#use rtos(timer=0,minor_cycle=1us)
float ret = 0;
#task(rate=16ms,max=1us) //tarea para los pulsadores
void pulsadores(){
for (; ;){
delay_ms(500);
if(input(pin_B6)==0){// && ret <=8.33){
output_D(0b00001000); //esta salida es para un led que coloque para rastrear en donde esta ejecutandose el programa,
ret += 0.231; //es decir si el programa entro a la condición. esta condición es para incrementar el tiempo de disparo
}
else
if(input(pin_B7)==0){// && ret > 0){ //esta condición es para disminuir el tiempo de disparo, si ret es menor que cero el pulso pasaría a
output_D(0b00000000); //tiempos anteriores al del origen de la señal seno de 0°
ret -= 0.231;
}
}
}
#task(rate=16ms,max=1us)
void fases(){ //maneja las fases a 0 y 120°, coloque un retardo de 500ms para que tome un solo pulso
delay_ms(500);
delay_ms(1);
output_high(PIN_D0);
delay_ms(0.1);
output_low(PIN_D0);
}
Gracias
void main(void)
{
port_b_pullups(true);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_adc_ports(no_analogs);
set_tris_B(0b11111111);
set_tris_D(0b00000000);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
rtos_run();
}
-
keyb1 es sólo una variable auxiliar de tipo char.
Saludos.
-
este fue el codigo que monte para la instruccion que me indico pero no funciono, si es posible mírelo a ver si esta bien o esta mal en algún lugar. Gracias
#include <18f4550.h>
#fuses HS, NOWDT, NOBROWNOUT, NOMCLR, NOPROTECT, NOWRT
#use fast_io(B)
#use delay(clock=20000000)
char keyb1;
float ret;
void main(void)
{
port_b_pullups(true);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_adc_ports(no_analogs);
set_tris_B(0b11111111);
set_tris_D(0b00000000);
while(1) {
if (input(pin_B6)==0 && keyb1==1) {
keyb1 == 0;
delay_ms(500);
ret += 0.231;
delay_ms(ret);
output_D (0b0000000001);
delay_ms(0.1);
output_D (0b0000000000);
}
if (input(pin_B6)==1 && keyb1==0) {
keyb1 = 1;
}
}
}
-
#int_EXT //esta interrupción es la del cruce por cero, cuando cambia de bajo a alto ejecuta el proceso
void EXT_isr(){ // no estoy muy seguro a los 8.33ms que seria el equivalente a 180°, creo que deberia ser 5.55ms que seria
delay_ms(ret); //desface a 120° que es el desface de las otras dos ondas.
output_D (0b0000000001);
delay_ms(0.1);
output_D (0b0000000000);
delay_ms(5.45);
output_D (0b0000000010);
delay_ms(0.1);
output_D (0b0000000000);
delay_ms(5.45);
output_D (0b0000000100);
delay_ms(0.1);
output_D (0b0000000000);
}
#int_RB //esta interrupcion es por cambio de estado en el puerto B4 a B7 en este caso el pulsador de incremento
void RB_isr(void){ //esta conectado al pin B6, cuando ocurre el cambio de estado de alto a bajo y el contador de retardo (ret)
if (input(pin_B6)==0 && ret <= 5.55) { //es menor de 8.33, incrementa ret en 0.231 que seria el equivalente a 5°
ret += 0.231;
RBIF = 0;
}
}
He copiado tu código con algún cambio.
Si RB_isr se llama por flanco, no hace falta añadir el código que te copié.
Tienes razón en el desfase de 5.55ms
No entiendo por qué al pulsar B6 deja de dar pulsos. ¿Y si desactivas el bit de interrupción RBIF?
¿Puedes comprobar si funciona ahora?
Saludos
-
Lo he estado analizando y no encuentro como desactivar el bit del RBIF, me podría ilustrar la instrucción de como deshabilitarla.
-
No conozco el compilador CSS. En el compilador C18 es:
INTCONbits.RBIF = 0;
Saludos.
-
disable_interrupt(INT_RB) ;-)
-
Hola MLO, el problema creo que está en que hay que borrar el bit de interrupción (RBIF) para que no vuelva a saltar la rutina de interrupción otra vez al retornar.
Creo que tu código desactiva la interrupción (RBIE) de manera que no saltaría nunca más. ¿Cómo se borra RBIE en CSS?
Saludos.
-
No se debe poner valores float en los delay_xx, pues no tienen el efecto deseado. Miren el Help, solo admite variables o constantes de 16 bits, es decir, de 0 a 65535.
Para 5.5ms deberia ser: delay_us(5500);
-
compañeros muchas gracias, con los cambios realizados el programa ha evolucionado satisfactoriamente, pero aun tengo un pequeño problema:
Inicialmente cuando corro el programa aparecen los pulsos desfasados, aunque no he verificado los tiempos de desface pero el problema es que cuando presiono el pulsador de incremento no me realiza ningún desface, si entra en esa parte del código pero no hace nada, luego si presiono varias veces el pulsador me desaparecen todos los pulsos, igualmente si presiono el de decremento no pasa nada ni los desfasa ni aparecen.
El código es:
#include <18f4550.h>
#fuses HS, NOWDT, NOBROWNOUT, NOMCLR, NOPROTECT, NOWRT
#use fast_io(B)
#use delay(clock=20000000)
#priority RB,EXT
float ret;
//float ret1 = 5.55;
//float disp = 0.231;
#int_EXT
void EXT_isr(){
delay_ms(ret);
output_D (0b0000000001);
delay_us(100);
output_D (0b0000000000);
delay_us(5450);
output_D (0b0000000010);
delay_us(100);
output_D (0b0000000000);
delay_us(5450);
output_D (0b0000000100);
delay_us(100);
output_D (0b0000000000);
}
#int_RB
void RB_isr(void){
delay_ms(125);
if (input(PIN_B6)==0 && ret <= 5550){
delay_ms(125);
output_high(PIN_C0);
ret += 231/10;
output_low(PIN_C0);
disable_interrupts(INT_RB);
}
else
if(input(PIN_B7)==0 && ret > 0){
delay_ms(125);
output_high(PIN_C1);
ret -= 0.231;
output_low(PIN_C1);
disable_interrupts(INT_RB);
}
}
void main(void)
{
port_b_pullups(true);
setup_adc_ports(no_analogs);
set_tris_B(0b11111111);
set_tris_C(0b00000000);
set_tris_D(0b00000000);
enable_interrupts(global);
enable_interrupts(INT_EXT);
ext_int_edge(L_to_H);
enable_interrupts(INT_RB);
ext_int_edge(H_to_L);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
while(TRUE);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
}
Hice las correcciones que sugirió jeremylf para valores enteros en los delay y la sugerencia de Picuino de desactivar el RBIF con la instrucción que sugirio MLO, pero la variable ret como esta si cambia y necesito que sea así en valores de 0.231ms la coloque como una fracción porque no se como colocarle algún modificador para que me la tome en milisegundos o microsegundos.
Adjunto el archivo de la simulación.
Muchas gracias por ayudarme en esto.
-
estoy haciendo el código por RTOs porque quiero aprovechar la oportunidad para aprender el manejo de las mismas, adjunto el código pero en este el problema es que no se generan los pulsos.
#include <18f4550.h>
#fuses HS, NOWDT, NOBROWNOUT, NOMCLR, NOPROTECT, NOWRT
#use fast_io(B)
#use delay(clock=20000000)
#use rtos(timer=0,minor_cycle=1us)//8330us) //8330us
float ret = 0;
#task(rate=16666us,max=1us)
void pulsadores(){
//for (; ;){
delay_ms(125);
if(input(pin_B6)==0 && ret <=8.33){
output_high(PIN_C0);
ret += 0.231;
}
if(input(pin_B7)==0 && ret > 0){
output_low(PIN_C0);
ret -= 0.231;
}
//rtos_yield();
}
//}
#task(rate=16666us,max=1us)
void fase0(){ //maneja la fase a 0
delay_us(100);
if(input(pin_B0)==0){ //cruce por cero
if(input(pin_B0)==1){
output_high(PIN_C1);
delay_ms(ret);
output_high(PIN_D0);
delay_us(100);
output_low(PIN_D0);
}
}
}
void main(void)
{
port_b_pullups(true);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_adc_ports(no_analogs);
set_tris_B(0b11111111);
set_tris_C(0b00000000);
set_tris_D(0b00000000);
output_low(PIN_D0);
output_low(PIN_D1);
output_low(PIN_D2);
output_low(PIN_C0);
output_low(PIN_C1);
rtos_run();
;
}
-
:shock: :shock:
que despiste!!! es:
clear_interrupt(INT_RB)
Saludos
-
Muchisimas gracias a todos los que participaron: Picuino, Jeremylf, MLO. sin su ayuda no habría podido lograrlo. Aun falta ajustar los ángulos de disparo ya que la prueba la hice con un angulo de casi 30° y pues así no habría suficiente control, así que hay que reducirlo a 5° mas o menos pero se genera el problema de la coma flotante pero eso ya es carpintería para el final. De nuevo compañeros muchisimas gracias por el apoyo en este proyecto.