Go Down

Topic: Problem with reading bytes from an ADC (MAX11614) without register (Read 600 times) previous topic - next topic

Guoliang

Oct 16, 2019, 02:08 pm Last Edit: Oct 16, 2019, 02:19 pm by Guoliang Reason: add code tag
Hello guys,


I have some problems to read the output signal from an ADC (MAX11614) using Arduino I2C wire codes.

Setups:
Pull-up resistors (1k ohm) are used for both SDA and SCL pins. They are connected between the voltage source (5V) and SDA/SCL.
Both led driver and ADC are activated by a port expander.
ADC gets its input signal from a transimpedance amplifier which converts current to voltage.

Devices:
Arduino Nano (ATmega328P old bootloader), Arduino app version 1.8.9 (Windows PC)
Port expander (PCA9534) - Address 0x21
Led driver (SC620) - Address 0x70
ADC (Max11614) - Address 0x33

Current status:
I obtained the device addresses by using I2C scanner. And I am able to control the leds through led driver. But I am not able to get the correct output bytes from ADC. Currently, I obtained two bytes from ADC even without connecting anything to the transimpedance amplifier.

Questions:
1) What does the output means? The output data fluctuated a little bit from time to time. And it does not response to the signal change of my sensor.
2) Based on the component datasheet for ADC, it does not mention any output register to store the output value. I am not sure can I request the data from the device address directly.

Basically, I am expecting the result to be changed corresponding to the input current from my sensor.

Please see the screenshot for the serial monitor and the attached Arduino codes for your reference. Thanks.

Hi! Here is my code:
Code: [Select]

#include <Wire.h>

#define port_expander 0x21
#define led_driver    0x70
#define adc           0x33

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

  // set I/O pins
  Wire.beginTransmission(port_expander);// transmit to device #21 (port expander)
  Wire.write(0x03);                     // Set register pointer to the configuration register (0x03)
  Wire.write(0x00);                     // Set all ports of register 3 as output
  Wire.endTransmission();
}
void updateExts()
{
  Wire.beginTransmission(port_expander);// transmit to device #21 (port expander)
  Wire.write(0x01);                     // Set register pointer to the output port register (0x01)
  Wire.write(0x77);                     // Set all pins to its logic high level
  Wire.endTransmission();
}
void updateledds()
{
  Wire.beginTransmission(led_driver);   // transmit to device #70 (led driver)
  Wire.write(0x00);                     // Set register pointer to the led on/off register (0x00)
  Wire.write(0xc0);                     // Set pins 7 and 8 to its logic high level - led on: 0xc0
  Wire.write(0x09);                     // Set register pointer to the gain register
  Wire.write(0x0f);                     // Set gain register as '1111' - current step: 500 uA
  Wire.write(0x07);                     // Set register pointer to the dimming control register (led 7)
  Wire.write(0x28);                     // Set multiplier to 40
  Wire.write(0x08);                     // Set register pointer to the dimming control register (led 8)
  Wire.write(0x28);                     // Set multiplier to 40
  Wire.endTransmission();
  delay(1000);
  Wire.beginTransmission(led_driver);   // transmit to device #70 (led driver)
  Wire.write(0x00);                     // Set register pointer to the led on/off register (0x000)
  Wire.write(0x00);                     // Set pins to its logic low level 
  Wire.endTransmission();
}
void updateAdc()
{
  Wire.beginTransmission(adc);          // transmit to device #33 (ADC)
  Wire.write(0x88);                     // Sets setup byte
  Wire.write(0x0c);                     // Set configuration byte
  if (Wire.endTransmission () == 0)
    {
    Serial.println("Success");
    }
  else
    {
    Serial.println("failure ... maybe slave wasn't ready or not connected");
    }
}
void loop()
{
  updateExts();
  updateledds();
  updateAdc();

  Wire.beginTransmission(adc);
  Wire.write(0x88);
  Wire.endTransmission();
  Wire.beginTransmission(adc);
  Wire.requestFrom(adc,2);
  byte c = 0;
  while(Wire.available())
  {
    c = Wire.read();
    Serial.println(c);
  }
  Wire.endTransmission();
  delay(1000);
}





pylon

Quote
Pull-up resistors (1k ohm) are used for both SDA and SCL pins. They are connected between the voltage source (5V) and SDA/SCL.
1k is to weak, the must be 2k2 or better 3k3 to put the sink current below 3mA.

Quote
Both led driver and ADC are activated by a port expander.
What does that mean? I cannot find the wiring diagram in your post!

Code: [Select]
  Wire.write(0x77);                     // Set all pins to its logic high level

This is not true, it sets pins 0-2 and 4-6 to logic high, 3 and 7 are low.

The Wire.endTransmission() before the delay() call in the loop() isn't necessary and should be removed.

Why do you configure the chip for external clock? As you don't provide that clock in your code I guess that's a mistake.

Guoliang

Hello pylon,

Thank you for your reply. Attached is a simple illustration about the wiring diagram.
U1- Port expander
U2 - Analog switch
U3 - OPAMP
U4 - TIAMP
U5 - ADC
U6 - LED driver

There are some typos on my initial post:
1) the pull-up resistor is 10k ohm instead of 1k ohm.
2) the comment line for "Wire.write(0x77);" was wrong. Based on my design, I set pin 3 and 7 low.

I did not set the clock on my codes because I would like to use the default clock generated by Arduino Nano. That is why I set the CLK bit on the setup byte high on my ADC.

I tried to change the clock to internal clock. But the result is the same.

pylon

