Hi,
I have a MAX5812L I2C Dac converter and I'm trying to use it with an arduino Leonardo. Here is my simple program:
#include <Wire.h>
int i = 0;
void setup(void) {
Serial.begin(115200);
while(!Serial);
Serial.println("Hello!");
Wire.begin();
}
void loop(void) {
int output = pow(2, i++) + 1;
if(i > 12)
i = 0;
Serial.print("output: ");
Serial.println(output);
Wire.beginTransmission(0x10);
// début de la transmission au périphérique d'adresse #16 (0x10)
Wire.write(output );
// envoi d'un octet val
byte error = Wire.endTransmission();
Serial.print("error: ");
Serial.println(error);
delay(1000);
}
Here are my outputs:
error: 3
error: 3
error: 3
error: 3
error: 3
error: 3
error: 3
error: 3
error: 3
error: 3
error: 0
error: 3
As you can see, The 2048th value is sent without error, but why ? Do you have any idea ?
There is communication between Leonardo and my device because this is not the error 2 (bad address), so I guess the way I send data is wrong but how can I do ?
Thanks
It is the good outputs, I've just hide then for this forum because this is not essential.
Here are the error code significations from Wire library:
0: success.
1: data too long to fit in transmit buffer.
2: received NACK on transmit of address.
3: received NACK on transmit of data.
4: other error.
5: timeout
So, almost value failed to transmit except the penultimate which is sent successfully.
Sended values are :
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096
dac_test.pdf (943,6 Ko)
More strange, I made a similar program to send values between 0 and 4096 that return me 0 when failed and 1 when success (linked the file). There is a pattern of 20 failed for 12 success at the begginning and then 16 failed for 16 success.
I'm using the Adafruit_MCP4725 library for this exemple, I think this is not optimised for my DAC but I don't know how to adapt it so It's working perfectly.
Here is my program;
#include <Wire.h>
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
void setup(void) {
Serial.begin(115200);
while(!Serial);
Serial.println("Hello!");
// For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
// For MCP4725A0 the address is 0x60 or 0x61
// For MCP4725A2 the address is 0x64 or 0x65
dac.begin(0x10);
Serial.println("Generating a sine wave");
}
void loop(void) {
uint16_t i;
for (i = 0; i < 4096; i++)
{
Serial.print(dac.setVoltage(i, false));
Serial.print(";");
}
Serial.print("\n\nEND\n\n");
}
Bad idea! We decide what is essential and what not. If you just hide information without even telling us we just waste our time trying to help you.
I don't believe that, not with above code! That code would produce values 1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 1025, 2049, 4097 and sent the values 1, 2, 3, 5, 9, 17, 33, 65, 129, 1, 1, 1, 1.
Maybe the pow() function did a calculation error and produced a valid command byte because I would expect the chip to return NAK if the command byte is invalid.
So, as you can see, this is not a beautiful triangle signal because there is many missing values...
Do you have any ideas why the unpair values aren't sent ?
#include <Wire.h>
uint16_t output4096 = 0;
byte error;
bool isGoingUp4096 = true;
void setup() {
Serial.begin(115200);
while(!Serial);
Serial.println("Hello!");
Wire.begin();
Wire.beginTransmission(0x10);
Wire.write(0x40); //Power up device
error = Wire.endTransmission();
Serial.print("error begin: ");
Serial.println(error);
}
void loop() {
if(isGoingUp4096){
output4096 += 1;
}else{
output4096 -= 1;
}
if(output4096 >= 4096){
isGoingUp4096 = false;
output4096 = 4096;
}else if(output4096 <= 0){
isGoingUp4096 = true;
output4096 = 0;
}
// début de la transmission au périphérique d'adresse #16 (0x10)
Wire.beginTransmission(0x10);
Wire.write(0xC0 + highByte(output4096)); //upper 8-bit data for DAC
Wire.write(lowByte(output4096)); //lower 8-bit data for DAC
error = Wire.endTransmission();
Serial.print("error on: ");
Serial.print(output4096);
Serial.print(";error: ");
Serial.println(error);
}
And a quick look at the output:
Hello!
error begin: 0
error on: 1;error: 3
error on: 2;error: 0
error on: 3;error: 3
error on: 4;error: 0
error on: 5;error: 3
error on: 6;error: 0
error on: 7;error: 3
error on: 8;error: 0
error on: 9;error: 3
[...]
error on: 4087;error: 3
error on: 4088;error: 3
error on: 4089;error: 3
error on: 4090;error: 3
error on: 4091;error: 3
error on: 4092;error: 3
error on: 4093;error: 3
error on: 4094;error: 3
error on: 4095;error: 3
error on: 4096;error: 0
Please show a sketch in a readable way, between code tags in your post.
Show the results as well in your post (you can put them between code tags as well).
I see some improvements. You need a 100% working sketch, and you are now at 1%. That's how to look at it.
Your sketch has no delay in the loop(). It fills the I2C bus and continuously bothers the DAC. At least put a delay at the end of the loop().
Thanks for your answer !
I've updated my post and will try now your advices and keep you in touch EDIT
I've put a delay of 5, 10 and 50 ms but it's the same result, many values aren't sent...
Keep in mind that the DAC chip could be broken. Or the voltage of the Leonardo is too low. Or you have a breadboard with bad contacts. Or the 'ADD' pin is floating. Or you have SDA next to SCL in a cable. Or the wrong pullup resistors. Or one of the other basic problems. Could you show a photo with the wiring ?
Normally 2 data bytes are written and 2 data bytes are read. For a simple command, a single data byte is okay, so your single byte of 0x40 is okay for power up.
Let's not rush forward, because something very basic is very wrong.
I suggest to try to get rid of the error code by sending the power up command over and over again, with a delay(). That is a valid command, so let's fix the I2C bus with that command.
Here is my schema, I'm making a custom card based on an Arduino Leonardo, I wasn't able to test it on a breadboard...
There is others part in the board, ACCELERO, which is using I2C aswell, with an address of 0X0E. I've test it in another program and it seems to work.
In the DAC group, the CAY16-103J4LF is a group of resistor of 10K ohm, do you think it could be the source of my problem ?
I think the wiring is good because I can detect it with an I2C scanner and communicate with it. But maybe there is an obvious error I can't see, this is my first board ever
You wrote that you have a "Leonardo" board to make it simple for us, but we like to know everything. There are problems with the I2C bus on your board.
Where are the 100nF decoupling capacitors ?
You have 10k resistors in the signal path of SDA and SCL to the DAC. You are basically giving up on the I2C bus.
The capacitors "C8", "C9" and "C10" have the GND at the top and the 5V at the bottom. Please don't make a schematic like that.
The KXTJ3-1057 is a 3.3V sensor chip. That means it has a 3.3V I2C bus. The ATmega32U4 is running at 5V and it has therefor a 5V I2C bus. You connect those two I2C buses. The noise margin has gone and you are operating beyond the specifications in the datasheet.
The only pullup resistors on the I2C bus are the 10k near the KXTJ3-1057 to 3.3V. That is not okay for the ATmega32U4. It needs at least 3.5V at SDA and SCL to see it as a valid high level.
Decoupling capacitors of 100nF should be everywhere. At the power and GND of every noisy chip.
Yes, a level shifter is a good solution. Adafruit often includes a level shifter on the module itself.
The level shifter has 10k pullup on every side, that could be enough pullup, or you may add a little more.