Página 1 de 1

Como eu posso medir tensão com pic e max7221

MensagemEnviado: 25 Set 2015 19:36
por rosiley
Boa noite pessoal, antes de mais nada quero agradecer a ajuda que tenho recebido neste forum e que está sendo de grande importância para o meu aprendizado e os meus projetos, mais vamos lá.

Estou desenhando um voltimetro com pic e display de 7 segmentos sendo multiplexado pelo max 7221, este projeto vai ler dois canais analógicos onde será mostrado em 8 display, sendo 4 para um canal e 4 para outro canal como segue o código abaixo. Fazer com que o processador acesse o display eu consigo, mais fazer com que o mesmo mostre o valor é ai que o bicho pega.

cpp code
#include <16f877.h>          //Inclui arquivo header do PIC 16F877
#device ADC = 10 //Define 10 bits para o resultado da conversão AD

#include <stdio.h> // inclusão de SPRINTF
#include <string.h> // inclusão de STRLEN

#use delay (clock=20000000) /*Definição da frequência do cristal para cálculo
..dos delays*/
#fuses HS, NOWDT, PUT,BROWNOUT, NOLVP //Configuração dos bits de controle

//Definições para a comunicação serial
#use RS232 (Baud=9600, xmit = PIN_C6, rcv = PIN_C7)

//variáveis para armazenamento da conversão

int32 ad0,ADC0; // AN0
int32 ad1,ADC1; // AN1
int32 ad2,ADC2; // AN2
//int32 ad3,ADC3; // AN4

#INT_TIMER0 //Diretiva de indetificação da int. do Timer 0

void PiscaLED()
{
static boolean PiscaLed; //para piscar o led.
static int contador; //para contar o tempo de 1 segundo.
set_timer0(131-get_timer0());
contador++;
if(contador == 125) //Se contou 125 (1 segundo).
{
contador=0; //zera contagem.
PiscaLed = !PiscaLed; //Inverte bit;
output_bit(pin_C0, PiscaLed); //Liga/desliga LED.
}
}

//Formato do protocolo = AN0:0000:AN1:0000:00000000
void escreve_serial() //Função de envio do protocolo para a serial
{
printf("AN0:%04lu",ad0);//Envia dados de conversão A/D1
printf(";"); //Controle do protocolo
printf("AN1:%04lu",ad1); //Envia dados de conversão A/D2
printf(";"); //Controle do protocolo
printf("AN2:%04lu",ad2); //Envia dados de conversão A/D3
printf(";"); //Controle do protocolo
}

#define N_MAX 2
#define MAX_DIN PIN_B4
#define MAX_CS PIN_B3
#define MAX_CLK PIN_B2
#include <MAX72xx.c>

char a,b,c,d,e,f;
char g,h,i,j,k,l;

