motor pap con ccs

Hola. ¿Alguien me podría ayudar con el siguiente trabajo?

Debo programar en ccs y controlar un motor pap, por ahora solo una velocidad y debe girar a la izquierda durante 5 minutos, detenerse 5 minutos, luego girar a la derecha 5 minutos.

Lo realizado hasta ahora es:
Código:
# include <16f877a.h>
# device *=16
# use delay(clock=4M)
# fuses xt,NOWDT
  

 int32 Cont = 0;               //Variable que Cuenta.
 int32 Cont1 = 0;
                //Interrupcion del Timer1.
#int_Timer1 
void TIMER0_isr( void )
   {
      Cont++;               //Incrementa el Contador.
      Cont1++;
      set_timer0(3036 );     //Carga el Timer0.
   }
   
void main( )
   {  
      set_tris_c(0b11110000);  //Puerto c pin 4 rntrada resto salida.
      set_tris_D(0b11111000);  //Puerto c pin 4 rntrada resto salida.
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);;   //Preescaler de 64.
      enable_interrupts( INT_TIMER1 );      //Habilita la Interrupcion del Timer0.
      enable_interrupts( GLOBAL );         //Habilita la Interrupcion Global.
      set_timer1( 3036 );               //Carga el Timer0.
      while( true )
      {
      if (input(pin_d3)==1)// pulsador de partida
      {
      if( 0<Cont >=5 )            //cuando llegue 5 min parta ( los valores los modifico despues)
        {
            
        output_high ( pin_b3 );//led indivador
        output_high (pin_d5);//idem anterior
            
        /^*******secuencia 
        output_high( pin_c4 );
        output_high (pin_c5);
        output_high (pin_c6);
        output_low (pin_c7);
        delay_ms(1);
        
        output_low ( pin_c4 );
        output_high (pin_c5);
        output_high ( pin_c6 );
        output_low (pin_c7);
        delay_ms(1);

        output_low ( pin_c4 );
        output_low (pin_c5);
        output_high ( pin_c6 );
        output_high (pin_c7);
        delay_ms(1);

        output_hihg ( pin_c4 );
        output_low (pin_c5);
        output_low ( pin_c6 );
        output_high (pin_c7);
        delay_ms(1);
   
                    }
         else if( 5<Cont>=10 )        //aqui han pasado 5 debe detenerse y esperar.
         {
                 output_low ( pin_b3 );
                 output_low (pin_d5);
        output_low ( pin_c4 );
        output_low (pin_c5);
        output_low ( pin_c6 );
        output_low (pin_c7);
        
         }
                
         if( Cont1 ==15 )            //pasaron los 5 min, funcione en sentido contrario por 5 min
         {
        // output_high ( pin_b3);
         output_high (pin_d7);
         // falta secuencia
         }
         else if( Cont1 >20)        //si han pasado 5 min pare.
         {
         //output_low ( PIN_b3 );
         output_low (pin_d7);
         output_low (pin_d5);
         Cont = 0;
         Cont1 = 0;
         }
      }
      
            if (input(pin_d3)==0)// todo detenido
        {
         //output_low ( PIN_b3 );
         output_low (PIN_d5);
         output_low (PIN_d7);
      }
      
      }
      }
Lo que me ha pasado es que no puedo hacer que se cumplan los if.
Al sacar la secuencia y dejar solo b3,d5 y d7, lo hace pero en un sentido todo bien, en sentido contrario b3 empieza a parpadear y ahí queda y no avanza sin cumplir con la secuencia.

Cualquier ayuda se agradece infinitamente.

Juan carlos.
 
Última edición por un moderador:
Estoy un poco confundido con tus ifs, ¿qué quieres comprobar con estas condiciones?
Código:
if( 0<Cont >=5 )

else if( 5<Cont>=10 )
 
si la verdad que estan raros esos if...

