MCP3304 13 BİT ADC

Başlatan coskun_yildirim, 23 Ekim 2015, 01:16:52

coskun_yildirim

MCP3304 13 bit için iki  ayrı uç kullanarak diferansiyel modda 13 biti veriyor.Ben ccs c ile mcp3208 12 bit olarak ölçüm yapabiliyorum.Mcp3304 bize iki ayrı kanaldan -4095 ile +4095 arasında değer veriyormuş. Mcp3208 de farklı olarak sign biti olduğunu biliyorum.referans voltajını 2.5 volt verdim.CH1 e 2,5 volt sabit ve CH0 a pot bağlayarak 5 volt verdim ve MCP3208 in kütüphanesiyle CH0 ve CH1 in değerlerini ayrı ayrı okuyarak CH0 a bağladığım pot ile 5 voltu artırıp çoğalttım.Hyper terminalde CH0 ve CH1 in değerleri birbirine zıt oranda aynı farkta değişmekte ve iki ayrı kanalın farkını aldığımda gerçekten 13 bit değerini veriyor.Benim sizden istediğim 0 ile 8192 arasında nasıl okuma yapabilrim.Kütüphanede nasıl bir değişiklik yapmalıyım. Lütfen bilgili abilerimiz yardımcı olsun.Çok uğraştım ancak işin içinden çıkamadım.En azından bir yol gösterecek.

Kabil ATICI

5V ölçtüğüne göre;
2.5V referans gerilimi üret. Bunun için çeşitli yöntemler var. (hazır referans gerilim üreteci entegreler, gerilim bölücü direnç, veya opamp gibi)
Bunu adc ch(-) ucuna bağla. Ölçmek istediğin gerilimi  adc ch(+) ucuna bağla.
Normal ölçüm yapabilirsin.

Bundan sonra tek yapman gereken senin ölçüm sonucunu değerlendirmek.

buna göre,

ölçüm                           gerçek değer
0...2.5V aralığın   --->  2.5V...5V
0... -2.5V aralığın---> 0..2.5V

denk düşer. Kullandığın adc  (negatif değerleri farklı tanımladığından bunları ölçeklemen gerekir)
ambar7

coskun_yildirim

hocam 2,5 volt referans entegrem var.Dediğiniz gibi - uca 2.5 volt referans voltajı verdim. + uca 5 voltu pot ile bağladım.mcp3208  kütüphanesinde ne gibi değişiklik yaparak 13 biti alırım.


#ifndef MCP3208_CS

#define MCP3208_CLK  PIN_d3//clock
#define MCP3208_DOUT PIN_d2//veri alma
#define MCP3208_DIN  PIN_d1 //veri gönderme
#define MCP3208_CS   PIN_d0//seçim

#endif


void adc_init() {
   output_high(MCP3208_CS);
}


void write_adc_byte(BYTE data_byte, BYTE number_of_bits) {
   BYTE i;

   delay_us(2);
   for(i=0; i<number_of_bits; ++i) {
      output_low(MCP3208_CLK);
      if((data_byte & 1)==0)
         output_low(MCP3208_DIN);
      else
         output_high(MCP3208_DIN);
      data_byte=data_byte>>1;
      delay_cycles(50);
      output_high(MCP3208_CLK);
      delay_cycles(50);
   }
}


BYTE read_adc_byte(BYTE number_of_bits) {
   BYTE i,data;

   data=0;
   for(i=0;i<number_of_bits;++i) {
      output_low(MCP3208_CLK);
      delay_cycles(50);
      shift_left(&data,1,input(MCP3208_DOUT));
      output_high(MCP3208_CLK);
      delay_cycles(50);
   }
   return(data);
}

signed long int read_analog_mcp(BYTE channel, BYTE mode) {
int b1=0,b2=0;
int sign=0;
int l;
int h;
   BYTE ctrl_bits;

   delay_us(200);

   if(mode!=0)
      mode=1;

   output_low(MCP3208_CLK);
   output_high(MCP3208_DIN);
   output_low(MCP3208_CS);

   if(channel==1)               // Change so MSB of channel #
      ctrl_bits=4;            //      is in LSB place
   else if(channel==3)
      ctrl_bits=6;
   else if(channel==4)
      ctrl_bits=1;
   else if(channel==6)
      ctrl_bits=3;
   else
      ctrl_bits = channel;

   ctrl_bits = ctrl_bits<<1;

   if(mode==1)                  // In single mode
      ctrl_bits |= 1;
   else                        // In differential mode
      ctrl_bits &= 0xfe;

   ctrl_bits=ctrl_bits<<1;      // Shift so LSB is start bit Shift yüzden LSB biti başlayın
   ctrl_bits |= 1;

   write_adc_byte( ctrl_bits, 7);   // Send the control bits Kontrol bitlerini Gönder

   
   h=read_adc_byte(8);
   l=read_adc_byte(8);
   output_high(MCP3208_CS);

   return make16(h,l)/2;
}


