PİC16F877A ADC DC Voltaj Okuma Problemi

Başlatan immortall, 06 Kasım 2020, 17:25:59

immortall

Arkadaşlar merhaba PİC16F877A ile adc kullanarak 12V batarya gerilimini LCD ekranda görüntülemek istiyorum. Fakat bir türlü beceremedim. Ekranda sürekli 0 V görünüyor. Sorun nedir tam olarak yardımcı olursanız sevinirim. CCS C kodları aşağıdaki gibidir;
#define LCD_ENABLE_PIN PIN_B2
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_DATA4 PIN_C4
#define LCD_DATA5 PIN_C5
#define LCD_DATA6 PIN_C6
#define LCD_DATA7 PIN_C7

#include <lcd.c>

void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);
   int adc_giris=0;
   float voltaj=0;
   lcd_init();

   while(TRUE)
   {
      set_adc_channel(0);
      delay_us(20);
      adc_giris=read_adc();
      voltaj=adc_giris*9.0/1023.0;
      printf(lcd_putc, "\f voltaj= %f V",voltaj);
      delay_ms(1000);
   }

}




fide

#1
İnt olarak tanımladığın değer maksimum 256 alır. 9 * 256 /1023 sonucu maksimum girilte bile ancak 2-3 olur.
İnt yerine unsigned int16 tanımlayıp yeniden dene.
Hala olmadıysa wizard ayarlarında vref- gnd, vref+ vcc ile ilgili ayar var mı onlara bak.

Muhtemelen int yerine unsigned int16 tanımı sıkıntını çözecektir.

Simulasyon için sıkıntı yok ama gerçekte işlemci ile uğraşırken işlemci bacağına vcc den fazla gerilim verirsen işlemciyi bozarsın. ( 3.3 volt ile beslenen mculardaki 5volt tolerant pinler hariç)

Bunun için maksimum gerilimde işlemci pininde en fazla 5 volt olacak şekilde gerilim bölücü ile bunu bölmelisin  aklında olsun.
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

immortall

#2
Dediğiniz gibi unsigned int16 yaptım fakat sorun hala aynı. Hala 0 V gözüküyor. Wizard ayarlarında vref- gnd, vref+ vcc benzeri ayarlar var resimdeki gibi. Resimdeki devrede pin ucunda 4.92 V gerilim var. Sanırım pratikte de sıkıntı olmaz. Yanlışım varsa düzeltin lütfen. Son olarak wizard ayarları nasıl olmalı? Kodun son hali;

#include <deneme.h>
#define LCD_ENABLE_PIN PIN_B2
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_DATA4 PIN_C4
#define LCD_DATA5 PIN_C5
#define LCD_DATA6 PIN_C6
#define LCD_DATA7 PIN_C7

#include <lcd.c>

void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);
   unsigned int16 adc_giris=0;
   float voltaj=0;
   lcd_init();

   while(TRUE)
   {
      set_adc_channel(0);
      delay_us(20);
      adc_giris=read_adc();
      voltaj=adc_giris*12.0/1023.0;
      printf(lcd_putc, "\f voltaj= %f V",voltaj);
      delay_ms(100);
   }

}
Teşekkürler.




fide

#3
kristal yok devrede. Kendi simulasyonumda bulamadım.
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

immortall

Ekranda voltajı gösteriyorum fakat pot değeri gözüküyor galiba. Hesaplama mı yanlış acaba?


CCS C kodu
#include <stdio.h>
#define LCD_ENABLE_PIN PIN_B2
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_DATA0 PIN_D0
#define LCD_DATA1 PIN_D1
#define LCD_DATA2 PIN_D2
#define LCD_DATA3 PIN_D3
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7

#include <lcd.c>


