MCP4725 12bit Digital to analog converter

In this example we are going to connect from Raspberry Pi to MCP4725 12 bit digital to analog converter.

(And at bottom there I tell of how to get it to work also on H3 based Orange Pi)

DISCLAIMER

We do not take any responsibility for possible errors in the guide or errors that you might do wiring it up. Incorrect wiring can result in damaged sensor or damaged Raspberry Pi.

This is how the front of my breakout board was for the MCP4725.

Main parameters from the sensors Data sheet:

Analog output will be from between zero voltage to the voltage you feed into the board. So in case of Raspberry Pi then the analog output will be 0V to 3.3V.

The EEPROM feature on this board is to save default state. Default state is the value the analog output will have when you turn on your Raspberry Pi, long before your application runs.

The board has settable address in case if you need to wire two such at once.

Usually it will come with the address soldered between middle pin and GND. (Mine for some reason was unset and I just used it like that as I found it on address 0x60.
If you have more than one then you can solder between middle address pin and the VCC (the right side address pin). If your board came soldered between middle and GND then you would need to de-solder that first.

To complicate things more then if you have two such boards connected then you would need to cut between the pull up resistors on one board.

If you cut between the pullups for the purpose of wiring two such boards at once then you can always solder the cut later if wanting to change it back. 

Pieces we use in this guide:

If you are not familiar with working with a breadboard or on how to place a cobbler on the breadboard then click here bellow

Breadboard

I2C Tools

To install the I2CTools you use the following command:

sudo apt-get install i2c-tools

You need to enable the i2c bus in the Raspberry PI settings, which you can do in the Raspberry Pi user interface.


Wiring up the board:

First we solder the header pins into the brake-out board if needed. It was possible on mine to either solder the pins on front or back.

I wired the OUT pin and the 2nd GND pin (the one side by the out pin) to digital multimeter set to measure voltage.

Once the board has been soldered with header pins or wires then we are ready to wire up the sensor which we do as follows:

MCP4725
Raspberry PI cobbler
VCC 3.3 V
GND (the GND pin side by the VCC pin) GND
SCL SCL (Physical pin 5)
SDA SDA (Physical pin 3)
OUT SDA (Physical pin 3)
GND (the GND pin side by the OUT pin) SDA (Physical pin 3)
OUT To digital multimeter
GND (the GND pin side by the OUT pin) To digital multimeter
Raspberry Pi pin layout

If you need more information about the GPIO headers on Raspberry Pi or other boards then click bellow.

Raspberry Pi Pin guideOrange Pi One Pin guideOrange Pi Pin guide for most H3 modelsOrange Pi Zero 3 Pin  guideOrange Pi 5 Plus Pin guideRock 64 Pin guide

Sanity tests in console:

After you have connected everything and made sure that wiringPI, i2ctools are installed that I2C is enabled in the Raspberry PI settings, then we are ready to do sanity tests in console, or you can run the I2C example project that comes with the I2C Plugin.

If doing it in console then you would issue command like this:

sudo i2cdetect -y 1

This should show our device at 0x40. Or if you use the example project that comes with the I2C plugin then you click Get adapters and then select the adapter and then click Scan the selected adapter this should get you 96, which converted to Hex is 0x60, same as the i2cdetect returns.  (This address will be different of course if you changed the address of the sensor by soldering the pads).

The example project that comes with the I2C Plugin, which can help you scan for the device address. It returned 96 for me which is 0x60 in hex.

If you can see your converter chip on address 0x60 (or 96 dec) or any other address which your version might be on then we are ready to look at the Xojo code.

The Xojo code:

Coding against this device was unusually simple but I still made small driver class around it, called MCP4725(see download
link at bottom).

I added property to the Window:

Private Property mDevice As MCP4725

The Opening event of the window makes the connection:

(Notice we set the I2C bus number and the address of the board there)

Sub Opening() Handles Opening
  try
    mDevice = new MCP4725(1, &h60)
    
    WriteValue(false)
  catch ex as I2CException
    MessageBox(ex.Message)
  end try
End Sub

Small utility method in the window:

Public Sub WriteValue(writeToEEPROM as Boolean)
  if mDevice = nil then
    return
  end if
  
  try
    mDevice.SetValue(Slider1.Value / (Slider1.MaximumValue * 1.0), writeToEEPROM) 
    
    if writeToEEPROM then
      MessageBox("Value has been stored")
    end if
  catch ex as I2CException
    MessageBox(ex.Message)
  end try
End Sub

The slider value changed:

Sub ValueChanged() Handles ValueChanged
  WriteValue(false)
End Sub

Code for the button to save to the EEPROM:

Sub Pressed() Handles Pressed
  WriteValue(true)
End Sub

The small driver class:

Protected Class MCP4725

Private mAdapter As I2C.Adapter

Constant, Name = REG_WRITE, Type = Double, Dynamic = False, Default = \"&h40", Scope = Private
EndConstant

Constant, Name = REG_WRITEEPROM, Type = Double, Dynamic = False, Default = \"&h60", Scope = Private
EndConstant

Sub Constructor(adapterNo as Integer, deviceId as UInt32)
  #If TargetARM And TargetLinux Then
    mAdapter = I2C.Adapter.Open(adapterNo)
    mAdapter.SetAddress(deviceId)

  #else
    #Pragma unused adapterNo
    #Pragma unused deviceId
  #Endif

End Sub

Sub SetValue(value as Single, writeEprom as Boolean)
  #If TargetARM And TargetLinux Then
    value = Max(Min(value, 1.0),0.0)

    // Board wants 12 bit value and 4095 is highest 12 bit value
    var intValue as UInt16 = value * 4095

    var mb as new MemoryBlock(2)

    mb.UInt8Value(0) = Bitwise.ShiftRight(intValue,4) and &hFF
    mb.UInt8Value(1) = Bitwise.ShiftLeft(intValue,4) and &hFF

    mAdapter.WriteWord(if(writeEprom,REG_WRITEEPROM, REG_WRITE), mb.UInt16Value(0))
  #endif
End Sub

Getting the code

You can find this example code at Example code for GPIO guides.

Running the code:

When running the code the voltage meter will show zero when slider slider is to far left, and it will go to 3.3 V when slider is to far right.

To test saving to the EEPROM then I selected a value on the slider and then pressed the button to save.  Then i turned off the Raspberry Pi and turned it back on and the voltage meter went right away to the value I had saved in the EEPROM, confirming that saving of default value had been successful.


I got this also to work on H3 based Orange Pi running Armbian.

To get things to work on H3 based Orange Pi I had to: