Encendido de luz (semáforo) PIC16F88

#41
Imagine que meter esos delays me generarian problemas :cry: , pero era lo unico que conocia para realizar esa funcion. Entre las publicaciones que he checado encontre este tuyo, me recomiendas utilizar contadores para controlar el tiempo que ocuparé el encendido de cada LED? Espero que con algo asi ahora si pueda cambiar de caso. Estoy en toda la disposicion de seguir leyendo y buscar mas ejemplos aqui en el foro. Tengo como 2 semanas apenas con esto.
Gracias por responder.



Saludos!
 

Adjuntos

#42
me conmueve tu honestidad y tu lucha por conocimiento

te explicare:

el sistema Multitarea consiste en hacer una base de tiempo, esta base de tiempo parte de una unidad fija de reloj.

digamos 50us

obteniendo esta base de reloj podemos sacar muchos multiplos de este reloj, puede ser mas pequeño

todo depende de los ticks del CPU

ejemplo

1 tick= 1/(fosc/4)

digamos que tenemos un cristal de 20Mhz

1 tick estaria dado en 20/4= 5Mhz ahora 1/5Mhz
nos daria 0.2us como un tick

que significa que cada instruccion se ejecutaria a 0.2us asi que esa seria nuestra frecuencia limite para hacer un timer o base de tiempo.

pero por comodidad haremos un ejemplo con un timer de 1ms

en el CCS tenemos la estructura del timer de la siguiente manera:

Código:
#INT_TIMER0
void TIMER0_isr(void)
{
   //codigo
}
esta estructura nos permite hacer un desbordamiento de timer con la cual podemos hacer nuestra base de tiempo

hay calculadoras para hacer un calculo rapido para el desbordamiento de timer en lo particular me gusta el Pic Timer Calculator 0.9.0

hay que hacer unos calculillos para obtener la frecuencia de desbordamiento del timer.

en este caso busque el resultado del timer con un cristal de 20Mhz para timer 0

y me dio los siguientes resultados:

timer 0
preescaler 1:32
modo 8 bit
y el modo de interrupcion es 100

ahora el codigo quedaria del siguiente modo ;)


Código:
#INT_TIMER0
void TIMER0_isr(void)
{
   //codigo
   set_TIMER0(100);   //desborda cada 1ms
   clear_interrupt(INT_TIMER0);      // limpia la bandera de interrupcion CCS lo hace por defecto
}
y en el main quedaria asi:

Código:
void main()
{

   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32|RTCC_8_bit); //preescaler a 32 y 8 bits
   enable_interrupts(global);
while(1)
{
//codigo
}

}


ahora ya que tenemos toda la base de la estructura del programa nos falta hacer nuestra base de tiempo que es la que nos importa como dije

esta interrupcion se dara cada 1ms

podemos generar tiempos de 1,2,3 segundos o 50ms, 500ms ,etc.
siempre y cuando no sean menores a 1ms

ahora lo que falta es hacer uso de variables globales para hacer las cuentas tanto en la interrupcion como usarlas en el main


eso se hace asi:

Código:
#include<blabla.h>
#include <etc.c>
y asi ...


int16 contador; //lo usaremos para contar 1000milisegundos que forman 1 segundo
char segundo1,segundo2,segundo3; //seran nuestros segundos


#INT_TIMER0
void TIMER0_isr(void)
{
   contador++;
   if(contador>=1000)
   {
      contador=0; //reiniciamos la cuenta
       segundo1++;
       segundo2++;
       segundo3++;
   }

   set_TIMER0(100);   //desborda cada 1ms
   clear_interrupt(INT_TIMER0);      // limpia la bandera de interrupcion CCS lo hace por defecto
}




void main()
{

   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32|RTCC_8_bit); //preescaler a 32 y 8 bits
   enable_interrupts(global);
   while(1)
   {
     if(segundo1>=3) //si son 3 segundos prende led
     {
        segundo1=0;
        //prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
              //apagamos o hacemos otra cosa  
           }

      if(segundo2>=1) //si son 1 segundos prende led
     {
        segundo2=0;
        //prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
              //apagamos o hacemos otra cosa  
           }


     if(segundo3>=60) //si son 60 segundos prende led
     {
        segundo3=0;
        //prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
              //apagamos o hacemos otra cosa  
           }


   }//fin de while

}// fin del main


y asi bajita la mano hisimos un proseso multitarea en el prendido de 3 leds con 3 tiempos diferentes

los 3 son totalmente independientes , estudia el codigo, piensalo, juega con el

y seguimos con el proseso de

LECTURA DE BOTONES

sin rebotes con multitarea ;)
 
Última edición:
#44
¿Qué tal, TRILO-BYTE? Ya estuve leyendo tu programa.
Este fin de semana no pude trabajar en el, hasta ahorita, pero creo que estoy haciendo algo mal, no sé si en los fuses o si tengo que agregar alguna librería.
Si puedo compilar el código, pero no hace nada el micro.

Este es el código que puse. (NOTA: puse 4000000 porque es el cristal que tengo.)
Te anexo la imagen del Timer Calculator, el dato de 131 fue el que agregué en el código.

Saludos!

PHP:
#include <16f628a.h>
            //libreria donde esta la funcion rand(); 

#fuses   INTRC_IO,NOWDT,NOPROTECT
#use delay(clock=4000000)




  int16 contador; //lo usaremos para contar 1000milisegundos que forman 1 segundo
char segundo1,segundo2,segundo3; //seran nuestros segundos


#INT_TIMER0
void TIMER0_isr(void)
{
   contador++;
   if(contador>=1000)
   {
      contador=0; //reiniciamos la cuenta
       segundo1++;
       segundo2++;
       segundo3++;
   }

   set_TIMER0(131);   //desborda cada 1ms
   clear_interrupt(INT_TIMER0);      // limpia la bandera de interrupcion CCS lo hace por defecto
}




void main()
{

   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32|RTCC_8_bit); //preescaler a 32 y 8 bits
   enable_interrupts(global);
   while(1)
   {
     if(segundo1>=3) //si son 3 segundos prende led
     {
        segundo1=0;
        output_high(PIN_B0);//prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
             output_low(PIN_B0); //apagamos o hacemos otra cosa  
           }

      if(segundo2>=1) //si son 1 segundos prende led
     {
        segundo2=0;
        output_high(PIN_B1);//prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
              output_low(PIN_B1);//apagamos o hacemos otra cosa  
           }


     if(segundo3>=60) //si son 60 segundos prende led
     {
        segundo3=0;
        output_high(PIN_B2);//prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
              output_low(PIN_B2);//apagamos o hacemos otra cosa  
           }


   }//fin de while

}// fin del main


Aquí está la imagen, no se había subido.
 

Adjuntos

Última edición por un moderador:
#45
no se aver prueba asi:
Código:
#include <16f628a.h>
            //libreria donde esta la funcion rand(); 

#fuses   XT,NOWDT,NOPROTECT //con cristal 
#use delay(clock=4M) // 4 Mhz




  int16 contador; //lo usaremos para contar 1000milisegundos que forman 1 segundo
char segundo1,segundo2,segundo3; //seran nuestros segundos


#INT_TIMER0
void TIMER0_isr(void)
{
   contador++;
   if(contador>=1000)
   {
      contador=0; //reiniciamos la cuenta
       segundo1++;
       segundo2++;
       segundo3++;
   }

   set_TIMER0(6);   //desborda cada 1ms
   clear_interrupt(INT_TIMER0);      // limpia la bandera de interrupcion CCS lo hace por defecto
}




void main()
{

   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_4|RTCC_8_bit); //preescaler a 4 y 8 bits
   enable_interrupts(global);
   while(1)
   {
     if(segundo1>=3) //si son 3 segundos prende led
     {
        segundo1=0;
        output_high(PIN_B0);//prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
             output_low(PIN_B0); //apagamos o hacemos otra cosa  
           }

      if(segundo2>=1) //si son 1 segundos prende led
     {
        segundo2=0;
        output_high(PIN_B1);//prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
              output_low(PIN_B1);//apagamos o hacemos otra cosa  
           }


     if(segundo3>=60) //si son 60 segundos prende led
     {
        segundo3=0;
        output_high(PIN_B2);//prendemos led eso depende del pin que uses o hacer otra cosa
     }
     else{ 
              output_low(PIN_B2);//apagamos o hacemos otra cosa  
           }


   }//fin de while

}// fin del main
 
Última edición:
#48
¿El pin de MCRL tiene una resistencia de 10 KΩ a VCC?



A ver, creo que planteé mal el programa, porque sólo un instante de tiempo se mantiene encendido y lo demás está apagado.



Prueba lo siguiente:

El programa lo ando planteando mal desde hace años, pero ya está corregido. :unsure:

PHP:
#include <16f628a.h>
            //libreria donde esta la funcion rand(); 

#fuses   XT,NOWDT,NOPROTECT //con cristal 
#use delay(clock=4M) // 4 Mhz




  int16 contador; //lo usaremos para contar 1000milisegundos que forman 1 segundo