if( 0<Cont >=5 ) //cuando llegue 5 min parta ( los valores los modifico despues)
{

si solo quieres que cuando cont valga 5 basta con.
if(cont <=5){
aqui va tu codigo
}

lo mismo bastaria cuando cuente hasta 10...

else if( Cont>=5 && cont<=10 ) //aqui han pasado 5 debe detenerse y esperar.
codigo {
}

algo asi pero no se no entiendo tu codigo.
 
Estoy un poco confundido con tus ifs, ¿qué quieres comprobar con estas condiciones?
Código:
if( 0<Cont >=5 )

else if( 5<Cont>=10 )

Lo que quice o quiero decir es que cada vez que el cont este dentro de este rango active las salidas para la secuencia del motor pap y dos contadores (cont y cont1) pues son dos direcciones, no se si esta bien, espero me pueda ayudar

Juka
 
En efecto es como dice luis30, si quieres poner la condición:

cont MAYOR que 5 Y cont MENOR O IGUAL que 10

entonces tienes que usar ambas condiciones con un operador binario AND (escrito &&).

Tal cual está tu código, primero se evalúa la primera condición ( 5 < cont ), si se cumple da verdadero (1), sino dará falso (0), y luego se hace una segunda comparación, 1 >= 10, o 0 >= 10, según lo que diera la primera comparación. En cualquier caso no se cumplirá, y por eso quizá empieza a parpadear.

Por otro lado, en vez de asignar los valores de salida pin a pin, ¿por qué no escribes directamente el puerto? Haría el código más corto de escribir, más rápido de ejecutarse, y hay quien diría que más claro de leer.


Saludos!
 
En efecto es como dice luis30, si quieres poner la condición:

cont MAYOR que 5 Y cont MENOR O IGUAL que 10

entonces tienes que usar ambas condiciones con un operador binario AND (escrito &&).

Tal cual está tu código, primero se evalúa la primera condición ( 5 < cont ), si se cumple da verdadero (1), sino dará falso (0), y luego se hace una segunda comparación, 1 >= 10, o 0 >= 10, según lo que diera la primera comparación. En cualquier caso no se cumplirá, y por eso quizá empieza a parpadear.

Por otro lado, en vez de asignar los valores de salida pin a pin, ¿por qué no escribes directamente el puerto? Haría el código más corto de escribir, más rápido de ejecutarse, y hay quien diría que más claro de leer.


Saludos!

Lo que necesito hacer es cuando la cuenta de cont sea :

1.- menor a 5 y mayor o igual a cero se encienda los pin d5 y b3
0<=cont<=5

2.- Mayor que 5 y menor o igual que 10, se apaguen los pin d5 y b3
5<cont<=10

3.- Mayor que 10 y menor o igual a 15, se prendan los pin b3 y d7
10<cont<=15
4.- Mayor que 15 y menor o igual a 20, se apaguen pin b3 y d7
15<cont<=20
5.- mayor a 20, reseteé cont y empiece de nuevo


Las modificaciones en el programa adjunto.

Código:
# include <16f877a.h>
# device *=16
# device adc=10
# use delay(clock=4M)
# include <lcd420.c>
# fuses xt,NOWDT
#include <internal_eeprom.c>
  

 int32 Cont = 0;               //Variable que Cuenta.
 int32 Cont1 = 0;
                //Interrupcion del Timer1.
#int_Timer1 
void TIMER0_isr( void )
   {
      Cont++;               //Incrementa el Contador.
      Cont1++;
      set_timer0(3036 );     //Carga el Timer0.
   }
   
void main( )
   {  
      set_tris_b(0b11111111);  //
      set_tris_c(0b11110000);  //
      set_tris_D(0b11111000);  //
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);;   //Preescaler de 64.
      enable_interrupts( INT_TIMER1 );      //Habilita la Interrupcion del Timer0.
      enable_interrupts( GLOBAL );         //Habilita la Interrupcion Global.
      set_timer1( 3036 );               //Carga el Timer0.
      while( true )
      {
      if (input(pin_d3)==1)// pulsador de partida
      {
      if(cont>=0&&cont<=5)            //cuando llegue 5 min parta ( los valores los modifico despues)
        {

        output_high ( pin_b3 );//led indivador
        output_high (pin_d5);//idem anterior
            
                    }
      if(cont>5&&cont<=10)        //aqui han pasado 5 debe detenerse y esperar.
         {
                 output_low ( pin_b3 );
                 output_low (pin_d5); 
        
         }
                
      if(cont>10&&cont<=15)            //pasaron los 5 min, funcione en sentido contrario por 5 min
         {
         output_high ( pin_b3);
         output_high (pin_d7);
         // falta secuencia
         }
      if(cont>15&&cont<=20)        //si han pasado 5 min pare.
         {
        output_low ( PIN_b3 );
         output_low (pin_d7);
         output_low (pin_d5);
         }
        if(cont<=21)        //se reseta el contador
         {

         Cont = 0;
         }
      }
      
            if (input(pin_d3)==0)// todo detenido
        {
         output_low ( PIN_b3 );
         output_low (PIN_d5);
         output_low (PIN_d7);
      }
      
      }
      }
