Problema con un secuencial de luces

Saludos al foro.
Estoy creando un secuencial de LEDs con el PIC16F84 y la idea es que mediante un pulsador (on) se prenda un LED, después de 5 segundos se prenda el otro y el anterior se quede prendido y así sucesivamente hasta prender 10 LEDs.

El problema que tengo, es que este sistema debe tener una PARADA DE EMERGENCIA (stop) lo cual haga que cuando se presione éste pulsador, el sistema se pare por completo.

Hasta ahora avancé en algo el programa y funciona, pero cuando presiono "stop" el sistema se para, pero cuando vuelvo a presionar "on", el sistema empieza desde donde se interrumpió y yo quiero que cuando se presione "on", mi sistema vuelva a empezar desde el principio.

¿Cómo podría hacer eso? Hasta ahora no logro resolverlo.
Espero algo de su ayuda, amigos. Saludos.

Este es mi programa:

Código:
#include <16f84a.h>
#fuses xt,nowdt
#use delay  (clock=4000000)
#byte trisa=0x85
#byte trisb=0x86
#byte porta=0x05
#byte portb=0x06
#bit     on=porta.2
#bit   stop=porta.3
int8 i=0;
void detener();

void main(){
   trisa=0b01100;
   trisb=0x00;
   porta=0x00;
   portb=0x00;
   

   while(1){
      
      if(on==0){
         
         portb=0b10000000;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         portb=0b11000000;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         portb=0b11100000;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         portb=0b11110000;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         portb=0b11111000;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         portb=0b11111100;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         portb=0b11111110;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         portb=0b11111111;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         porta=0b10;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         porta=0b11;
         for(i=0;i<20;i++){
         delay_ms(250);
         if(stop==0)
         detener();
         }
         
         
      }
      
   }  

}
   
void detener(){
   while(on==1){
   porta=0x00;
   portb=0x00;
   
   }
}
 
Última edición por un moderador:
todo esta muy feo

puedes rotar un bit en el puerto es muy facil

ejemplo:

char contador;
char valor;
char bit=1;

for(contador=0 ; contador !=8 ;contador++)
{
valor=bit<<1;

output_b(valor);
}

por cada paso del for el bit se va rotando 1 vez a la izquierda

lo del otro boton pues pedes meter una interrupcion
 
Si es más fácil con un for y rotar los bits, pero eso no hará la secuencia que se desea porque se irán poniendo en cero los otros bits.

Usando la interrupción externa de RB0 y con un poleo para comprobar el cambio de una bandera, se puede hacer.

El bit que se pierde al usar RB0 se puede reponer con un pin del puerto A.
 
es verdad no vi esa secuencia

pero sigo con mi idea del rotado ejemplo

int16 valor= 0x00FF; que es igual a 0000000011111111


si lo roto 8 veces a la izquierda quedaria asi 1111111100000000

y si lo roto 8 veces a la derecha quedaria asi 0000000011111111

pero como el puerto B solo tiene 8 bits se veria bien la secuencia ;)

for(contador=0 ; contador !=8 ;contador++)
{
valor=valor<<1;

output_b(valor);
}

//secuencia 2
for(contador=7 ; contador ==0 ;contador++)
{
valor=valor>>1;

output_b(valor);
}
 
Gracias por la sugerencia de rotar los bits, me parece mejor ya que se reduce el código....y la razón por la que hice asi largo y poco optimizado mi código es por que aún soy novato en esto del lenguaje C......Una pregunta más por fa amigos ¿Como puedo introducir interrupciones en el programa para que cuando presione "stop" mi secuencia se detenga por completo y después al presionar "star se inicie nuevamente"? :)
 
Última edición:
Una forma de rotar los bits manteniendo en 1 los que se van rotando, es de esta manera:
PHP:
void main (void)
{
   int8 i;
  
  while (true)
  {
      PORTB = 1;           // Inicio de secuencia en bit 0
      delay_ms(150);
      
      for(i=1;i<8;i++)
      {
         PORTB <<= 1;      // Rotar bit por bit hacia la izquierda.
         PORTB += 1;       // Complementar la rotación.
         delay_ms(150);
      }
      
      for(i=1;i<8;i++)
      {
         PORTB >>= 1;      // Rotar bit por bit hacia la derecha.
         PORTB |= 1;       // Complementar la rotación.
         delay_ms(150);
      }
      
      PORTB = 0;           // Finalizar la secuencia.
      delay_ms(150);
  }
}
En el primer bucle for, van quedando en 1 todos los bits que se han rotado hacia la izquierda, y en el segundo bucle se van poniendo en 0 pero hacia la derecha.
 
