Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

ADC 1023'den sonra sapıtıyor

Başlatan polilies, 13 Ekim 2011, 00:06:09

polilies

  Merhaba Arkadaşlar;

ADC ile 5k'lik bir trimpot üzerinden gerilim okuyorum ve bunu 2X16 ekranda göstermeye çalışıyorum. Aslında değeri görüyorumda zaten ancak

değer 1023 yani 5volt'u gördükten sonra potu tersine çevirip azaltmaya başlayınca değer birden 9900 gibi yüksek bir rakam alıyor ve mnimumda da mesela 293'te kalıyor. Bunun sebebiyle ilgili

bir fikri olan var mı? ya da bu hatayla karşılaşan. Teşekkür ederim.
#include <16f877a.h>
#device *=16
#device ADC=10
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=4M)

#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_BAUD 19200
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define LCD_POWER  PIN_D7
#include "modbus.c"
#include "Flex_LCD.c"
#use I2C(master, SCL=PIN_C3, SDA=PIN_C4)

#define MODBUS_ADDRESS 0xF7



/*This function may come in handy for you since MODBUS uses MSB first.*/
int8 swap_bits(int8 c)
{
   return ((c&1)?128:0)|((c&2)?64:0)|((c&4)?32:0)|((c&8)?16:0)|((c&16)?8:0)
          |((c&32)?4:0)|((c&64)?2:0)|((c&128)?1:0);
}
int data; 
int ack;
unsigned long celc=0,adc=0;
int16 hold_regs[] = {0x8800,0x7700,0x6600,0x5500,0x4400,0x3300,0x2200,0x1100};
int16 input_regs[] = {0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800};
int16 event_count = 0;

void main()
{
   setup_adc_ports(RA0_ANALOG);
   setup_adc(adc_clock_internal);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   set_adc_channel(0);
   //int8 coils = 0b00000101;
   //int8 inputs = 0b00001001;
   //enable_interrupts(GLOBAL);
   //enable_interrupts(int_rda);
   
      output_high(LCD_POWER);  // Turn on power to LCD 
      output_low(LCD_RW);      // Set R/W pin on LCD to a low level
      lcd_init();
      delay_ms(200);
      //printf ("\r\n\r\n\r\n"); 
      delay_ms(200);
      printf(lcd_putc,"Temp:\n");
      delay_ms(2000);
   
   modbus_init();

   while(TRUE)
   {
   while(modbus_kbhit())
   {
   if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
      {
         switch(modbus_rx.func)
         {
            
            case FUNC_READ_HOLDING_REGISTERS:
            case FUNC_READ_INPUT_REGISTERS:
               if(modbus_rx.data[0] || modbus_rx.data[2] ||
                  modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
                  modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
                     modbus_read_holding_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]);
                  else
                     modbus_read_input_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
                  
                  event_count++;
               }
               break;
            
            default:    //We don't support the function, so return exception
               modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
         }
      }    
   }
        i2c_start(); 
        ack = i2c_write(0x9A); 
        ack = i2c_write(0x00); 

        /* send start again */ 
        i2c_start(); 
        ack = i2c_write(0x9b); 
        data = i2c_read(0); 
        i2c_stop();        
        
        delay_ms(200);
        celc = (long)data;        
        lcd_gotoxy(6,1);
        //printf (lcd_putc,"%ld",celc);
        delay_ms(100);               
        delay_ms(400);
        input_regs[0] = celc;
        //enable_interrupts(int_rda);
   
///////////////////////////////ADC///////////////
        
        adc = 0;
        adc = read_adc();
        delay_us(100);
        input_regs[1] = adc;//(int)(0.00488758*(float)adc);
        printf (lcd_putc,"%lu",adc);
        //lcd_gotoxy(0,2);
        //printf("\f%ld",input_regs[1]);
        if(adc>1023)
        {
         adc = 1023;
        }        
  }
}

kodda modbus uygulaması da yer aldığı için kafanızı karıştırmasın ADC bloğu en altda yer alıyor. Ben tip değişimlerinden şüpheleniyorum çünkü veriyi attığım register üzerinden PC'ye çektiğimde  de çok acayip bir değer alıyorum. iyi çalışmalar

frederic

#1
Hocam adc bloğunuzda hangi adc kanalından okuma yapacaksanız onu set etmelisiniz,daha sonra read_analog() fonksiyonunu kullanmalısınız.

set_adc_channel(0);

Bu satır 0. analog  kanalının numarasıdır,0 rakamı ra0 kanalını temsil etmektedir,bir deneyin bakalım düzelmezse başka çaresine bakarız.

Veli B.

Read_ADC() fonksiyonunuzu ve kurulum kısmını incelemek lazım. Bahsettiğiniz problem ADFM den kaynaklı gibi görünüyor.Bu bit 0 mı 1 mi?

fahri-

Bence adc normal çalışıyor. senin hatan lcd deki son değeri silmiyorsun ve 1 ler basamağındaki sayı kalıyor. lcd ye yeni yazacağın zaman önce yazı yazacağın yere 4 boşluk yaz. yani eski sayıyı sil. sonra yeni rakamı yaz. printf  de bunu önleyen formatlar var.