Electronic – arduino – MCP3424, how to read channels in parallel

adcarduinoi2c

About this question

I do not have an electronics engineering background, and this is one of my first challenges with communicating via I2C, and with writing to a register, so please do not assume too much knowledge from my side. I'm programming an Arduino.

When asking about a specific electronic component/chip, I assume people can not experiment/test to give me a correct answer. I also expect that people will not even know this component. Therefore I will try to add much information in this question.

Please let me know if you need more information.

The component has four ADCs

I am using the 4-channel component, MCP3424 (datasheet). It comes in two packages. I'm using the MCP3424 E/SL, 4 channel SOIC version, not the MCP3422 or MCP3423 2 channel version.

I believe it has four ADCs. On RS-Online, it seems like the E/SL version has 4 ADCs (direct link), while the E/ST has only one (direct link).
enter image description here

I assume this must mean, that it can do sampling on several channels simultaneously. I don't see any other reason to put more than one ADC on the component.

Am I right?

Communication via I2C

Communication happens by sending one config byte, then waiting for a sampling to end, and read the result.

Format of Config Byte

enter image description here

The interesting ones are:

  • bit three from left, counting from 1: Continous sampling
  • bit one and two from left, counting from 1: Address

More about the config byte can be found on the datasheet page 18, also depicted here.

Format of read result

My examples will only be with an 18 bit resolution (bit 5 and 6 set to 1). The read back result will be four bytes: the first three containing the value, and the fourth containing the config byte.

However, the leftmost bit, !RDY, tells if the value is "new", ie if it is a new reading, since the last reading. The first time reading one result, the value is 0, and for the subsequent ones it is 1, until the ADC is ready with a new sample value.

How to use it without sampling in parallel

I know perfectly well how to do this. And all examples I have found online, also simple du this. Just write a config byte to the component, then read a value back.

How to set each channel to sample automatically contiously, and read the channels in parallel

The pseudo code could be smth like

setup():
    start sampling channel 1, 18bit, 0gain, continuously
    start sampling channel 2, 18bit, 0gain, continuously
    start sampling channel 3, 18bit, 4gain, continuously
    start sampling channel 1, 18bit, 2gain, continuously

readADCs():
    // Run every 500ms
    // 18 bit samples take 375ms, so must happen in parallel 
    // to get a new sample for all every 500ms
    read channel 1
    read channel 2
    read channel 3
    read channel 4

My best attempt

So I hope, that the following sets each ADC to sample continously. This is Arduino code.

void setup() {

    Wire.write(0b00011100);
    Wire.write(0b01011100);
    Wire.write(0b10011110);
    Wire.write(0b11011101);
}

Then, how do I read a specific channel. If I just ask the component for the result, it will return the result of the channel on the register. With the setup above, I would get the reading for channel 4. But let's say I want the reading from channel 2. In some way I just need to tell it, that I want the result of channel 2. I don't want to ask it to sample anything, it should just keep doing a continous sampling, and I just want the most resent sample that it created while automatically sampling.

Below is my best guess

void readADCs() {

    // Channel 1
    // ...

    // Channel 2
    Wire.beginTransmission(104);
    Wire.write(0b01011100); // I hope not to affect, just to select
    Wire.endTransmission();
    Wire.requestFrom(104);
    Wire.read(); // val byte 1
    Wire.read(); // val byte 2
    Wire.read(); // val byte 3
    Wire.read(); // config byte
}

So my best guess is. If I want to read channel 2, I write a config byte which is exactly the same, as what I used for starting sampling channel 2.

However, this does not work. There is no sample ready, even if it has had more than the necessary 375ms.

How do I achieve this?

I have tried to do my best with describing the desired result and what I have tried, but I know it isn't easy to read.

Could you give me advice on how to let all ADCs sample in parallel, and then read from them, without interfering?

Best Answer

I have the latter with four ADCs. I assume this must mean, that it can do sampling on several channels simultaneously.

Unfortunately not. There is only one ADC and, to convert more than one channel, this has to be done sequentially by addressing the internal multiplexer thus "reading" another channel. No simultaneous sampling unfortunately: -

enter image description here

Note the input multiplexer selects ONLY one of four channels at any one time. This is quite a common method used to read multiple channels but there are simultaneous sampling ADCs out there. Try looking at Linear tech, TI's or ADI's portfolios.