Espero me puedan ayudar e indicar donde está mi problema.
Solo enciende led 7
Adjunto programas.


Juka
 

Adjuntos

  • motor.rar
    23.9 KB · Visitas: 1
Última edición por un moderador:
Tienes que meter las condiciones entre paréntesis (no estoy seguro si es 100% necesario, no recuerdo bien el orden de prioridad en este caso, pero es una buena precaución)
Código:
if ((cont>5) && (cont<=10))
De todas formas sigue siendo innecesario usar la doble condición. Si "cont" se incrementa en orden, puedes poner esto:

Código:
if (cont<=5)
    {
    //código
    }
else if (cont <=10)
    {
    //código
    }
else if (cont <=15)
    {
    //código
    }
else if (cont <=20)
    {
    //código
    }
else if (cont == 21)
    {
    //código
    }
Y escribiendo esto acabo de ver el por qué se reinicia siempre. Al no usar if..else, se evalúan todas las condiciones. La última condición
Código:
if(cont<=21)
siempre se cumple, ya que "cont" siempre es menor que 21. Tienes que poner "igual que", o "mayor o igual que".

Espero que te sirva.

Saludos.
 
Bueno, no sé si meter mi cuchara pero he movido motores a pasos de una manera diferente a la que aquí se muestra.

¿Por qué razón no me gusta este método?
Pues por la razón de que usamos una secuencia ya sea full step o half step casi a voluntad con mapeo diferente de los pines.

¿Cómo lo hacemos?
Metemos una secuencia del motor a pasos en un arreglo.
Unos los conocen como ARRAY, otros como arreglo y unos cuantos lo llaman VECTOR.

Ll arreglo va así:

char secuencia[8]={128,192,64,96,32,48,16,144};

Éstos números son la traducción del binario al decimal.

10000000 = 128
11000000 = 192
01000000 = 64
01100000 = 96
00100000 = 32
00110000 = 48
00010000 = 16
10010000 = 144


Así de fácil.

Ahora lo que sigue es hacer que el motor se mueva , es decir, nuestra secuencia numérica y ahora puede ser reflejada en un puerto cualquiera.

Para mover la secuencia se usa un ciclo for anidado con otro for.
Es decir, un for es para mover la secuencia y el segundo for para el número de repeticoones.

Hay que tener claro, que cuando no se mueva el motor o esté en reposo, debemos limpiar el puerto porque si no lo hacemos podemos quemar el driver, puente H o calentar el motor.

El código será el siguiente:

