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
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 ?
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
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
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");
}
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);
}
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;
}
}