void main()
{
//Configura as entradas analógicas AN0 a AN4
SETUP_ADC_PORTS(AN0_AN1_AN2_AN4_VSS_VREF);
//Utiliza o clock interno para tempo de aquisição
SETUP_ADC(ADC_CLOCK_Internal);
//Habilita interrupção global
Enable_Interrupts(GLOBAL);
//Habilita interrupção por recepção de dados na serial
Enable_Interrupts(INT_RDA);
//Habilita interrupção pelo overflow do Timer 0
ENABLE_INTERRUPTS(INT_TIMER0);
/*Configura Timer 0 para incremento pelo ciclo de máquina Prescaler de 1:256 e
modo de operação em 8 bits*/
SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
//Inicia o Timer 0 com o valor 61 - Interrupção a cada 25ms
SET_TIMER0(61);

Iniciar_MAX72xx(0xFF); //Ativa o decodificador
Comandos_MAX72xx(0x0A,0X08); //Itensidade minima

while(true)
{

SET_ADC_CHANNEL(0); //Configura o canal de leitura 0
delay_ms(10); //Tempo de ajuste do canal (necessário)
ad0 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

SET_ADC_CHANNEL(1); //Configura o canal de leitura 1
delay_ms(10); //Tempo de ajuste do canal (necessário)
ad1 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

SET_ADC_CHANNEL(4); //Configura o canal de leitura 1
delay_ms(10); //Tempo de ajuste do canal (necessário)
ad2 = READ_ADC(); //Faz a conversão AD e a salva na variável ad0

ADC0 = (ad0 * 500) /1023;
ADC1 = (ad1 * 500) /1023;
ADC2 = (ad2 * 500) /1023;


for(a=0;a<10;a++)
for(b=0;b<10;b++)
for(c=0;c<10;c++)
for(d=0;d<10;d++)
for(e=0;e<10;e++)
for(f=0;f<10;f++)

for(g=0;g<10;g++)
for(h=0;h<10;h++)
for(i=0;i<10;i++)
for(j=0;j<10;j++)
for(k=0;k<10;k++)
for(l=0;l<10;l++)
{
Enviar_MAX72xx(1,1,a);// Primeiro display, Posição no display, valor no display
Enviar_MAX72xx(1,2,b);
Enviar_MAX72xx(1,3,c);
Enviar_MAX72xx(1,4,d);
Enviar_MAX72xx(1,5,e);
Enviar_MAX72xx(1,6,f);

Enviar_MAX72xx(2,1,g);// Segundo display, Posição no display, valor no display
Enviar_MAX72xx(2,2,h);
Enviar_MAX72xx(2,3,i);
Enviar_MAX72xx(2,4,j);
Enviar_MAX72xx(2,5,k);
Enviar_MAX72xx(2,6,l);
delay_ms(100);
}

}
}

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 26 Set 2015 22:39
por andre_luis
ok, mas não ficou claro o que está acontecendo e o que deveria acontecer...

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 26 Set 2015 23:58
por rosiley
Boa noite, o circuito está funcionando ou seja está enviando os valores para o pc via rs232, mais eu não estou conseguindo fazer com que o display mostre os valores.

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 27 Set 2015 11:09
por andre_luis
Voce não está instanciando a função escreve_serial() em nenhum lugar do seu programa...

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 27 Set 2015 12:12
por Djalma Toledo Rodrigues
'
Crítica ao C

Detesto essas Sintaxes idiotas. Começa pelo nome C

A Intel havia patenteado os mnemônicos
Aí, no impedimento, em vez de "Inc x" ==> "X++"

? E para decrementar em C ? "X+-" ? conf. que não sei

Mas, voltando ao caso
Isso em Assembler seria tão mais simples.

* Depois coloco o jeito meu de ter os Mnemônicos disponíveis na Ide ao Programar.

Dj. (Se sentindo clítico, como dizem no Face.)

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 27 Set 2015 15:36
por Djalma Toledo Rodrigues
'
Mas, me parece que há um equivoco na Concepção do Programa
é o Display Led que deve ser multiplexado e não os seguimentos.

Verifique.

Dj.

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 28 Set 2015 12:00
por ze
Permita-me também alguns olhares críticos
-pra este mc e este propósito, não é necessário o tal max (que nunca vi na vida). Este mc tem muitas portas que podem podem com relativa facilidade multiplexar 8 dígitos de 8 segmentos numa interrupçao qualquer de timer (quase dá pra digitar o fonte on line aqui agora). Pra isso tem que lançar mão de algum conhecimento básico do hw do pic.
-concordo com o equívoco do dj. Publique seu esquema. Mais fácil pra ver 'o que que há. O que está se passando por sua cabeça' (fábio júnior, anos 80)
-discordo do c ser menos simples do que o asm (mas isso nada a ver)
-Se insistir no max, 1ª mente veja como ele funciona (não vi) e envie um dado qualquer pra ele. Use simulador

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 28 Set 2015 13:11
por rosiley
Segue o desenho para análise e um link onde eu estou tentando fazer igual.


https://www.youtube.com/watch?v=ikgQyHx_yB0