Código:
void main()
{
unsigned char motor[8]={128,192,64,96,32,48,16,144};    //secuencia de pasos
signed char contador;
char pasos;


for(;;)
{
   
   
   for(pasos=0;pasos!=25;pasos++)//se mueve los pasos que uno desea en mi caso son 25 pasos para dar media vuelta
{
   for(contador=0;contador!=8;contador++) //mueve la secuencia del motor de la secuencia 0 a la 7 sin llegar a 8
   {
      output_b(motor[contador]);// la secuencia se ve reflejada en el puerto B donde contador mueve la secuencia
      delay_ms(4); //retardo minimo para un motor a pasos
   }
}
output_b(0);//limpiar puerto


//meter aqui codigo para esperar 

} 


}
 
Última edición por un moderador:
Lo que necesito hacer es cuando la cuenta de cont sea :

1.- menor a 5 y mayor o igual a cero se encienda los pin d5 y b3
0<=cont<=5

2.- Mayor que 5 y menor o igual que 10, se apaguen los pin d5 y b3
5<cont<=10

3.- Mayor que 10 y menor o igual a 15, se prendan los pin b3 y d7
10<cont<=15
4.- Mayor que 15 y menor o igual a 20, se apaguen pin b3 y d7
15<cont<=20
5.- mayor a 20, reseteé cont y empiece de nuevo


Las modificaciones en el programa adjunto.

Código:
# include <16f877a.h>
# device *=16
# device adc=10
# use delay(clock=4M)
# include <lcd420.c>
# fuses xt,NOWDT
#include <internal_eeprom.c>
  

 int32 Cont = 0;               //Variable que Cuenta.
 int32 Cont1 = 0;
                //Interrupcion del Timer1.
#int_Timer1 
void TIMER0_isr( void )
   {
      Cont++;               //Incrementa el Contador.
      Cont1++;
      set_timer0(3036 );     //Carga el Timer0.
   }
   
void main( )
   {  
      set_tris_b(0b11111111);  //
      set_tris_c(0b11110000);  //
      set_tris_D(0b11111000);  //
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);;   //Preescaler de 64.
      enable_interrupts( INT_TIMER1 );      //Habilita la Interrupcion del Timer0.
      enable_interrupts( GLOBAL );         //Habilita la Interrupcion Global.
      set_timer1( 3036 );               //Carga el Timer0.
      while( true )
      {
      if (input(pin_d3)==1)// pulsador de partida
      {
      if(cont>=0&&cont<=5)            //cuando llegue 5 min parta ( los valores los modifico despues)
        {

        output_high ( pin_b3 );//led indivador
        output_high (pin_d5);//idem anterior
            
                    }
      if(cont>5&&cont<=10)        //aqui han pasado 5 debe detenerse y esperar.
         {
                 output_low ( pin_b3 );
                 output_low (pin_d5); 
        
         }
                
      if(cont>10&&cont<=15)            //pasaron los 5 min, funcione en sentido contrario por 5 min
         {
         output_high ( pin_b3);
         output_high (pin_d7);
         // falta secuencia
         }
      if(cont>15&&cont<=20)        //si han pasado 5 min pare.
         {
        output_low ( PIN_b3 );
         output_low (pin_d7);
         output_low (pin_d5);
         }
        if(cont<=21)        //se reseta el contador
         {

         Cont = 0;
         }
      }
      
            if (input(pin_d3)==0)// todo detenido
        {
         output_low ( PIN_b3 );
         output_low (PIN_d5);
         output_low (PIN_d7);
      }
      
      }
      }
Espero me puedan ayudar e indicar donde está mi problema.
Solo enciende led 7
Adjunto programas.


Juka

lo que pasa es que cuando se presiona el pin d3 te inicia una rutina de comparación lo cual nunca se lleva a cabo por que en seguida sueltas el botón entonces el programa solo se ejecuta una ves y llega al final donde pones de nuevo if (input(pin_d3)==0)// todo detenido
que obviamente ya estará detenido por que el pulsador ya no esta presionado, también en el punto.

if(cont<=21) //se reseta el contador
{

Cont = 0;
}

