REXYGEN Community Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Login

    Solved I2C EZO component

    Communication (RS232, RS485, I2C, SPI, UDP, TCP, ...)
    4
    20
    2.1k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • B
      belgacom
      last edited by

      HI Everybody,

      I'm new with Rexygen, but I'm really surprise with the amount of possibilities, it's really amazing.
      I have already done some I/O simulation, and everything works perfectly.

      My project with Rexagen would be to integrate Ph / ORP /etc probes into my swimming pole management.
      To do that I'll add EZO I2C components ( https://www.whiteboxes.ch/shop/ezo-ph-circuit/) on the GPIO of my raspberry.
      I'm not familiar on how I can manage I2C data with rexygen.

      Is someone can guide on how to proceed ?

      Arnaud

      1 Reply Last reply Reply Quote 0
      • S
        Scoobsalamander
        last edited by

        There are a few I2C examples in Rexygen studio.

        1 Reply Last reply Reply Quote 0
        • R
          reitinge
          last edited by reitinge

          Hi Arnaud,
          you can use the Rexlang block for I2C communication. As Scoobsalamander has mentioned, there are some I2C examples that can be used as a starting point of your own implementation. Use the Start from an Example Project choice in the Rexygen Studio menu and search 0502 Generic I2C Communication. Description of examples can be found at https://www.rexygen.com/example-projects/0502_Generic_I2C_Communication/0502_Generic_I2C_Communication.html.
          Documentation for Rexlang block is here: https://www.rexygen.com/doc/ENGLISH/MANUALS/BRef/REXLANG.html.
          Best regards,
          Jan

          B 1 Reply Last reply Reply Quote 0
          • B
            belgacom @reitinge
            last edited by

            @reitinge Hello thank you for your time

            I appreciate . I'll have a look at these example.
            Thx again.

            Arnaud

            1 Reply Last reply Reply Quote 0
            • B
              belgacom
              last edited by

              Hello again everybody.

              I just received my I2c components, and I'm really lost to understand how adapt the i2c example for my hardware.
              I have understand the line of the rexlang MCP3422 ADC, with i2c handle, adress, ect. But I I don't understand the communication itself.

              I have as example for my hardware :

              4.jpg 3.jpg 2.jpg 1.jpg

              With these information I don't understand how I need to adapt the rexlang function made for MCP3422 to match the EZO read/write.

              If I understand well, I would say that :

              Start is : Open I2C;
              I2C adress: is 0x63;
              after I don't know how to code the Read or Write function.
              In the example of MCP3422, the variable are 2 array [3] for bufTx and bufRx;
              and we put 0x88 ( I understand why with the explanation) in the bufTx[0]
              and there is a write count of 1 and read of 2.
              I think it's this part that I need to adapt ?

              And stop is close I2C.

              Does anyone can help me to understand how to modify the code of an I2C example to match my hardware.
              It would be a nice Christmas present for me 😉

              Thanks.

              Arnaud.

              1 Reply Last reply Reply Quote 0
              • R
                reitinge
                last edited by reitinge

                Hi Arnaud,
                it's always a little bit tricky to get communication done without testing and remotely, but I'll do my best.

                At beginning, it is handy to enable Information messages from Rexygen block in the system log:

                1. Open RexDraw and connect to your Target device (in the menu Target -> Connect or F7 key).
                2. Click on Target menu again and select Configure System Log.
                3. Check the Function block messages -> Information box (as marked on attached figure) and hit the OK button.
                  55921c75-19ac-40f6-84e8-c733dd528a1c-image.png

                For I2C communication you should:

                1. Firstly, you should open communication channel on specific bus. This is done only once in the init() method in Rexlang with command i2c_bus_handle = OpenI2C(deviceName);, where deviceName is name of the bus you want to communicate on. For example /dev/i2c-1:
                  i2c_bus_handle = OpenI2C("/dev/i2c-1");
                  Please check, if communication was established successfuly. You can do that with the Trace() command:
                  Trace(traceID,value);
                  For example:
                  Trace(1,i2c_bus_handle);
                  If you run your script, you should see in the Log something like this:
                  a719830f-3a01-42c6-a6a1-077d36422833-image.png
                  The 0001 value is the traceID and 1 (0x1) is value of i2c_bus_handle. If i2c_bus_value is negative, something went wrong.

                2. Next step is setting address of your device (0x63 for you). This step is done only once too in the init() method: i2c_chip_address = 0x63;

                3. You have to prepare data which you want to send. Use the i2c_bufTx array variable which is prepared in the MCP3422 example. For example on this image
                  ad6c2c12-0275-4551-a838-b771f624625d-image.png
                  you should set following values to i2c_bufTx array: i2c_bufTx[0] = 1; i2c_bufTx[1] = 57; i2c_bufTx[2] = 46; i2c_bufTx[3] = 53; i2c_bufTx[4] = 54; i2c_bufTx[5] = 48; i2c_bufTx[6] = 0;
                  Be aware, in the Example the array has length only 3 bytes and you need 7 bytes. So enlarge the array in Declaration variables section.

                4. Use the I2C() method. This method will send and receive data in one step. You can modify the main() method of MCP3422 example as follow:

                i2c_bufTx[0] = 1;
                i2c_bufTx[1] = 57;
                i2c_bufTx[2] = 46;
                i2c_bufTx[3] = 53;
                i2c_bufTx[4] = 54;
                i2c_bufTx[5] = 48;
                i2c_bufTx[6] = 0;
                
                i2c_write_count = 7; // you are sending 7 bytes
                i2c_read_count = 5; // you are expecting receive 5 bytes long (you probably need to modify it!!!)
                //Sending data via I2C
                i2c_ret_fun = I2C(i2c_bus_handle, i2c_chip_address, i2c_bufTx, i2c_write_count, i2c_bufRx, i2c_read_count);
                

                The answer of your device should be stored in the i2c_bufRx array now. Make sure you read the correct number of bytes and have a long enough array.

                Try some easy write/read command first and let me know, if it works!

                Cheers,
                Jan

                B 1 Reply Last reply Reply Quote 0
                • B
                  belgacom @reitinge
                  last edited by

                  @reitinge

                  Hello again thx for your time.

                  When I try to add trace function, I have an error in the during compiling : function 'trace' is not declared ?
                  The example that you attach in your response, is when you request data from device. ( so we read data )

                  But if I want to write I have this data :

                  send.jpg

                  So Do I have to generate an array of 5 and send Start, I2c address, write, "the wanted function", stop ?
                  And easy test for me is to make a led blinking on the EZo chip :

                  find.jpg

                  If I understand their example, I need to WRITE find in the EZO and there is no returns values because it's making a led blinking.
                  The example with ascii code return, is when I do a reading of the probe for example.
                  My question is if I write Find, Do I have to send ( write; find ) And I alerady have the start, with open I2c and adresse, and stop or do I have to send all data ?

                  Hope I'm enough clear ?

                  Arnaud.

                  R 1 Reply Last reply Reply Quote 0
                  • R
                    reitinge
                    last edited by reitinge

                    Trace() function has capital T. Find Rexlang documentation for details (https://www.rexygen.com/doc/ENGLISH/MANUALS/BRef/REXLANG.html#x270-26900015).

                    The start and stop of each message is generated automatically with the I2C command. In main() method, you should need to specify only i2c_bufTx array and number of bytes from this array, which will be send. You can try following for Find example:

                    i2c_bufTx[0] = 70;   //F
                    i2c_bufTx[1] = 105;  //i
                    i2c_bufTx[2] = 110;  //n
                    i2c_bufTx[3] = 64;   //d
                    i2c_write_count = 4; 
                    i2c_read_count = 0; //nothing to read
                    //Sending data via I2C
                    i2c_ret_fun = I2C(i2c_bus_handle, i2c_chip_address, i2c_bufTx, i2c_write_count, i2c_bufRx, i2c_read_count);
                    

                    The init () method does not change, nor does the exit() method.

                    1 Reply Last reply Reply Quote 0
                    • R
                      reitinge @belgacom
                      last edited by

                      @belgacom I'm sorry, decadic ASCII value for "d" is 100, not 64.

                      i2c_bufTx[3] =100;   //d
                      
                      B 1 Reply Last reply Reply Quote 0
                      • B
                        belgacom @reitinge
                        last edited by

                        @reitinge

                        I do have a negative result with the trace function .

                        here is a print screen of the log and the current BF code :

                        trace .jpg

                        What could be the error to have the trace at -106.

                        Arnaud

                        1 Reply Last reply Reply Quote 0
                        • R
                          reitinge
                          last edited by

                          Error -106 means Invalid parameter. Error codes are documented here: https://www.rexygen.com/doc/ENGLISH/MANUALS/BRef/BRef_ENGap3.html

                          • Please, delete the space between Trace and (.
                          • Check value of the parameter p0 in the Rexlang block (attached figure). 24b4564a-93f8-4b58-8b55-551866ceadce-image.png
                            This is the value which is set into the variable i2c_dev. In my case, it is the bus /dev/i2c-1. This depends on your wiring.
                          • Are you sure, you are running the Rexygen program on your Raspberry? The Error: REXLANG open this file type is not possible on this platform indicate, that you might run on your local PC and there is no I2C bus.

                          Cheers,
                          Jan

                          B 1 Reply Last reply Reply Quote 0
                          • B
                            belgacom @reitinge
                            last edited by

                            @reitinge

                            Hello, Happy new year. Thanks for your help and sorry for the time lost for my com issue. I was targeting Localhost and not my Pi. Except the fact that command need to be send in Hex and not in Dec, your code works find.

                            I'm able to send command and read values back.
                            Thanks a lot.

                            I still have a couple of question for you :

                            1. now I have the reading of my probe in bufRx [1] to [5] in DEC. and I need to convert it in ASCII. (51 46 56 57 54 = 3.896 )
                              Is there a function for that, in Rexlang or another FB to use ?

                            2. Between a write and a read, I have for example 900ms to wait . So currently I have done 2 Rexlang, 1 to write, 1 to read.
                              And I use a timer between both FB. Is there a way to do it directly in Rexlang, or do I have to continue to use 2 block ?
                              I didn't find answer in the doc.

                            Have a good day.

                            Arnaud.

                            R 1 Reply Last reply Reply Quote 0
                            • R
                              reitinge @belgacom
                              last edited by reitinge

                              @belgacom
                              Happy new year to you too. You are welcome. I'm sorry for decadic <-> hexadecimal converting trouble. I usually send values as a hex, but I thought the decimal values would work as well.

                              1. For converting DEC/HEX values into string, you can use something like this:
                                  int i;    
                                  char message[5];    
                                  /*bufRx[1] = 51;    
                                  bufRx[2] = 46;    
                                  bufRx[3] = 56;    
                                  bufRx[4] = 57;    
                                  bufRx[5] = 54;*/    
                                  for (i=1; i<6; i++)    
                                	message[i-1] = bufRx[i];    
                                  Trace(1,message); 
                                
                              2. Yes, you can use one Rexlang block for reading / writing. The easiest way is to use some type of simple if-else or switch-case structure in the main() function. Rexlang provides functions as Sleep() or Suspend() (see documentation https://www.rexygen.com/doc/ENGLISH/MANUALS/BRef/REXLANG.html#x270-26900015) but I think the right way is to send a request and periodically checking if the answer received. You should change the period of your task where the Rexlang block is too. https://www.rexygen.com/doc/ENGLISH/MANUALS/BRef/EXEC.html The Rexlang block source code (and all others blocks in the task) are executed only once per period time.

                              Best regards,
                              Jan

                              B 1 Reply Last reply Reply Quote 0
                              • B
                                belgacom @reitinge
                                last edited by

                                @reitinge

                                Hello, Happy new year. Hope you are going .
                                I tried to use trace with you code up here, but even if the block is returning the correct value of my Ezo components,
                                I have an 508 error.

                                errore 508 .jpg
                                therefore no trace is seen in the log . any idea why 508 error ?

                                Anyway even if I hand write 5 values into message[5], how after do I see it on the HMI page.
                                If I use a declaration of output like :

                                long output(x) message; or string output(x) I can't manage to see values in message.
                                How do I proceed ?

                                thx

                                Arnaud

                                1 Reply Last reply Reply Quote 0
                                • R
                                  reitinge
                                  last edited by

                                  Hi Arnaud,
                                  thanks, I hope you are fine too. Can you post here your actual code from Rexlang, please? When an error occurs, code execution stops, so the outputs may not be updated. We will try to find and fix the Numeric range check error.

                                  Cheers,
                                  Jan

                                  B 1 Reply Last reply Reply Quote 0
                                  • B
                                    belgacom @reitinge
                                    last edited by belgacom

                                    @reitinge

                                    Hi.

                                    I had time to dig a littl bit, and I find solution to do the write and read in 1 rexlang.
                                    After that no more issue with alarm and I'm able to trace " message"

                                    It works fine.
                                    But still I don't understand how to display the value of "message" in the HMI designer.

                                    trace.jpg

                                    I tried with standard display and string display.
                                    I would like also to trend the ASCII value ( 3.xxxx)
                                    Can you give me a hand on this ?

                                    Thx.

                                    Arnaud.

                                    my code :

                                    /[5]*************************************
                                    *

                                    • REXLANG - Reading data from MCP3422 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) adc_value;
                                    long output(1) adc_value1;
                                    long output(2) adc_value2;
                                    long output(3) adc_value3;
                                    long output(4) adc_value4;
                                    long output(5) adc_value5;
                                    long output(6) adc_value6;
                                    long output(7) message;
                                    string output(8) message;

                                    //declaration of variables
                                    long i2c_bufTx[4]; //buffer for transmitting data
                                    long i2c_bufRx[7]; //buffer for receiving data
                                    long i2c_bus_handle;
                                    long i2c_chip_address;
                                    long i2c_write_count;
                                    long i2c_read_count;
                                    long i2c_ret_fun;
                                    int i;
                                    char message[5];

                                    //the init procedure is executed once when the REXLANG function block initializes
                                    int init(void)
                                    {
                                    i2c_bus_handle = OpenI2C(i2c_dev); // open I2C bus
                                    Trace(1,i2c_bus_handle);

                                    i2c_chip_address = 0x63; // 7-bit address of the I2C device

                                    return 0;
                                    

                                    }

                                    //the main procedure is executed once in each sampling period
                                    long main(void)
                                    {
                                    //i2c_bufTx[0] = 0x46;
                                    //i2c_bufTx[1] = 0x69;
                                    //i2c_bufTx[2] = 0x6E;
                                    //i2c_bufTx[3] = 0x64;

                                    i2c_bufTx[0] = 0x52;

                                    // i2c_bufTx[0] = 0x53;
                                    //i2c_bufTx[1] = 0x6C;
                                    //i2c_bufTx[2] = 0x65;
                                    //i2c_bufTx[3] = 0x65;
                                    //i2c_bufTx[4] = 0x70;

                                    i2c_write_count = 1;
                                    i2c_read_count = 0;

                                    //Sending data via I2C
                                    i2c_ret_fun = I2C(i2c_bus_handle, i2c_chip_address, i2c_bufTx, i2c_write_count, i2c_bufRx, i2c_read_count);

                                    Suspend (3);
                                    i2c_write_count = 0;
                                    i2c_read_count = 7;

                                    i2c_ret_fun = I2C(i2c_bus_handle, i2c_chip_address, i2c_bufTx, i2c_write_count, i2c_bufRx, i2c_read_count);

                                    adc_value = (i2c_bufRx[0]);
                                    adc_value1 = (i2c_bufRx[1]);
                                    adc_value2 = (i2c_bufRx[2]);
                                    adc_value3 = (i2c_bufRx[3]);
                                    adc_value4 = (i2c_bufRx[4]);
                                    adc_value5 = (i2c_bufRx[5]);

                                    for (i=1; i<6; i++)
                                    message[i-1] = i2c_bufRx[i];
                                    Trace(1,message);

                                    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;
                                    }

                                    B R 2 Replies Last reply Reply Quote 0
                                    • B
                                      belgacom @belgacom
                                      last edited by

                                      This post is deleted!
                                      1 Reply Last reply Reply Quote 0
                                      • R
                                        reitinge @belgacom
                                        last edited by reitinge

                                        @belgacom
                                        Hi Arnaud,
                                        congratulations to your first received message! 🙂

                                        Your problem with publishing message outside of Rexlang is due to the names of your variables. Output 7, 8 and variable message have the same name and this is a problem. Try something like this:

                                        • Rename outputs:
                                        double output(7) outMessageDouble;
                                        string output(8) outMessageStr;
                                        
                                        • In the main() method, assign message variable value to output(8) and you can also convert the string value into double and assign it into output(7):
                                        outMessageStr = message;
                                        outMessageDouble = str2double(message);
                                        

                                        Please resize message variable length from 5 to 6. In the Rexlang, the last char array index contains "end-of-string indicator". If you write something to the last index of the char array, you will have a memory leak problem.

                                        Cheers,
                                        Jan

                                        B 1 Reply Last reply Reply Quote 0
                                        • B
                                          belgacom @reitinge
                                          last edited by

                                          @reitinge

                                          Everything works fine !
                                          Thank you.

                                          R 1 Reply Last reply Reply Quote 0
                                          • R
                                            reitinge @belgacom
                                            last edited by

                                            @belgacom You are welcome 🙂

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            This is a community forum for REXYGEN users and fans. Detailed information can be found at REXYGEN homepage.

                                            There is also an outdated REXYGEN community forum.

                                            Powered by NodeBB.