Ir ao conteúdo
  • Cadastre-se

Gerar e ler frequencia e dutty


cesarlg

Posts recomendados

Ola galera.. absorvi da net alguns codigos ccs e tentei simplificar ao maximo, mas nao consigo unir em um unico Pic 16f877a. Um gera um pwm de 1khz fixo, apenas variando seu duty. Ok ,, o segundo faz a essa leitura.. separadamente funcionam bem, com exessao do leitor se confundir qd o duty for <10% ou >90%.

agora tentei unir de varias maneiras, nao tendo exito.

gostaria de saber como implementar um codigo com o outro e reunir a funçao em um unico pic.

ps.: como diminuo esses codigos a um botao p qd clicados serem exibidos? deixando o topico + compacto.!

#include <16F877A.h>

#FUSES NOWDT
#FUSES XT
#FUSES PUT
#FUSES NOPROTECT
#FUSES NOBROWNOUT
#FUSES NOLVP
#FUSES NOCPD

#use delay(clock=4000000)

#define botao_incremento PIN_D0
#define botao_decremento PIN_D1


int8 ciclo_1;
int1 modo=0;


void main()
{

SETUP_CCP1(CCP_PWM);

setup_timer_2(T2_DIV_BY_4,249,1);
set_pwm1_duty(0);
set_pwm2_duty(0);

while (TRUE)
{

if (modo == 0)

{
if (input(botao_incremento))
{
ciclo_1 = ciclo_1 + 5;
do{}
while(input(botao_incremento));
}

if (input(botao_decremento))
{
ciclo_1 = ciclo_1 - 5;
do{}
while(input(botao_decremento));
}

set_pwm1_duty(ciclo_1);
set_pwm2_duty(0);
}


}
}

leitura

#include <16f877a.h>             

#FUSES NOWDT
#FUSES HS
#FUSES PUT
#FUSES NOPROTECT
#FUSES NOLVP
#FUSES NOCPD

#use delay(clock=4000000)
#include <LCD.C>

int1 pulso=0;
int16 T_descida_1=0,T_subida_1=0,T_ON=0,T_total=0,T_subida_2=0;
float32 AP=0.0,freq, d;

int flag;


#int_ccp1
void ccp1_int(void)
{
if (flag == 3)
{
flag = 0;
}

if(flag==0)
{
T_subida_1=CCP_1;
setup_ccp1(CCP_CAPTURE_FE);
}

if (flag == 1)
{
T_descida_1=CCP_1;
setup_ccp1(CCP_CAPTURE_RE);
}

if(flag==2)
{
T_subida_2=CCP_1;
setup_ccp1(CCP_CAPTURE_RE);

if(pulso==0)
{
pulso=1;
}
}
flag++;
}

void main()
{
lcd_init();


setup_timer_1(T1_INTERNAL);
setup_ccp1(CCP_CAPTURE_RE);
flag = 0;

enable_interrupts(int_ccp1);
enable_interrupts(global);
nuevopulso=0;

do
{
if(pulso==1)
{
T_ON=(T_descida_1-T_subida_1);
T_total = (T_subida_2-T_subida_1);

AP = (float)T_total;

freq=(float)1/(AP)*1000000;

d = (float)T_ON*100/T_total;

printf(lcd_putc,"\fFreq = %fHz\nDuty = %2.2f%%", freq,d);
delay_ms (200);
pulso=0;
}
}
while (TRUE);
}

Link para o comentário
Compartilhar em outros sites

Bom, para colocar o botão que você deseja, faça assim:

coloque o que você deseja esconder aqui[.spoiler]

Substitua o . (ponto) por /(barra).

Sobre a questao do código, daqui a pouco volto com a solução. Mas veja que já está praticamente pronto.

EDIT:

Bom, fiz aqui. Eu nao tinha percebido antes mas realmente, se o duty for menor que 10% e maior que 90%, dá uns resultados meio que malucos.

Consegui melhorar isso aumentando a frequencia do cristal de 4Mhz para 12Mhz. Ainda dá o erro. Mas somente ali próximo de 3% de duty cicle.

O problema ocorre quando o pulso fica com o tempo muito pequeno e o PIC não consegue medir com esse código. ok.....

Mas tem um datalhe, isso que deseja realizar, gerar e ler o mesmo pulso nao faz muito sentido na forma como você quer fazer.

Claro que serve como aprendizado, sem dúvidas. Para você nao ter que faezr um gerador de clock, pega o proprio PIC e mando o mesmo gerar o clock e depois lê. Tá certo.....

Mas veja que já que o PIC gera o PWM, temos uma fórmula para o cálculo do duty cicle sem precisar realmente lê-lo.

Primeiro o código que fiz que cumpre o que você quer:



#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //Clock <=4Mhz
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection

#use delay(clock=12000000)

#include <LCD.C>

#define botao_incremento PIN_B0
#define botao_decremento PIN_B1

int8 ciclo_1 = 93;

int1 pulso=0;
int16 T_descida_1=0,T_subida_1=0,T_ON=0,T_total=0,T_subida_2=0;
float32 AP=0.0,freq, d;
int flag;

#int_ccp1
void ccp1_int(void)
{
if (flag == 3)
{
flag = 0;
}

if(flag==0)
{
T_subida_1=CCP_1;
setup_ccp1(CCP_CAPTURE_FE);
}

if (flag == 1)
{
T_descida_1=CCP_1;
setup_ccp1(CCP_CAPTURE_RE);
}

if(flag==2)
{
T_subida_2=CCP_1;
setup_ccp1(CCP_CAPTURE_RE);

if(pulso==0)
{
pulso=1;
}
}
flag++;
}

void main()
{
lcd_init();

setup_timer_1(T1_INTERNAL);

setup_ccp1(CCP_CAPTURE_RE);
SETUP_CCP2(CCP_PWM);
setup_timer_2(T2_DIV_BY_4,249,1);

enable_interrupts(int_ccp1);
enable_interrupts(global);
flag = 0;

while (TRUE)
{
if (input(botao_incremento))
{
ciclo_1 = ciclo_1 + 5;
do{}
while(input(botao_incremento));
}

if (input(botao_decremento))
{
ciclo_1 = ciclo_1 - 5;
do{}
while(input(botao_decremento));
}

set_pwm2_duty(ciclo_1);

if(pulso==1)
{
T_ON=(T_descida_1-T_subida_1);
T_total = (T_subida_2-T_subida_1);

AP = (float)T_total/3;

freq=(float)1/(AP)*1000000;

d = (float)T_ON*100/T_total;

printf(lcd_putc,"\fFreq = %fHz\nDuty = %2.2f%%", freq,d);
delay_ms (200);
pulso=0;
}
}
}
#include <16F877A.h>

Circuito:

pwm_gera_e_le_16f877a.png

Para calcular sem ter que realmente ler:

Exemplo:

Para valores de 16 Bits:

Temos que setup_timer_2(T2_DIV_BY_4,249,1) e com isso temos um periodo de 249. Se fizermos set_pwm1_duty(124L) (note o "L") temos que:


--------------------------- = ------------ = ------ = 12.4%
(Timer 2 periodo +1) * 4 (249 +1) * 4 1000
   16-bit Duty cycle                  124          124

Para valores de 8 Bits:

Agora se ao invés de set_pwm1_duty(124L) usarmos set_pwm1_duty(124) sem o "L", quer dizer q estamos no modo 8 bits. Isso nos dá:


--------------------------- = ------------ = 49.6%
(Timer 2 periodo +1) 250
   8-bit Duty cycle                  124

Falou

Link para o comentário
Compartilhar em outros sites

Caro Matheus. obrigado.. tentei simular esse codigo e nao funcionoucomo esperado.. mudei o clock para 4mhz, pois ja estou usando outras funçoes e então nao queria alterar isso. Mudei para fuse para XT.

AP = (float)T_total/3; para AP = (float)T_total;

agora vem outras perguntas kkkk

1--- o pwm nao esta partindo do zero

2---int8 ciclo_1 = 93; ? porque?

