Pages

Wednesday 15 March 2017

Addressing multiple MCP4724s in the same Arduino project



So, you want to add a DAC to your Arduino project?  No?  Then what do you want?  Oh, you want to add three (or more) DACs to your Arduino project.  Well then, my friend, you're screwed.  We all know that you can only have two addresses: The address when the A0 pin is tied to ground and the address when it is tied to VCC. 

You could get a few more addresses by shopping at different places, as the addresses are set differently in some cases, but that's hassle, right?  Plus, you probably did what I did and just ordered as many as you needed from the same place and are now stuck with a maximum of two unique addresses.

The cheap-ass MCP4725s I got down eBay for about £0.95 a pop have the address 0x60 when the A0 pin is tied to ground and 0x61 when it's tied to VCC.  When I say "A0 pin", what I mean is the address solder pads.  If you spend a bit extra ($4.95) and buy from Adafruit, not only will the addresses be 0x62/0x63, but you will actually have an A0 pin to play with!  That alone may make it worth your while to treat yourself, as you will soon see.

So, how can I address 4 MCP4725s when they only have two unique addresses?  I turned to the data sheet to look for a solution to my addressing problem.  It says:

The address byte is the first byte received following the START condition from the master device. The first part of the address byte consists of a 4-bit device code which is set to 1100 for the MCP4725. The device code is followed by three address bits (A2, A1, A0) which are programmed as follows:
  • The choice of A2 and A1 bits are provided by the customer as part of the ordering process. These bits are then programmed (hard-wired) during manufacturing 
  •  The A2 and A1 are programmed to ‘00’ (default), if not requested by customer 
  •  A0 bit is determined by the logic state of A0 pin. The A0 pin can be tied to VDD or VSS, or can be actively driven by digital logic levels. The advantage of using the A0 pin is that the users can control the A0 bit on their application PCB circuit and also two identical MCP4725 devices can be used on the same bus line.
    When the device receives an address byte, it compares the logic state of the A0 pin with the A0 address bit received before responding with the acknowledge bit. The logic state of the A0 pin needs to be set prior to the interface communication. 
Well, first of all, no one asked me to provide the A2 and A1 bits as part of the ordering process.  I'll have to contact eBay about that.  Secondly, there's the answer!  We can change the state of A0 dynamically because the unit checks what its address should be every time it receives an I2C transmission.  Sweet!

What this means is that we can sacrifice one of the Arduino's digital output pins per ADC4725 and use it as a chip-select pin.  Sure, it means that we've turned the lovely two-wire I2C interface into some sort of grotesque Frankenstein three-wire interface, but at least you get to use your DACs and there's always I2C IO expanders if you run out of digital pins in your project, so quit your jibber jabber.

Onto the nitty gritty.  If, like me, you opted for the cheapskate option and are now wondering how to access the A0 pin, you need to break it out for yourself.  If you're squeamish, look away now, because what follows is not pretty.

The middle of the three ADDR solder pads (circled in yellow) must be connected to a new header pin

In my defence, my soldering iron is a piece of junk with a huge tip which is about to snap off but I can't find replacements and I've also got crappy big solder which doesn't seem to flow properly.  I wonder if any of these things is to do with being a cheapskate and always selecting what to buy based on price and price alone?  Nah, how could it?  Oh, and for good measure, I have to solder kneeling on the floor in front of a chest of drawers which I protect from being burnt with newspaper.  In this instance, I used pliers and elastic bands to hold things kind of steady while I worked.  No elastic bands were harmed in the making of this project.  Actually, one did get burnt, but not fatally.  I need a workshop!

I used a small strand of wire, which I separated out from a multi-stranded wire, to connect the middle ADDR solder pad to the seventh header pin, which I glued in place using epoxy.  The boards came with six-pin headers unsoldered and needed to be put together upon arrival.  I could have soldered a seven-pin header on, but in my excitement, I soldered the headers onto all boards as soon as they turned up and then couldn't be bothered to unsolder them.  I think that you'll agree that the glued-on look works, well, though.

Soldered in place and covered in UHU glue

Once you've seen how good a glued-on header pin can look, you'll never go back

The soldering took for absolutely ages because I kept shorting the solder pads together and having to desolder and start again.  Once done, I covered the thin strand of wire in UHU to protect it from oxidisation and to keep it in place.

That takes care of the hardware.  Now how do you drive these things?  Well luckily for you, I've taken care of the software changes.  I forked the Adafruit MCP4725 Arduino library.  You can find my version here: https://github.com/mitchyboy9/Adafruit_MCP4725

I won't bother explaining how to use the library because there is an example sketch that shows how to address multiple MCP4725s.

Here are two MCP4725s connected up for testing.  The resistor/capacitor combo in the background is another way of creating an analog output using a PWM signal

This shows how to wire the Frankenstein MCP4725s up to an Arduino Uno.  I2C, power &ground are as usual.  Choose any digital pins you like for addressing and configure them in software (2, 3 & 4 are just an example here)