esta condicion siempre es verdadera por lo cual cont siempre es 0, debes corregir eso y si es que al presionar y soltar quieres que te haga toda la secuencia hasta que pase el tiempo que le das a cada ciclo te faltan algunos while.
 
¿por que razon no me gusta este metodo?
pues por la razon de que usamos una secuencia ya sea full step o half step casi a voluntad CON mapeo diferente de los pines.

Justamente lo que comenté, que es mejor escribir directamente un valor en el puerto, en vez de hacerlo pin a pin. Se escribe menos código y si usan menos instrucciones en el micro.

10000000 = 128
11000000 = 192
01000000 = 64
01100000 = 96
00100000 = 32
00110000 = 48
00010000 = 16
10010000 = 144

unsigned char motor[8]={128,192,64,96,32,48,16,144}; //secuencia de pasos

A mí esta parte me gusta más hacerla en hexadecimal, ya que pasar de o desde binario es directo.

Código:
1000 0000 = 0x80
1100 0000 = 0xC0
0100 0000 = 0x40
0110 0000 = 0x60
0010 0000 = 0x20
0011 0000 = 0x30
0001 0000 = 0x10
1001 0000 = 0x90

unsigned char motor[8] = {0x80, 0xC0, 0x40, 0x60, 0x20, 0x30, 0x10, 0x90};

La ventaja que le veo es que si quieres escribir en la parte baja del puerto (P0..P3), sólo tienes que intercambiar los dígitos, no tienes que andar dividiendo entre 16. Pero para gustos, colores ;)
 
fijate que eso es muy cierto no lo habia visto asi en realidad yo metia mi secuencia de

10100000
11110000
etc.

y un programita que hise me transformaba de binario a decimal es decir metia texto salia texto de un block de notas jaja pero nunca lo vi de esa manera tan facil
 
Que configuración de motor paso estás usando ? Unipolar, Bipolar ? Full - step, Half - Step ? Necesitás control de dirección ?

CCS tiene una guía de ejemplo para realizar un control de motor paso a paso. La misma la podés usar para manejar un motor bipolar o unipolar.

PHP:
#include <input.c>

#BYTE port_b = 6

#define FOUR_PHASE TRUE

#ifdef FOUR_PHASE

BYTE const POSITIONS[4] = {0b0101,
                           0b1001,
                           0b1010,
                           0b0110};
#else
BYTE const POSITIONS[8] = {0b0101,
                           0b0001,
                           0b1001,
                           0b1000,
                           0b1010,
                           0b0010,
                           0b0110,
                           0b0100};
#endif


drive_stepper(BYTE speed, char dir, BYTE steps) {
   static BYTE stepper_state = 0;
   BYTE i;

   for(i=0; i<steps; ++i) {
     delay_ms(speed);
     set_tris_b(0xf0);
     port_b = POSITIONS[ stepper_state ];
     if(dir!='R')
       stepper_state=(stepper_state+1)&(sizeof(POSITIONS)-1);
     else
       stepper_state=(stepper_state-1)&(sizeof(POSITIONS)-1);
   }
}

use_pot() {
  BYTE value;

  setup_adc(adc_clock_internal);
  set_adc_channel( 1 );
  printf("\r\n");

  while( TRUE ) {
    value=read_adc();
    printf("%2X\r",value);
    if(value<0x80)
       drive_stepper(value,'R',8);
    else if(value>0x80)
       drive_stepper(128-(value-128),'F',8);
  }

}


use_switch(BYTE speed, char dir) {

   BYTE steps;

   printf("\n\rSteps per press: ");
   steps = gethex();

   while(true) {
      while(input(PIN_B7)) ;
      drive_stepper(speed,dir,steps);
      while(!input(PIN_B7)) ;
      delay_ms(100);
   }
}


