Problems Sequential reading channels ADC MCP3424 via I2C
-
Hello, I am Alexander and probing a lot with Rexygen, with good results until now. However, at this moment I am trying to read data with the Rexlang block (I2C communication) from an ADC (analog-digital converter) MCP3424, without succes. I am relatively new with respect to the Rexlang block and i2c. I know that I have to send a not-acknowledge (NAK) bit and a stop bit to exit the current read operation and send a new read command for the latest conversion data. However I don't know how to do that.
Hopefully somebody is willing to help me with my problem.
Many thanks in advance.Below my code:
/************************************************************ * * REXLANG - Reading data from MCP3424 AD converter via I2C * *************************************************************/ string parameter(0) i2c_dev; // the I2C bus is defined by the p0 parameter //assigning variables to outputs, these variables are WRITE-ONLY long output(0) channel1; // output of value of ADC channel 1 long output(1) channel2; // output of value of ADC channel 2 long output(2) channel3; // output of value of ADC channel 3 long output(3) channel4; // output of value of ADC channel 4 //declaration of variables long i2c_bufTx[3]; //buffer for transmitting data long i2c_bufRx[3]; //buffer for receiving data long i2c_bus_handle; long i2c_chip_address; long i2c_write_count; long i2c_read_count; long i2c_ret_fun; //the init procedure is executed once when the REXLANG function block initializes int init(void) { i2c_bus_handle = OpenI2C(i2c_dev); // open I2C bus /* Address: 1 1 0 1 A2 A1 A0 */ i2c_chip_address = 0x68; // 7-bit address of the I2C device return 0; } //the main procedure is executed once in each sampling period long main(void) { /* Configuration register: ===================================================================================== | bit 7 | bit 6-5 | bit 4 | bit 3-2 | bit 1-0 | ------------------------------------------------------------------------------------- | 1 = start conversion | 00 = channel 1 | 1 = continuous | 00 = 12-bit | 00 = gain x1 | | 0 = no effect | 01 = channel 2 | 0 = one-shot | 01 = 14-bit | 01 = gain x2 | | | 10 = channel 3 | | 10 = 16-bit | 10 = gain x4 | | | 11 = channel 4 | | 11 = 18-bit | 11 = gain 8x | ===================================================================================== */ i2c_bufTx[0] = 0x90; // read channel 1, continuous, 12bit, gain 1 (see MCP3424 datasheet) i2c_write_count = 1; i2c_read_count = 2; //Sending data via I2C i2c_ret_fun = I2C(i2c_bus_handle, i2c_chip_address, i2c_bufTx, i2c_write_count, i2c_bufRx, i2c_read_count); channel1 = ((i2c_bufRx[0]<<8) + i2c_bufRx[1])/2; return 0; i2c_bufTx[0] = 0xB0; // read channel 2 continuous, 12bit, gain 1 (see MCP3424 datasheet) i2c_write_count = 1; i2c_read_count = 2; //Sending data via I2C i2c_ret_fun = I2C(i2c_bus_handle, i2c_chip_address, i2c_bufTx, i2c_write_count, i2c_bufRx, i2c_read_count); channel2 = ((i2c_bufRx[0]<<8) + i2c_bufRx[1])/2; return 0; } //the exit procedure is executed once when the task is correctly terminated // (system shutdown, downloading new control algorithm, etc.) long exit(void) { if(i2c_bus_handle>=0) Close(i2c_bus_handle); // close I2C bus return 0; } -
@AlexanderH Hi Alexander,
Great to see you experimenting with REXYGEN and getting good results so far! It’s nice that you started from the example library — that’s definitely the right approach. The
I2Cfunction in REXYGEN works a bit differently compared to Arduino or other low-level implementations. Since REXYGEN tasks usually don’t run with very short cycle times, a singleI2Ccall performs both write and read operations within one cycle. This command takes care of sending the message, waiting briefly, and then reading the response. That means you don’t need to manually handle the NAK or stop condition — the function itself takes care of it.I looked through your code and have a few notes that might help:
- I noticed that right after calculating
channel1, you have areturn 0;. Because of that, the code for channel2 never runs — I guess that’s just for debugging, but it’s worth pointing out. - In each REXYGEN cycle, you currently configure the converter for continuous read mode. This might not behave as you expect, and it’s probably unnecessary. Try switching to one-shot mode first and see what kind of values you get. Later, you can set continuous mode once, and then in your
main()you can just read the data by settingi2c_write_count = 0. That way, theI2Cfunction won’t send any configuration bytes, it will only read — according to the documentation, that should work. - You can use the
Trace()function to print out the value ofi2c_ret_funfor debugging. Keep in mind that you need to enable these messages in the system log:
Go to Target → Diagnostic messages, tick Information in Function block messages, and make sure Enable logging is checked in the Options tab of the block properties dialog. Only then you’ll see the messages in the System log. - And finally, double-check the I2C address of the MCP3424 — it’s configurable, so make sure it matches your hardware setup.
Hope this helps you move forward! Please let us know how it goes — it’s always interesting to see REXLANG + I2C projects in action.
Cheers,
Jan - I noticed that right after calculating
-
@Jan-Reitinger Dear Jan, Thanks for these valuable tips :-). I will start with it this weekend. Hopefully I will succeed. If not, I will let you know via this forum. I will keep you posted. Greetings, Alex