I2C protocol with arduino

i need communicate with 3 sensor using two data line. therefore i use I2C protocol. i try to did it, can you help me to do it.

#include <Wire.h>
#define DAC_ADDRESS_1 0x60 // MCP4725 address for DAC1
#define DAC_ADDRESS_2 0x61 // MCP4725 address for DAC2
#define DAC_ADDRESS_3 0x62 // MCP4725 address for DAC3

void setup() {
  Wire.begin(); // initialize I2C bus
}

void loop() {
  // send values to DACs
  writeDAC(DAC_ADDRESS_1, 1023); // set DAC1 to maximum value (1023)
  writeDAC(DAC_ADDRESS_2, 512); // set DAC2 to half of maximum value
  writeDAC(DAC_ADDRESS_3, 0); // set DAC3 to minimum value (0)

  delay(1000); // wait for 1 second before changing values
}

void writeDAC(byte address, int value) {
  byte msb = value >> 8; // get the most significant byte of the value
  byte lsb = value & 0xFF; // get the least significant byte of the value

  // write the value to the DAC
  Wire.beginTransmission(address);
  Wire.write(64); // send control byte
  Wire.write(msb); // send most significant byte of value
  Wire.write(lsb); // send least significant byte of value
  Wire.endTransmission();
}

How did you assign different addresses to the sensors?
Did you use the i2c_scanner example already?

1 Like

Hello pra_k

Take a view to get some additional information.

That Arduino footprint in your post seems a bit odd.

1 Like

All three DAC will have the same address. This is not allowed on the i2c bus. The only way they can have different addresses is if you buy the chips direct from the manufacturer. You would need to buy probably 10,000 units at least!

However, you can change the address by connecting the A0 pin to Vcc or GND. Unfortunately this will give you 2 different addresses and you need 3 different addresses.

There is a trick you can use to get around this problem. You can connect each of the 3 A0 pins of the DAC to 3 Arduino digital output pins.

Then, in your sketch, you can set the Arduino pins so that one DAC has a different address to the other 2 DACs. Then the Arduino can talk to that one DAC alone with no interference from the other 2 DACs.

The Arduino can select which DAC to talk to by changing the 3 output pins.

1 Like
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;
//LCD===================================================================
#include <LiquidCrystal_I2C.h>
// Set the LCD address to 0x27 or 0x3f for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x20, 16,2);
//=====================================================================


void setup(void) 
{
  Serial.begin(9600);

  lcd.init();
  lcd.backlight(); 
  analogReference(INTERNAL);
  ads.begin();
}
//======================================================================
void loop(void) 
{
  int16_t adc0, adc1, adc2, adc3;
  float Vadc0, Vadc1, Vadc2, Vadc3;
  
  adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);
  
  Vadc0 = (adc0 * 0.1875)/1000;
  Vadc1 = (adc1 * 0.1875)/1000;
  Vadc2 = (adc2 * 0.1875)/1000;
  Vadc3 = (adc3 * 0.1875)/1000;


  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(adc0);
  lcd.setCursor(8,0);
  lcd.print(adc1);
  lcd.setCursor(0,1);
  lcd.print(adc2);
  lcd.setCursor(8,1);
  lcd.print(adc3);
delay(100);
}

this is code in ADS1115, can i this adc, adc1, adc2 value use to as digital value
#include <Wire.h>
#define DAC_ADDRESS 0x60 // MCP4725 address for DAC 1, 2, 3

const byte dacAdrsPins[3] = {2, 3, 4}; //pins connected to the A0 pins of the DACs

void setup() {
  Wire.begin(); // initialize I2C bus
}

void loop() {
  // send values to DACs
  writeDAC(0, 1023); // set DAC1 to maximum value (1023)
  writeDAC(1, 512); // set DAC2 to half of maximum value
  writeDAC(2, 0); // set DAC3 to minimum value (0)

  delay(1000); // wait for 1 second before changing values
}

void writeDAC(byte dacNumber, int value) {

  for (byte d=0; d<3; d++)
    if (d==dacNumber) digitalWrite(dacAdrsPins[d], HIGH); else digitalWrite(dacAdrsPins[d], LOW);

  // write the value to the DAC
  Wire.beginTransmission(DAC_ADDRESS);
  Wire.write(64); // send control byte
  Wire.write(highByte(value)); // send most significant byte of value
  Wire.write(lowByte(value)); // send least significant byte of value
  Wire.endTransmission();
}
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;
//LCD===================================================================
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x20, 16,2);

#define DAC_ADDRESS 0x60 // MCP4725 address for DAC 1, 2, 3
const byte dacAdrsPins[3] = {2, 3, 4}; //pins connected to the A0 pins of the DACs

//=====================================================================



void setup() {
  Serial.begin(9600);
  Wire.begin(); // initialize I2C bus

  lcd.init();
  lcd.backlight(); 
  analogReference(INTERNAL);
  ads.begin();

}

