Tutorial_11 : Seven Segment Multiplexing Library - sudeshmoreyos/Morey_os-demo-1.0 GitHub Wiki

Home <<Prev 11 Next>>

This library is used to implement Seven-Segment multiplexing. This library currently supports display of numbers with or without dot, numbers/digits which are reversed upside down and custom symbols. The pre-requisites for this library are SevenSegment Library and Timer Delay Driver.

1. Introduction to Seven Segment Multiplexing

As we learned in SevenSegment Library, we need 8 digital outputs to control a single seven segment. There are many applications where we will need more than one seven segments. For example a digital clock, in which we will need at least four seven segments to display hour and minute digits. Which means we will require 8 x 4 = 32 digital outputs. While our Arduino Uno has only 20 pins. So it wont be possible to implement digital clock using Arduino Uno. So how to solve this problem? Seven Segment multiplexing is our answer to this problem.

By multiplexing seven-segment displays the number of pins required to drive the displays can be reduced. In this scheme we connect seven segments as shown below :

image

As shown above a pins of all seven segments are connected together. Similary b, c, d, e, f , g and h pins are connected together. While the common pins of each seven segments are kept independent. Eight pins i.e. a, b, c, d, e, f , g and h pins are connected to eight digital outputs while rest four common pins are connected to other four independent digital pins. So instead of 32 pins we required only 8 + 4 = 12 digital pins. Effectively we saved 20 pins.

The basic principal of operation is that we glow one seven segment at a time. So if we have to display 1234 on the seven segments,

  1. we first display 1xxx, where x indicates segment is off
  2. Then we display x2xx
  3. then xx3x
  4. finally we display xxx4
  5. then again we display 1xxx
  6. And process continues.

But this on/off switching of each segment is so fast that our eyes gets the illusion that all four seven segments are on simultaneously. However to implement the coding of seven segment multiplexing is bit complex. Further multi-tasking becomes even difficult when we write code for multiplexing. SevenSegmentMulti library effectively solves this problem. Typical connections with Arduino Uno is as follows :

image

2. SevenSegmentMulti Library

SevenSegmentMulti Library uses SevenSegment Library and TimerDelay Driver. Kindly refer these before proceeding further in this tutorial.

To include seven segment multiplexing header file in your code, you need to add following lines in your code :

#include "lib/SevenSegmentMulti.h"

#include "TimerDelay.h"

Since SevenSegmentMulti needs TimerDelay lib, hence its header must also be included. However, SevenSegment lib is included by default. You can also find sources for SevenSegmentMulti library here SevenSegmentMulti Lib

This Lib supports following initialization and functions :

2.1 Seven Segment Multiplexing Initialization

First step is to initialize three variables

  1. Seven segment structure
  2. Seven segment multi structure and
  3. Array containing common pins.

These variables holds the essential data required by SevenSegmentMulti lib functions. Initialization is done as follows :

SevenSegment_t seg1 = {pin2,pin3,pin4,pin5,pin6,pin7,pin8,pin9};

SevenSegmentMulti_t multi_seg1;

mos_uint8_t seg_pins1[4] = {pinA0, pinA1, pinA2, pinA3};

In above declaration, first we have created a struct of type SevenSegment_t. We have assigned digital pins to struct which should be connected to Seven segment display in segment order A, B, C, D, E, F, G and H. Then we created a struct of type SevenSegmentMulti_t. This struct will hold all data needed by SevenSegmentMulti functions. And lastly we created an array seg_pins, which holds the digital pins connected to common pins of Seven Segments. All these variables should be defined above setup function.

2.2 SevenSegmentMulti_begin

Declaration :

void SevenSegmentMulti_begin (SevenSegmentMulti_t * seven_segment_multi_obj, SevenSegment_t * seven_segment_obj, mos_uint8_t * segment_common_pins, mos_uint8_t segment_count);

This function has four inputs, first is SevenSegmentMulti_t struct pointer, second is SevenSegment_t struct pointer, third is array which contains pins to connect to the common pins of seven segments and last is total segment count. Function is usually declared in setup function as

