Ir ao conteúdo

Contador com PIC


ogaittiago

Posts recomendados

Postado

Caros colegas do Forum.

Estova tentando em fazer um programa em C para o PIC 16f877A, porém não estou obtendo sucesso. :naonao:

o que eu estou tenando fazer é:

Quero que uma entrada receba um Clock que será variavel ( varia a Frequência) e o programa perceba essa variação.

Tentei contar o clock e ir dividindo pela varedura, cada vez que alterace saberia que o clock mudou.

Porém já não estava entendo o meu proprio programa.:muro::wacko:

E depois que verificasse a mudança eu iria usar para setar uma saída por um determidado tempo. Ou setar via PWM durante tambem um certo tempo.

Se alguem puder me dar uma LUZ.

Desde já agradeço;

Obrigado.

Tiago Souza

Postado

Não entendi direito sua dúvida.

O programa deve perceber a mudança do clock e fazer com q um contador aumente apenas se mudra esse clock?

Aí se mudar o clock de entrada, v faz o que?

Falou

Postado
Não entendi direito sua dúvida.

O programa deve perceber a mudança do clock e fazer com q um contador aumente apenas se mudra esse clock?

Aí se mudar o clock de entrada, v faz o que?

Falou

Não não

Eu é que estava contando o Clock para tentar verificar essa mudança.

A ideia como todo é assim.

Eu vou variar um um Clock (poder ser via 566, ou mesmo com um 555) com um potenciometro. (Que será o ajuste do processo).

O PIC terá de verificar essa mudançã, e fazer com que a saida reaja:

  • ou setando simplesmente uma saida variando o tempo.
  • ou variando o PWM por um tempo já definido.

Na saida irei utilizar provavelmente um TRIAC, mas se não der certo uso um RELE mesmo.

Será que deu para entender a ideia...

Postado

Entendi.

você quer que determinado clock seja "transportado" para um PWM que irá a um TRIAC controlará uma carga.

Se for usar PWM, relé não dá certo. Um TRIAC dá.

Me diga qual o intervalo de variação do CLOCK e para quais valores ele deve relacionar no PWM(duty-cycle). Exemplo:

Para frequencia entre 100Hz e 200hz, o duty-cycle é 20%

Entre 200 e 300hz, o duty é 50%.. algo assim.

Falou

Postado
Entendi.

você quer que determinado clock seja "transportado" para um PWM que irá a um TRIAC controlará uma carga.

Se for usar PWM, relé não dá certo. Um TRIAC dá.

Me diga qual o intervalo de variação do CLOCK e para quais valores ele deve relacionar no PWM(duty-cycle). Exemplo:

Para frequencia entre 100Hz e 200hz, o duty-cycle é 20%

Entre 200 e 300hz, o duty é 50%.. algo assim.

Falou

Valeu Matheus pela atenção que está dando.

Porém não é bem assim não.

Hoje funciona atravês de uma placa com alguns componentes e as 3saidas são a triac e seu disparo são através de 555, na placa tem 5 ci555 2 ainda não descobri para que serve. e o clock para o dispado dos triacs são regulados atraves dos 3 potenciometros.

Mas essa tal placa não possibilita muitas mudanças.

Então pensei em utilizar microcontrolador, a ideia inicial erá através das entradas analogicas, porém como terei de isolar o circuito do microcontrolador (fotoaclopadores) não daria para usar diretamente as entradas analogicas (a não ser se eu utilizasse um conversor tensão/frêquencia {566}).

Ai fiquei na ideia de utilizar somente com entradas normais.

o potencimetro continuará a variar o frequência de saida do 555(70Hz á 7Khz).

As cargas são:

  • 1 - transformador abaixador de 220/12V que alimenta uma resistencia (liga por menos de 2 segundo).
  • 2 - Outro transformador abaixador de 220/12V que alimenta outra resistencia (liga por menos de 2 segundo).
  • 3- Um solenoide (ele libera por alguns instantes dependendo do ajustado no POtenciometro). Notei que fica com tres tensões (0V, 140V e 220V).

Postado

Agora começou a contar:

while (TRUE) 
{

if (input (PIN_B0)==1& (x1=1))
{
valor = valor+1, x1=0;
}
else
{x1=1;}
}

Porém ainda falta como eu saber que a contagem está variando, acho que teria de ter uma referencia. ou utilizar o clock interno como base e ai verificar que a minha contagem está variando.:confused:

???

Postado

