Go Down

Topic: MCP3301: ADC esterno a 13 bit con interfaccia SPI (Read 658 times) previous topic - next topic

gcam

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

BrainBooster

Quote
for (int i=11; i>=0; i--)

:smiley-roll: ma non era a 13 bit l'adc?

gcam

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 ?

gcam

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.

Go Up