Ir ao conteúdo
  • Cadastre-se

advtec

Membro Pleno
  • Posts

    109
  • Cadastrado em

  • Última visita

Tudo que advtec postou

  1. Matheus, novamente, muito obrigado. Coloquei a tensão de 2,8V em Vref- o que, portanto, resulta num range de 2,2V. A configuração está assim: setup_adc_ports(sAN0, VREF_VDD); No Proteus, ao simular, houve o retorno da seguinte mensagem: Mesmo assim, no Protoboard a leitura resultante é 00. Inverti, no Proteus, a ligação dos 2,8V para o Vref+. O resultado foi a medição do valor corretamente. Digo, entretanto, corretamente, configurando a fórmula de conversão para os 2,8V, porque para os 2,2V (5 - 2,8) não dá resultado correto (passa longe). No protoboard, entretanto, a leitura é também 00. No protoboard só funciona se eu usar o Vref padrão. A tensão de 2,8V estou conseguindo com um diodo zener. Aproveito para perguntar: posso assumir que o Proteus está simulando o PIC trabalhar com 5V (presumo que sim, porque a fórmula de conversão usando VDD de 5V resulta em medição correta). Abaixo, o meu código inteiro da parte do termômetro (separei do restante do projeto e vou trabalhar somente nele até conseguir dominar esse assunto de Vref e conversões): #include <16F886.h> #device adc=10 #use delay(clock=20000000) #use fast_io(a) #use fast_io( #use fast_io(c) #fuses HS,NOWDT,NOMCLR,PUT,NOPROTECT,NOBROWNOUT,NOLVP #define disp1 pin_c0 //pino de acionamento do display 1 (dezena) #define disp2 pin_c1 //pino de acionamento do display 2 (unidade) void le_temp_converte(void); void trata_timer1(void); unsigned char varDez = 0, varUni = 0; byte const display[] = { //"mascara" de dados apresentados nos displays 0b01111110, //0 0b00001100, //1 0b10110110, //2 0b10011110, //3 0b11001100, //4 0b11011010, //5 0b11111010, //6 0b00001110, //7 0b11111110, //8 0b11011110, //9 0b11110010, //E 0b10100000, //r 0b00001100, //I 0b10101000, //n 0b11100010, //F 0b00100000, //i 0b10000000, //- (16) }; void le_temp_converte(void){ unsigned int16 temp1 = 0, temp2 = 0, temp_ADC_scaling = 0; unsigned char i; for(i=0; i<30; i++) { delay_us(30); temp1 = read_adc(); temp2 = temp2 + temp1; } temp2 = temp2/30; temp_ADC_scaling = (temp2 * 500) / 1023;//p/ Vref = VDD 5V. varUni = temp_ADC_scaling % 10; varDez = temp_ADC_scaling / 10; } #int_timer0 void trata_timer0(void) { } #int_timer1 void trata_timer1(void) { boolean displays; displays = !displays; if(displays) { output_low(disp2); output_b((display[varDez])); output_high(disp1); } else { output_low(disp1); output_b((display[varUni])); output_high(disp2); } set_timer1(63660); } void main() { setup_comparator(NC_NC_NC_NC); set_adc_channel(0); //canal 0 como analogico setup_adc_ports(sAN0, VREF_VDD); setup_adc(ADC_CLOCK_INTERNAL); set_pwm1_duty(false); setup_ccp1(ccp_off); output_a(0b00000000); output_b(0b00000000); output_c(0b00000000); delay_ms(100); set_tris_a(0b11011111); set_tris_b(0b00000001); set_tris_c(0b00000000); SETUP_TIMER_0 (RTCC_INTERNAL|RTCC_DIV_256); SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_8); SETUP_TIMER_2(T2_DIV_BY_16,195,16); enable_interrupts(GLOBAL); enable_interrupts(int_timer0); enable_interrupts(int_timer1); disable_interrupts(int_timer2); disable_interrupts(INT_EXT); ext_int_edge(H_TO_L); set_timer0(1); set_timer1(63660); set_timer2(195); disable_interrupts(periph); disable_interrupts(int_ccp1); disable_interrupts(int_rb); while(true) { le_temp_converte(); delay_ms(50); } } Abaixo, o circuito no Proteus: Parece estar faltando alguma configuração ainda. Mais alguma ideia? Novamente, muito obrigado e bons trabalhos. Edição: Após várias consultas e configurações, sem resultado, configurei assim: setup_adc_ports(sAN0, VREF_VREF); Então, neste caso, o range vai do pino VREF- ao pino VREF+. Como VREF+ já estava com 2,8V (fixada com um zener), coloquei o pino VREF- em 0V. Ajustei a fórmula e a leitura ficou correta (e estará até mesmo mais correto, porque não corro o risco de diferenças no VDD afetarem as medições, porque de 0V a 2,8V - ou outra tensão que eu fixar - não haverá flutuações). Embora esteja funcionando, ainda assim gostaria de saber porque isto está ocorrendo, ou seja: por que se eu configuro o range a partir de VREF até VDD não funciona? Lembro que tentei fazer as ligações em VREF- e em VREF+ também. Alguma ideia?
  2. Entendi. Fiz da maneira citada, porque o arquivo de cabeçalho do compilador informa: #define VREF_VDD 0x2000 //| Range Vref-Vdd Então, pensei que o range seria do Vref (no caso, os 3,9V que citei) ao VDD, que é de 5V. Mas, já vou alterar aqui seguindo sua dica. Também havia me esquecido do range mínimo de 2V. Muito obrigado, Matheus. Farei as alterações e volto. Bons trabalhos.
  3. Olá a todos. Estou montando um termômetro, que é parte de um projeto maior. Estou usando o LM35 como elemento sensor, ligado a uma porta analógica do PIC. Os testes foram bem com VREF configurado como VDD. Entretanto, para maior resolução, fixei no pino VREF+ uma tensão de 3,9V. Então, o range vai de 3,9V a 5V, me dando o range de 1,1V. A ideia é aumentar a precisão. Veja se estou certo: sendo o range de 1,1V e, considerando a resolução do conversor AD 10 bits, terei 1,1V / 1023 = 0,0010752688172, ou seja, terei, arredondando, 1mV para cada degrau da conversão. Como estou usando apenas dezena e unidade para ver a medição (o projeto só precisa disso, mas é necessária a boa precisão para outras razões do mesmo projeto) e usando dois displays comuns de catodo comum, estou usando a seguinte fórmula para conversão: temp_ADC_scaling = (temp_ADC_scaling * 100) / 1023 Para ver os valores nos displays, uso: varUni = temp_ADC_scaling % 10 varDez = temp_ADC_scaling / 10 varUni e varDez são as variáveis globais que recebem os dados para exibição nos displays. Enfim, o problema: depois que eu fixei VREF no pino VREF+ (pino 5) em 3,9V, não consigo obter o valor nos displays. Na simulação, 30ºC promovem uma leitura de 7 nos displays. Ressalto que, voltando tudo ao estado anterior com VREF em VDD, o circuito funciona (com precisão reduzida). Estou usando o PIC 16F886, programando em C-CCS. A minha configuração está assim: setup_comparator(NC_NC_NC_NC); set_adc_channel(0); setup_adc_ports(sAN0, VREF_VDD); setup_vref(VREF_HIGH); //não entendi bem - é para definir q o pino VREF+ está em uso? setup_adc(ADC_CLOCK_INTERNAL); O arquivo de cabeçalho está assim: // Constants used in setup_vref() are: // #define VREF_LOW 0xa0 #define VREF_HIGH 0x80 // Or (with |) the above with a number 0-15 // Constants used for SETUP_ADC() are: #define ADC_OFF 0 // ADC Off #define ADC_CLOCK_DIV_2 0x100 #define ADC_CLOCK_DIV_8 0x40 #define ADC_CLOCK_DIV_32 0x80 #define ADC_CLOCK_INTERNAL 0xc0 // Internal 2-6us // Constants used in SETUP_ADC_PORTS() are: // First argument: // OR together desired pins #define sAN0 1 //| A0 #define sAN1 2 //| A1 #define sAN2 4 //| A2 #define sAN3 8 //| A3 #define sAN4 16 //| A5 #define sAN5 32 //| E0 #define sAN6 64 //| E1 #define sAN7 128 //| E2 #define sAN8 0x10000 //| B2 #define sAN9 0x20000 //| B3 #define sAN10 0x40000 //| B1 #define sAN11 0x80000 //| B4 #define sAN12 0x100000 //| B0 #define sAN13 0x200000 //| B5 #define NO_ANALOGS 0 // None #define ALL_ANALOG 0x1F00FF // A0 A1 A2 A3 A5 E0 E1 E2 B0 B1 B2 B3 B4 B5 // Optional Second argument: #define VSS_VDD 0x0000 //| Range 0-Vdd #define VSS_VREF 0x1000 //| Range 0-Vref #define VREF_VREF 0x3000 //| Range Vref-Vref #define VREF_VDD 0x2000 //| Range Vref-Vdd A minha função de leitura e conversão está assim: void le_temp_converte(void){ unsigned int16 temp_ADC_scaling; temp_ADC_scaling = read_adc(); temp_ADC_scaling = (temp_ADC_scaling * 100) / 1023; varUni = temp_ADC_scaling % 10; varDez = temp_ADC_scaling / 10; } Antecipo meus agradecimentos. Bons trabalhos.
  4. Boa tarde. Na família 12f tem-se que ajustar aquele "Valor de Calibração", que pode variar de um chip para outro. Trata-se de de um valor localizado no final da memória de programa que permite garantir a correta calibração do oscilador interno. É necessário, portanto, recuperar este valor antes de programar o uC. Você seleciona o modelo correto de PIC. Então, deve-se começar com uma leitura da memória flash do uC. Ao finalizar a leitura do micro, você terá o conteúdo da memória. Mesmo que o uC não tenha sido utilizado, todas as posições de memória devem conter o valor 3FFF com exceção do último endereço (0x03FF). Este último endereço de memória contém o valor de calibração do uC. Anote esse valor, que deverá estar em hexadecimal. Carregue no seu gravador o arquivo .HEX que deseja programar o chip. Provavelmente, ao realizar isto, o valor de calibração do uC foi substituído pelo valor hexadecimal por “default” $3FFF. Vá lá, onde deveria estar o valor de calibração, e edite, inserindo o valor que você anotou. No IC-PROG é só dar um duplo clique para isso. No processo de gravação, o programador agora "verá" o valor de calibração lá com a finalidade de comparar o conteúdo do último endereço com o valor de calibração introduzido manualmente. Espero que tenha ajudado. Bons trabalhos.

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

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!