Matheus vou falar somente a ideia principal.

  • contar os pulsos do Clock (Frequencia)
  • Perceba a variação.
  • E a cada variação eu acione a saida por um instante de tempo. (menor frequência menor tempo, maior frequencia maior tempo).

Valeu Novamente

Tiago Souza

Postado

Certo. Vamos por partes.

Para medir a frequencia você não precisa necessariamente contar os pulsos.

Conte apenas 2 pulsos. Um pulso alto e o vale. você consegue isso com o módulo CCP.

Assim:

Circuito:

Semttulo-4.png

Código:

#include <16f628a.h>             //O PIC utilizado, obigatório!
//ser utilizado de 8 bits também.
#FUSES NOWDT //Sem Watch dog, evitando reset
#FUSES HS //Crystal de oscilação igual a 4mhz
#FUSES PUT //Tempo de início do PIC
#FUSES NOPROTECT //Codigo sem proteção de leitura, software livre!
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection

#use delay(clock=12000000) //Meu clock
#include <LCD_flex.C> //Rotina de LCD modo 4 vias. Obrigatório!

int1 nuevopulso=0;
int16 TFB=0,TFS=0,TF=0;
float32 AP=0.0,freq;
int1 cambio=0;

#int_ccp1
void ccp1_int()
{
if(cambio==0)
{
TFS=CCP_1;
setup_ccp1(CCP_CAPTURE_FE);
cambio=1;
}

else
{
TFB=CCP_1;
setup_ccp1(CCP_CAPTURE_RE);
cambio=0;

if(nuevopulso==0)
{
nuevopulso=1;
}
}
}

void main()
{
lcd_init();
setup_timer_1(T1_INTERNAL);
setup_ccp1(CCP_CAPTURE_RE);
cambio = 0;

enable_interrupts(int_ccp1);
enable_interrupts(global);

do
{
if(nuevopulso==1)
{
TF=(TFB-TFS);
AP = (TF*1.0)/3;
freq=(1/(AP*2)*1000000);
printf(lcd_putc,"\fFreq = %2.2fHz", freq);
delay_ms (200);
nuevopulso=0;
}
}
while (TRUE);
}

Ok. A primeira parte fizemos. Medimos a frequêcia.

Agora vamos supor q ela está lá em 500hz como no exemplo que passei.

SE ele aumentar para 600hz, qual saída vamos setar e durante quanto tempo?

Se ela diminuir para 100hz, qual saída e quanto tempo?

Falou

Postado

Agora vamos supor q ela está lá em 500hz como no exemplo que passei.

SE ele aumentar para 600hz, qual saída vamos setar e durante quanto tempo?

Se ela diminuir para 100hz, qual saída e quanto tempo?

Falou

Então cara Matheus!!!

Estou indo Para o serviço lá olho com mais calma.

Mas acho que não vai dar para usar o modulo CCP pois terei 3 entradas assim que ativação 3 saidas.

poder ser qualquer pino como entrada e saida.

Os tempo serão aproximadamente em 100Hz em 0.4s e em 1KHz em 2s.

Mas os tempos depois posso acertar.

Vou indo lá daki a pouco já entro novamente.

Tiago Souza

S.T.A.R.S.

Postado
Não tem portância ser 3 Entradas.

Nesse código usei o CCP1. Ainda temos o CCP2 e ainda podemos utilizar o RB0....

Ms aí teremos que utilizar o 16F877A.

Falou

Então Matheus!

Sobre o PIC, 16F628A ou 16F877A eu tenho os 2 aqui comigo.

E sobre o codigo do medidor de frequÊncia, como eu não tinha no meu "CCS C" o arquivo do Include LDC_flex.c dei uma procurada e usei esse: http://forum.clubedohardware.com.br/include-lcd-flex/855169?p=4772232

Outra coisa, aqui deu um erro em declarações de variaveis pois ele não entendeu o tipo float32 então deixei so float.

aqui no meu Proteus ele está fazendo somente uma Leitura quando mudo para outra frequência não altera no LCD.

Falou!!!

Tiago Souza

Postado

Acredito que seja o mesmo, mas só para confirmar:

LCD_flex.c:

// flex_lcd.c

// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.

#define LCD_DB4 PIN_D0
#define LCD_DB5 PIN_D1
#define LCD_DB6 PIN_D2
#define LCD_DB7 PIN_D3

#define LCD_E PIN_A1
#define LCD_RS PIN_A3
#define LCD_RW PIN_A2

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

#define USE_LCD_RW 1

//========================================

#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));

delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;

output_high(LCD_E);
delay_cycles(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

output_low(LCD_E);

return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);

delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);

// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
address = lcd_line_two;
else
address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;

case '\n':
lcd_gotoxy(1,2);
break;

case '\b':
lcd_send_byte(0,0x10);
break;

default:
lcd_send_byte(1,c);
break;
}
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif

O código que você testa é igual ao meu?

Beixe os arquivos aqui para simular:

http://www.4shared.com/file/tDvncrMh/Medidor_de_Frquencia.html

Falou

Postado

O código que você testa é igual ao meu?

Beixe os arquivos aqui para simular:

http://www.4shared.com/file/tDvncrMh/Medidor_de_Frquencia.html

Falou

Então baixei seu codigo e dá o mesmo erro, não sei se tem haver com a versão de meu proteus 6.2

Outra coisa quando eu eu mudo a frequqncia não muda no LCD e seu eu continuar mudando o Proteus dá uma erro e para:

ErroSimulaoProteus.jpg

E o circuito que utilizei no proteus é exatamente da figura que colocou lá em cima:

Semttulo-4.png

E a sobre o float32 estava vendo no Livro" Compilador C CCS y simulador PROTEUS para microcontroladores PIC" e não tem, o que vi é que o float tem o tamanho de 32bit.Minha versão do c-ccs:

VersodoPCCSC.jpg

Obrigadão pela atenção!!!

Tiago Souza:)

Postado
O proteus utilizo o 7.7 e o ccs o 4.057, no 4shared tem o ccs.

Falou

Bom dia Matheus.

Baixei o Proteus 7.7 - agora tudo beleza

o seu arquivo abriu e funciona em qualquer frequência, no que eu tinha montado também também funcionou beleza.

Porém agora o ISIS depois de um tempo ele dá aquela mensagem de que parou de funcionar e fecha o Proteus.

Tiago Souza

Postado
você abre o circruito e ele fecha?

Experimenta deletar toda vez o .PWI que fica junto do arquivo do circuito.

Falou

Ele abre funciona um pouco ai fecha o programa.

Deletei o .PWI e continua a mesma coisa.

Tiago Souza

Postado
Instalou seguindo o tutorial do site q passei?

Falou

sim instalei conforme o video que tem no site.

Mas voltando ao codigo, eu tentei setar uma saida quando chegava em 1khz porém ele nao ativava.

Tentei colocar no" while" e no" DO".

Tiago Souza

Postado

Fiz aqui e deu certo!

Se a frequencia for maior que 950hz, ele ativa o pino A0.

veja:

http://www.4shared.com/file/-vV8-VW1/Medidor_de_Frquencia_2.html

Ou apenas o código:

#include <16f628a.h>             //O PIC utilizado, obigatório!
//ser utilizado de 8 bits também.
#FUSES NOWDT //Sem Watch dog, evitando reset
#FUSES HS //Crystal de oscilação igual a 4mhz
#FUSES PUT //Tempo de início do PIC
#FUSES NOPROTECT //Codigo sem proteção de leitura, software livre!
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection

#use delay(clock=12000000) //Meu clock
#include <LCD_flex.C> //Rotina de LCD modo 4 vias. Obrigatório!

int1 nuevopulso=0;
int16 TFB=0,TFS=0,TF=0;
float32 AP=0.0,freq;
int1 cambio=0;

#int_ccp1
void ccp1_int()
{
if(cambio==0)
{
TFS=CCP_1;
setup_ccp1(CCP_CAPTURE_FE);
cambio=1;
}

else
{
TFB=CCP_1;
setup_ccp1(CCP_CAPTURE_RE);
cambio=0;

if(nuevopulso==0)
{
nuevopulso=1;
}
}
}