void setup(void)

{

SevenSegment_begin(&seg1, CATHODE);

SevenSegmentMulti_begin(&multi_seg1,&seg1,seg_pins1,4);

TimerDelay.begin(TIMER_DELAY0,1,&timer_callback);

}

As shown above, it is important to note that before calling SevenSegmentMulti_begin function, SevenSegment_begin function must be called to initialize seven_segment_obj. Also we will need TimerDelay driver to run multiplexing code, so we need to include TimerDelay.begin function in setup as well.

SevenSegment_begin function simply initializes seg1 struct variable. Then this variable is passed as input to SevenSegmentMulti_begin function. SevenSegmentMulti_callback function is discussed in the next section.

2.3 SevenSegmentMulti_callback

Declaration :

void SevenSegmentMulti_callback(SevenSegmentMulti_t * seven_segment_multi_obj);

This function switches the display of digit after every call. For example, number to be displayed on seven segment array us 1234. The displayed numbers after every call of SevenSegmentMulti_callback functions are as follows :

  1. First call : 1xxx, where x indicates segment is off
  2. Second call : x2xx
  3. Third call : xx3x
  4. Fourth call : xxx4
  5. Fifth call : 1xxx
  6. And process continues.

This function must be periodically called. To do so we should use TimerDelay driver. As discussed in the introduction section, in seven segment multiplexing we switch on/off each seven segment one by one. This is implemented by periodically running SevenSegmentMulti_callback function using TimerDelay driver. In the below example, we are using TimerDelay.begin function to periodically run timer_callback function after every 1 milli-second. Which means we are switching seven segments on/off after every 1 milli second. TimerDelay driver is using TIMER_DELAY0 i.e. TIMER0 of atmega328P IC used in Arduino Uno. For more details about TimerDelay driver, please refer TimerDelay Driver. So code including timer_callback should look like this :

void timer_callback(void)

{

SevenSegmentMulti_callback(&multi_seg1);

}

void setup(void)

{

SevenSegment_begin(&seg1, CATHODE);

SevenSegmentMulti_begin(&multi_seg1,&seg1,4,seg_pins1);

TimerDelay.begin(TIMER_DELAY0,1,&timer_callback);

}

Please note to periodically call SevenSegmentMulti_callback function, we should not use an independently running task for following reasons :

  1. In Morey_os multi tasking is implemented using co-operative threads. Further, Morey_os is not a real time operating system. Hence Macros like DELAY_SEC or DELAY_SEC_PRECISE, do not guarantee to give exact specified delay at every run. While TimerDelay driver uses TIMER functionality of selected controller, hence specified delay is guaranteed.

  2. Usually SevenSegmentMulti_callback function must be called after a very short duration like 1 milli-second or so. In a morey_os task, it is advised not to give the delay less than 0.05 seconds i.e. 50 milli-seconds using DELAY_SEC macros.

2.4 SevenSegmentMulti_print

Declaration :

void SevenSegmentMulti_print (SevenSegmentMulti_t * seven_segment_multi_obj, mos_uint16_t number);

This function is used to print a number on a Seven segment array. It has two inputs, first is SevenSegmentMulti struct pointer and other is the number to be displayed. An example function call is :

SevenSegmentMulti_print(&multi_seg1,2345);

2.5 SevenSegmentMulti_printDot

Declaration :

void SevenSegmentMulti_printDot(SevenSegmentMulti_t * seven_segment_multi_obj, mos_uint16_t number, mos_uint8_t * dot_position);

This function is same as SevenSegmentMulti_print with only difference that we can display one or more digits with dot. It has three inputs, first is SevenSegmentMulti struct pointer, second one is the number to be displayed and the last one is positions of digits with dots. An example function call is :

SevenSegmentMulti_printDot(&multi_seg1,2345,{0,0,1,0});

234.5 number will be displayed, which means third digit i.e. 4 will be displayed along with a dot.

2.6 SevenSegmentMulti_printReverse

Declaration :