void main()
{
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);
   unsigned int16 adc_giris=0;
   float voltaj=0;
   lcd_init();

   while(TRUE)
   {
      set_adc_channel(0);
      delay_ms(100);
      adc_giris=read_adc();
      voltaj=adc_giris*(12.0/1024.0);
      delay_ms(10);
      printf(lcd_putc, "\f voltaj= %f V",voltaj);
      delay_ms(2000);
   }

}

fide

Float yazdırmadan önce okuduğun int16 değerini %lu ile adc_giris değerini yazdırıp dener misin? En azından doğru okuyor mu onu bilirsin.
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

bayelektronik

#6
Adc portlarına picin besleme voltajından fazla gerilim vermeyin. 12 Volt ölçmek için pot ile ölçüm kaynağı arasına  uygun bir direnç ile besleme voltajına denkleşen bir değer belirleyin(Pot değeri %59 ayarlı gördüm). Sonra pot ile ayar yapın. Ayrıca tek ölçüm ile sağlıklı bir değer alamazsınız en azından ortalama alın. Hesabıda "(max_Voltaj /1024)*okunan_Deger" şeklinde yapın. Parantezi doğru yere veya işlemi doğru sıraya koymak gerek.

immortall

Alıntı yapılan: fide - 09 Kasım 2020, 08:01:40Float yazdırmadan önce okuduğun int16 değerini %lu ile adc_giris değerini yazdırıp dener misin? En azından doğru okuyor mu onu bilirsin.
Dediğinizi denedim pot %0 da iken 65472 değerini ekrana basıyor. %100 ken 0 değerini.

fide

Pot uçlarınızı değiştirirseniz %0 da 0, %100 de 65535 çıkacaktır ama hatırlafığım kadarıyla f877a 10 ysda 12 nit. 65535 olması zor
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

immortall

Adc pot un %100 değerinde 65472 gibi bir sayı okuyor. 1024 okuması gerekmez mi? Gerilim bölücüyü resimdeki gibi yaptım. Pot 10k da kullandım sonuç yine aynı. Sanırım pek farketmiyor. Yaptığım hesaplama;

Va=Vin*(5.6/5.6+3.9) => Va=Vin*0.5895
çözünürlük=5/1023= 0.00489
Voltaj=(Va/0.5895)=1.6964*Va=1.6964*0.00489*Adc'de okunan değer
Voltaj=0.008295*Adc'de okunan değer.
Bir başka yerde aşağıdaki gibi hesap yapılmış.
[
ADC Math

The accuracy depends upon the accuracy of the resistors at the input end and the stability of reference voltage, Vdd = +5V. I found Vdd is stable to +5.02 V. I measured R1 and R2, and their values are 1267 and 3890 Ohms. So this gives,

0 – 5.02 V Analog I/P ---> 0-1023 Digital Count
=> Resolution = (5.02 - 0)/(1023-0) = 0.004907 V/Count
Va = 1267*Vin/(1267+3890) = 0.2457*Vin
=> I/P voltage = 4.07*Va = 4.07* Digital Count * 0.004907
= 0.01997 * Digital Count
= 0.02*Digital Count (Approx.)
To avoid floating point, use I/P voltage = 2*Digital Count.
Example, suppose Vin = 7.6V. Then,
Va = 0.2457*Vin = 1.87V

=> Digital Count = 1.87/0.004907 = 381

=> Calculated I/P Voltage = 2*381 = 0762 = 07.6V (First 3 digits of 4 digit product)
]

CCS C kodu:

#define LCD_ENABLE_PIN PIN_B2
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c>
unsigned  int16 adc_giris;
float gerilim;
void main()
{   
   set_tris_a(0x01);
   set_tris_d(0x00);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_adc_ports(AN0);
   lcd_init();
   
    while(TRUE)
   {
      set_adc_channel(0);
      delay_us(20);
      adc_giris=read_adc();
      gerilim=adc_giris*0.008295;
      printf(lcd_putc,"\f ADC= %lu ",adc_giris);
      printf(lcd_putc,"\n Voltaj= %f V",gerilim);      
      delay_ms(1000);
      
   }

}