Quote
I did not set the clock on my codes because I would like to use the default clock generated by Arduino Nano. That is why I set the CLK bit on the setup byte high on my ADC.
The Nano doesn't produce such a clock signal by default. Of course the Nano produces the clock signal for the I2C bus (it's the master) but it doesn't produce a clock signal for the conversion. You shouldn't set that bit (except you have some other good reason to do so).
If you set that bit and use your posted code it won't show correct results.

Quote
U2 - Analog switch
Why do you use that switch to isolate the I2C bus from some chips?

BTW, long ago that I saw schematics that clear drawn by hand!

Guoliang

Thank you for the explanation on the clock signal. I think I was not completed clear about it previously. And I think internal clock might be sufficient for the conversion.

Regarding of the analog switch, it might be very useful to control multiple devices with the same slave address in the future. At the current stage, I think it is not so important.

ps: I am not the one who designed the circuit. But it will be very beneficial if I can use the circuit. So I did some reverse engineering tasks to figure out the schematic based on a given pcb.

pylon

Quote
Regarding of the analog switch, it might be very useful to control multiple devices with the same slave address in the future. At the current stage, I think it is not so important.
This is usually done by a I2C bus multiplexer (p.e. PCA9547).


Quote
Thank you for the explanation on the clock signal. I think I was not completed clear about it previously. And I think internal clock might be sufficient for the conversion.
Does it work with the internal clock?

Guoliang

Unfortunately, it did not work with the internal clock as well. The result is the same. Based on your recommendation and the datasheet, I made a few changes for the code:

1) Change the setup byte to internal clock
2) Change the clock for I2C bus to 300 kHz for Fast mode. As mentioned on the datasheet, the data can be clocked out from the ADC with up to 1.7 MHz.
3) Change the internal voltage reference from supply voltage to reference voltage. I think it will be easy for my hand calculation if I want to double check the output value.

I double checked the functionality of my photodiode using an OPAMP. It works perfectly fine.

I still think there is something wrong with my code.

Code: [Select]

#include <Wire.h>

#define port_expander 0x21
#define led_driver    0x70
#define adc           0x33

void setup()
{
  Wire.begin();                         // wake up I2C bus
  Serial.begin(9600);
  Wire.setClock(300000);

  // set I/O pins
  Wire.beginTransmission(port_expander);// transmit to device #21 (port expander)
  Wire.write(0x03);                     // Set register pointer to the configuration register (0x03)
  Wire.write(0x00);                     // Set all ports of register 3 as output
  Wire.endTransmission();
}
void updateExts()
{
  Wire.beginTransmission(port_expander);// transmit to device #21 (port expander)
  Wire.write(0x01);                     // Set register pointer to the output port register (0x01)
  Wire.write(0x77);                     // Set all pins to its logic high level
  Wire.endTransmission();
}
void updateledds()
{
  Wire.beginTransmission(led_driver);   // transmit to device #70 (led driver)
  Wire.write(0x00);                     // Set register pointer to the led on/off register (0x00)
  Wire.write(0x00);                     // Set pins 7 and 8 to its logic high level - led on: 0xc0
  Wire.write(0x09);                     // Set register pointer to the gain register
  Wire.write(0x0f);                     // Set gain register as '1111' - current step: 500 uA
  Wire.write(0x07);                     // Set register pointer to the dimming control register (led 7)
  Wire.write(0x28);                     // Set multiplier to 40
  Wire.write(0x08);                     // Set register pointer to the dimming control register (led 8)
  Wire.write(0x28);                     // Set multiplier to 40
  Wire.endTransmission();
  delay(1000);
  Wire.beginTransmission(led_driver);   // transmit to device #70 (led driver)
  Wire.write(0x00);                     // Set register pointer to the led on/off register (0x000)
  Wire.write(0x00);                     // Set pins to its logic low level 
  Wire.endTransmission();
}
void updateAdc()
{
  Wire.beginTransmission(adc);          // transmit to device #33 (ADC)
  Wire.write(0x80);                     // Sets setup byte
  Wire.write(0x0c);                     // Set configuration byte
  if (Wire.endTransmission () == 0)
    {
    Serial.println("Success");
    }
  else
    {
    Serial.println("failure ... maybe slave wasn't ready or not connected");
    }
}
void loop()
{
  updateExts();
  updateledds();
  updateAdc();

  Wire.beginTransmission(adc);
  Wire.write(0x80);
  Wire.endTransmission();
  Wire.requestFrom(adc,2);
  byte c = 0;
  while(Wire.available())
  {
    c = Wire.read();
    Serial.println(c);
  }
  delay(1000);
}

Guoliang

The code is working now..

I made two mistake:
1) For the reading part, I shall not call the setup byte again. It will reset the configuration byte. As a correction, I can just call the configuration byte instead.
2) I changed the bits for scan configuration from 00 to 10. I am not completed sure about the reason. But it does produce the correct result.

Here is the code for the ADC and read command:
Code: [Select]

void updateAdc()
{
  Wire.beginTransmission(adc);          // transmit to device #33 (ADC)
  Wire.write(0x80);                     // Sets setup byte
  Wire.write(0x4e);                     // Set configuration byte
  if (Wire.endTransmission () == 0)
    {
    Serial.println("Success");
    }
  else
    {
    Serial.println("failure ... maybe slave wasn't ready or not connected");
    }
}
void loop()
{
  updateExts();
  updateledds();
  updateAdc();

  Wire.beginTransmission(adc);
  Wire.write(0x4e);                     // Set configuration byte
  Wire.endTransmission();
  Wire.requestFrom(adc,2);
  byte c = 0;
  while(Wire.available())
  {
    c = Wire.read();
    Serial.println(c);
  }
  delay(1000);
}

Go Up