void SevenSegmentMulti_printReverse (SevenSegmentMulti_t * seven_segment_multi_obj, mos_uint16_t number, mos_uint8_t * reverse_position);

This function is same as SevenSegmentMulti_print with only difference that we can display one or more digits in reversed manner. It has three inputs, first is SevenSegmentMulti struct pointer, second one is the number to be displayed and the last one is positions of digits to be displayed in reversed manner. An example function call is :

SevenSegmentMulti_printReverse(&multi_seg1,2345,{0,0,1,1});

Which means third and fourth digit, i.e. 4 and 5 will be displayed reversed.

2.7 SevenSegmentMulti_printDotReverse

Declaration :

void SevenSegmentMulti_printDotReverse(SevenSegmentMulti_t * seven_segment_multi_obj, mos_uint16_t number, mos_uint8_t * dot_position, mos_uint8_t * reverse_position);

This function is combination of SevenSegmentMulti_printReverse and SevenSegmentMulti_printDot. It has four inputs, first is SevenSegmentMulti struct pointer, second one is the number to be displayed and the third one is the positions of digits with dot and last one is the positions of digits to be displayed reverse. An example function call is :

SevenSegmentMulti_printDotReverse(&multi_seg1,2345,{0,1,1,0}, {0,0,1,1});

Which means Second and third digit will be displayed with dot and third and fourth digits will be displayed in reverse fashion.

2.8 SevenSegmentMulti_customPrint

Declaration :

void SevenSegmentMulti_customPrint (struct seven_segment_struct * seven_segment_obj, mos_uint8_t * * custom_data);

This function is used to display custom data on Seven Segment array. It has two inputs, first is SevenSegmentMulti struct pointer, second one is the two dimensional array. This two dimensional array should be of size 8 x segment count. An example function call is :

void SevenSegmentMulti_customPrint (&multi_seg1,{{0,1,1,0,0,0,0,0},{0,0,0,0,0,0,1,0},{1,1,1,1,1,1,0,0},{0,0,0,0,0,0,1,0}});

which will display 1-0- on the display.

3. SevenSegmentMulti lib Example

Let us now check an example code named seven-segment-multiplexing that can be found in example folder (examples/board-examples/arduino-uno/seven-segment-multilpexing). The code is as follows :

#include "morey_os.h"

#include "TimerDelay.h"

#include "lib/SevenSegmentMulti.h"

SevenSegment_t seg1 = {pin2,pin3,pin4,pin5,pin6,pin7,pin8,pin9};

SevenSegmentMulti_t multi_seg1;

mos_uint8_t seg_pins1[4] = {pinA0, pinA1, pinA2, pinA3};

void timer_callback(void)

{

SevenSegmentMulti_callback(&multi_seg1);

}

void setup(void)

{

SevenSegment_begin(&seg1, CATHODE);

SevenSegmentMulti_begin(&multi_seg1,&seg1,4,seg_pins1);

TimerDelay.begin(TIMER_DELAY0,1,&timer_callback);

}

TASK_CREATE(multi1,"Multi Seg-1");

TASK_AUTOSTART(&multi1);

TASK_RUN(multi1)

{

static int i=0;

BEGIN();

while(1)

{

for(i=0; i<10000; i++)

{

SevenSegmentMulti_print(&multi_seg1, i);

DELAY_SEC_PRECISE(0.01);

}

}

END();

}

3.1 Code Explanation :

  1. morey_os.h header file is compulsory to include in all codes. Since we will need TimerDelay lib functionality, we have added TimerDelay.h header too. Further we have included lib/SevenSegmentMulti.h header to use Seven Segment Multi functions.

#include "morey_os.h"

#include "TimerDelay.h"

#include "lib/SevenSegmentMulti.h"

We need to creat three variables. Struct seg1 of type SevenSegment_t, struct multi_seg1 of type SevenSegmentMulti_t and an array seg_pins1 containing common pins of Seven segments.

SevenSegment_t seg1 = {pin2,pin3,pin4,pin5,pin6,pin7,pin8,pin9};

