[RISOLTO] MCP4922 e Arduino DUE

Ciao a tutti,

vorrei utilizzare un DAC in accoppiata con l´arduino DUE.

So che il messaggio da mandare é quello riportato nella figura allegata.

Quindi devo mandare un messaggio di 16 bit. Il problema é che Arduino DUE lavora a 32 bit e quindi non so come fare.

Innanzitutto spero che il messaggio da mandare sia giusto:

[0011 (Bit di controllo del DAC, rispettivamente DAC A / DAC B selection, BUFFERED / UNBUFFERED, GAIN 1 / GAIN 2, output Shutdown)] + [Valore da mandare composto da 12 bit (quindi posso mandare un valore tra 0 e 4095)]

In tutto se voglio mandare ad esempio 4095 dovró mandare il messaggio seguente:
0011111111111111

Ho provato in questo modo:

short msg=0011111111111111;
  
  SPI.transfer(10,msg);

e in questo modo:

byte msg1=00111111;
byte msg2=11111111;
SPI.transfer(10,msg,SPI_CONTINUE);
SPI.transfer(10,msg2);

Ma non funziona niente :frowning: .

Il codice intero é semplicemente questo

#include <SPI.h>

void setup() {
  // put your setup code here, to run once:
SPI.begin(10);
}

void loop() {
  // put your main code here, to run repeatedly: 
  // The entire message to send a 4095 number will be:
  // 0011 | 111111111111
  
byte msg1=00111111;
byte msg2=11111111;
SPI.transfer(10,msg,SPI_CONTINUE);
SPI.transfer(10,msg2);
}

Qualcuno puó aiutarmi?

Dopo tanta ricerca ho finalmente capito che non é possibile utilizzare la libreria SPI.h per il mio scopo.

Il DAC MCP4922 accetta solo parole da 16 bit e la libreria SPI.h funziona con 8 bit.

Quindi quello che devo fare ora é cercare un modo per effettuare il porting del codice seguente, che funziona per il mio ARDUINO UNO, per il mio ARDUINO DUE:

/*
  MCP4922 test
  outputs steadily rising voltages through both DACs
  
  Steve Woodward, 2010
  most code borrowed from
  http://mrbook.org/blog/2008/11/22/controlling-a-gakken-sx-150-synth-with-arduino/
  
  connections
  ====================================================
  
  +5v           > 4922 pin 1
  Ard pin 10    > 4922 pin 3   (SS - slave select)
  Ard pin 13    > 4922 pin 4   (SCK - clock)
  Ard pin 11    > 4922 pin 5   (MOSI - data out)
  Ground        > 4922 pin 8   (LDAC)
  +5v           > 4922 pin 11  (voltage ref DAC B)
  Ground        > 4922 pin 12
  +5v           > 4922 pin 13  (voltage ref DAC A)
 
 
  4922 pin 14 DAC A > 1k resistor > synth CV in
  
 */ 
 
// MCP4922 DAC out
#define DATAOUT 11//MOSI
#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK  13//sck
#define SLAVESELECT0 10//ss
 
int i = 0;
 
void setup() {
  SPI_setup();
  Serial.begin(115200);
}
 
void loop() {
 i++;
 Serial.println(i);
 write_note(i);
 if(i>=4096) {
  i=0; 
 }
 delay(8);
}
 
void write_note(int i) {
  write_valueY(i);
  write_valueX(i);
}
 
// **************************************************
// SPI for DAC
 
void SPI_setup(){
 
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT0,OUTPUT);
  digitalWrite(SLAVESELECT0,HIGH); //disable device
 
  SPCR = (1<<SPE)|(1<<MSTR) | (0<<SPR1) | (0<<SPR0);
  clr=SPSR;
  clr=SPDR;
  delay(10);
}
 
// write out through DAC A
void write_valueX(int sample)
{
  // splits int sample in to two bytes
  byte dacSPI0 = 0;
  byte dacSPI1 = 0;
  dacSPI0 = (sample >> 8) & 0x00FF; //byte0 = takes bit 15 - 12
  dacSPI0 |= (1 << 7);// A/B: DACa or DACb - Forces 7th bit of x to be 1. all other bits left alone.
  dacSPI0 |= 0x10;
  dacSPI1 = sample & 0x00FF; //byte1 = takes bit 11 - 0
  dacSPI0 |= (1<<5);  // set gain of 1
  digitalWrite(SLAVESELECT0,LOW);
  SPDR = dacSPI0;			  // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
 
  SPDR = dacSPI1;
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  digitalWrite(SLAVESELECT0,HIGH);
  //delay(2);
}
 