void main()
{
lcd_init();
setup_timer_1(T1_INTERNAL);
setup_ccp1(CCP_CAPTURE_RE);
cambio = 0;

enable_interrupts(int_ccp1);
enable_interrupts(global);

do
{
if(nuevopulso==1)
{
TF=(TFB-TFS);
AP = (TF*1.0)/3;
freq=(1/(AP*2)*1000000);

if (freq > 950)
{
output_high (PIN_A0);
}
else
{
output_low (PIN_A0);
}

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

Falou

Postado

Que estranho do seu jeito funcionaou.

o que será que fiz de errado? Será que foi porque coloquei depois do printf?

Olha como eu tinha feito:

    
[COLOR="Blue"] do [/COLOR]
{
[COLOR="blue"]if[/COLOR](nuevopulso==1)
{
TF=(TFB-TFS);
AP = (TF*[COLOR="SeaGreen"]1.0[/COLOR])/[COLOR="seagreen"]3[/COLOR];
freq=([COLOR="seagreen"]1[/COLOR]/(AP*[COLOR="seagreen"]2[/COLOR])*[COLOR="seagreen"]1000000[/COLOR]);
printf(lcd_putc,[COLOR="Purple"]"\fFreq = %2.2fHz"[/COLOR], freq);
delay_ms ([COLOR="seagreen"]200[/COLOR]);
nuevopulso=[COLOR="seagreen"]0[/COLOR];

[COLOR="blue"] if [/COLOR](freq == [COLOR="seagreen"]1000[/COLOR]) { output_high (PIN_A1);}

else
{output_low (PIN_A1);}

}
}
while (TRUE);

}

Tb coloquei >950 e nada. estranho a logica parece a mesma...

Valeu Matheus.

Vou agora tentar fazer uma saida completa.

Uma outra duvida, todas a formulas e contas para eu fazer a saida coloco dentro desse if né? Pois o mesmo está girando nesse loop?

Tiago Souza

Postado

O seu não deu certo porq você colocou depois do nuevopulso=0;. Aí ele já saída do loop e não executava sua função.

Sim, todas as contas vão dentro do IF.

você disse que irá medir 3 frequencias né.

Fiz outro código aqui mais enxuto para medir as 3. Só q ele usa o 16F877A.

Uma outra dica: Não faça uma condição em qua a frequencia seja igual a um número específico como você fez: if (freq == 1000). Faça por itervalo, por exemplo:

if ((freq > 990) && (freq <1100))

Dificilmente você consegue medir um número exato.

Falou

Postado
O seu não deu certo porq você colocou depois do nuevopulso=0;. Aí ele já saída do loop e não executava sua função.

Ah é mesmo não me atentei, ainda não tinha usado muitas funções com o DO.

Sim, todas as contas vão dentro do IF.

você disse que irá medir 3 frequencias né.

Fiz outro código aqui mais enxuto para medir as 3. Só q ele usa o 16F877A.

Falou

beleza Matheus!

Se der para postar ficarei agradecido.:D

Uma outra dica: Não faça uma condição em qua a frequencia seja igual a um número específico como você fez: if (freq == 1000). Faça por itervalo, por exemplo:

if ((freq > 990) && (freq <1100))

Dificilmente você consegue medir um número exato.

Falou

Opa vale por mais essa dica!!!! :D

Nesse caso vou usar um formula para que o valor varie conforme a frequência( tipo para simular uma AN)

PS: Cara você já não pensou em dar curso?

valeu!!!

Tiago Souza

Postado

O código que pega as 3 frequencias, é todo diferente do outro. Mas funciona do mesmo jeito:

#include <16f877a.h>             //O PIC utilizado, obigatório!
//ser utilizado de 8 bits também.
#FUSES NOWDT //Sem Watch dog, evitando reset
#FUSES XT //Crystal de oscilação igual a 4mhz
#FUSES PUT //Tempo de início do PIC
#FUSES NOPROTECT //Codigo sem proteção de leitura, software livre!
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection

#use delay(clock=4000000) //Meu clock

#include <LCD.C> //Rotina de LCD modo 4 vias. Obrigatório!

int16 freq_1=0, freq_2=0,freq_3;
int1 flag;

int16 p, q,r;

int8 cont;

#int_timer1
void trata_timer1(void)
{
flag=1;

p = freq_1*2;
q = freq_2*2;
r = freq_3*2;
freq_1 = 0;
freq_2 = 0;
freq_3 = 0;

set_timer1(3036);
}

#int_ccp1
void ccp1_int()
{
freq_1++;
}

#int_ccp2
void ccp2_int()
{
freq_2++;
}

#int_ext
void trata_ext()
{
freq_3++;
}

void main()
{
lcd_init();
setup_ccp1(CCP_CAPTURE_RE);
setup_ccp2(CCP_CAPTURE_RE);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);

enable_interrupts(int_ccp1);
enable_interrupts(int_ccp2);
enable_interrupts(int_timer1);
enable_interrupts(int_ext);
enable_interrupts(global);

set_timer1 (3036);

while (TRUE)
{
if (flag == 1)
{
printf (lcd_putc,"\fF_1:%lu\nF_2:%lu F_3:%lu",p,q,r);
delay_ms (200);
flag=0;
}
}
}

Eu dando curso? Q isso!!! Tenho muito q aprender ainda!!!

uhauhaahu

Falou

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...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!