SevenSegmentMulti_t multi_seg1;

mos_uint8_t seg_pins1[4] = {pinA0, pinA1, pinA2, pinA3};

  1. Declaring timer_callback function which should contain SevenSegmentMulti_callback function to periodically switch the display of each segment.

void timer_callback(void)

{

SevenSegmentMulti_callback(&multi_seg1);

}

  1. Three functions must be called in the setup function. First one is SevenSegement_begin function to initialize the seven segment pins and type. Second one is SevenSegementMulti_begin function to initialize Seven Segment multiplexing and finally TimerDelay.begin function to initialize TimerDelay. SevenSegmentMulti function initializes four seven segments. While TimerDelay use TIMER_DELAY0 and calls timer_callback function after every one milli second.

void setup(void)

{

SevenSegment_begin(&seg1, ANODE);

SevenSegmentMulti_begin(&multi_seg1,&seg1,4,seg_pins1);

TimerDelay.begin(TIMER_DELAY0,1,&timer_callback);

}

  1. We will creat only one task named multi1. Please note TASK_CREATE Macro has two inputs. First input is name of the task to be created, other input is string name of the task which is used during code debugging process. We will discuss more about code debugging in subsequent tutorials.

TASK_CREATE(multi1,"Multi Seg-1");

  1. Next we auto-start the only task i.e. multi1 at startup or powerup of the board. We can optionally start these tasks manually inside some other tasks. Starting or ending tasks inside a task will be discussed in subsequent tutorials. For now we will auto-start all tasks at controller/board boot time.

TASK_AUTOSTART(&multi1);

  1. Next we declare TASK_RUN for the task. multi1 task implements only SevenSegmentMulti_print function. In TASK_RUN(multi1) a static integer variable 'i' is declared. Please note all variables in Morey_os must be declared as static. Reason for this is declared in subsequent tutorials.

After BEGIN(); Macro code implements a while(1) loop. Inside a while loop we are running a for loop from 0 to 9999. And we are printing the value of i on seven segment displays. The i value is updated after every 10 milli-seconds.

To give delay in morey_os we can use DELAY_SEC() or DELAY_SEC_PRECISE() macros. Detailed discussion of these two macros is done in DELAY_SEC Macros. Also it is very important to note that both tasks uses while(1) which is an infinite loop. Morey_os is based on cooperative threads, thats why this infinite loop must have at least one DELAY_SEC() or DELAY_SEC_PRECISE() macro. And we have used DELAY_SEC_PRECISE(1) inside for loops, hence this condition is satisfied.

TASK_RUN(multi1)

{

static int i=0;

BEGIN();

while(1)

{

for(i=0; i<10000; i++)

{

SevenSegmentMulti_print(&multi_seg1, i);

DELAY_SEC_PRECISE(0.01);

}

}

END();

}

  1. Content of Makefile is as follows :

PROJECT = seven-segment-multiplexing

MOREY_OS_PATH = ../../../..

BOARD = ARDUINO_UNO

include $(MOREY_OS_PATH)/Makefile.include

PROJECT Macro will hold name of the project file name. MOREY_OS_PATH holds the location of Morey_os root directory. BOARD Macro should hold ARDUINO_UNO since we are programming for Arduino_uno board. And last line should remain the same as mentioned above.

  1. This code requires only one special configuration. TimerDelay library is based on interrupt. Since Interrupt is never called by any function, while compilation AVR_GCC always includes interrupt functions and dependencies in compiled code. So even if we are not using TimerDelay lib in our code, after compilation it will still be included. To solve this problem, Morey_os uses TIMER_DELAY_ENABLE macro. If this macro is not defined TimerDelay lib is skipped from compilation. Since we are using TimerDelay lib in our code, we must define TIMER_DELAY_ENABLE macro in config.h header file :

#ifndef CONFIG_H

#define CONFIG_H

#define COMPILER AVR_GCC

#define TIMER_DELAY_ENABLE

#endif

Home <<Prev 11 Next>>