// write out through DAC B
void write_valueY(int sample)
{
  // splits int sample in to two bytes
  byte dacSPI0 = 0;
  byte dacSPI1 = 0;
  dacSPI0 = (sample >> 8) & 0x00FF; //byte0 = takes bit 15 - 12
  dacSPI0 |= 0x10;
  
  dacSPI1 = sample & 0x00FF; //byte1 = takes bit 11 - 0
  dacSPI0 |= (1<<5);  // set gain of 1
  
  digitalWrite(SLAVESELECT0,LOW);
  SPDR = dacSPI0;			  // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
 
 
  SPDR = dacSPI1;
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  digitalWrite(SLAVESELECT0,HIGH);
  //delay(2);
}

Qualcuno puó aiutarmi per favore?

Grazie mille,
Fab.

f.schiano: Dopo tanta ricerca ho finalmente capito che non é possibile utilizzare la libreria SPI.h per il mio scopo. Il DAC MCP4922 accetta solo parole da 16 bit e la libreria SPI.h funziona con 8 bit. ....

Non credo c'entri nulla ... ... non lavori mica su un bus parallelo, per cui o gli arriva una word da 16 bit o nulla ... qui lavori su un bus seriale dove i bit sono inviati serialmente. Se guardi il datasheet del MCP4922 a pagina 25, vedi chiaramente che l'unica cosa che conta è il segnale di CS che deve rimanere LOW per tutti i bit trasmessi.

La libreria SPI ti permette di farlo (e tu prima c'hai provato), difatti dice chiaramente :

You can use an additional SPI_CONTINUE or SPI_LAST parameter to manage the Slave Select line after the transfer. SPI_CONTINUE keeps the specified SS pin active (low) after the transfer to allow the send of additional bytes via the transfer() function in the same SPI transaction.

Quindi ... tu devi preparati due variabili uint8_t (o byte, come vuoi) e, dopo aver programmato bene la libreria (verifica come devi trasmettere i bit e usa la setBitOrder) gli devi trasmette di seguito i due byte (16 bit) mantenendo il CS LOW ovvero usando per il primo SPI_CONTINUE e per il secondo SPI_LAST.

Guglielmo

Hai ragione, ho appena risolto e sai quale era il problema?

Connettevo sempre i restanti pin relativi al protocollo SPI ai pin 11 e 13 dell´arduino DUE mentre sul DUE i pin SPI e quelli 11,12,13 non sono connessi come puoi vedere dalla tabella seguente:

Quindi bisogna connettere i pin del DAC ai pin SPI dell´arduino DUE come mostrato nella figura seguente:

Appena possibile faccio un tutorial di tutto l´occorrente e di come fare passo passo per connettere il DUE a un DAC MCP4922.

Per ora vi lascio il codice:

#include <SPI.h>

void setup() {
  // put your setup code here, to run once:
SPI.begin(10);
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(10, 1);
SPI.setClockDivider(10,84);
}

void loop() {
  // put your main code here, to run repeatedly: 
  
  // The entire message to send a 4095 number will be:
  // 0111 | 111111111111
  
  byte msg1=0b01111111; // 01111111
  byte msg2=0b11111111; // 11111111
  SPI.transfer(10,msg1,SPI_CONTINUE);
  SPI.transfer(10,msg2,SPI_LAST);
  delay(1000);
}

Spero sia utile a qualcuno,
Fab

Bene !!! :)

Cortesemente allora metti [RISOLTO] nel titolo del primo post così si capisce che è stato risolto ;)

Gugleilmo

Qui potete trovare il tutorial su quello che sono riuscito a fare. http://schianorobotics.altervista.org/arduino.html

Spero sia utile a qualcuno, in caso positivo un semplice grazie sarebbe molto apprezzato :)

Fab, occhio, quando si scrivono dei tutorial, a non dare informazioni errate ...

Trascrivo dal tuo :

"The big difference between and Arduino DUE and other Arduinos about SPI is that with the DUE is possible to address up to 3 different SPI devices at the same time, instead on the Arduino UNO for example there is just one pin to address an SPI device (this pin is called CS Chip Select), that is the pin 10."

Guarda che NON è affatto vero ... il pin 10 è quello di base usato da alcune librerie, ma, essendo il segnale di SS solo un segnale di abilitazione del device SPI, QUALUNQUE pin di I/O, usato in output, può funzionare da SS.

A riprova hai che la scheda WiFi usa il pin 10 come SS del WiFi ed il pin 4 come SS della SD e ... funziona perfettamente sulla UNO !!!

Quale pin di usa come SS è quindi solo una cosa decisa a livello software e, le librerire scritte meglio, ti permettono di indicare quale pin usi come SS per il device che devono gestire.

Mi raccomando ... se si vogliono scrivere dei tutorial ... documentarsi bene sull'argomento ... ;)

Guglielmo

Scusami hai ragione. Correggo subito :)

EDIT: CORRETTO . Se trovate altri errori fatemi sapere