Happy DACing.

18 comments:

  1. Could you explain more on how different digital logic levels change the state of AO?

    ReplyDelete
    Replies
    1. This question doesn't seem relevant to this post, as A0 isn't used at all. In a nutshell, though, when used as an input, the voltage sensed at A0 can be converted to an integer between 0 and 1023 using analogRead():
      https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/

      Delete
  2. Hello, I'd like to discuss with you more about the detials, could you leave a contact message for me

    ReplyDelete
    Replies
    1. If you have a specific question about this post, I would be happy to help. What is it?

      Delete
  3. Hi there, the explanation was amazing and straight forward, i'm using this chip actually to build an artificial hand, and i had some question about the possibility to use 40 pieces, (8 chips per finger), is there any possibility?

    ReplyDelete
    Replies
    1. Yeah, I don't see why you can't put 40 of these puppies into a project. It's just a matter of having enough I/O pins to be able to select them (i.e. you'll need 40 pins for addressing and 2 for I2C). If you're using the Arduino MEGA 2560, then you're good to go as it has 54 digital I/O pins. If not, you could use something like the MCP23017 I2C I/O expander, or a shift register such as 74HC595 to give you more pins. These additional pins will come at the cost of a slight delay in being able to address them i.e. switching between which one of your 40 MCP4724 to control.

      Another way would be to use an I2C multiplexer e.g. TCA9548A (which can control 8 same-address devices, so you would need 5 of them).

      I'll leave you to weigh up the pros and cons of each approach. If you find any other ways, let me know. Have fun!

      Delete
  4. This was hilarious, and very very helpful! I've been looking for ages to find a possibility to use multiple DACs in a arduino mega project (51 to be exact) and now Im possitive it might actually work!

    Thank you for this!

    ReplyDelete
    Replies
    1. Alex, I see here that they look a little bit different, do you think its possible to configure this in the same way you did?
      MCP4725:
      https://www.sparkfun.com/products/12918

      Delete
    2. I'm glad you enjoyed the post. Crikey! 51 DACs?! What's the project? Sounds fun. Good luck with it - I'm sure you'll get it working.

      Delete
    3. Those units from Sparkfun look fine. You will have to de-solder the blob connecting the ADDR pin to GND and then connect the ADDR pad to a header pin, like I have in this post. If I were you, though, and I was going to spend $4.95 per unit, I would get the ones from Adafruit (linked near the beginning of the post) because they're also $4.95 and you will save yourself a lot, lot, lot of time breaking out the ADDR pins of 51 of these guys!

      Delete
    4. I see! Ive been looking into those guys as well, but got the impression it wouldn't work :/ but thats a relief! So do i get this right, I could place 8 different DACs on one single bus with different addresses, only by connecting the A0 pin to a digital pin on the arduino? (And then use a multiplexer to get all the 51) Would they be able to read values all at the same time?
      Thank you for all your help!

      Delete
    5. There are a couple of ways of doing it. You either just use one I2C bus and select each DAC via the digital pin that you have connected to the DAC's ADDR pin. All of these pins will be LOW, except for the pin connected to the one DAC that you want to communicate with (I hadn't thought of it until now, because my project didn't require it, but you could also set as many pins as you like to HIGH to do a batch update on those DACs).
      Using an I2C multiplexer, like I mentioned in an earlier comment, is a different way of doing things. You wouldn't need to sacrifice any digital pins. All you would need to do is buy the multiplexers and connect your DACs to them. I haven't used one, because I didn't have one to hand and wanted to move my project forward so I came up with the workaround-solution in this blog post.

      Delete
    6. I just noticed the last part of your question: "Would they be able to read values all at the same time?". This makes me wonder if you have confused DAC with ADC. The MCP4725 is an output device. It doesn't read anything. You use it to set an analogue voltage. If you want to read an analogue voltage, you need an ADC.

      Delete
    7. Ok then I got everything right! Now I have some alternatives thanks to you. I realize my question was poorly written, Im going to use DACs and I really meant if the Arduino could send out digital values to the different DACs simultaneously, but i understand now that it will do it one by one (which is ok!)

      Delete
  5. Hi.
    just read this blog, very interesting it certainly throws a new direction in solving multiple dac addressing in my project.
    I want to generate a 3 phase sine wave using three MCP4725s. To over come the addressing problem I planned to multiplex the clock wire (scl).

    ReplyDelete
  6. Do you think I can use two of them on the bus and two with chip select like you did at the same time? sorry is may question looks stupid but I do not have mutch free digital pin. thanks in advance.

    ReplyDelete
  7. It is really necessary to add the A0 pin if I only need to use 2xDAC? Can I operate with 2xDAC just by using the 0x61 and 0x62 addresses without hardware modifications?

    ReplyDelete
    Replies
    1. If you only need two of these puppies, things are simpler for you. You can just hard-wire the A0 pin using the ADDR solder pad (circled in yellow in the first photo in this post) i.e. you don't need to break out the A0 pin.

      Delete