admiro tu manera de programar D@rkbytes pero

hay un problema hay que escribir el codigo de una manera mas simple de explicar el codigo como:
PORTB <<= 1; // Rotar bit por bit hacia la izquierda.
PORTB += 1; // Complementar la rotación.

yo le entiendo pero algunos compañeros donde tienen problemas con el aprendizaje del C

no me gusta es que hay delays

si bien hay ejemplos de RTOS donde meten cochinadas como delays

la idea es de que aprendan los colegas hacer uso del delay no tan largo es decir un mini delay de unos cuantos micro segundos ò una interrupcion.

yo pongo ejemplos de pequeños retardos pues para una programacion generica pic, aver,freescale ,pc usan maneras diferentes de llamar una interrupcion

he manejado varios micros y aveces sacar un proyecto y para no usar timer o interrupcion uso un delay facil de calcular ejemplo delay_us(10);
y un incremeto para calcular un retardo conocido digamos 10ms
 
Sucede que siempre trato de simplificar lo más que se pueda un programa y acercarme a su sintaxis.
Si el lenguaje C me permite hacer: Variable <<= 1; pues es una gran ventaja.
Si el programa estuviera en Basic, no me quedaría otra, que escribir: Variable = Variable << 1

También, siempre trato de comentar los programas y es ahí en donde se entiende lo expuesto.

Sobre los retardos, es obvio que todos los usamos cuando empezamos.
Es la forma más simple de trabajar cuando se desconoce el uso de los timers.
Por eso los compiladores de alto nivel los incluyen como instrucciones básicas.

Por algo se empieza y no toda la vida vamos a programar de la misma forma.
Cada vez descubrimos algo nuevo y vamos mejorando nuestra forma de programar.

El objetivo es que nuestro microcontrolador realice lo que queremos aunque se escriban cientos de líneas.
El tiempo y la experiencia son los que harán que cada día nuestra programación sea más eficiente y sencilla. ;)
 
Bueno rotar un bit seria lo mismo que un secuenciador a la deredha o izquierda pero como se puede hacer para que me cambie la velocida de secuencia segun los pulsos en una entrada??.
 
Asignando el valor del retardo a una variable y modificarlo con pulsadores.
Pero por existir retardos en ejecución, el programa tardará en atender la lectura de los pulsadores.
Y mientras más alto sea el retardo, más se tardará el programa en leer y establecer un nuevo valor.

El polling o poleo para verificar otras tareas, puede mejorar el proceso pero se usa más código.
 
un poleo basico para modificar la velocidad sin hacer tanto relajo seria algo asi:

usaremos un pequeño retardo digamos 10us y usaremos una variable que se incremente cada vez que pase este retardo.

este retardo sirve para hacer un retardo mas grande un "seudo retardo".

todo se hace en la ejecucion del programa:



int contador;
int16 milisegundos
while(1)
{
if(contador>=25) //40us por 25 es 1ms
{
contador=0; //reseteo mi contador
milisegundos++;
}



if(milisegundos >=500)
{
milisegundos=0; //reseteo milisegundos

//prendo un led

}

else
{
//mantengo apagado al led
}



delay_us(40);
contador++;
}
 
Todo lo que han ido explicando tanto D@rbytes como TRILO-BYTE, mas o menos yo lo entiendo, pero creo que os habeis ido un poco del tema ya que lo que preguntaba juanMarcerola era si se le podia explicar como hacer el stop.

De paso eso sirve para aquellos que nos gusta aprender sepamos un poco mas aunque luego se nos olviden muchas cosas.

Aunque no biene al caso un ejemplo seria esto que pongo acontinuacion:


Código:
if(tercero=='#')
        {
      potencia = 10*primero + segundo;
      
      potencia = (potencia>28) ? 28 : potencia;
      
      return(potencia);
        }

por mas que lo miro no lo entiendo, esto es por que muchos, lamentablemente, al no poner el texto al lado de las instruciones, funciones, etc, pues a los que somos lentos de entender nos cuesta comprender ciertas linias, menos mal que algunos como trilo o D@rk en sus explicaciones nos ayudan mejorando mucho las linias de codigo.

Por cierto y vuelvo a repetir que no biene acuento, en ese trocito de codigo que quiere decir?

Código:
potencia = (potencia>28) ? 28 : potencia;

Gracias de paso.
 
Última edición:
Atrás
Arriba