https://www.youtube.com/watch?v=g91CJSjKz18

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 28 Set 2015 13:28
por andre_luis
Onde está declarada a função Enviar_MAX72xx() ?

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 28 Set 2015 14:50
por ze
Mesmo aumentando o número de displays desde o 1º post, eu ainda evitaria o max (que pode estar pirando a cabeça). Talvez alguns 74hc164, hc595 da vida .
Não vi video. Se for 6 displays por canal ad, acho que está sobrando coisa pois 10bits = 1023 no máximo 4 displays mas eu usaria só 3 (ou 2) pra medir de 0 a 5V
Mais coisa sobrando é int32 num mc de 8 bits. Neste caso nem precisa (talvez nem deva)

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 04 Nov 2015 19:37
por rosiley
Boa noite pessoal, pesquisando na net encontrei este código que começou a clarear a minha visão e comecei implementando ao meu projeto mas estou com uma dúvida no que diz aos valores.

1° Os digitos visualizados no display o primeiro digito sempre mostra 0 ;
2° Como faço para fazer com que o segundo max7219 mostre outro valor. Segue o código para análise.

cpp code
#include <12f683.h> 
#fuses intrc_io,noput,nowdt,noprotect,nomclr,nobrownout,noieso,nofcmen
#device adc=10
#use delay(clock=4M)
#use fast_io(a)
#use spi(do=pin_a0,clk=pin_a2,bits=16,load_active=1,load=pin_a1,idle=1)
//We have to write this directive, you can add stream and change the pin do, clk, load
//I've used bits 16 'cause max7219 needs 16 bits =)
//The idle is 1, if you put 0, nothing will appear on your displays <- this is really important


int address, data, adqnum, digit[4]; //address, data max's variables
//adqnum for 100 samples
//digit[4] this array keeps 4 digits used in this project
int16 packetmax, result; //packetmax goes to the max7219
//result keeps the value used to obtain digits
int32 adcvalue=0; //this variable keep the adc value read 100 times
float calculus; //variable used for (adcvalue * (5/1023))

void maxsend(){ //routine for max7219 just
packetmax=make16(address,data); //make a 16 bit variable address byte high, data byte low
spi_xfer(packetmax); //transfer using spi software
} //just 5 lines including #use spi. It's really simple right?

void maxsetup(){ //configure properly
address=0x09, data=0xff, maxsend(); //it's up to you
address=0x0a, data=0x01, maxsend(); //just read a minute the datasheet
address=0x0b, data=0x03, maxsend(); //it's easy and fast.
address=0x0f, data=0x00, maxsend();
address=0x0c, data=0x01, maxsend();
}

void algebra_digits(){
calculus=adcvalue*0.4887585533; //500 is the max value, 500=5.00V, but it's float
result=calculus; //transfer the correct value to int result
//if you want to measure a higher voltage just change the float value
//and don't forget using resistors as needed.

//the following 4 lines are used to obtain digits
digit[0]=result-((result/10)*10); //units place
digit[1]=(result/10)-((result/100)*10); //tens place
digit[2]=(result/100)-((result/1000)*100); //hundreds place
digit[3]=result/1000; //thousands place
}

void main(){
setup_comparator(nc_nc_nc_nc); //no comparator module
setup_adc(adc_clock_div_16); //Tad = 4.0us
setup_adc_ports(an3_analog); //gpio4 as analog input, u can choose your favorite pin
set_adc_channel(3); //select channel 3 =gpio4
set_tris_a(0b00011000); //set port
delay_ms(1000); //wait just for relaxing =), this line is not that important
maxsetup(); //

while(1){
for(adqnum=1;adqnum<=100;adqnum++){ //collect 100 samples, I usually do this, u can use your favorite method
adcvalue=adcvalue+read_adc(); //for acquisition.
delay_us(20);
}
adcvalue=adcvalue/100;
algebra_digits(); //call algebra routine to get each digit
address=0x01, data=digit[0], maxsend();
address=0x02, data=digit[1], maxsend();
address=0x03, data=(digit[2] | 0b10000000), maxsend(); //use OR for adding decimal point
address=0x04, data=digit[3], maxsend();
adcvalue=0; //clean adcvalue
}
}

Re: Como eu posso medir tensão com pic e max7221

MensagemEnviado: 30 Abr 2016 11:35
por rosiley
Obrigado a todos que me ajudaram e informo que consegui resolver o problema, o meu projeto já lê os canais corretamente nas duas linhas de display, agora tenho outra missão. Fazer com que a segunda linha de display leia os valores dos canais 2, 4 e 5 do conversor ad controlado atraves de uma chave.