Go Down

Topic: [Solved] I2C reading more than 1 byte  (Read 1 time) previous topic - next topic

Rhydm

May 28, 2018, 10:40 pm Last Edit: May 30, 2018, 03:50 pm by Rhydm
Hello.

I'm pretty new to I2C and arduino in general. Mainly using guides, but I've not managed to find a solution this time.

I'm trying to read 2 bytes of data being sent via I2C. The master is a USB to I2C programmer - https://www.telos.info/p/hw/conniimm20/

Since the intended I2C slave is a OTP memory LED driver I'd like to use my arduino nano as a "dummy" to see all the data is being sent correctly before I ruin the LED driver.

The programmer is using an Intel HEX file as a source, example:

:0200E10001AA72 (01 AA are the 2 data bytes)
:0200E200ACA8C8 (AC A8 are data, : 02 00E2 00 ACA8 C8)
:0200E800001CFA
:0200EB000054BF
and many many more :)

My code - using a simple example for I2C slave but I only get the 1st byte to the serial monitor (01 or AC for example). The address and type in the HEX file is of no concern for me atm as I'd only like to see if the programmer sends all the rows and both bytes.

Code: [Select]
#include <Wire.h>

void setup() {
  Wire.begin(0x50);                // join i2c bus with address 0x50
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  //delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent() {

   
    byte c = Wire.read(); // receive byte as a character
    Serial.println(c, HEX);         // print the character

}



I'm on a pretty tight schedule atm so I've not been able to explore the Wire.h library and what it offers. Just searched google for a while but with no luck getting a straight forward answer. I hope I've described what I want well enough.

I'd appreciate any solutions or suggestions for my problem.

GolamMostafa

#1
May 29, 2018, 12:42 am Last Edit: May 29, 2018, 01:14 am by GolamMostafa
Try this:

byte dataArray[16];     //make global declaration
Code: [Select]
void receiveEvent(int howmnay); //howmany registers the number bytes received from Master
{
     for(int i=0; i<howmany; i++)
     {
          dataArray[i] = Wire.read();  
     }

     for (int i=0; i<howmany; i++)
     {
         Serial.print(dataArray[i]);   //check what you are receiving against an Intel-Hex frame
      }
      
      Serial.println();

}


OR

1. Use the 2nd field (02 after : = number of information byte in the Intel-Hex frame) as a variable (say, x). This figure could be from 00 to 20.

2.  Load x with the value of the 2nd field.

3.  now, repeat the above codes:

int x = 2nd field of Intel-Hex frame
byte dataArray[16];     //make global declaration
Code: [Select]
void receiveEvent();
{
     for(int i=0; i<x; i++)
     {
          dataArray[i] = Wire.read();  
     }

     for (int i=0; i<x; i++)
     {
         Serial.print(dataArray[i]);  
      }
      
      Serial.println();

}

Koepel

#2
May 29, 2018, 08:42 am Last Edit: May 29, 2018, 08:45 am by Koepel
Set the baudrate to 115200.
9600 is too slow for this.

Use the 'howMany' parameter or 'Wire.available()' to print all bytes.

Which led driver is it ?
Is it expensive ?
You can try to read and write normal registers of the led driver, and then try to write the OTP memory. Maybe you need 50 of them before you know how to do it. When they are cheap, perhaps that is affordable.

Some logic analyzer can analyze the I2C and show the data in hexadecimal notation. That can be helpful to check if the I2C communication is correct.

Rhydm

Try this:
I've tried your 1st solution and it works. Thank you very much.

Set the baudrate to 115200.
9600 is too slow for this.
That worsened the situation :) The LED driver is for a work related project and is the big brother of ELMOS E522.46 which can run more LEDs but it's still classified, sorry. Thanks for the suggestion, it might come in handy some other time :)

Koepel

That worsened the situation
When you change the baudrate in the sketch, you have to change the baudrate in the serial monitor of the Arduino IDE as well. If the 115200 baud made it worse, then there is something going on that I don't understand.

That led driver seems to run on 3.3V internally. In that case it uses a 3.3V I2C bus.
It seems to be a lot of low level electronics control. The datasheet explains it well, but it is still hard to understand. If you have any questions about I2C, I will be glad to answer them.

Rhydm

If you have any questions about I2C, I will be glad to answer them.
I'm having some problems with the Telos programator, as it's not sending the HEX files correctly... only if the addresses are in ascending order and only odd or even ones, not mixed :D But that issue is for them to handle/explain since it's supposed to be plug and play.

Now for testing purposes I've made some short 5-ish line HEX files with only even or odd addresses. Here's an example of an "odd" one:

:0200C10003FF3B
:0200C300ACFF90
:0200C50001AD8B
:0200C70003FF35
:0200C90003FF33


The message I get on serial monitor is as follows: 3FFACFF1AD3FF3FF
My question is; is this line how it's supposed to be or should I get lines with only 2 bytes written out each line (3FF then ACFF and so on for example).

Koepel

#6
May 29, 2018, 09:08 pm Last Edit: May 29, 2018, 09:17 pm by Koepel
The Serial.print() can do many things except a nice formatted output.
For example a hex value of "0x03" is printed as 3 with the HEX format.
You could try this:

Code: [Select]

for(int i=0; i<howmany; i++)
{
  int data = Wire.read();
  if( data < 0x10)
  {
    Serial.print( "0");    // add the extra zero in front.
  }
  Serial.print( data, HEX);
  Serail.print( ",");
}
Serial.println();


A new line is for a new package of data. That means the Master (the software on the computer or the hardware Master device) concatenates the data into a single package. That is very specific behaviour. Is there a setting for that which can be turned off ?

To be sure, you could write the 'howMany' to the Serial port as well.
Code: [Select]

void receiveEvent(int howMany);
{
  Serial.print( howMany, DEC);
  Serial.print( ":");
  ...


It is possible to make the receiveEvent() function shorter and faster by printing the data in the loop() with a buffer between the receiveEven() and the loop().
It is even possible to omit that buffer by using the empty receiveEvent() trick.

Rhydm

Is there a setting for that which can be turned off ?
 
Thanks for the extra suggestions. Will try it out tomorrow.

About the settings... the "user interface" offers extremely limited settings, fml. It does have a "script" option where I could write some C# code. Which I've never used before so I was kinda hoping the "graphical" master option would work. And from what I've glanced from some samples they are also set up to concentrate data - only have the option to set an I2C address and data so I'd basically have to start from scratch, making it read the hex file and sending it.

GolamMostafa

The message I get on serial monitor is as follows: 3FFACFF1AD3FF3FF
My question is; is this line how it's supposed to be or should I get lines with only 2 bytes written out each line (3FF then ACFF and so on for example).
It depends on how you have decided to interpret the information contained in an Intel-Hex frame. If you think that every frame is conveying separate information, then it is preferable (mind that Serial Monitor suppresses the leading 0)  to present them in separate lines like:

Code: [Select]
03FF from this frame : 02 00C1 00 03FF 3B (START, #infoBytes, address, EOF, info, CHKSUM)
ACFF           "            :02 00C3 00 ACFF 90
01AD          "             :02 00C5 00 01AD 8B
03FF           "             :02 00C7 00 03FF 35
03FF           "              :02 00C9 00 03FF 33


 

Rhydm

It depends on how you have decided to interpret the information contained in an Intel-Hex frame. If you think that every frame is conveying separate information, then it is preferable (mind that Serial Monitor suppresses the leading 0)  to present them in separate lines like:
 
Every frame should convey separate data, but the programmer's user interface apparently bundled them up. Thanks for your input tho :)

Go Up