MCP4725 Communication

I'm going to be using the MCP4725 12-bit DAC and had a few questions about interfacing with it.

I found this sample code;

/*
Using the Sparkfun Breakout Board for MCP4725 I2C DAC
 
 this link made me understand how to use MCP4725 digital to analog converter
 http://blog.michaelbparks.com/2008/09/sparkfun-dac-breakout-board-tutorial_8918.html
 
 
 DAC MCP4725  values 0 - 4095;  0 - 5 volts
 
 byte Device = 96;  //= binary 1100 000 = (MCP4725 device code) & A2 & A1 & A0
 factory sets A2 & A1 to 0 & 0, we can set A0 to 1 or 0
 A0=0 if connected to Ground, A0=1 if connected to Vdd
 
 Stephan Schulz / www.maybevideodoes.de   /  27/03/2009
 */


byte Program = 64;
byte Device = 96; // This hardwired into the IC and the BoB, in other words, it is a given.

int maxValue = 1570; // 1570 is the max output for my project but can go up to 4095

int minValue = 0;
int value = minValue;
int dir = 1;

#include <Wire.h>

void setup()
{
  Wire.begin();

  Serial.begin(9600);
  Serial.println("i2c");

}

void loop()
{

  byte b1 = byte((value / 16));
  byte b2 = byte(value % 16);

  Wire.beginTransmission(Device);
  Wire.send(Program);
  Wire.send(b1);
  Wire.send(b2 << 4); // Needed twice, since the 4 lowest bits (of 12) are in the fourth byte
  Wire.endTransmission();


  value = value + dir;
  if(value > maxValue) dir = -1;
  if(value < minValue) dir = 1;

  delay(5);
}

The tutorial he has listed in his code is no longer present so I was hoping someone here could shed some light into it for me.

I'm looking to replace my I2C function in the following code with the MCP4725 communication;

#include <Wire.h>

//Variables 
volatile byte rpmcount = 0;
unsigned long rpm = 0;
unsigned long timeold = 0;
int analog_rpm = 0;
int potPin = 1;
int potVal;
unsigned long rpm_max = 0;

 void setup()
 {
   attachInterrupt(0, RPM_Func, FALLING);                            //Setup interrupt on pin 2 and set the pull-up resistor on
   digitalWrite(2, HIGH);
   Wire.begin();                                                     //Join I2C bus (address optional for master)
 }
 
 void loop()
 {
   potVal = analogRead(potPin);                                      //Read the maximum RPM pot value, this will be used later for scaling
   rpm_max = map(potVal, 0, 1023, 3500, 10000);
   if (rpmcount >= 5) {                                              //If there are more than 5 counts, calculate the RPM
     rpm = (((rpmcount * 1000000) / (micros() - timeold))) * 60;
     timeold = micros();
     analog_rpm =  map(rpm, 0, potVal, 0, 255);                      //Map the RPM to an analog value based on the earlier value read from 
     writeI2C(analog_rpm);                                           //the potPin and output it to the I2C buffer
     rpmcount = 0;                                                   //Reset the count
   }
   
   else {
     analog_rpm = 0;                                                 //If there are less than five counts, tell the I2C buffer that RPM
     writeI2C(analog_rpm);                                           //is zero
   }
 }
 
 void writeI2C(int val)                                              //Function to write values to the DAC I2C buffer
 {
   const int I2C_address = 0x98;                                     //Write address of I2C DAC
   Wire.beginTransmission(I2C_address);
   Wire.send(val);
   Wire.endTransmission();
 }
 
 void RPM_Func()                                                     //Function used by the interupt to increment the rpm counter
 {
   rpmcount++;
 }

I'm not sure why he's doing the modulo math, and the increment stuff. Is that just part of his example or is it required for the communication. Any assistance you can provide would be helpful.

-Ian

iyeager:
I'm not sure why he's doing the modulo math, and the increment stuff.

I can't see any modulo maths in that sketch code. Can you say which line(s) you're referring to, please?

Here's code I've come up with, does this appear like it will work?

#include <Wire.h>

//Variables 
byte Program = 64;
byte Device = 96; 													//Is this to replace the address I set later?
volatile byte rpmcount = 0;
unsigned long rpm = 0;
unsigned long timeold = 0;
int analog_rpm = 0;
int potPin = 1;
int potVal;
unsigned long rpm_max = 0;

 void setup()
 {
   attachInterrupt(0, RPM_Func, FALLING);                            //Setup interrupt on pin 2 and set the pull-up resistor on
   digitalWrite(2, HIGH);
   Wire.begin();                                                     //Join I2C bus (address optional for master)
 }
 
 void loop()
 {
   potVal = analogRead(potPin);                                      //Read the maximum RPM pot value, this will be used later for scaling
   rpm_max = map(potVal, 0, 1023, 3500, 10000);
   if (rpmcount >= 5) {                                              //If there are more than 5 counts, calculate the RPM
     rpm = (((rpmcount * 1000000) / (micros() - timeold))) * 60;
     timeold = micros();
     analog_rpm =  map(rpm, 0, potVal, 0, 4095);                     //Map the RPM to a 12-bit analog value based on the earlier value read from 
     writeI2C(analog_rpm);                                           //the potPin and output it to the I2C buffer
     rpmcount = 0;                                                   //Reset the count
   }
   
   else {
     analog_rpm = 0;                                                 //If there are less than five counts, tell the I2C buffer that RPM
     writeI2C(analog_rpm);                                           //is zero
   }
 }
 
 void writeI2C(int val)                                              //Function to write values to the DAC I2C buffer
 {
   //So I can comment out the next line???	
   /*const int I2C_address = 0x98;                                     //Write address of I2C DAC*/
   Wire.beginTransmission(Device);									 //Address?
   Wire.send(Program);												 //I'm assuming this is the get ready to write command
   Wire.send(val);													 //Can I just send the command or do I need to do the mudolo math to it???
   Wire.endTransmission();
 }
 
 void RPM_Func()                                                     //Function used by the interupt to increment the rpm counter
 {
   rpmcount++;
 }

Anachrocomputer:

iyeager:
I'm not sure why he's doing the modulo math, and the increment stuff.

I can't see any modulo maths in that sketch code. Can you say which line(s) you're referring to, please?

  byte b1 = byte((value / 16));
  byte b2 = byte(value % 16);

OK, thanks! Those two lines make the two 'byte' variables, one that holds the 8 most significant bits of the 12-bit 'value' and the other holds the least significant 4 bits. Then, he sends them separately to the 12-bit DAC, as the comment says:

  Wire.send(b1);
  Wire.send(b2 << 4); // Needed twice, since the 4 lowest bits (of 12) are in the fourth byte

Your latest code seems to make no attempt to split the 12-bit 'val' into high and low bytes for transmission, so I suspect that it won't work. You'll need to add some code, with either modulus arithmetic or bit-masking, to split the 12-bit DAC value into 8-bit bytes.

So something like this,

void writeI2C(int val)                                              //Function to write values to the DAC I2C buffer
 {
   byte b1 = byte(val / 16);                                         //Convert value from a 16bit number to 8bit pieces
   byte b2 = byte(val % 16);
   Wire.beginTransmission(Device);				     
   Wire.send(Program);						     //Get ready to write command
   Wire.send(b1);
   Wire.send(b2 << 4);                                               //Move last 4 bits into correct position since the four lowest bits   						     
   Wire.endTransmission();                                           //are in the fourth byte position.
 }

should work?

-Ian

That looks more like it, yes. You'll need to refer to the DAC data sheet to be sure. Or try it, of course!