char segundo1,segundo2,segundo3; //seran nuestros segundos


#INT_TIMER0
void TIMER0_isr(void)
{
   contador++;
   if(contador>=1000)
   {
      contador=0; //reiniciamos la cuenta
       segundo1++;
       segundo2++;
       segundo3++;
   }

   set_TIMER0(6);   //desborda cada 1ms
   clear_interrupt(INT_TIMER0);      // limpia la bandera de interrupcion CCS lo hace por defecto
}




void main()
{

   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_4|RTCC_8_bit); //preescaler a 4 y 8 bits
   enable_interrupts(INT_TIMER0);  //ME FALTO ESTA INSTRUCCION MUY IMPORTANTE!!!
   enable_interrupts(global);
   while(1)
   {


//corregido andaba planteando mal el programa, lo planteaba para hacer PWM y no para 
//una señal cuadrada, para que una señal sea cuadrada deben durar los 2 periodos
//el mismo tiempo por eso la segunda sentencia va al doble de la primera


     if(segundo1>=3) //si son 3 segundos prende led
     {
      output_high(PIN_B0);//prendemos led eso depende del pin que uses o hacer otra cosa
     }
     if(segundo1>=6)
     {
      segundo1=0;
      output_low(PIN_B0);
     }

      
      
     if(segundo2>=1) //si son 1 segundos prende led
     { 
      output_high(PIN_B1);//prendemos led eso depende del pin que uses o hacer otra cosa 
     }
     if(segundo2>=2)
     {
      segundo2=0;
      output_low(PIN_B1);
     }
     


     if(segundo3>=5) //si son 5 segundos prende led
     {
      output_high(PIN_B2);//prendemos led eso depende del pin que uses o hacer otra cosa
     }     
     if(segundo3>=10)
     {
      segundo3=0;
      output_low(PIN_B2);
     }



   }//fin de while

}// fin
 
Última edición por un moderador:
#50
Ahora debes empezar a plantear por ti mismo la escritura de una LCD.

Digamos, encender un led cada 0.5 segundos, generar un tren de pulsos a unos cuantos Kilohertz y escribir en la LCD una palabra cada 2 segundos y al mismo tiempo leer un ADC y mostrarlo en la LCD.

Todo eso es posible, gracias al TIMER.
 
Última edición por un moderador:
#51
Voy a escribir un programa con eso que pides.
Creo que tengo un LCD por aquí, pero también voy a ir metiendo el Timer 0 en mi programa con el que estaba teniendo problemas. (El del semáforo)
Aunque aún falta ver lo de los botones con multitarea.

De verdad muchas gracias por la paciencia y por enseñarme como funciona el Timer.
Seguiré publicando los avances.
 
Última edición por un moderador:
#52
Que tal, estoy de regreso para seguir con el aprendizaje... estuve fuera de esto por motivos de trabajo :/ pero les dejo un semáforo con tiempo fijo realizado con timer0, lo que realmente necesito hacer es un semaforo con 4 funciones... Tiempo fijo, Luces aleatorias(random), Avanzar luz por luz (Manual) y Avanzar luz por luz (Random). Necesito utilizar 2 push.

TRILO-BYTE, seguia lectura de botones sin rebotes con timer0 :D de verdad gracias... dejo el programa aqui.


Código:
#include <16f628a.h> 
         

#fuses   XT,NOWDT,NOPROTECT //con cristal  
#use delay(clock=4M) // 4 Mhz 




  int16 contador; //lo usaremos para contar 1000milisegundos que forman 1 segundo 
char segundo1,segundo2,segundo3; //seran nuestros segundos 


#INT_TIMER0 
void TIMER0_isr(void) 
{ 
   contador++; 
   if(contador>=1000) 
   { 
      contador=0; //reiniciamos la cuenta 
       segundo1++; 
       segundo2++; 
       segundo3++;
   } 

   set_TIMER0(6);   //desborda cada 1ms 
   clear_interrupt(INT_TIMER0);      // limpia la bandera de interrupcion CCS lo hace por defecto 
} 




