Go Down

Topic: Digital Analog Converter MCP4922 (Read 2550 times) previous topic - next topic

f.schiano

Hi to everyone,

I need to give an output between 0 and 4V with my Arduino DUE.

I have a Digital to Analog Converter MCP4922 but to use it I should change the SPI library because the stuff I was using for the Arduino UNO, on the DUE is not working because The sketch is written for an ATmega based Arduino. On a Due I can't use the direct port manipulation commands of the ATmega platform, so I have to rewrite the sketch to use digitalWrite() instead of the port manipulations and the SPI library instead of the register manipulations in the sketch.

I know that on the DUE there is already a DAC integrated, but the output can be only between 0 and 3.3V, actually they give an output between 0.549V and 2.775V.

I want an output between 0 and 4V. How can I have it?

I was thinking that there are mainly 2 ways:

1. Add an Operational Amplifier
2. Change the SPI library to let it work with the DUE.

What do you think is the best way? or what do you suggest to me and why?

Thanks a lot,
Fab.
L'impossibile...richiede solo piu' tempo!

Stephan_Duino

If you go with SPI look at this thread. SPI is different on the ARM chip
http://forum.arduino.cc//index.php?topic=157203.msg1424519#msg1424519
I know its more about slave mode but plenty of tips for DUE SPI in there.

If you can use the Due 12bit DAC all the better.

Can you not use a pair of resistors to do a voltage divide and then a bit of math on the output to scale it to what you want.

Stephan_Duino

Just noticed this post
http://forum.arduino.cc//index.php?topic=194694.0

Puts a damper on the idea of using the Due DAC.

CrossRoads

http://ww1.microchip.com/downloads/en/DeviceDoc/22250A.pdf

See page 23-24.
You bring CS low, send out 2 bytes via SPI.transfer(x);  bring CS high.
You really need a library for that?
Due does not support SPI.transfer( ) command?
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

f.schiano


Just noticed this post
http://forum.arduino.cc//index.php?topic=194694.0

Puts a damper on the idea of using the Due DAC.


Thanks for the reply but that page is not really useful for me because people are searching for a solution to connect the DUE as slave and it also seemed that they didnĀ“t find a solution . By the way my problem is another one.

I want to use a DAC MCP4922 on the Arduino DUE


http://ww1.microchip.com/downloads/en/DeviceDoc/22250A.pdf

See page 23-24.
You bring CS low, send out 2 bytes via SPI.transfer(x);  bring CS high.
You really need a library for that?
Due does not support SPI.transfer( ) command?


Thanks for the reply ,

I will look into it.

Fab.
L'impossibile...richiede solo piu' tempo!

f.schiano

Ok. I looked a little bit more into it and what I have to send is the one in the picture attached.

So now I know what message I have to send but, in your opinion can I send it with just an SPI.write(msg) command?

Thanks a lot,
fab.

L'impossibile...richiede solo piu' tempo!

f.schiano

I think I can do it in this way:

Code: [Select]

#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
 
  msg= ...
  SPI.transfer(10,msg)
}


What is msg?

The problem now is how to create a message of 2 bytes on the Arduino DUE, because the integers are of 32 bits.

Thanks for your help,
Fab.
L'impossibile...richiede solo piu' tempo!

f.schiano

#7
Oct 30, 2013, 11:59 am Last Edit: Oct 31, 2013, 08:42 am by f.schiano Reason: 1
I tried with this:

Code: [Select]
short msg=0011111111111111;
 
  SPI.transfer(10,msg);


and with this:
Code: [Select]

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


But nothing is working :( .

Please help
L'impossibile...richiede solo piu' tempo!

f.schiano

I figured out that the library SPI.h is only for 8 bit data values. So I can´t use the library to address my MCP4922 DAC.

Assumed that this is true what I have to do now is to port the following code, that is working on my Arduino UNO, to the DUE:

Code: [Select]

/*
  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);
}



I need some help for that please.
L'impossibile...richiede solo piu' tempo!

f.schiano

I figured out how to solve my problem. :)

The library was useful , what I wrote in my previous post was a bullshit.

Here you can find a small tutorial to understand what I did:
http://schianorobotics.altervista.org/arduino.html

Hope it helps someone. If yes a "thanks" would be really appreciated !!!
L'impossibile...richiede solo piu' tempo!

Manewc

Thanks so much for this, really helped me out.

I know how to send data across one channel, still not sure how to switch between channels?

thanks

manewc

MarkT


http://ww1.microchip.com/downloads/en/DeviceDoc/22250A.pdf

See page 23-24.
You bring CS low, send out 2 bytes via SPI.transfer(x);  bring CS high.
You really need a library for that?
Due does not support SPI.transfer( ) command?


Won't work on the Due - the CS line is handled in hardware and you must not
drive it directly.  See the extensions to SPI for the Due, its all mentioned on the
Due product page I believe.  SPI.transfer() brings CS low and takes it high again
automagically on every call.

Note on the Due you are limited to 3 or 4 particular CS pins (4 and 10 and some others).  However you can use other pins for CS, but have to use one of the hardware pins _as well_
since the SPI hardware needs to drive one of them automatically IIRC.
[ I won't respond to messages, use the forum please ]

Go Up