Selfmade i2c 7-segments display with ATtiny85

0. Intro

Because I had a bunch of common anode 7 segment displays i decided learn how to make i2c slave device.

1. 7-segment LEDs

My 7-segment LEDs are marked as 5611BH and looks like this:

5611BH common anode 7- segment LED
5611BH common anode 7- segment LED
Common anode 7-segment LED circuit.
Common anode 7-segment LED circuit.

2. 7-segment LEDs module

I connected four 7-segment displays together on PCB and i added resistors (470Ω).

One 7-seg LED with resistors
One 7-seg LED with resistors
All four 7-segment LEDs connected together
All four 7-segment LEDs connected together
LED module front view
LED module front view
LED module back view
LED module back view

3. Shift registers module

I use 74HC595 shift registers to drive 7-segment LEDs.

One 74HC595 Shift register
One 74HC595 Shift register
7-segment LED + 74HC595 Shift Register
7-segment LED + 74HC595 Shift Register
Connecting multiple 74HC595 shift registers together.
Connecting multiple 74HC595 shift registers together.
LED module + 74HC595 Shift Register module
LED module + 74HC595 Shift Register module

4. ATtiny85 module

ATtiny85 module
ATtiny85 module

IMG_20181225_203210.jpg

5. Master Code

Example master (Arduino Uno or Nano) code:

6. Programming ATtiny85

Look my tutorial: Programming ATtiny85 with Arduino Uno

Download and install TinyWire libary: https://github.com/lucullusTheOnly/TinyWire

7. Slave code

Example slave (ATtiny85) code:

/*
* Chip: ATtiny85
* ATtiny85 as i2c Slave Receiver
* Date: 23.12.2018
* Author: Tauno Erik
*/
#include 
byte own_address = 10; //Slave i2c address
// Arduino uno: latch 8, data 11, clock 12
// ATtiny PB1, PB3, PB4
int latchPin = 1; // Pin connected to ST_CP of 74HC595
int dataPin  = 3; // Pin connected to    DS of 74HC595
int clockPin = 4; // Pin connected to SH_CP of 74HC595
// Array holds digits 0-9
byte numArray[11];
uint8_t    i = 0;
uint8_t   ii = 0;
uint8_t  iii = 0;
uint8_t iiii = 0;
void setup() {
 // Setup TinyWire I2C slave
 TinyWire.begin( own_address );
 // Sets callback for the event of a slave receive
 TinyWire.onReceive( onI2CReceive );
 // Set pins to output because they are addressed in the main loop
 pinMode(latchPin, OUTPUT);
/*  
* 7-segment LED:
*  |--A--|
*  F     B
*  |--G--|
*  E     C
*  |--D--|   
*         H
*         
*  GF+AB
*    #
*  ED+CH
*
*  0b00000000
*    ABCDEFGH
*  
*  0- High! (Common anode!)
*  1- Low
*/

  numArray[0] = 0b00000011; 
  numArray[1] = 0b10011111; 
  numArray[2] = 0b00100101; 
  numArray[3] = 0b00001101; 
  numArray[4] = 0b10011001; 
  numArray[5] = 0b01001001; 
  numArray[6] = 0b01000001; 
  numArray[7] = 0b00011111; 
  numArray[8] = 0b00000001; 
  numArray[9] = 0b00001001;
 numArray[10] = 0b11111111; // all off
 digitalWrite(latchPin, 0);
 shiftOut(dataPin, clockPin, 0b11111110);
 shiftOut(dataPin, clockPin, 0b11111110);
 shiftOut(dataPin, clockPin, 0b11111110);
 shiftOut(dataPin, clockPin, 0b11111110);
 digitalWrite(latchPin, 1);
 delay(400);
} //setup end
void loop() {
} //loop end
/**********************************************************************
* I2C Slave Receive Callback:
* Note that this function is called from an interrupt routine and shouldn't 
* take long to execute
**********************************************************************/
void onI2CReceive(int howMany){
 digitalWrite(latchPin, 0);
 //while(TinyWire.available()>0){
 while(1 < TinyWire.available()){
    int c = TinyWire.read();
   shiftOut(dataPin, clockPin, numArray[c]);
 }
 //lastone
 int x = TinyWire.read();
 shiftOut(dataPin, clockPin, numArray[x]);
 digitalWrite(latchPin, 1);
}
/********************************
* 
********************************/
void numsOut(int i, int ii, int iii, int iiii){
 digitalWrite(latchPin, 0);
 shiftOut(dataPin, clockPin, numArray[iiii]); //0xxx
 shiftOut(dataPin, clockPin, numArray[iii]);  //x0xx
 shiftOut(dataPin, clockPin, numArray[ii]);   //xx0x
 shiftOut(dataPin, clockPin, numArray[i]);    //xxx0
 digitalWrite(latchPin, 1);
 }
/*************************************
* 
*************************************/
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
 // This shifts 8 bits out MSB first, 
 // on the rising edge of the clock,
 // clock idles low
 //internal function setup
 int i=0;
 int pinState;
 pinMode(myClockPin, OUTPUT);
 pinMode(myDataPin, OUTPUT);
 //clear everything out just in case to
 //prepare shift register for bit shifting
 digitalWrite(myDataPin, 0);
 digitalWrite(myClockPin, 0);
 //for each bit in the byte myDataOut�
 //NOTICE THAT WE ARE COUNTING DOWN in our for loop
 //This means that %00000001 or "1" will go through such
 //that it will be pin Q0 that lights. 
 for (i=7; i>=0; i--)  {
   digitalWrite(myClockPin, 0);
   //if the value passed to myDataOut and a bitmask result 
   // true then... so if we are at i=6 and our value is
   // %11010100 it would the code compares it to %01000000 
   // and proceeds to set pinState to 1.
   if ( myDataOut & (1<<i) ) {
     pinState= 1;
   }
   else {  
     pinState= 0;
   }
   //Sets the pin to HIGH or LOW depending on pinState
   digitalWrite(myDataPin, pinState);
   //register shifts bits on upstroke of clock pin  
   digitalWrite(myClockPin, 1);
   //zero the data pin after shift to prevent bleed through
   digitalWrite(myDataPin, 0);
 }
 //stop shifting
 digitalWrite(myClockPin, 0);
}

8. Demo

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.