void main() 
{ 

   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_4|RTCC_8_bit); //preescaler a 4 y 8 bits 
   enable_interrupts(INT_TIMER0);  //IMPORTANTE 
   enable_interrupts(global); 
   while(1) 
   { 


//corregido andaba planteando mal el programa, lo planteaba para hacer PWM y no para  
//una señal cuadrada, para que una señal sea cuadrada deben durar los 2 periodos 
//el mismo tiempo por eso la segunda sentencia va al doble de la primera 


       
//ENCENDIDO DE VERDE Y DESTELLO DE VERDE//
//ESTOY USANDO TRANSISTORES 3906 POR ESO EL ENCENDIDO LO TENGO EN LOW//     
     
       
       if(segundo1<=3)
       {
           output_low(PIN_B0); //PRENDE VERDE
       }
       
                              //DESTELLO DE VERDE//
       
                             if(segundo1>=4)
                             {
                                        if(contador<=500)
                                           {
                                            output_high(PIN_B0);
                                           }
                                        if(contador>=500)
                                           {
                                            output_low(PIN_B0);
                                           }
                              }
      
          
                                
                     if(segundo1>=6)
                        {
                         output_high(PIN_B0);    
                        }
     
       
                    if(segundo1>=10)   //REGRESO A 0 EL CONTADOR SEGUNDOS1
                    {
                     segundo1=0;
                    }
     
       
       
         //ENCENDIDO DE AMBAR//
       
       
             if(segundo2<=5)
             {
              output_high(PIN_B1);
              }
       
                      if(segundo2>=6)
                       {
                       output_low(PIN_B1);
                       }
       
                           if(segundo2>=7)
                             {
                             output_high(PIN_B1);
                              }
       
                                  if(segundo2>=10)
                                  {
                                   segundo2=0;
                                   }
       
       
       
          //ENCENDIDO DE ROJO//
       
                   if(segundo3<=6)
                    {
                     output_high(PIN_B2);
                     }
       
                             if(segundo3>=7)
                                {
                                 output_low(PIN_B2);
                                   }
       
                                        if(segundo3>=10)
                                        {
                                          output_high(PIN_B2);
                                          segundo3=0;
                                         }
       
       
       
       
    }   //CIERRO WHILE
} //CIERRO MAIN
 
#53
muy bien muy bien

felicidades hay compañeros que por mas que se les explica siguen usando delay

ya quitaste delay de tu sistema es muy buen avance.

por ahi creo que dario puso una libreria para usar botones
no la he revisado pero supongo que su codigo es mas eficiente que el mio.
creo que esta dentro de este mismo tema
 
#54
Dario es D@arkbytes? Porque si es el mismo, yo utilice la libreria que el subio (botton) y viene en mi programa anterior.

Entonces lo que puedo hacer es juntar la libreria del Push y el timer0?
Crees que con eso pueda hacer lo que dije en el mensaje anterior?


Saludos
Y gracias por responder a mis mensajes y explicarme lo del timer0 (Y)
 
#57
hay muchos darios asi como davits digo trilo-bytes es la misma gata pero revolcada

lo que digo SI puedes usar la libreria

¿hay conflictos con timer?

no se no he revisado la libreria pero pues el pic deberia traer otro TIMER si hay algun conflicto
digamos ya estoy usando timer 1 en XY cosa especifica usamos otro
 
#58
Gracias por la aclaración y por la ayuda. Ya busqué quien es Dario, buscaré la librería que publicó y comento como me fue con eso.;)

Como no cumplo las Políticas del Foro, me editaron el mensaje.


Normas del Foro 2.9 Los usuarios no pueden publicar, solicitar ni difundir información que promueva el plagio, la piratería, la divulgación de números de serie, crack o similares, o copias no autorizadas de material protegido por derechos de autor.​
 
Última edición por un moderador:
#59
Gracias por la aclaración y por la ayuda.
Ya busqué quien es Dario, buscaré la librería que publicó y comento cómo me fue con eso.
Si te refieres a la librería "Button.c", yo la publiqué aquí en el Foro, comentando que no es de mi autoría.
Hace algún tiempo, buscando una buena solución para el problema de los rebotes en los pulsadores, encontré una librería escrita en C para PIC C Compiler.
Esta librería surge de una instrucción de PICBasic "BUTTON Pin,Down,Delay,Rate,BVar,Action,Label" que sirve muy bien para este propósito y lo que hace esta librería es muy similar, pues fue realizada para imitar a la instrucción de PICBasic, pero sin el salto a otra subrutina "Label".
El autor, del cual ya no recuerdo su nombre ni el sitio, describe detalladamente las funciones que usó para crear la rutina button, y también los parámetros a usar.

Adjunto esta librería que es de libre distribución y un ejemplo sencillo de su uso.

Suerte.
Descarga: Librería Button.c
 
#60
Yo ya use esa libreria y da 0 rebotes... lo unico que no se es si esa es la libreria a la que se refiere TRILO.

Esa ya la tengo descargada. Gracias D@rkbytes.... lo que hare es probar esa libreria con mi codigo de TIMER0.
 
Arriba