Timers em Loop

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Timers em Loop

Mensagempor picman62 » 25 Jan 2015 11:16

Bom dia Andre, Ze, e membros do fórum.

Gostaria da ajuda de voces para solucionar um probleminha de rotina de instrução.
Fiz o seguinte código abaixo para iniciar 3 pulsos de PWM em tempos diferentes para cada 'cont' de display. Ou seja, quando pressiono o botão do input B4, é mudado a página do display e quando pressiono B7 a primeira vez o PWM inicia. Quando pressiono B7 a segunda vez, PWM para. Então apertooo B4 e mudo de página.
Isso foi criado com interrupts e funciona bem.
Obs. Está incluso só o 'cont1', mas são 3 conts(3 mudanças de página no LCD).
Código: Selecionar todos
void button_isr()
{
   
   if( !input(PIN_B7) && !signal )
      signal = 1;
   else
   
   
   if( !input(PIN_B7) && signal )
      signal = 0;   

void main()
{

 
   enable_interrupts(global);
   enable_interrupts(int_rb);

   ext_int_edge( H_TO_L );

   output_drive(pin_c2);
   INT SW4;

while(true)
{
 ISPRESSED_KEY4=TRUE;
   
   if(cont==1)
           
   do // interrupts to loop state of PWM and out of it
     
   {
   
    if(signal) // if PWM is sent through C2 pin
   
   {     
           setup_timer_2(T2_DIV_BY_4,249,1);
           set_pwm1_duty(748);//enable PWM   
           setup_ccp1(CCP_PWM); //enable PWM
           delay_ms(100);
           setup_ccp1(CCP_OFF);//disable PWM
           delay_ms(500);
   }
       
   }
   
   
    while(input(pin_b4)==1); //if SW4 is pressed while in SW1   
   
}
}


O problema é que criei um código com contador de frequencia, bargraph e led.Esse código está funcionando bem. Quando insiro esse código na rotina com o PWM, o PWM não funciona mais em loop e os dois timers iniciam em tempos diferentes. Não sei o que houve. O que preciso é que os dois iniciem ao mesmo tempo e o PWM fique no loop de on/off até ser desligado juntamente com o contador, bargraph e led pelo pressionamento do botão B7 pela segunda vez.
Portanto com certeza é uma questão de chaves inseridas corretamente e comandos de instrução corretos, que não estou conseguindo identificar.
O comando 'do ...if(signal)' funcionava para o PWM, mas agora quando coloco os dois (PWM e TIMER1) o PWM não funciona.

Abaixo está o código completo somente dessa porção da programação inteira do PIC. Está incluso somente o TIMER1, pois não sei como inserir o primeiro código do PWM acima que estava funcionando.
Será que alguém consegue identificar o porque e fazer a instrução certa para que funcione como necessito?
Obrigado.
Código: Selecionar todos
if ( (SW4 && !ISPRESSED_KEY4) )
   
  {
         
         ISPRESSED_KEY4=TRUE;
   
   if((cont==1)||(cont==2)||(cont==3))   
           
   do
   
   {
   
   if(signal)
   
   {   
         
         set_timer1(0);
         setup_timer_1(t1_external | T1_DIV_BY_1);
         delay_ms(1000);
         setup_timer_1(T1_DISABLED);
         value=get_timer1();
         
         if(cont==1)
         printf (lcd_putc,"\fF1=       %LU\r\n",value);
         A=value/200;
         B=value/300;
         C=value/400;
         D=value/10000;
       
         
         if(cont==2)
         printf (lcd_putc,"\fF2=     %LU\r\n",value);
         A=value/360;
         B=value/460;
         C=value/560;
         D=value/10000;
         
         if(cont==3)
         printf (lcd_putc,"\fF3=    %LU\r\n",value);
         A=value/520;
         B=value/1200;
         C=value/2000;
         D=value/10000;
         
         
       
       
   if(value>=counter-3 && value<=counter+2)
         bargraph(A);      //print line 2 with the bargraph output
         
   else if ((value>=counter-6 && value<counter-2) || (value>=counter+5 && value<counter+20))
         bargraph(B);
     
   else if((value>=counter-15 && value<counter-6) || (value>=counter+20 && value<=counter+35))
         bargraph(C);
     
   else
         bargraph(D);
   
   
   
   if(value>=counter-3 && value<=counter+2)
               
   do
      {
         output_high(pin_c1);
         delay_ms(10);
         output_low(pin_c1);
         delay_ms(10);
       
      }
     
      while(signal);
     
   if((value>=counter-6 && value<counter-2) || (value>=counter+5 && value<counter+20))
               
   do
      {
         output_high(pin_c1);
         delay_ms(90);
         output_low(pin_c1);
         delay_ms(90);
       
      }
     
      while(signal);
     
   if((value>=counter-15 && value<counter-6) || (value>=counter+20 && value<=counter+35))
     
   do
      {
         output_high(pin_c1);
         delay_ms(160);
         output_low(pin_c1);
         delay_ms(160);
       
      }
     
      while(signal);
     
   if(value<counter-15 || value>counter+35)
   
   do
      {
         output_low(pin_c1);
         
      }
             
      while(signal);


      }
   
       
      if(!signal) // if PWM is sent through C2 pin

   
      {         
           
            printf(lcd_putc,"\f");
            lcd_gotoxy(1,1);
            if(cont==1)
            lcd_putc("F1");
            if(cont==2)
            lcd_putc("F2");
            if(cont==3)
            lcd_putc("F3");
            lcd_gotoxy(7,2);
            printf(lcd_putc," %04LU ",counter);
            break;
           
   }
       
   }
   
    while(input(pin_b4)==1); //if SW4 is pressed while in SW1
   }
picman62
Nibble
 
Mensagens: 53
Registrado em: 21 Dez 2014 08:40

Re: Timers em Loop

Mensagempor xultz » 26 Jan 2015 07:19

Eu não estudei teu código, mas leituras de botões costumam dar problemas esquisitos por causa de bounce. Esse efeito é um problema mecânico, que ao pressionar o botão, até que o mesmo firme o contato, apresenta comportamentos como se tivesse sido pressionado várias vezes, de forma muito rápida. Você consegue observar este efeito com um osciloscópio digital.
Existem muitas técnicas de debounce. Uma delas é colocar um capacitor em paralelo com a chave, mas isto ameniza o problema, geralmente não resolve. Eu gosto de fazer debounce em firmware, onde uma interrupção de timer (geralmente uso interrompendo a cada 1 ms) faz leitura das chaves, e só considera que a chave foi pressionada ou solta se realizar 20 leituras consecutivas do mesmo estado.
Pode ser que teu problema seja esse, você pressiona a chave uma vez, e o PIC entende que foi pressionada 2, ou mais vezes.
98% das vezes estou certo, e não estou nem aí pros outros 3%.
Avatar do usuário
xultz
Dword
 
Mensagens: 3001
Registrado em: 13 Out 2006 18:41
Localização: Curitiba

Re: Timers em Loop

Mensagempor andre_luis » 26 Jan 2015 07:57

picman62 escreveu:mas agora quando coloco os dois (PWM e TIMER1) o PWM não funciona


O PWM já não utiliza intrinsicamente o TIMER1 na sua estrutura ?

Imagem
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Timers em Loop

Mensagempor ze » 26 Jan 2015 08:36

Apesar de termos estilos incompatíveis, até que tentei analisar seu código um pouco (pero no mucho). desculpe a minha confusão mas vc está fazendo um frequencímetro pra ler num bargraf? e ao mesmo tempo gerando sinal pwm? está querendo saber a propria freq gerada ou é uma outra?
Mas 1º considere o questionamento do andré sobre timer1 que foi pertinente. Se for o caso, é melhor usar outro timer (cujo acesso se tem num pino) para ler frequência externa.
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Re: Timers em Loop

Mensagempor andre_luis » 26 Jan 2015 11:28

Bom, olhando com calma, acho que me enganei, o TIMER1 parece que não é mesmo compartilhado com o PWM.

Mas de qualquer modo, apesar de ter lido e relido a descrição do problema, não ficou muito claro pra mim.
Novamente, um fluxograma ajudaria.
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Timers em Loop

Mensagempor picman62 » 26 Jan 2015 12:43

Andre, o PWM utiliza o timer2.
É pertinente o comentário do Xultz. Esse negócio de debounce é complicado mesmo...
Ze, sim utilizo o frequencimetro para ler o bargraph, ou melhor, para me certificar da correta frequencia.

Estive revisando o código e tentei uma estratégia. O que fiz foi copiar somente a seção em que o PWM é acionado juntamente com o timer1 e criei outro código no CCS. Coloquei os headers, etc. e os dois em while(true).
Funcionaram perfeitamente. Não houve delay algum ao pressionar o botão de start dos dois.
Isso significa que o problema reside na formatação das instruções que estão no código que postei anteriormente.

Nessa revisão percebi algo que pode ou não ser relevante para criar um problema e que pode ou não ter relação com tudo isso.
Seria bom voces acompanharem o que vou descrever vendo o código que postei anteriormente.

A programação inicia, com o display dizendo 'bem vindo', etc. etc. Até que para e pede para apertar um botão. Esse é o botão B4. Quando há o primeiro aperto, aparece o TEXTO1, no segundo o TEXTO 2, no terceiro o TEXTO 3. No quarto aperto mostra o nivel da bateria e se houver um quinto aperto, retorna novamente ao TEXTO 01. Quando estava revendo não lembrava porque coloquei esse código assim:
Código: Selecionar todos
 if (cont>=4) counter1(texto1)
if(cont>=1) counter2(texto02)
if(cont>=2)counter3(texto03)

Tentei lembrar porque não coloquei simplesmente if(cont==1) counter1(texto01). E foi aí que percebi que se fizesse assim, o cont1 virava texto2, porque considera que apertando a primeira vez é o cont==0.
picman62
Nibble
 
Mensagens: 53
Registrado em: 21 Dez 2014 08:40

Re: Timers em Loop

Mensagempor ze » 26 Jan 2015 14:45

reformulando a questão: vc faz o pic se comportar como um frequencímetro fazendo-o ler a sua própria frequencia de pwm e fazendo-o mostrar num bargraph? confusão... nem sei se me entenderia. Mas se sim, acho que tem modos mais eficientes. enfim...

Detalhes... se cont=3, ao fazer
if(cont>=1) counter2(texto02) --esta condição é verdadeira. Vai executar a função
if(cont>=2)counter3(texto03) --e esta, idem
Mas se isto não lhe foi empecilho... ótimo.

Mas então... pelo jeito já se autosolucionou-se a si próprio
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Re: Timers em Loop

Mensagempor picman62 » 26 Jan 2015 16:46

ze escreveu:reformulando a questão: vc faz o pic se comportar como um frequencímetro fazendo-o ler a sua própria frequencia de pwm e fazendo-o mostrar num bargraph? confusão... nem sei se me entenderia. Mas se sim, acho que tem modos mais eficientes. enfim...

Detalhes... se cont=3, ao fazer
if(cont>=1) counter2(texto02) --esta condição é verdadeira. Vai executar a função
if(cont>=2)counter3(texto03) --e esta, idem
Mas se isto não lhe foi empecilho... ótimo.

Mas então... pelo jeito já se autosolucionou-se a si próprio


Mil desculpas Ze, esqueci de responder a sua pergunta.

Não, estou enviando um pulso de frequencia em intervalos a um aparelho que quando recebe envia a resposta na mesma frequencia.

Estou reformulando o código com o PWM que por enquanto ainda não está em loop. Isso com certeza se deve ao fato de que não estou construindo o código com os braces corretamente talvez. Assim que terminar, vou postar aqui para voces olharem e tentarem identificar como reformular a instrução para que funcione corretamente.
Não sei se tenho que fazer um outro interrupt ou não.
Enfim, até mais tarde.
picman62
Nibble
 
Mensagens: 53
Registrado em: 21 Dez 2014 08:40

Re: Timers em Loop

Mensagempor picman62 » 27 Jan 2015 08:40

Update:
Consegui o meu intento que foi colocar PWM funcionando em loop corretamente sem precisar usar o famigerado 'while(true)'. É incrível mas quanto mais cabeçadas eu dou, mais eu aprendo. Percebi que a correta utilização dos braces(chaves) é fundamental para organizar tudo.
Sei muito bem que isso é linguagem C básica, mas não tem jeito, estou aprendendo C ao mesmo tempo que pratico nesse projeto. No fórceps mesmo.
Percebi também uma coisa que não sabia. O CCS compiler tem um modo de lidar com as rotinas mesmo que em chaves. Ele tem uma maneira de lidar com hierarquias e prioridades internamente. Descobri que tem que se colocar as rotinas em uma ordem de prioridades específica, se não o bicho compila mas não executa direito. Incrivel.

No momento, o código está 99% pronto. Só falta inserir a rotina de leds que devem piscar em tempos diferentes para cada frequencia. Ainda não consegui fazer essa rotina sem comprometer o que já consegui até aqui. Mas se consegui chegar até aqui, algumas cabeçadas a mais e completo essa joça, tenho fé.
Se não conseguir até quinta feira, vou postar o código aqui para voces me dizerem onde devo enfiar essa rotina dos leds da maneira correta. Primeiro vou a luta.
Abçs a todos.
picman62
Nibble
 
Mensagens: 53
Registrado em: 21 Dez 2014 08:40

Re: Timers em Loop

Mensagempor andre_luis » 27 Jan 2015 11:40

picman62 escreveu:O CCS compiler tem um modo de lidar com as rotinas mesmo que em chaves. Ele tem uma maneira de lidar com hierarquias e prioridades internamente. Descobri que tem que se colocar as rotinas em uma ordem de prioridades específica, se não o bicho compila mas não executa direito


De um modo geral, isso pode estar mais relacionado á logica do programa do que propriamente ao compilador, que para otimizar um caso em que sabidamente nunca iria sair daquele laço, simplesmente nem compila o que vem depois.
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Timers em Loop

Mensagempor picman62 » 27 Jan 2015 22:47

Andre, o código abaixo está funcionando bem com o PWM e o bargraph. O PWM está funcionando em loop.
Porém não é executado o pin_c1 com o LED. Já tentei com output_high, etc. e também nada.
Se porém eu escrever abaixo do IF(...)
Código: Selecionar todos
led=!led;


O led finalmente pisca. Mas o faz com um intervalo de delay acende/apaga de uns 4 segundos. Não sei de onde o compilador achou esse tempo de 4s.
Pode me explicar o porque?
Sei que é uma questão de construção dos statements e colocação das chaves, porque se excluir todo o cabecalho acima da instrução do LED, ele pisca. Notei também que se excluir o comando do PWM, os leds funcionam. Então as instruções para o PWM e para o LED piscar estão em conflito. Um só funciona se o outro não estiver presente. Porque? Qual é a instrução a ser escrita para que o LED pisque sem prejudicar nenhuma outra função já programada?

cpp code
#include <16f877a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,BROWNOUT
#use delay(clock = 20000000)

BYTE signal = 0;

#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <LCD.C>
#include <LCD_bargraph.c>
#use fast_io(c)
#byte portc=0x07
#bit led=portc.1
#bit t1_overflow=0x0C.0
#int_rb



void button_isr()
{

if( !input(PIN_B7) && !signal )
signal = 1;
else


if( !input(PIN_B7) && signal )
signal = 0;
}


void main()
{
enable_interrupts(global);
enable_interrupts(int_rb);

ext_int_edge( H_TO_L );

output_drive(pin_c2);

setup_adc_ports(AN0_VREF_VREF);
setup_adc( ADC_CLOCK_INTERNAL );


port_B_pullups(0xFF);


lcd_init();
init_user_chars();

int A;
int B;
int C;
int D;
unsigned int16 value;

set_tris_c(0b00000001);



INT1 SW1;
INT1 SW2;
INT1 SW3;
INT1 SW4;


BOOLEAN ISPRESSED_KEY1=FALSE; // Boolean logic=0;
BOOLEAN ISPRESSED_KEY2=FALSE; // Boolean logic=0;
BOOLEAN ISPRESSED_KEY3=FALSE; // Boolean logic=0;
BOOLEAN ISPRESSED_KEY4=FALSE; // Boolean logic=0;

int Cont;
if ( (SW4 && !ISPRESSED_KEY4) )

{
ISPRESSED_KEY4=TRUE;

if((cont==1)||(cont==2)||(cont==3))

do // interrupts to loop state of PWM and out of it

{

if(signal) // if PWM is sent through C2 pin

{
set_timer1(0);
setup_timer_1(t1_external | T1_DIV_BY_1);
delay_ms(1000);
setup_timer_1(T1_DISABLED);
value=get_timer1();
}


if(Cont==1)

{
printf (lcd_putc,"\ftexto1 %LU\r\n",value);
A=value/200;
B=value/300;
C=value/400;
D=value/10000;
setup_timer_2(T2_DIV_BY_4,249,1);
set_pwm1_duty(748);

}
if(Cont==2)
{
printf (lcd_putc,"\ftexto2 %LU\r\n",value);
A=value/360;
B=value/460;
C=value/900;
D=value/10000;
setup_timer_2(T2_DIV_BY_4,142,1);
set_pwm1_duty(430);
}
if(Cont==3)
{
printf (lcd_putc,"\ftexto3 %LU\r\n",value);
A=value/520;
B=value/1200;
C=value/2000;
D=value/10000;
setup_timer_2(T2_DIV_BY_4,96,1);
set_pwm1_duty(292);
}


if(value>=counter-3 && value<=counter+2)
bargraph(A); //print line 2 with the bargraph output

else if ((value>=counter-6 && value<counter-2) || (value>=counter+5 && value<counter+20))
bargraph(B);

else if((value>=counter-15 && value<counter-6) || (value>=counter+20 && value<=counter+35))
bargraph(C);

else
bargraph(D);


if(value>=counter-3 && value<=counter+2)// NÃO ESTÁ FUNCIONANDO! NÃO ACONTECE NADA.
{
output_bit(pin_c1(1));
delay_ms(10);
output_bit(pin_c1(0));
delay_ms(10);

}


if(signal)
{
setup_ccp1(CCP_PWM); //enable PWM // PWM funciona OK e está em loop.
delay_ms(100);
setup_ccp1(CCP_OFF);//disable PWM
delay_ms(1000);

}


if(!signal) // if PWM is not sent through C2 pin

{

printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
if(cont==1)
lcd_putc("GOLD");
if(cont==2)
lcd_putc("SILVER");
if(cont==3)
lcd_putc("DIAMOND");
lcd_gotoxy(7,2);
printf(lcd_putc," %LU ",counter);
break;






}



}


while(input(pin_b4)==1); //if SW4 is pressed while in SW1


}
picman62
Nibble
 
Mensagens: 53
Registrado em: 21 Dez 2014 08:40

Re: Timers em Loop

Mensagempor andre_luis » 28 Jan 2015 17:28

picman62 escreveu:O PWM está funcionando em loop.
Porém não é executado o pin_c1 com o LED. Já tentei com output_high, etc. e também nada.
Se porém eu escrever abaixo do IF(...)
Código: Selecionar todos
led=!led;


O led finalmente pisca. Mas o faz com um intervalo de delay acende/apaga de uns 4 segundos. Não sei de onde o compilador achou esse tempo de 4s


Não consegui identificar exatamente em qual linha do código acima voce se refere, pois não encontrei essa função output_high, e existem vários if´s no programa.
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ

Re: Timers em Loop

Mensagempor picman62 » 29 Jan 2015 23:25

Andre, obrigado pelo retorno.
Estou há dias mexendo nesse código e descobri coisas interessantes.
Relatei que quando a instrução do PWM é mantida, não há nenhuma atividade nos leds. Estive há dois dias mudando toda a forma de executar essas instruções mas sempre com o mesmo resultado nulo.
O PWM emite um pulso durante 100ms. e fica mudo durante 1 segundo. Nesse exato momento, o timer1 produz uma leitura no display em que se a frequencia lida for digamos exatos 5Khz, o led pisca em intervalos de 10ms. Pois bem, isso nunca funcionou no código que postei. Hoje descobri que se eu aumetar o delay para 100ms e diminuir os delays do PWM, o led finalmente pisca. Mas notei algumas anomalias como por exemplo, piscar, mas de modo irregular com o periodo desligado maior do que o ligado. ALém disso percebi que dependendo da relação dos delays entre o PWM e o LED, esse último pisca sincronizado com o PWM! A conclusão que estou tendo no momento é que esse problema pode estar totalmente relacionado com o simulador do Proteus. Como estou longe do meu hardware, não posso fazer o teste real, mas em breve o farei.
picman62
Nibble
 
Mensagens: 53
Registrado em: 21 Dez 2014 08:40


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x