long int read_analog( BYTE channel )   // Auto specifies single mode
{
   return read_analog_mcp( channel, 1);
}


void convert_to_volts( long int data, char volts[6]) {
   BYTE i, d, div_h, div_l;
   long int temp,div;

   div=0x3330;

   for(i=0;i<=4;i++) {
     temp=data/div;
     volts=(BYTE)temp+'0';
     if(i==0) {
       volts[1]='.';
       i++;
     }
     temp=div*(BYTE)temp;
     data=data-temp;
     div=div/10;
   }
   volts='\0';
}

coskun_yildirim

Hocam ardunio daki kütüphaneyi ccs c ye çevirebilir misiniz. Ben denedim ama olmadı farklı değerler alıyorum.

// read the MCP3304 in quad differential mode, non-bit-banging version
#include <Serial.h>
#include <SPI.h>

#include <HardwareSerial.h>

long ticks = 0;

// for Uno
#define SELPIN 10    // chip-select
#define DATAOUT 11   // MOSI
#define DATAIN 12    // MISO
#define SPICLOCK 13  // Clock

// for Mega2560 / Max32
//#define SELPIN 53    // chip-select
//#define DATAOUT 51   // MOSI
//#define DATAIN 50    // MISO
//#define SPICLOCK 52  // Clock

int readvalue;


void setup(){
  //set pin modes
  pinMode(SELPIN, OUTPUT);

  // disable device to start with
  digitalWrite(SELPIN, HIGH);

  SPI.setClockDivider( SPI_CLOCK_DIV8 ); // slow the SPI bus down
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);    // SPI 0,0 as per MCP330x data sheet
  SPI.begin();

  Serial.begin(115200);
}


void loop() {
  long ticks = millis();
  int A = 0, B = 0;

  A = read_adc(1);
  B = read_adc(2);

  // do whatever you want with these readings

  long tcnv = millis() - ticks;

  delay(100 - tcnv);
}

// non-bit-banging version
// channel ranges from 1.. 3 (not zero!)
// maximum clock frequency is 2.1 MHz @ 5V
//
// this is SPI_CLOCK_DIV8
// at DIV64, 512 in 60ms (8.5 ksps)
// at DIV32, 512 in 35ms (14.6 ksps)
// at DIV16, 512 in 22ms (23.3 ksps)
// at DIV8, 512 in 16ms (32 ksps)

int read_adc(int channel){
  int adcvalue = 0;
  int b1 = 0, b2 = 0;
  int sign = 0;

  // command bits for MCP3304
  // 0000 = diff, ch0 = in+, ch1 = in-
  // 0010 = diff, ch2 = in+, ch3 = in-
  // 0100 = diff, ch4 = in+, ch5 = in-

  digitalWrite (SELPIN, LOW); // Select adc

  // first byte
  // first byte will always be B000010xx where xx are the D2 and D1 channel bits 
  byte commandbits = B00001000;
  commandbits |= (channel >> 1);         // high bit of channel

  SPI.transfer(commandbits);       // send out first byte of command bits

  // second byte; Bx0000000; leftmost bit is D0 channel bit
  commandbits = B00000000;
  commandbits |= (channel << 7);        // if D0 is set it will be the leftmost bit now
  b1 = SPI.transfer(commandbits);       // send out second byte of command bits

  // hi byte will have XX0SBBBB
  // set the top 3 don't care bits so it will format nicely
  b1 |= B11100000;
  Serial.print(b1, BIN); Serial.print(" ");
  sign = b1 & B00010000;
  int hi = b1 & B00001111;

  // read low byte
  b2 = SPI.transfer(b2);              // don't care what we send
  Serial.print(b2, BIN); Serial.print("\r\n");
  int lo = b2;
  digitalWrite(SELPIN, HIGH); // turn off device

  int reading = hi * 256 + lo;

  if (sign) {
    reading = (4096 - reading) * -1;
  }

  return (reading);
}