main() {

   BYTE speed, steps;
   char dir;

   setup_port_a(RA0_RA1_RA3_ANALOG);

   while (TRUE) {
       printf("\n\rSpeed (hex): ");
       speed = gethex();

       if(speed==0)
          use_pot();

       printf("\n\rDirection (F,R): ");
       dir=getc()|0x20;
       putc(dir);

       printf("\n\rSteps (hex): ");
       steps = gethex();

       if(steps==0)
          use_switch(speed,dir);

       drive_stepper(speed,dir,steps);
   }

}
 
me hiso bolas ese codigo tanto que ni lo revise

mover un motor a pasos es relativamente sencillo en realidad

es una secuencia dentro de un arreglo, y mediante un bucle mover el arreglo y lo que hay dentro del arreglo enviarlo al puerto

TAN TAN!
asi de facil

char arreglo[4 ] ={ 1,2,3,4};
char i;

for(i=0; i !=4 ; i ++ )

{

output_b( arreglo[ i ] );

}


lo que hace el for es mover lo que hay dentro del arreglo para que el puerto lo envie

si queremos hacer varias repeticiones pues metemos lo anterior a un for que repita varias veces

yo por ejemplo digo que se repita todo 5 veces

char arreglo[4 ] ={ 1,2,3,4};
char i;
char repite;

for(repite=0 ; repite!=5 ;repite++ )
{

for(i=0; i !=4 ; i ++ )

{
output_b( arreglo[ i ] );
}

}

nada mas!!!
 
me hiso bolas ese codigo tanto que ni lo revise

mover un motor a pasos es relativamente sencillo en realidad

es una secuencia dentro de un arreglo, y mediante un bucle mover el arreglo y lo que hay dentro del arreglo enviarlo al puerto

TAN TAN!
asi de facil

char arreglo[4 ] ={ 1,2,3,4};
char i;

for(i=0; i !=4 ; i ++ )

{

output_b( arreglo[ i ] );

}


lo que hace el for es mover lo que hay dentro del arreglo para que el puerto lo envie

si queremos hacer varias repeticiones pues metemos lo anterior a un for que repita varias veces

yo por ejemplo digo que se repita todo 5 veces

char arreglo[4 ] ={ 1,2,3,4};
char i;
char repite;

for(repite=0 ; repite!=5 ;repite++ )
{

for(i=0; i !=4 ; i ++ )

{
output_b( arreglo[ i ] );
}

}

nada mas!!!

Me parece muy interesante sus aportes, pero en primer lugar le responderé a luis 30, en verdad estaba malo la ultima parte debía ser >= a 21, lo del pin d3 es porque mientras este pulsado este pin la condición se debe cumplir.

a TRILO-BYTE, decirle que soy novato en esto de programar ya sea en c, como utilizar el ccs ( no mas de 30 días), por eso del uso de pin a pin, ademas en la siguiente dirección https://www.forosdeelectronica.com/showthread.php?p=936462#post936462 deje los archivo de lo que hice y la nota de que puede ser mejorado

así que y dado que cumplía lo que me habían pedido por ahora esta bien.

Sin embargo y con la idea de mejorarla y optimar el programa tengo una consulta que hacerle, en su ejemplo le dio 25 cuentas, como lo puedo hacer para cumplir con una hora sin que el motor funcione, luego funcione 5 minutos, pare otra hora y luego funcione pero en sentido inverso del anterior , ademas que cuando exista corte de energia guarde la cuenta para que empiece desde ahí, si gusta lo puede hacer en el archivo interrupciones_web ultimaversion del link indicado.

Espero su respuesta, eso si recuerde que soy novato y no de por hecho que le entenderé de inmediato

Aprovechando la oportunidad en otro trabajo que me dieron debo hacer una matriz de 8x40 con led, con registro 74hc164, en donde las letras se desplacen y la verdad es que no se me ocurre como hacerlo, así que si no es molestia agradecer orientación y/o ejemplos que comparta

Juan Carlos

PD: se me olvidaba indicar que el archivo interrupciones_web ultimaversion estan las modificaciones hechas por mi antes de sus comentarios
 
Última edición:
Atrás
Arriba