Pages: [1]   Go Down
Author Topic: MCP3301: ADC esterno a 13 bit con interfaccia SPI  (Read 561 times)
0 Members and 1 Guest are viewing this topic.
italia
Offline Offline
Full Member
***
Karma: 1
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Devo collegare ed utilizzare l'ADC MCP3301.
L'ADC utilizza l'interfaccia SPI, che sembra semplice da utilizzare.

Però mi sfuggono alcune cose:
1.per quanto riguarda la configurazione
    SPI.setClockDivider
    SPI.setDataMode
    SPI.setBitOrder()

quale sono i valori ottimali e/o esatti da utilizzare ?

Sto utilizzando il codice seguente per acquisire i valori, però non riesco a capire se funziona correttamente.

Come faccio a verificare ?

// inslude the SPI library:
#include <SPI.h>

# define CS 10   // Pin Selezione
//# define MOSI 11  // MOSI
# define MISO 12   // MISO
# define SCLK 13 // CLOCK

#define FASTADC 1
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

long readvalue0;

void setup()
{
 // Set pin modalità
 pinMode (CS, OUTPUT);
 //pinMode (MOSI, OUTPUT);
 pinMode (MISO, INPUT);
 pinMode (SCLK, OUTPUT);
 
 // Disabilitare il dispositivo per iniziare
 digitalWrite (CS, HIGH);
 //digitalWrite (MOSI, LOW);
 digitalWrite (SCLK, LOW);

 Serial.begin (115200);
 
//SPI.setClockDivider (SPI_CLOCK_DIV2);
//SPI.setClockDivider (SPI_CLOCK_DIV4);
//SPI.setClockDivider (SPI_CLOCK_DIV8);
//SPI.setClockDivider (SPI_CLOCK_DIV16);
//SPI.setClockDivider (SPI_CLOCK_DIV32);
//SPI.setClockDivider (SPI_CLOCK_DIV64);
SPI.setClockDivider (SPI_CLOCK_DIV128);


 SPI.setDataMode (SPI_MODE0);
 //SPI.setDataMode (SPI_MODE1);

 //SPI.setBitOrder (MSBFIRST);
 //SPI.setBitOrder (LSBFIRST);
}

void loop ()
{
 long t0=micros();
 for(int k=0; k<500; k++)
 {
   readvalue0 = read_adcSlow ();
   Serial.println (readvalue0, DEC);
 }
}

int read_adcSlow ()
{
  long avg = 0; int value=0;
  for (int k=0; k<16; k++)
  {
    //Select adc
    digitalWrite (CS, LOW);  //pull CS low to enable
 
    //cycle clock twice, ignore two null bits

    digitalWrite (SCLK, HIGH);
    digitalWrite (SCLK, LOW);
    digitalWrite (SCLK, HIGH);
    digitalWrite (SCLK, LOW);
 
    // Legge i bit di adc
    for (int i=11; i>=0; i--)
    {
      //value += digitalRead (MISO) << i;
      value += (bitRead(PINB, 4) << i);
      //cycle clock
      digitalWrite (SCLK, HIGH);
      digitalWrite (SCLK, LOW);
    }
    avg=avg+value;
    digitalWrite (CS, HIGH);
    //delayMicroseconds (10);
  }
  avg=avg/4;
  return avg;
}

Praticamente
Logged

Deep south of Italy
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2961
The quieter you become, the more you can hear
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
for (int i=11; i>=0; i--)
smiley-roll ma non era a 13 bit l'adc?
Logged

italia
Offline Offline
Full Member
***
Karma: 1
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

si infatti è un 13 bit, o meglio un 12 bit più segno.
quindi ?
Nel datasheet c'è: null,null,sb,b11,b10,b9.....b0

ma con 'sb' si stabilisce il segno ?

comunque il metodo di lettura è corretto ?
Logged

italia
Offline Offline
Full Member
***
Karma: 1
Posts: 128
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sempre sull'MCP3301. Sul datasheet è riportato:

For the MCP330X devices, the recommended minimum clockspeed during the conversion cycle (tCONV) is 85 kHz.
Failure to meet this criteria may introduce linearity errors into the conversion outside the rated specifications.
It should be noted that, during the entire conversion cycle, the A/D converter does not have requirements for clock speed or duty cycle as long as
all timing specifications are met.


Considerando che per ogni acquisizione sono necessari 16 clock. Gli 85 KHz sono facilmente raggiungibili. Basta fare un oversampling di 16 ed acquisire almeno a 332 Hz. Mentre se gli 85 K sono campioni, significa che l'ADC non è utilizzabile, con l'ARDUINO ???.

Vorrei utilizzare la funzione
SPI.transfer(0) in questo modo:

digitalWrite(10, LOW);                 
highByte = SPI.transfer(0x00);  //XXXSVVVV  -> XXX bit nulli, S segno, V bit significativi.     
lowByte = SPI.transfer(0x00); //VVVVVVVV
digitalWrite(10, HIGH);               

per leggere i valori dell'ADC. Però i primi tre bit da sinistra di highByte sono nulli o non significativi.

Come faccio a comporre il valore, escludendo i tre bit nulli e considerando che il 4° bit da sinistra fornisce il segno.

grazie.
Logged

Pages: [1]   Go Up
Jump to: