How to properly send I2C data?

Hello,
I have a Nano writing to an Adafruit 7 segment display - using the Adafruit library
But I would like to understand what is going on in the I2C data-stream
So I collected some of the data-stream with a logic analyzer - with the hopes that I could learn how to duplicate the data-stream with nothing more than wire.h

0x70 is the address of the slave device.

A few samples of the data-stream look like this:

0x70, ack, 0x21
0x70, ack, 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x70, ack, 0x81
0x70, ack, 0xEF

Do I put Wire.beginTransmission(0x70) before every wire.write statement?
Or does this statement only have to be created one time only?

For the multiple data bytes - do I need to put 0x70 as the starting data-byte within every wire.write statement?

Do I need to put Wire.endTransmission(); after every wire.write statement?

Should I be adding any delay statements anywhere?

Sincere thanks!
dw

Wire.beginTransmission sets the address that you want to send the data to or receive from.
Wire.write places the actual data in a buffer to be send; you can write multiple times
Wire.endTransmission starts the actual transmission of address and data (in case of a write).

After Wire endTransmission, I think you need to setup the address again; I would definitely do it but the library might remember the last address.

All your questions are answered in the Adafruit library.

The I2C bus uses the I2C address with a Read/Write bit in the first byte.
Does your logic analyzer decode a I2C signal ? Then you should see if it was reading or writing.
Can you show a screendump ?

I have written a alternative explanation of the functions of the Wire library.

Perhaps there is a smaller library for the 7-segment displays. Which displays are they ? and which Adafruit libraries do you use ?

Thanks to both of you.

The Adafruit library that successfully sends data to the display is: Adafruit_LEDBackpack.h

The commands include:
matrix.begin(0x70); which is located within the Setup function

The other command statements are located in the main loop.
matrix.print(x); - where x is an integer from 0-9999
matrix.writeDisplay();

the
Here is a screen-shot from analyzer - and I can go back and take a signal screen show if you would like to see that.

Here is a screen shot of one 4 digit number to display

There is an obvious logic to the way the number for each digit is controled.
Here is the value of 1010
The system always sends out 17 bytes
From left to right:
Byte (2 of 17) contains the value for the first digit.
Byte (4 of 17) contains the value for the second digit
Byte (8 of 17) contains the value for the third digit
Byte (10 of 17) contains the value for the forth digit.
So I should be able to figure out how to do this with just the wire.h library.
write to 0x70 ack data: 0x00 0x06 0x00 0x3F 0x00 0x00 0x00 0x06 0x00 0x3F 0x00 0x00 0x00 0x00 0x00 0x00 0x00

The signal screen shot is not the same value as the 1010 that you see the hex numbers in the 17 bytes

Thanks for the pictures :smiley:
Can you set the logic analyzer to show the data as hexadecimal ?

The Adafruit LED_Backpack library is here: GitHub - adafruit/Adafruit_LED_Backpack: Adafruit LED Backpack Library for our 8x8 matrix and 7-segment LED backpacks. There are also examples, such as sevenseg.ino.
I don't see any delay() in the library.

The first number 0x21 is written here: Adafruit_LED_Backpack/Adafruit_LEDBackpack.cpp at master · adafruit/Adafruit_LED_Backpack · GitHub.

Let's assume that only data is written and that never data is read from the 7-segment display.

With my link to Github, do you have enough information to create that data with only the Wire library ?

The data is many Wire.write() between Wire.beginTransmission and Wire.endTransmission().
There can be maximum 32 Wire.write(). That is the buffer size in the Wire library for an Arduino Uno.

By the way, I am very fond of the LHT00SU1 logic analyzer in combination with sigrok/PulseView software.

Here is a screen shot of the value 1010 sent to the display.
I was not able to get all of the bytes - so a few are missing at the right hand side of the picture

Yes - here it is

#include <Wire.h>
#include "Adafruit_LEDBackpack.h"

Adafruit_7segment matrix = Adafruit_7segment();
int x;

void setup() {
   pinMode(LED_BUILTIN, OUTPUT);
  matrix.begin(0x70);
}

void loop() {
x = 1999;
while(x < 9000){
  matrix.print(x);
  matrix.writeDisplay();
  delay(1000);
  x = x + 11;
}

Here is some code that I tried - with just wire.h all by itself.
But the strange thing is - the analyzer never picked up any I2C signals from this code.
Its like its not running for some reason

void setup() {
  Wire.begin();
}


void loop() {
   

  Wire.beginTransmission(0x70);
  Wire.write(0x21);
  Wire.endTransmission();
  delay(50);

  Wire.beginTransmission(0x70);
  for(byte a = 0; a <= 16; a++){
    Wire.write(0x00);
  }
   
  Wire.endTransmission();
  delay(50);

  Wire.beginTransmission(0x70);
  Wire.write(0x81);
  Wire.endTransmission();
  delay(50);

  Wire.beginTransmission(0x70);
  Wire.write(0xEF);
  Wire.endTransmission();
  delay(50);

  Wire.beginTransmission(0x70);
  for(byte a = 0; a <= 8; a++){
   Wire.write(0x00);
  }
   Wire.write(0x3F);

   for(byte a = 0; a <= 6; a++){
    Wire.write(0x00);
    Serial.print("0x00");
   }

I see this in the Adafruit Led BackPack library

Wire.write((uint8_t)0x00)

I wonder if my code is missing the (uint8_t) ?

Part of the library includes this code - which I don’t understand.
It appears “displaybuffer” is an array variable - but I can’t see it called out anywhere as a variable.
And it also appears there is some bit shifting going on - and I don’t understand why it would need that

  for (uint8_t i = 0; i < 8; i++) {
    Wire.write(displaybuffer[i] & 0xFF);
    Wire.write(displaybuffer[i] >> 8);
  }

WAIT!
I just discovered this web-site
This fellow has already done this - and provided an example sketch

That seems to be nice and slimmed down code. There is not test in setup() if the display is connected to the I2C bus, you could add that.

I’ve taken the code example from that web-site and trimmed it down for my own needs.
There are some case statements that I’ve added - which I could truncate down a little more - and put into a for-loop.
But the code itself is pretty tiny - so I probably won’t bother.

What it is doing at this point - is displaying numbers from 9 - 9999
My final product will be to have the Arduino accept a value serially and display it.
Making the back-pack a Serial rather than I2C backpack.
It can then be driven by any micro-controller that can output Asynchronous Serial

I’m converting each number to display into its string form - in order to derive the number of digits.
Then parsing each digit back into its numeric form

/*  
 *  I2C HT16K33 driven 7 segment display sold by Adafruit
 *  This code can be easily ported to non-Arduino platforms which have their own I2C library.
 *  Instructions and framework provided by Dejan, www.HowToMechatronics.com  
 */

 //NUMERIC VALUES
 /*
0x3F 63 = 0 
0x06 6 =  1
0x5B 91 = 2 
0x4F 79 = 3 
0x66 102 = 4 
0x6D 109 = 5 
0x7D 125 = 6 
0x07 7 = 7 
0x7F 127 = 8 
0x6F 111 = 9 
*/


#include <Wire.h>

byte numvalue[10]= {63, 6, 91, 79, 102, 109, 125, 7, 127, 111};// values needed to form numbers 0-9 in 7-segement pattern.
String numberstring; // varible to convert displayed number into a string so that we can capture its lentgh
byte numstrlen; // variable to capture the string length
String tempstr;  // variable to store one digit value converted from string
byte temp; // variable to capture each digits converted string character value back to number
uint16_t displayBuffer[8]; // variable to send to the display via I2C
int mynum;// variable to hold the number we want to display
 
void setup() {
  Wire.begin();
  Serial.begin(9600);

  // Turn on displays oscillator
  Wire.beginTransmission(0x70);
  Wire.write(0x21); 
  Wire.endTransmission();

  //Set the displays brightness
  Wire.beginTransmission(0x70);
  Wire.write(0xE0);
  Wire.endTransmission();

  //Disable display blink mode
  Wire.beginTransmission(0x70);
  Wire.write(0x81);
  Wire.endTransmission();
}// end of setup



// ========================== MAIN =============================
 
void loop() {

for(mynum = 0; mynum <= 9999; mynum++){
  numberstring = String(mynum);
  numstrlen = numberstring.length();

switch (numstrlen) {
    case 0:    // No number to display
      displayBuffer[0] = 0;
      displayBuffer[1] = 0;
      displayBuffer[3] = 0;
      displayBuffer[4] = 0;
      show();
      break;
    case 1:    // 1 Digit to display
      displayBuffer[0] = 0;
      displayBuffer[1] = 0;
      displayBuffer[3] = 0;
      tempstr = numberstring[0];
      temp = tempstr.toInt();
      displayBuffer[4] = numvalue[temp];
      show();
      break;
    case 2:    // 2 digits to display
      displayBuffer[0] = 0;
      displayBuffer[1] = 0;
      tempstr = numberstring[0];
      temp = tempstr.toInt();
      displayBuffer[3] = numvalue[temp];
      tempstr = numberstring[1];
      temp = tempstr.toInt();
      displayBuffer[4] = numvalue[temp];
      show();
      break;
    case 3:    // 3 digits to display
      displayBuffer[0] = 0;
      tempstr = numberstring[0];
      temp = tempstr.toInt();
      displayBuffer[1] = numvalue[temp];
      tempstr = numberstring[1];
      temp = tempstr.toInt();
      displayBuffer[3] = numvalue[temp];
      tempstr = numberstring[2];
      temp = tempstr.toInt();     
      displayBuffer[4] = numvalue[temp];
      show();
      break;
    case 4:    // 4 digits to display
      tempstr = numberstring[0];
      temp = tempstr.toInt();
      displayBuffer[0] = numvalue[temp];
      tempstr = numberstring[1];
      temp = tempstr.toInt();
      displayBuffer[1] = numvalue[temp];
      tempstr = numberstring[2];
      temp = tempstr.toInt();     
      displayBuffer[3] = numvalue[temp];
      tempstr = numberstring[3];
      temp = tempstr.toInt();     
      displayBuffer[4] = numvalue[temp];
      show();
      break;
  }// end of switch case 
  delay(10000);
}// end of for-loop (numbers to display)
  
  clear();
 
}// end of MAIN loop


//  ------------------------------  FUNCTIONS -------------------------------
 
void show(){
  Wire.beginTransmission(0x70);
  Wire.write(0x00); // start at address 0x0
 
  for (int i = 0; i < 8; i++) {
    Wire.write(displayBuffer[i] & 0xFF); 
    Wire.write(displayBuffer[i] >> 8);
  }
  Wire.endTransmission();  
}

 // clear buffer -----------------------------------------------------
void clear(){
  for(int i = 0; i < 8; i++){
    displayBuffer[i] = 0;
  }
}

I want to thank everyone for your great comments and helpfullness!!
Love the toys!!! dw :-]

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.