This project deals with the designing of a seven-segment display(SSD) I2C driver using ATmega328.
A seven-segment display is generally available in a ten-pin package. While eight pins correspond to the eight LEDs, the remaining two pins (at middle) are common and internally shorted. Therefore, when using a microcontroller to operate a seven-segment LED display, 8 pins are required to control individual LEDs in the display, which can be brought down to 4 using a decoder. This number increases as more SSDs are added into the display.
In most applications, however, using a single-digit seven-segment display (SSD), may not be sufficient to display the entire information, hence multiple SSD units are connected in parallel. In order to display different characters, symbols or numbers, the data being displayed on each SSD has to be different. However, to drive multiple such SSDs simultaneously, the number of pins required to control them multiplies by the number of SSDs being used. Since the number of I/O pins available on a microcontroller or a driver is limited, this becomes a significant problem. The most widely used solution to this problem is time-division multiplexing of the SSD data. At any instant of time, a controller or SSD decoder only operates on a single SSD rather than multiple SSDs at the same time. This has to be done fast enough to evade the human persistence of vision but has to be slow enough to give the LEDs on the display enough time to perform switching action. The individual SSDs are selected using another circuit which usually consists of transistors as switches.
The microcontroller may need to perform other functions alongside displaying information on the SSD display, which may or may not require the usage of I/O lines. However, this can affect the display timings of the SSD and may result in unwanted pauses or shut down of the display until the CPU has finished executing the corresponding set of instructions.
In the case of interfacing a microcontroller with an SSD display, using another microcontroller as a driver which acts as a peripheral to the main microcontroller can be very helpful. It can also make the display system isolated and the main microcontroller can be made free to execute other instructions. The driver will have to take care of the timing and switching of appropriate components in the display system. The interfacing between the main controller and the I2C driver controller can be done using various communication protocols such as SPI(Serial Peripheral Interface), UART(Universal Asynchronous Receiver Transmitter), I2C(Inter-Integrated Circuits), etc. Of these, UART is not extendible and is useful only for fixed device-to-device communication and like SPI does not guarantee for verification of whether the data has been sent correctly. I2C provides all these benefits and is cheaper to implement with only 2 lines for clock (SCL) and data (SDA) respectively. I2C also allows for multiple masters and slaves on the same bus and so it would be possible for multiple devices to access the same resource (SSD display).
Setup:Device used as master: Arduino UNO R3
Microcontroller used for thedriver: Atmel ATMEGA328 (boot loaded)
Programmer used: FTDI R232RL (USB to Serial TTL logic)
Programming platform used: Arduino IDE 1.8.9
Display type: 6x1 SSD LED common anode display
The connections of the SSD display with the driver are as follows:
The I2C master device (main controller) collects the data from an LDR connected to its ADC pin A0 and transmits the data over to the I2C slave (SSD driver) using the slave address. The driver displays the slave address on the SSD display on reset. When it receives data from a master, it changes the data of one of the digits at a time on a data buffer and keeps displaying the data on the buffer onto the SSD display.
The LUT(Look Up Table) is to be written on the master device for more flexibility. The data for the segments is considered such that binary 1 represents LED ON, however, the device used is of common anode type and so, the logic is inverted by the driver before displaying. The master sends the address of the location of the digit first followed by the data to be displayed by the segment. The address should be in the range 1-6, as used in the hardware. The driver rejects any address outside this range.
Programming:Link to download slave firmware.
Slave: SSD_Driver.ino
#include <Wire.h> //library;
int flag=1,m=0,n=0; //preset conditions;
byte arr[6]={0,0,0,0,0,0}; //initial buffer;
int segment[8]={0,1,2,3,4,5,6,7}; //segment/LED a,b,c,d,e,f,g,h;
int select[6]={13,12,11,10,9,8}; //digit number 1,2,3,4,5,6;
byte LUTmap=B11111111; //initial state – all LEDs off;
void setup() {
for(int i=0;i<=13;i++)
pinMode(i,OUTPUT); //all pins are output;
callforsegment(B00000000); flag++; //select digit 1;
callforsegment(B11111100); flag++; //display 0;
callforsegment(B00000010); flag++; //select digit 3;
callforsegment(B11110010); flag++; //display 3;
callforsegment(B00000011); flag++; //select digit 4;
callforsegment(B11111110); flag++; //display 8;
callforsegment(B00000100); flag++; //select digit 5;
callforsegment(B01101110); flag++; //display H(hex address);
Wire.begin(0x38); //i2c slave address for the driver;
Wire.onReceive(receiveEvent); //action on receiving data via i2c bus;
}
void segWrite(byte a) {
LUTmap=~a; //convert to common anode logic;
for(int i=0;i<8;i++)
//display to each segment in a digit;
digitalWrite(segment[i],bitRead(LUTmap,7-i));
}
void loop() {
for(int i=0;i<6;i++) {
digitalWrite(select[i],HIGH); //selecting one of the digits;
segWrite((byte)arr[i]); //writing data to the digit;
delay(5); //ON time;
digitalWrite(select[i],LOW); //deactivating the selected digit;
}
}
void callforsegment(int a) {
if(flag%2==1 && a<=7 && a>=0)
m=a; //first byte about digit location;
else {
n=a; //second byte about data for the digit;
flag=0;
}
arr[m]=(byte)n; //store data to the buffer space;
}
void receiveEvent(int howMany) {
while (1 < Wire.available()) //loop through all except last;
char c = Wire.read(); //receive byte as a character;
int x = Wire.read(); //receive byte as an integer;
callforsegment(x);
flag++;
}
Master: ADC_master.ino
#include <Wire.h>
#include <SSDmaster.h> //include library;
SSDmaster device(0x38); //address of slave driver;
void setup() {
Wire.begin();
}
void loop() {
int ldrval=analogRead(A0); //variable to store ADC data;
device.ssdDisplay(1,B00011100); //display L;
device.ssdDisplay(2,B01111010); //display D;
device.ssdDisplay(3,B00001010); //display R;
device.ssdDisplaynum(4,(byte)ldrval); //display ADC value;
delay(250); //rate of updation;
}
Results:Powering ON the driver displays the I2C slave address. When connected with the appropriate I2C master device which identifies its slave address, the data sent from the master (in this case light intensity) is printed on to the display.
EndNote:Use the SSD_Driver library to build the required system.
Comments