void loop() {
  int16_t adc0, adc1, adc2;
  float Vadc0, Vadc1, Vadc2;
  
  adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);

  Vadc0 = (adc0 * 0.1875)/1000;
  Vadc1 = (adc1 * 0.1875)/1000;
  Vadc2 = (adc2 * 0.1875)/1000;

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(adc0);
  lcd.setCursor(8,0);
  lcd.print(adc1);
  lcd.setCursor(0,1);
  lcd.print(adc2);
  lcd.setCursor(8,1);

  // send values to DACs
  writeDAC(0, adc0); // set DAC1 to maximum value (1023)
  writeDAC(1, adc1); // set DAC2 to half of maximum value
  writeDAC(2, adc2); // set DAC3 to minimum value (0)

  delay(1000); // wait for 1 second before changing values
}

void writeDAC(byte address, int value) {

  for (byte d=2; d<5; d++)
    if (d==dacAdrsPins) digitalWrite(dacAdrsPins[d], HIGH); 
    else digitalWrite(dacAdrsPins[d], LOW);

  // write the value to the DAC
  Wire.beginTransmission(DAC_ADDRESS);
  Wire.write(64); // send control byte
  Wire.write(highByte(value)); // send most significant byte of value
  Wire.write(lowByte(value)); // send least significant byte of value
  Wire.endTransmission();

}


i did try this project with this code. it 2 DAC value changed with one pot, can you check it

This will not work correctly. The array does not have indexes 3 or 4. You are comparing a number to an array pointer, it will never be equal. Why did you change the code I suggested?

Also I forgot you have to set these pins as OUTPUT:

void setup() {
  Wire.begin(); // initialize I2C bus
  for (byte d=0; d<3; d++)
    pinMode(dacAdrsPins[d], OUTPUT);
}

Your schematic looks the same as before. I don't see the A0 pins connected to the arduino and I don't see any pot.

1 Like

Hello pra_k

Did you check the arrangement of the essential termination resistors for a proper I²C communication needed?
I can´t see any of these in your schematic.

1 Like

ok i will check

Maybe you will find this version easier to understand

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;
//LCD===================================================================
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x20, 16,2);

#define DAC_ADDRESS 0x61 // MCP4725 address for DAC 1, 2, 3
#define DAC1_ENABLE 2
#define DAC2_ENABLE 3
#define DAC3_ENABLE 4

//=====================================================================



void setup() {
  Serial.begin(9600);
  Wire.begin(); // initialize I2C bus

  lcd.init();
  lcd.backlight(); 
  analogReference(INTERNAL);
  ads.begin();

  pinMode(DAC1_ENABLE, OUTPUT);
  pinMode(DAC2_ENABLE, OUTPUT);
  pinMode(DAC3_ENABLE, OUTPUT);

}

void loop() {
  int16_t adc0, adc1, adc2;
  float Vadc0, Vadc1, Vadc2;
  
  adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);

  Vadc0 = (adc0 * 0.1875)/1000;
  Vadc1 = (adc1 * 0.1875)/1000;
  Vadc2 = (adc2 * 0.1875)/1000;

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(adc0);
  lcd.setCursor(8,0);
  lcd.print(adc1);
  lcd.setCursor(0,1);
  lcd.print(adc2);
  lcd.setCursor(8,1);

  // send values to DACs
  writeDAC(DAC1_ENABLE, adc0); // set DAC1 to maximum value (1023)
  writeDAC(DAC2_ENABLE, adc1); // set DAC2 to half of maximum value
  writeDAC(DAC3_ENABLE, adc2); // set DAC3 to minimum value (0)

  delay(1000); // wait for 1 second before changing values
}

void writeDAC(byte dacEnablePin, int value) {

  digitalWrite(dacEnablePin, HIGH);
  // write the value to the DAC
  Wire.beginTransmission(DAC_ADDRESS);
  Wire.write(64); // send control byte
  Wire.write(highByte(value)); // send most significant byte of value
  Wire.write(lowByte(value)); // send least significant byte of value
  Wire.endTransmission();
  digitalWrite(dacEnablePin, LOW);

}

Should DACX_ENABLE pins be at LOWs in the setup() function?

Yes, they will default to LOW.

1 Like

Are they automatically LOW or should the digitalWrite(DPin, LOW) function be executed?

This can definitely make a diffrerence...

From https://learn.sparkfun.com/tutorials/mcp4725-digital-to-analog-converter-hookup-guide/all:

" If you're going to have more than one MCP4725 on a bus, you'll also want to disable the pull-up resistors on all but one breakout. To make this easier, we've added another jumper on the back of the board. The pull-ups are enabled by default. If you need to disable them, you'll need to cut the traces on the jumper pad with an Xacto knife. If you ever need to re-enable the pull-ups, simply solder the three pads back together"

I don´t know if this is the model of MCP4725 that OP has...

2 Likes

Yes

1 Like

THANK YOU! this code is ok. but DAC 1 and 3 work, constant 2.5 v as output value provide only second DAC chip it not change with POT, can you check it problem is code or my circuit

I cannot see any problem with the code or schematic that would cause 2 outputs to work but not 3.

What values do you see on LCD? Do they change as expected when pots are adjusted?