3---se usasse o lcd para outra informaçao e quisesse ver essa atual ao clicar um botao (ou talves pressionado . seria assim?



#define botao_hz PIN_B3

while true:
if (input(botao_hz)) // clique no b3
{....... // todo codigo do while
do{}
while(input(botao_hz)); // falso
}
//se deixar o botao pressionado como?
//input_high(pin_b3) etc?

Link para o comentário
Compartilhar em outros sites

tentei simular esse codigo e nao funcionou

Aqui funcionou normalmente. Baixe os arquivos e tente: http://www.4shared.com/rar/MvWPWZPH/Geracao_PWM_e_leitura.html

1---int8 ciclo_1 = 93; ? porque?

Dá uma olhada na fórmula que te passei:

8-bit Duty cycle                  93
--------------------------- = ------------ = 49.73%
(Timer 2 periodo +1) 187

Dessa forma, o PWM começao já com 50% do duty.

2---preciso alterar >>> AP = (float)T_total/3; para AP = (float)T_total; ?

Se usar o cristal em 4Mhz, sim tem que mudar. A divisão por 3 é porque 12Mhz/3 = 4Mhz. Assim tenho o tempo em micro-segundos.

se usasse o lcd para outra informaçao e quisesse ver essa atual ao clicar um botao (ou talves pressionado . seria assim?



#define botao_hz PIN_B3

while true:
if (input(botao_hz)) // clique no b3
{....... // todo codigo do while
do{}
while(input(botao_hz)); // falso
}
//se deixar o botao pressionado como?
//input_high(pin_b3) etc?

Correto. Se deixar o botao pressionado, apenas retire o do{} while(input(botao_hz)).

Falou

Link para o comentário
Compartilhar em outros sites

realmente, passou despercebido a questao do numero 93.

estou inserindo o codigo q postei sobre apertar o botao p mostrar no lcd o valor. este primeiro funciona bem

   if (input(botao_hz))
{
printf(lcd_putc,"\fFreq = %fHz\nDuty = %2.2f%%", freq,d);
delay_ms (200);
pulso=0;

}

else
{
printf(lcd_putc,"\f");
}

ja este

   if (input(botao_hz))
{
printf(lcd_putc,"\fFreq = %fHz\nDuty = %2.2f%%", freq,d);
delay_ms (200);
pulso=0;
do{}
while(input(botao_hz));
}

}

o valor nao se atualiza qté novo clique. e nao sai da tela mais.

Link para o comentário
Compartilhar em outros sites

gostaria de implementar mais duas coisas, mas nao faço a minima ideia:

seria gerar o duty cicle 0 % até 70%. é possivel?

ja q temos impressizao até na faixa de 10% é possivel deixar zerado no lcd? sabemos q p pwm esta sendo gerado, mas na tela só mostrar a partir de qd ele firmaria o valor real?

valeu

Link para o comentário
Compartilhar em outros sites

O que você deseja realizar é muito simples.

Veja essas linhas do código:

if (input(botao_incremento))
{
ciclo_1 = ciclo_1 + 5;
do{}
while(input(botao_incremento));
}

Ora, a variável ciclo_1 que determina o duty. Sendo 70% do duty, teremos a variável citada com um valor máxima de:

   8-bit Duty cycle                   x
--------------------------- = ------------ = 0.7
(Timer 2 periodo +1) 187

Portanto:

x = 187*0.7 = 130.9 = 131

Dessa forma, apenas incremente a variável até a mesma ter esse valor.

Caso você aperte o botao de incremento novamente, faça uma condição do tipo:

if (ciclo_1 > 131 )

ciclo_1 = 131.

O mesmo raciocínio acima serve para não mostrar no LCD valores abaixo de 10%. Coloque uma condição do tipo:

if (duty < 10)

duty = 0;

O problema da mensuração incorreta do duty para valores de tempo tão pequenos pode ser melhorada também eliminando a quantidade imensa de contas do códigos.

Fiz aquele código daquela forma de propósito para ser o mais didático possível.

Podemos eliminar as divisões juntando tudo em uma equação só e simplificando.

Falou

Link para o comentário
Compartilhar em outros sites

amigos quero incrementar um pulsador na seguinte caracteristica 150 pulso por minuto com 2ms de pico , então se estou coreto seria 2.5hz, 2ms de high e 400ms em low. então o codigo

      if(input(botao_2hz))
{

output_high(pin_b0);
delay_ms(2);
output_low(pin_b0);
delay_ms(400);
do{}
while(input(botao_2hz));

gostaria de saber porque motivo , juntamente com minha inesperiencia nao funciona a questao de um clique iniciar e com outro terminar... desta maneira exposta só funciona deixado pressionado..

outra questao seria como levar a pulsaçao q ira atracar um solenoide (max. 1.5A). talves o ideal seria inverter os valores de tempo alto e baixo p funcionar neste esquema q envio? alguma outra ideia?

valeu!!!

post-198617-13884963811144_thumb.jpg

Link para o comentário
Compartilhar em outros sites

Primeiro que seu raciocínio está incorreto.

Se a frequência é de 2,5Hz, temos um período de 1/2,5 = 400mS.

Então seu pulso ficaria assim:

2mS --> ON

398mS --> OFF

Totalizando os 400mS.

Para que o pulso fique eterno, você precisa colocar um while na rotina.

Por exemplo, você cria uma variavel qualquer de controle.

Caso ela seja 0, nao executa o loop, caso seja 1, executa o codigo.

você altera o valor dessa variavel com o botao.

Em um pseudo código:

if (botao apertado)
{
aux = 1;
do {} //Essas duas linhas é apenas
while (botao apertado); //debouncing. Acostume a usar.
}

while (aux == 1)
{
executa meu loop de pulso;

if (botao apertado)
{
aux = 0;
do {} //Essas duas linhas é apenas
while (botao apertado); //debouncing. Acostume a usar.
}
}

OBS: Veja que dessa forma, o código trava no while. É apenas um exemplo para você ter uma ideia. Agora, bote os miolos a ferver e treine o algoritmo.

Sobre a solenoide, use apenas um TIP120/122. Mais fácil de usar que um mosfet e cumpre o papel.

Falou

Link para o comentário
Compartilhar em outros sites

Pessoal, chegou a hora de agrupar td o que precisava em um codigo só..

tudo funcionou razoavelmente, mas notei que a casa esta toda bagunçada.

os delays sofrem um atraso absurdo..

preciso ajuda para organizar

#include <16F877A.h>

#device adc=10

#FUSES NOWDT

#FUSES XT

#FUSES PUT

#FUSES NOPROTECT

#FUSES NODEBUG

#FUSES NOLVP

#FUSES NOCPD

#use delay(clock=4000000)

#include <lcd.C>

#define botao_incremento PIN_b3

#define botao_decremento PIN_b4

#define botao pin_b0

float v;

int menu = 1;

int1 pulso=0;

int16 T_descida_1=0,T_subida_1=0,T_ON=0,T_total=0,T_subida_2=0;

float32 AP=0.0,freq, d;

int flag;

int8 ciclo_1 = 25;

#int_ccp1

void ccp1_int(void)

{

if (flag == 3)

{

flag = 0;

}

if(flag==0)

{

T_subida_1=CCP_1;

setup_ccp1(CCP_CAPTURE_FE);

}

if (flag == 1)

{

T_descida_1=CCP_1;

setup_ccp1(CCP_CAPTURE_RE);

}

if(flag==2)

{

T_subida_2=CCP_1;

setup_ccp1(CCP_CAPTURE_RE);

if(pulso==0)

{

pulso=1;

}

}

flag++;

}

void main()

{

output_high(pin_e2);

setup_adc_ports(AN0_AN1_VREF_VREF);

setup_adc(ADC_CLOCK_DIV_64);

set_adc_channel(0);

delay_us(20);

lcd_init();

lcd_gotoxy(1,1);

lcd_putc(" LIGANDO");

delay_ms(2000);

lcd_gotoxy(1,2);

lcd_putc("*** ***");

delay_ms(400);

lcd_putc("\f AGUARDE");

delay_ms(1000);

lcd_gotoxy(1,2);

lcd_putc("*** ***");

delay_ms(400);

lcd_putc("\f INICIALIZANDO");

delay_ms(2000);

printf(lcd_putc,"\f \n\f ");

delay_ms(200);

printf(lcd_putc,"\f <> \n <> ");

delay_ms(100);

printf(lcd_putc,"\f <<>> \n <<>> ");

delay_ms(100);

printf(lcd_putc,"\f <<<>>> \n <<<>>> ");

delay_ms(100);

printf(lcd_putc,"\f <<<<<>>>>> \n <<<<<>>>>> ");

delay_ms(100);

printf(lcd_putc,"\f <<<<<<>>>>>> \n <<<<<<>>>>>> ");

delay_ms(100);

printf(lcd_putc,"\f <<<<<<<>>>>>>> \n <<<<<<<>>>>>>> ");

delay_ms(100);

printf(lcd_putc,"\f<<<<<<<<>>>>>>>> \n<<<<<<<<>>>>>>>> ");

delay_ms(100);

printf(lcd_putc,"\f>>>>>>>><<<<<<<< \n>>>>>>>><<<<<<<< ");

delay_ms(100);

printf(lcd_putc,"\f >>>>>>><<<<<<< \n >>>>>>><<<<<<< ");

delay_ms(100);

printf(lcd_putc,"\f >>>>>><<<<<< \n >>>>>><<<<<< ");

delay_ms(100);

printf(lcd_putc,"\f >>>>><<<<< \n >>>>><<<<< ");

delay_ms(100);

printf(lcd_putc,"\f >>>><<<< \n >>>><<<< ");

delay_ms(100);

printf(lcd_putc,"\f >>><<< \n >>><<< ");

delay_ms(100);

printf(lcd_putc,"\f >><< \n >><< ");

delay_ms(100);

printf(lcd_putc,"\f >< \n >< ");

delay_ms(100);

lcd_putc("\f MULTIFUNCAO \n Linha Diesel");

delay_ms(3000);

lcd_putc ("\f");

lcd_gotoxy (3,1);

lcd_putc("VERSAO");

delay_ms(600);

lcd_gotoxy (8,2);

lcd_putc ("0.37");

delay_ms(600);

lcd_putc ("\f");

lcd_gotoxy (6,1);

lcd_putc("by");

delay_ms(500);

lcd_gotoxy (5,2);

lcd_putc (" CESAR");

delay_ms(500);

lcd_putc ("\f PRONTO");

delay_ms(800);

setup_timer_1(T1_INTERNAL);

setup_ccp1(CCP_CAPTURE_RE);

SETUP_CCP2(CCP_PWM);

setup_timer_2(T2_DIV_BY_4,249,1);

enable_interrupts(int_ccp1);

enable_interrupts(global);

flag = 0;

while(true)

{{

v=read_adc();

v=(v*1.466)+0.7;

}

{

if(input(botao_incremento))

{

ciclo_1 = ciclo_1 + 5;

do{}

while(input(botao_incremento));

}

if (input(botao_decremento))

{

ciclo_1 = ciclo_1 - 5;

do{}

while(input(botao_decremento));

}}

if (ciclo_1>175)

ciclo_1=175;

set_pwm2_duty(ciclo_1);

if(pulso==1)

{

T_ON=(T_descida_1-T_subida_1);

T_total = (T_subida_2-T_subida_1);

AP = (float)T_total;

freq=(float)1/(AP)*1000;

d = (float)T_ON*100/T_total;

}

delay_ms(120);

if(input(PIN_b0)) menu ++;

if(input(PIN_b1)) menu --;

if(menu == 0) menu = 9;

if(menu == 9) menu = 1;

switch(menu)

{

case 2 : printf(lcd_putc,"\f%2.2f BAR\nDuty %2.2f%% 1KHz"v,d);

delay_ms (200);

pulso=0;

break;

case 3 : printf(lcd_putc,"\f2000 ppm 0.16ms \nBAR >> %4.2f"v);

(output_high(Pin_a5));

delay_us(160);

output_low(pin_a5);

delay_ms(29);

break;

case 4 : printf(lcd_putc,"\f400 ppm 1ms\nBAR >> %4.2f"v);

{

output_high(Pin_a5);

delay_ms(1);

output_low(Pin_a5);

delay_ms(149); }

break;

case 5 : printf(lcd_putc,"\f1000 ppm 1ms\nBAR >> %4.2f"v);

{

output_high(Pin_a5);

delay_ms(1);

output_low(Pin_a5);

delay_ms(59);

}

break;

case 6: printf(lcd_putc,"\f1500 ppm 1ms\nBAR >> %4.2f"v);

{

output_high(Pin_a5);

delay_ms(1);

output_low(Pin_a5);

delay_ms(39);

}

break;

case 7 : printf(lcd_putc,"\f150 ppm 2ms\nBAR >> %4.2f"v);

{

output_high(Pin_a5);

delay_ms(2);

output_low(Pin_a5);

delay_ms(398);

}

break;

default :

printf(lcd_putc,"\f MENU DE \n configuração");

}

if(input(botao)) // daki em diante é tempo de bip p cada tecla pressionada

{output_high(pin_e1);

delay_ms(100);

output_low(pin_e1);}

if(input(pin_b1))

{output_high(pin_e1);

delay_ms(100);

output_low(pin_e1);}

if(input(pin_b3))

{output_high(pin_e1);

delay_ms(100);

output_low(pin_e1);}

if(input(pin_b4))

{output_high(pin_e1);

delay_ms(100);

output_low(pin_e1);}

}

}

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!