Boa noite Claudio, tentei adaptar seu codigo do artigo (ref 188) mas sem sucesso, pode dar uma analisada se tem como implementar essa parte no meu codigo?
segue abaixo o que tentei fazer:
#include <main.h>
#zero_ram
#bit int_tmr0_on = 0x0b.5 //flag on/off de interrupçao do timer 0
signed int conta=0;
signed int tempo=0;
signed int16 dutyPwm=0;
int8 cnt, minutos, segundos;
int1 f_trava1,f_bipar,f_dl,f_pause;
//==============================================================================
//rotina de produção de som no disco piezoeletrico
void bipar() {
int16 c;
int8 a;
f_bipar=0;
for(a=0;a<5;a++){
for(c=0; c<2500; c++) {
output_high(beep);
delay_us(193); //ajuste conforme freq. ressonancia do piezoeletrico
output_low(beep);
delay_us(11);
}
delay_ms(100);//delay entre beeps
}
}
//=============================================================================
// ROTINA DE INTERRUPÇÃO DO TIMER 0 (CADA 8MS)
//=============================================================================
#INT_TIMER0
void TIMER0_isr(void)
{
set_timer0(get_timer0())+132; //carrega TMR0 com o valor
if(++cnt>=125){ //8ms * 125 = 1s
cnt=0;
if(--segundos==0xff){
segundos=59;
if( minutos>0) --minutos;
}
if(!minutos&&!segundos) {
output_low(rele);//desliga o rele de saída
disable_interrupts(int_timer0);//para a contagem
f_bipar=1;//sinaliza para bipar (fim da contagem)
f_pause=0;
}
}
}
#include <lcd.c>
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_BIT); //8,1 ms overflow
setup_timer_2(T2_DIV_BY_16,249,1); //8,0 ms overflow, 8,0 ms interrupt
setup_ccp1(CCP_PWM);
set_pwm1_duty((int16)0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
set_timer0(132);
output_low(rele);
lcd_init();
printf(lcd_putc," TESTE\n V1");// mensagem de apresentação
delay_ms(2000);
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u",conta);
printf(lcd_putc,"\nTEMPO:%u",tempo);
while(TRUE)
{
if(input(up)==0) { // aumenta duty pmw
dutyPwm = dutyPwm + 60;
if(dutyPwm>600){dutyPwm=600;}
set_pwm1_duty((int16)dutyPwm);
delay_ms(300);
conta=conta+10;
if(conta>100){conta=100;}//limita contador em 100
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTEMPO:%u",conta,tempo);
delay_ms(20);
}
if(input(dw)==0){ // diminui o duty pwm
dutyPwm = dutyPwm - 60;
if (dutyPwm<0){dutyPwm=0;}
set_pwm1_duty((int16)dutyPwm);
delay_ms(300);
conta=conta-10;
if(conta<0){conta=0;}// limita contador em 0
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTEMPO:%u",conta,tempo);
delay_ms(20);
}
if((rele)==1){ //ajustes somente em 'pausa'
if(input(seg)==0){ // botão de ajuste de segundos se pressionado começa incrementar
if(++segundos>59) segundos=0;
delay_ms(250);//velocidade de incremento
if(input(seg)==1) if(--segundos==0xff) segundos=59;;//se botão for solto durante o delay acima
f_pause=0;//muda de 'pause' para 'off'
}
if(input(min)==0){ //botão ajuste de minutos se pressionado começa incrementar
if(++minutos>59) minutos=0;
delay_ms(250);
if(input(min)==1) if(--minutos==0xff) minutos=59;//se botão for solto durante o delay acima
f_pause=0;//muda de "pause' para 'off'
}
}
if(ostp&&!f_trava1) {//botão start/pause (1 toque 'liga' outro 'pausa')
f_trava1=1;
if((segundos>0)||(minutos>0)){//liga menos com '00:00'
if((rele)==1){//liga a contagem
output_high(rele);//liga rele e aciona a carga
f_pause=1;
enable_interrupts(int_timer0);
}
else {
disable_interrupts(int_timer0);//para a contagem
output_low(rele); //desliga na pausa
}
}
}
if(input(ostp)==1) f_trava1=0; //reseta a trava
if(int_tmr0_on){
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTIMER ON ",conta);
delay_ms(20);
f_dl=0;
}
else{
if(!f_pause){
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTIMER OFF",conta);
delay_ms(20);
f_dl=1;//autoriza o bip somente após imprimir o acima
}
else{
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTIMER PAUSE",conta,);
delay_ms(20);
f_dl=0;
}
}
if((f_bipar)&&(f_dl)) {f_dl=0; bipar();} //beep de fim da temporização
delay_ms(1);//delay do loop principal
}
}
compila com as seguintes mensagens de erro
>>> Warning 204 "main.c" Line 109(1,1): Condition always FALSE
>>> Warning 204 "main.c" Line 131(1,1): Condition always FALSE
Sérgio
Ele compila mas não funciona, e não consegui colocar a parte do onde envias as dezenas de min e seg...
>>> Warning 204 "main.c" Line 109(1,1): Condition always FALSE
>>> Warning 204 "main.c" Line 131(1,1): Condition always FALSE
Memory usage: ROM=51% RAM=10% - 15%
0 Errors, 2 Warnings.
Build Successful.
Olá Sergio!
Os avisos 'Warning 204' geralmente são produzidos quando você fixa uma condição de 'while' sempre em 'true'. Se você usar for(;;) no lugar de "while(true) terá o mesmo resultado sem dar este aviso. Para que o código funcione, deverá testar um flag de quando está ligado o timer (ou a saída 'rele'). Se o timer estiver contando então permite que a saída pwm esteja ativa (ligando o pwm usando a instrução 'setup_ccp1(CCP_PWM')). Se o timer não estiver contando tempo deverá desligar o pwm com a mesma instrução setup_ccp1(CCP_OFF')
. Quanto a colocar os segundos no lcd, verifique se tudo está 'cabendo na linha' (16 bytes apenas). Também verifique a formatação correta do printf se for o caso.
Bom dia Claudio, não sei se entendi direito, mas o tem algum problema de o timer parar de contar e o pwm ficar ativo? o relé para desligar a bobina de ignição?
Quanto a colocar os segundos como falei tentei adaptar, sem sucesso, o seu código, mas vc não sou a biblioteca convencional do ccs( que por sinal consome um rom medonha no uC) então não sei como fazer pra usar com a função printf .
No código que postei acima pode corrigir?
a função dos segundos que falei eu suprimi do seu codigo e não consegui colocar segue abaixo:
env_lcd_c(0xc5);//linha 2 p5
env_lcd_d(minutos/10+'0');//envia dezenas de minutos
env_lcd_d(minutos%10+'0');//envia unidades de minutos
if( int_tmr0_on && (cnt<20)) //pisca ':' muito brevemente
{ env_lcd_d(' ');}//apaga ':'
else
{ env_lcd_d(':');}//mostra ':'
env_lcd_d(segundos/10+'0');//envia dezenas de segundos
env_lcd_d(segundos%10+'0');//envia unidades de segundos
Olá Sergio!
Sim, você pode deixar o pwm ligado e desligar apenas no relé se isto for te facilitar. Quanto a formatação usando biblioteca do CCS, como você mesmo percebeu, come muita flash. Mas se está sobrando espaço não tenho nada contra que você venha a usa-la. Tente usar algo assim:
(exemplo somente:)
printf(lcd_putc,"%02u:%02u\n\r" minuto,segundo);
as variáveis minuto e segundo são do tipo inteiro de 8 bits.
Se não estou enganado a formatação é:
%s para caracter;
%d e para inteiro com sinal
e o %u e para numeros inteiros positivos de 0 a 255 ou seja 8 bits
o %lu e de 16 bits
o \n serve para pular de linha
o \r serve para e o retorno de carro um Return no LCD
o \f limpa lcd
Lembre que a cada segundo o display tem que ser atualizado com o novo valor de contagem.
Não sou muito bom com printf e sempre que tenho que usa-lo pesquiso na internet com o tema : " Uso do printf no CCS".
Ola Claudio, obrigado pela dica!! vou dar uma pesquisada!! E quanto a desligar o pwm eu eliminaria a o relé correto? Pois parado o pwm o fet para de comutar e desligaria a bobina de alta, correto?
Abraço!
Boa noite Claudio, não consegui fazer o que queria, não entendi como fazer estou postando o que fiz até agora, pode complementar com o que preciso?
no botão tempo consegui ajustar o " TEMPO" desejado de 10 em 10 minutos, preciso agora que depois de ajustado o tempo selecionado de 10 à 60 min, ligue a saída ou ligue o pwm decremente do ajuste e desligue o rele ou o pwm e se possivel tocar um bip no final do tempo.
Sinceramente tentei mas não consegui, veja se pode me ajudar e comente o codigo por favor se puder.
#include <main.h>
#zero_ram
#bit int_tmr0_on = 0x0b.5 //flag on/off de interrupçao do timer 0
signed int conta=0;
signed int tempo=0;
signed int16 dutyPwm=0;
int8 cnt, minutos, segundos;
int1 f_trava1,f_bipar,f_dl,f_pause;
unsigned int1 flag1 = 0;
unsigned int1 flag2 = 0;
unsigned int8 contador=60;
//==============================================================================
//rotina de produção de som no disco piezoeletrico
void bipar() {
int16 c;
int8 a;
f_bipar=0;
for(a=0;a<5;a++){
for(c=0; c<2500; c++) {
output_high(beep);
delay_us(193); //ajuste conforme freq. ressonancia do piezoeletrico
output_low(beep);
delay_us(11);
}
delay_ms(100);//delay entre beeps
}
}
//=============================================================================
// ROTINA DE INTERRUPÇÃO DO TIMER 0 (CADA 8MS)
//=============================================================================
#INT_TIMER0
void TIMER0_isr(void)
{
set_timer0(132+get_timer0());//carrega TMR0 com o valor
cnt++;
}
#include <lcd.c>
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16|RTCC_8_BIT); //8,1 ms overflow
setup_timer_2(T2_DIV_BY_16,249,1); //8,0 ms overflow, 8,0 ms interrupt
setup_ccp1(CCP_PWM);
set_pwm1_duty((int16)0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
set_timer0(132);
output_low(rele);
lcd_init();
printf(lcd_putc," TESTE\n V1");// mensagem de apresentação
delay_ms(2000);
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTEMPO:%u",conta,tempo);
while(TRUE)
{
if(input(up)==0) { // aumenta duty pmw
dutyPwm = dutyPwm + 60;
if(dutyPwm>600){dutyPwm=600;}
set_pwm1_duty((int16)dutyPwm);
delay_ms(300);
conta=conta+10;
if(conta>100){conta=100;}//limita contador em 100
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTEMPO:%u",conta,tempo);
delay_ms(20);
}
if(input(dw)==0){ // diminui o duty pwm
dutyPwm = dutyPwm - 60;
if (dutyPwm<0){dutyPwm=0;}
set_pwm1_duty((int16)dutyPwm);
delay_ms(300);
conta=conta-10;
if(conta<0){conta=0;}// limita contador em 0
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTEMPO:%u",conta,tempo);
delay_ms(20);
}
if(input(min)==0){ //ajusta o tempo de acionamento
delay_ms(500);
tempo=tempo+10;
if(tempo>70){tempo=0;}
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTEMPO:%u",conta,tempo);
delay_ms(20);
Ficarei muito grato se puder me ajudar no final do codigo
segue a configuração dos pinos no ccs
#include <16F628A.h>
#FUSES PUT //Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES CPD //Data EEPROM Code Protected
#FUSES PROTECT //Code protected from reads
#use delay(internal=2MHz)
#use FIXED_IO( A_outputs=PIN_A7,PIN_A6 )
#define up PIN_A0//aumenta pwm
#define dw PIN_A1 // diminui pwm
#define ostp PIN_A2// essa entrada seria o start do temporizador
#define min PIN_A3 // estou usando apenas essa entrada para ajustar o tempo
#define seg PIN_A4// não usei
#define rele PIN_A6// saída do relé
#define beep PIN_A7// saída do beep
Ficarei grato se puder me ajudar! estou precisando desse código!
Obrigado!
Olá Sergio!
Cachorro velho também aprende, mas precisa repetir mais as instruções (risos)! Falando agora sobre habilidades de programação, eu não consigo fazer como os programadores profissionais fazem: abrem o código e logo diz o que está errado. Pelo que analisei até aqui, você conseguiu já ajustar os valores de duty cicle e o tempo em minutos que deseja que conte. Também não sei se já está funcionando o PWM corretamente. Só testando! Para conseguir criar o código eu sempre faço em partes e testo em placa de protoboard usando componentes reais. Apesar de existir programas simuladores de circuitos, eles deixam a desejar em determinados projetos que realizo. Testo somente no protoboard. Depois que cada rotina está realmente funcionando (bem testada na prática) então eu vou agregando ao 'Main'. Porque estou trazendo a atenção a este fato ? Mesmo para ajudar alguém em um projeto eu preciso montar o circuíto na placa do protoboard e em seguida começar a testar as rotinas que serão usadas. É difícil dizer se a rotina está realmente funcionando apenas olhando o código. O mesmo ocorre, quando preciso montar linhas de código. Será que está funcionando? Só testando. As vezes me pedem para ajudar com um dado projeto, mas eu não tenho o microcontrolador que será usado na montagem. Aí fica complicado ajudar.
No seu caso eu tenho o pic. Mas o problema é que não estou conseguindo dispor de tempo para realizar a montagem prática nos próximos dias, não sei se até a quinzena, para iniciar os testes. Se você não tiver objeção e puder esperar, o que posso fazer é o seguinte: Quando dispor novamente de tempo para escrever um novo artigo, irei ver se dá para fazer algo como o que pede, "um temporizador com saída pwm ajustável".
Ola Claudio obrigado pela resposta, quanto ao pwm, ajuste de porcentagem e atualizações do display eu testei no isis e está funcionando, vou montar uma placa e gravar o código no chip e testar no mundo real. Se você notar até fiz a parte para selecionar o tempo
" if(input(min)==0){ //ajusta o tempo de acionamento
delay_ms(500);
tempo=tempo+10;
if(tempo>70){tempo=0;}
printf(lcd_putc,"\f");
printf(lcd_putc,"CICLO:%u\nTEMPO:%u",conta,tempo);
delay_ms(20);"
até configurei o timer0, só não sei como colocar um botão para ligar o temporizador, para ligar um relé ou o pwm como vc mesmo sugeriu e fazer descontar o tempo selecionado por exemplo:" TEMPO: 20 " ,ir decrementando os minutos ao final do tempo desligar o relé ou o pwm.
Mas agradeço muito pela ajuda! aprendo bastante com você, tentei usar um trecho do seu código mas como sou meio "CRU"(risos) não entendi direito e abortei a ideia!
Abraço!
Olá Sergio!
Para acionar a contagem do tempo eu faço da seguinte forma: Crio uma flag (como ex. 'flag_on' declarando 'unsigned int1 flag_on =0; ) e usando um botão ligado ao pino desejado, faço alternar o seu estado a cada aperto (se '1' fica '0', se '0' fica '1'). Na rotina ‘main’ eu testo este flag e aciono o rele de saída (ligar), bem como ligo a interrupção do timer 0 para contar tempo, se for for '1'. Caso esta flag seja '0' desligo o rele e desligo a interrupção do timer 0. Esta frequência de 2mhz como pretende consegui? O oscilador interno é fixo em 4 mhz e você já está usando os pinos pin_a6 e pin_a7 (entrada do cristal) como saída de rele e saída para buzzer. Esta frequência está correta para obter 60 hz. Você citou a tempos atrás:
"Gostaria de saber se tem como fazer um pwm com com 60hz, tentei configurar no wizard do CCS , mas quando testo fica na frequência mínima de 244hz".
Supondo que o wizard usou a freq=4mhz e obteve 244 Hz e o que você precisa é aproximadamente 4 vezes menos, não seria então 4mhz/4 ou seja um cristal de 1 mhz externo? (Note que não fiz as contas ainda, mas só avaliando por cima).
Outro detalhe: você precisa fazer um ‘refresh’ do display a cada minuto (ou segundo dependendo da forma que for apresentar no display). Senão o operador não vai poder acompanhar o tempo restante. Necessita colocar bloqueios para não alterar a contagem enquanto estiver ligado o timer.
Tira uma dúvida: Você colocou a frequência de 2 mhz no pic, mas está usando os pinos para o xtal para buzzer e rele. Como você conseguiu obter esta frequência se o oscilador interno é fixo em 4mhz?
Bom dia meu amigo! Então! testei isso no isis proteus, não coloquei no mundo real!
Vou montar uma placa real como você mesmo mencionou porque já percebi que nem tudo que roda no Isis, roda na pratica e vice-versa. E outra, comecei a prestar bastante atenção nos pinos do pic no simulador e percebi que esses pinos do beep e do relé não estão funcionando! Quanto a frequência eu ajustei ela pelo Wizard do Ccs e ele permitiu e não resmungou! mas acho que só testando na pratica mesmo. No simulador coloquei um frequencímetro e bateu a frequência que eu queria, mas como mencionou que o oscilador interno é fixo em 4Mhz vou montar pra tirar esses duvidas e posto o resultado aqui!!
Muito obrigado meu amigo!!
Olá Sergio!
Caso queira tirar alguma ideia, veja a rotina abaixo:
/****************************************************************************
TEMPORIZADOR COM SAÍDA PWM E RELE
C/ PIC 16F628A
AUTOR: CLAUDIO LARIOS
USO DIDÁTICO
BLOG PICSOURCE
*************************************************************************/
#include <16F628A.h>
#define F_XTAL 4000000 //frequência do cristal
#define PRESCT2 16 //valor do prescaller para o timer 2 (16,4 ou 1)
#define FREQPWM 250 //valor da frequência do pwm desejada
#define V3_200 //comente se usar outras versões (não consegui funciona a rotina)
/************************************************************************/
#use delay(clock=F_XTAL) //frequência para a rotina de delay
#define use_portb_lcd TRUE //indica qual port será usado com o lcd
#include <lcd.c>
#zero_ram
//fuses
#FUSES PUT //Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage
#FUSES NOCPD //Data EEPROM Code Protected
#FUSES NOPROTECT //Code protected from reads
#FUSES XT //XTAL
#FUSES NOMCLR //IN NO PINO 4
#FUSES NOWDT //SEM WATCHDOG
//defines
#define up PIN_A0//aumenta pwm pino 17
#define dw PIN_A4 // diminui pwm pino 3
#define ostp PIN_A5// start do temporizador pino 4
#define min PIN_A3 // ajuste do tempo pino 2
#define rele PIN_A2 //saída do relé pino 1
#define beep PIN_A1 // saída do beep pino 18
//bit/byte
#byte ccpr1l = 0x15
#byte ccp1con= 0x17
#bit ccp1y = 0x17.4
#bit ccp1x = 0x17.5
//variavéis globais
signed int8 conta=0;
signed int8 tempo=0;
signed int16 dutyPwm=0;
unsigned int8 minutos, segundos;
unsigned int1 f_bipar=0;
unsigned int1 flag_atualiza=0;
unsigned int1 flag_on = 0;
char state ='D';
char percent='%';
//==============================================================================
//rotina de produção de som no disco piezoeletrico
void bipar() {
#DEFINE N_BIPS 5 //Quantidade de bips para indicar o fim do tempo
#DEFINE TEMPO_ENTRE_BIPS 100 // intervalo entre bips
int16 c;
int8 a;
f_bipar=0;
for(a=0;a<N_BIPS;a++){
for(c=0; c<2500; c++) {
output_high(beep);
delay_us(193); //ajuste conforme freq. ressonancia do piezoeletrico
output_low(beep);
delay_us(11);
}
delay_ms(TEMPO_ENTRE_BIPS);//delay entre beeps
}
}
/************************************************************************
ROTINA 'QUEBRA GALHO' POR CONTA DE UM POSSÍVEL BUG NA VERSÃO DO COMPILADOR
OU PERCA DE ALGUMA DLL DE MEU PC
*************************************************************************/
#ifdef V3_200 // se versão do compilador for 3.200
void _set_pwm1_duty(unsigned int16 duty_cycle){
if(bit_test(duty_cycle,0))ccp1y=1; else ccp1y=0;
if(bit_test(duty_cycle,1))ccp1x=1; else ccp1x=0;
duty_cycle=duty_cycle>>2;
ccpr1l=duty_cycle;
}
#endif
/*************************************************************************
ROTINA DE ATUALIZAÇÃO DO DISPLAY
*************************************************************************/
void atualiza_lcd(){
printf(lcd_putc,"\fPWM_D: %02u %c\nTIMER: %02u:%02u %c",conta,percent,minutos,segundos,state);
}
/*************************************************************************
ROTINA DE INTERRUPÇÃO DO TIMER 0
****************************************************************************/
#int_timer0
void isr_timer0(){
//--------------------------------------------------------
//gera 1 segundos com metodo de acumulo de erro
static int32 cnt32=0;
#define PRESC 64 // valor do prescaller do timer usado (8bits)
#define FATOR (256*PRESC*4)
cnt32+=FATOR;
if(cnt32>=F_XTAL){
cnt32-=F_XTAL;
flag_atualiza=1;//seta para rotina principal atualizar o display
if(--segundos==0xff){
segundos=59;
if( minutos>0) --minutos;
}
if(!minutos&&!segundos) {
state ='D';//sinaliza display 'desligado'
output_low(rele);//desliga o rele de saída
disable_interrupts(int_timer0);//para a contagem
f_bipar=1;;// bipar (fim da contagem)
flag_on=0;//reseta flag on
}
}
}
/****************************************************************************
ROTINA MAIN
*************************************************************************/
void main(){
/****************************************************************************
PWM COM FREQUÊNCIA MÍNIMA DE 250 HZ PARA XTAL DE 4MHZ
(OU 62Hz PARA XTAL DE 1MHZ +PRESCALLER T2 =16)
PARA FREQUÊNCIAS MENORES DE PWM USE XTAL DE 455 KHZ E PRESCALLER T2 =16
CÁLCULO DO PERÍODO DO PWM:
PWM period= [(PR2+1] * 4 * Tosc * Tmr2 prescale value
FREQ_PWM= 1/PWM period (frequência do PWM)
PR2= [(F_XTAL/(PRESCT2 * 4 * FREQPWM) - 1] (valor do registrador PR2)
*******************************************************************************/
//DEFINES
#define PARC1 (PRESCT2 * 4 * FREQPWM)
#define PARC2 F_XTAL/PARC1
#define VPR2 PARC2-1 //valor a ser usado no registrador PR2
//detecta erros de escolha de valores na compilação
#if VPR2>255 //se valor maior que 255 (8bits) informa erro
#error Resultado maior que permitido em VPR2 - Verifique opções abaixo:
#error 1) Use Xtal c/ menor frequência
#error 2) Use frequência de PWM maior
#error 3) Use prescaller com maior divisão se possível
#endif
#if VPR2<11//se valor menor que 255 (8bits) informa erro
#error Resultado menor que 10 em VPR2 - Verifique opções abaixo:
#error 1) Use Xtal c/ maior frequência
#error 2) Use frequência de PWM menor
#error 3) Use prescaller com menor divisão se possível
#endif
#if PRESCT2 ==16
setup_timer_2(T2_DIV_BY_16,VPR2,1); //Seleciona prescaller div 16
#endif
#if PRESCT2 ==4
setup_timer_2(T2_DIV_BY_4,VPR2,1); //Seleciona prescaller div 4
#endif
#if PRESCT2 ==1
setup_timer_2(T2_DIV_BY_1,VPR2,1); //Seleciona prescaller div 1
#endif
//***************************************************************************
setup_counters(RTCC_INTERNAL,RTCC_DIV_64);//timer 0 prescaller/ 64
setup_ccp1(CCP_PWM);
setup_vref (FALSE);
setup_comparator(NC_NC_NC_NC);
#ifdef V3_200
_set_pwm1_duty(dutyPwm);
#else
set_pwm1_duty(dutyPwm);
#endif
enable_interrupts(GLOBAL);
set_timer0(132);
output_low(rele);
lcd_init();
printf(lcd_putc," TEMP_PWM \n PICSOURCE ");// mensagem de apresentação
delay_ms(2000);
atualiza_lcd();//atualiza display
/*************************************************************************
LOOP PRINCIPAL DE REPETIÇÃO
****************************************************************************/
for(;;){
#define V_DUTY_MAX PARC2*4 //valor para Duty_cycle máximo (100%)
#define V_DUTY_INC V_DUTY_MAX/10 //valor para cada incremento do botão UP/DOWN
if(!input(up)) { // aumenta duty pmw
dutyPwm = dutyPwm + V_DUTY_INC;
if(dutyPwm>V_Duty_max){dutyPwm=V_DUTY_MAX;}
#ifdef V3_200
_set_pwm1_duty(dutyPwm);
#else
set_pwm1_duty(dutyPwm);
#endif
conta=conta+10;
if(conta>100){conta=100;}//limita contador em 100
atualiza_lcd();
delay_ms(500);
}
if(!input(dw)){ // diminui o duty pwm
dutyPwm = dutyPwm -V_DUTY_INC;
if (dutyPwm<0){dutyPwm=0;}
#ifdef V3_200
_set_pwm1_duty(dutyPwm);
#else
set_pwm1_duty(dutyPwm);
#endif
conta=conta-10;
if(conta<0){conta=0;}// limita contador em 0
atualiza_lcd();//atualiza display
delay_ms(500);//delay 500ms
}
if((!input(min))&& (!flag_on)){ //ajusta o tempo de acionamento
tempo=tempo+10;
if(tempo>=70){tempo=0;}
minutos=tempo;//repassa valor para minutos
segundos=0;//zera segundos
atualiza_lcd();//atualiza display
delay_ms(500);//delay 500ms
}
if(flag_atualiza){//atualiza o lcd a cada 1 segundo
flag_atualiza=0;//reseta flag de atualização
atualiza_lcd();//atualiza display
tempo=0;
if(f_bipar)bipar();
}
if(!input(ostp)){//liga ou pausa
if(minutos || segundos){//não liga se 00:00
flag_on=!flag_on;
while(!input(ostp)) delay_ms(50);//aguarda soltar interruptor
if(flag_on){//se flag_on estiver setado
enable_interrupts(INT_TIMER0);//liga interrupção do tmr0
state ='L';//indica 'ligado'
output_high(rele);//liga rele
atualiza_lcd();//atualiza display
}
else {
disable_interrupts(INT_TIMER0);//desliga interrupção do tmr0
state ='P';//indica 'pausa'
output_low(rele);//desliga saída do rele
flag_on=0; //reseta flag on
atualiza_lcd();//atualiza display
}
}
}
}//for(;;)
}//main()
---------------------------fim---------------------------------
Não estranhe a colocação da rotina _set_pwm1_duty(dutyPwm); (com um underline no começo) pois não consegui fazer a rotina interna do compilador funcionar. No seu caso, creio que deva estar funcionando, e poderá eliminar então as referências a ela e colocar a original.
O programa permite alterar a frequência, o valor do xtal, e prescaller do timer 2 (16,4,1) e calcula automaticamente o valor correto para cada percentual do pwm. Se a escolha de frequência pwm+xtal+prescaller_t2 resultar em estouro no valor, então uma mensagem de erro será mostrada já na hora de compilar, para que você acerte a configuração para a faixa permitida de pwm.
Como coloquei nos comentários do programa acima, use estas formulas:
PWM COM FREQUÊNCIA MÍNIMA DE 250 HZ PARA XTAL DE 4MHZ
(OU 62Hz PARA XTAL DE 1MHZ)
PARA FREQUÊNCIAS MENORES DE PWM USE XTAL DE 455 KHZ E PRESCALLER T2 =16
CÁLCULO DO PERÍODO DO PWM:
PWM period= [(PR2+1] * 4 * Tosc * Tmr2 prescale value
FREQ_PWM= 1/PWM period (frequência do PWM)
PR2= [(F_XTAL/(PRESCT2 * 4 * FREQPWM) - 1] (valor do registrador PR2)
Caso queira, poderá eliminar toda esta parte e fazer da sua forma, tendo o cuidado de escolher corretamente o valor do xtal, da frequência de pwm e valor do prescaller do timer 2.
A indicação no display mostrará na primeira linha, por ex. para 50 % duty cycle e tempo de 50 min e 12 segundos:
PWM_D = 50 %
e na segunda linha:
TIMER = 50:12 L
Onde: L = ligado, mas pode ser P para pausa e D para desligado.
Ola Claudio!! obrigado! estou resolvendo como sempre umas buchas aqui e assim que puder vou olhar bem calmamente seu código! Como sempre muito prestativo!!! Forte abraço!!! Deus abençoe você e sua família sempre!!
Bom dia Claudio, testei aqui e funcionou como esperado com cristal de 4mhz, comprei um cristal de 2mhz coloquei e não funcionou, se colocar qualquer cristal acima de 4mhz funciona, 2mhz não, e isso não é só esse programa que vc escreveu que não funciona, o que eu tinha escrito em post anteriores à este também não funcionam em 2mhz, em 4mhz sim. Tem alguma configuração diferente pra usar o cristal de 2mhz?
Abraço!