Tutorial 6 : SevenSegment Library - sudeshmoreyos/Morey_os-demo-1.0 GitHub Wiki

Home <<Prev 6 Next>>

In this tutorial we will learn how to implement SevenSegment library of Morey_os. In previous tutorial i.e. Tutorial-5 we learned about Digital Driver. Let me explain the basic difference between a driver and a library. Driver is a hardware functionality and mostly generic in nature. While library is usually written to control some specific external interface that may or may not use driver functionality.

For example, in this tutorial we will learn how to display digits/characters on seven segment display. Digital driver is used to use input output functionality of a controller. We can display different digits on a seven segment display by simply switching on and off different segments. If we wish to display digit 2 on seven segment display, we just need to know which segments to glow and which not. So Digital driver functionality is sufficient for us to control a seven segment display. However, if we use SevenSegment library, it provides functions to directly display digit 2. We don't need to worry about which segment to switch on or off, SevenSegment library functions manage all that. Effectively for seven segment application, our task becomes much easier compared to using only Digital driver functions.

1. Introduction to Seven Segment Display

Before we discuss more about Seven segment library, let us take a brief introduction of seven segment display. Wikipedia defines seven segment as "A seven-segment display is a form of electronic display device for displaying decimal numerals that is an alternative to the more complex dot matrix displays" link. A typical seven segment display looks something like below :

A Seven segment display has Seven Segments shown above as a, b, c, d, e, f, g plus one dot h. By combining the on off of these different segments, we can display different digits or some limited set of characters as well. These segments are available in different sizes and colors. Typically it has ten pins, eight for segments a to h and two as common pins. Electrically, there are two types of seven segment displays, Common Cathode and Common Anode. Both these types differ in the electrical arrangement of Segment LEDs as shown below :

Seven Segment-2

As you can see that, in the Common Cathode display, the negative terminals of all segments are connected to common pins and vice versa for common Anode. So if we wish to glow segment A, in common cathode we need to connect Seg A pin to positive supply while common pin to ground with a resistance in series at any of the common pins. And vice versa for Common Anode seven segment display. Typical electrical connections of a common cathode Seven segment display with a Arduino Board is shown below :

Segments A to H are connected to pin0 to pin7 and common pin is connected to gnd with resistance in series. Resistance value is typically 100 ohm. While in case of common Anode connections should be like :

Only difference here is that, common pin of common anode segment is connected with 5V supply.

2. Seven Segment Library

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

#include "lib/SevenSegment.h"

You can also find sources for SevenSegment library here SevenSegment Lib

This Lib supports following initialization and functions :

1. Seven Segment struct initialization

First step is to initialize the seven segment structure, which holds the essential data required by SevenSegment lib functions. Initialization is done as follows :

SevenSegment_t seg1={pin0,pin1,pin2,pin3,pin4,pin5,pin6,pin7};

In above declaration we are creating a struct of type SevenSegment_t. Also we are assigning digital pins to struct which should be connected to Seven segment display in segment order A, B, C, D, E, F, G and H. This structure should be defined above setup function. Sometimes it is possible that we don't want to connect all eight digital pins to seven segment display. For example, in some application if we don't need to display dot segment, there is no point to connect any digital pin to segment pin H. In that case we can define struct as :

SevenSegment_t seg1={pin0,pin1,pin2,pin3,pin4,pin5,pin6,NOT_USED_PIN};

So SevenSegment functions will simply skip that pin and you can save digital pins of your controller or board. Please note that NOT_USED_PIN can be used for any or all segments of the display.

2. SevenSegment_begin

Declaration :

void SevenSegment_begin (struct seven_segment_struct * seven_segment_obj, mos_uint8_t segment_type);

After SevenSegment_t struct initialization, first function that must be used is SevenSegment_begin. This function has two inputs. First is SevenSegment_t struct pointer and second is segment type which can be either ANODE for common anode or CATHODE for common cathode segment. This function assigns seven segment type to its struct variable and also initializes all digital pins used as output. Function is usually declared in setup function as :

void setup {

SevenSegment_begin(&seg1,CATHODE);

}

3. SevenSegment_print

Declaration :

void SevenSegment_print (struct seven_segment_struct * seven_segment_obj, mos_uint8_t digit);

This function is used to print digits on seven segment display. It has two inputs, first is SevenSegment_t struct pointer and other one is digits to be displayed. Digits that can be displayed using this function is as follows :

DIGIT0 or 0 or 0x00

DIGIT1 or 1 or 0x01

DIGIT2 or 2 or 0x02

DIGIT3 or 3 or 0x03

DIGIT4 or 4 or 0x04

DIGIT5 or 5 or 0x05

DIGIT6 or 6 or 0x06

DIGIT7 or 7 or 0x07

DIGIT8 or 8 or 0x08

DIGIT9 or 9 or 0x09

DIGITA or 10 or 0x0A

DIGITB or 11 or 0x0B

DIGITC or 12 or 0x0C

DIGITD or 13 or 0x0D

DIGITE or 14 or 0x0E

DIGITF or 15 or 0x0F

DIGIT_DOT or 16 or 0x10

DIGIT_DASH or 17 or 0x11

DIGIT_BLANK or 18 or 0x12

4. SevenSegment_printDot

Declaration :

void SevenSegment_printDot (struct seven_segment_struct * seven_segment_obj, mos_uint8_t digit);

This function is same as SevenSegment_print with only difference that along with digit or hex character, Dot is also displayed. This function will be useful to display decimal values on the display.

5. SevenSegment_printReverse

Declaration :

void SevenSegment_printReverse (struct seven_segment_struct * seven_segment_obj, mos_uint8_t digit);

This function is same as SevenSegment_print with only difference that digits or hex characters are displayed upside down. This function will be useful to display upside down or reversed digits. An example application could be Digital clock implementation using four seven segment displays. In order to implement ':' between Hour digits and Minute digits we need to reverse at least one Seven Segment display. This function will be helpful to display digits on such reversed display.

6. SevenSegment_printDotReverse

Declaration :

void SevenSegment_printDotReverse (struct seven_segment_struct * seven_segment_obj, mos_uint8_t digit);

This function is same as SevenSegment_printReverse with only difference that along with reversed/upside down digits or hex characters dot is displayed. This function will also be useful to display digits in Digital clock like examples as discussed previously.

7. SevenSegment_customPrint

Declaration :

void SevenSegment_customPrint (struct seven_segment_struct * seven_segment_obj, mos_uint8_t custom_data_pin_a, mos_uint8_t custom_data_pin_b, mos_uint8_t custom_data_pin_c, mos_uint8_t custom_data_pin_d, mos_uint8_t custom_data_pin_e, mos_uint8_t custom_data_pin_f, mos_uint8_t custom_data_pin_g, mos_uint8_t custom_data_pin_h);

The last function of this library is SevenSegment_customPrint. If user wish to display symbols other than digits or hex characters or special symbols like dot, minus or blank, he/she can use this function to display customs symbols. This function has 9 inputs. First input is SevenSegment_t struct pointer, and rest inputs are 1 ( on ) or 0 ( off ) state of segments A to H. Please note values other than 0 or 1 are invalid and will be treated as 1.

2. SevenSegment lib Example Code

Let us now check an example code named seven-segment-counter.c that can be found in example folder (examples/board-examples/arduino-uno/seven-segment). It implements two seven segment counters. First seven segment is common cathode while other one is common anode. The code is as follows :


// Declare here all header files used in the code.h , OS related files are included by default

#include "morey_os.h"

#include "lib/sevensegment.h"

SevenSegment_t seg1={pin0,pin1,pin2,pin3,pin4,pin5,pin6,pin7},seg2={pinA0,pinA1,pinA2,pinA3,pinA4,pinA5,pin8,pin9};

// Declare all initialization functions of controller peripherals in the setup function below

void setup(void)

{

SevenSegment_begin(&seg1, ANODE);

SevenSegment_begin(&seg2, CATHODE);

}

// Delcare all processes here

TASK_CREATE(SEVEN1,"SEVEN-1");

TASK_CREATE(SEVEN2,"SEVEN-2");

// Delcare autostart processes here. Atleast one process must be autostarted;

TASK_AUTOSTART(&SEVEN1, &SEVEN2);

TASK_RUN(SEVEN1)

{

// Declare all variables here, please read documentation to understand

// which variables should be declared as static variables

static int i=0;

// Process starts here

BEGIN();

while(1)

{

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

{

	SevenSegment_print(&seg1, i);

	DELAY_SEC_PRECISE(0.5);

} 

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

{

	SevenSegment_printDot(&seg1, i);	

	DELAY_SEC_PRECISE(0.5);

}

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

{

	SevenSegment_printReverse(&seg1, i);

	DELAY_SEC_PRECISE(0.5);

}

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

{

	SevenSegment_printDotReverse(&seg1, i);

	DELAY_SEC_PRECISE(0.5);

}

SevenSegment_customPrint(&seg1,1,0,0,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,1,0,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,1,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,1,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,0,1,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,0,0,1,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,0,0,0,1,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,0,0,0,0,1);

DELAY_SEC_PRECISE(0.5);

}

// process ends here

END();

}

TASK_RUN(SEVEN2)

{

// Declare all variables here, please read documentation to understand

// which variables should be declared as static variables

static int i=0;

// Process starts here

BEGIN();

while(1)

{

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

{

	SevenSegment_print(&seg2, i);

	DELAY_SEC_PRECISE(0.5);

} 

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

{

	SevenSegment_printDot(&seg2, i);	

	DELAY_SEC_PRECISE(0.5);

}

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

{

	SevenSegment_printReverse(&seg2, i);

	DELAY_SEC_PRECISE(0.5);

}

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

{

	SevenSegment_printDotReverse(&seg2, i);

	DELAY_SEC_PRECISE(0.5);

}	

SevenSegment_customPrint(&seg2,1,0,0,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,1,0,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,1,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,1,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,0,1,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,0,0,1,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,0,0,0,1,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,0,0,0,0,1);

DELAY_SEC_PRECISE(0.5);

}

// process ends here

END();

}


Code Explanation :

  1. morey_os.h header file is compulsory to include in all codes. Since we are using SevenSegment lib functionality, we have added lib/sevensegment.h header too.

#include "morey_os.h"

#include "lib/SevenSegment.h"

  1. Two structs of type SevenSegment_t are initialized by name seg1 and seg2. Respective digital pins of board are assigned to seg1 and seg2. seg1 is connected to pin0 to pin7 while seg2 is connected to pinA0 to pinA5 and pin8 & pin9.

SevenSegment_t seg1={pin0,pin1,pin2,pin3,pin4,pin5,pin6,pin7},seg2={pinA0,pinA1,pinA2,pinA3,pinA4,pinA5,pin8,pin9};

  1. seg1 is initialized as common Anode while seg2 is initialized as common Cathode.

void setup(void)

{

SevenSegment_begin(&seg1, ANODE);

SevenSegment_begin(&seg2, CATHODE);

}

  1. We have created two tasks named SEVEN1 and SEVEN2. 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(led_blink,"led blink");

TASK_CREATE(input_test,"input test");

  1. Next we autostart both the tasks 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 autostart all tasks at controller/board boot time.

TASK_AUTOSTART(&SEVEN1, &SEVEN2);

  1. Next we declare TASK_RUN for both the tasks. SEVEN1 task implements all five functions namely SevenSegment_print, SevenSegment_printDot, SevenSegment_printReverse, SevenSegment_printDotReverse and SevenSegment_customPrint for seg1. In TASK_RUN(SEVEN1) 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. Also 'for loops' are implemented till 'i = 18' or 'i < 19', to display dot (16), dash (17) and blank (18) symbols. SevenSegment_print function displays 0-9, A-F, dot, dash and blank after every 0.5 second delay. SevenSegment_printDot function displays 0-9, A-F, dot, dash and blank along with a dot after every 0.5 second delay. SevenSegment_printReverse function displays 0-9, A-F, dot, dash and blank in upside down manner after every 0.5 second delay. SevenSegment_printDotReverse function displays 0-9, A-F, dot, dash and blank in upside down manner along with a dot after every 0.5 second delay. Finally SevenSegment_customPrint function one by one displays each segment of both seven segment displays.

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 Tutorial 8 : DELAY_SEC Macros Demystified. 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(0.5); hence this condition is satisfied.


TASK_RUN(SEVEN1)

{

// Declare all variables here, please read documentation to understand

// which variables should be declared as static variables

static int i=0;

// Process starts here

BEGIN();

while(1)

{

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

{

	SevenSegment_print(&seg1, i);

	DELAY_SEC_PRECISE(0.5);

} 

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

{

	SevenSegment_printDot(&seg1, i);	

	DELAY_SEC_PRECISE(0.5);

}

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

{

	SevenSegment_printReverse(&seg1, i);

	DELAY_SEC_PRECISE(0.5);

}

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

{

	SevenSegment_printDotReverse(&seg1, i);

	DELAY_SEC_PRECISE(0.5);

}

SevenSegment_customPrint(&seg1,1,0,0,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,1,0,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,1,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,1,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,0,1,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,0,0,1,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,0,0,0,1,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg1,0,0,0,0,0,0,0,1);

DELAY_SEC_PRECISE(0.5);

}

// process ends here

END();

}


  1. SEVEN2 task implements exact operations for seg2.

TASK_RUN(SEVEN2)

{

// Declare all variables here, please read documentation to understand

// which variables should be declared as static variables

static int i=0;

// Process starts here

BEGIN();

while(1)

{

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

{

	SevenSegment_print(&seg2, i);

	DELAY_SEC_PRECISE(0.5);

} 

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

{

	SevenSegment_printDot(&seg2, i);	

	DELAY_SEC_PRECISE(0.5);

}

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

{

	SevenSegment_printReverse(&seg2, i);

	DELAY_SEC_PRECISE(0.5);

}

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

{

	SevenSegment_printDotReverse(&seg2, i);

	DELAY_SEC_PRECISE(0.5);

}	

SevenSegment_customPrint(&seg2,1,0,0,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,1,0,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,1,0,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,1,0,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,0,1,0,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,0,0,1,0,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,0,0,0,1,0);

DELAY_SEC_PRECISE(0.5);

SevenSegment_customPrint(&seg2,0,0,0,0,0,0,0,1);

DELAY_SEC_PRECISE(0.5);

}

// process ends here

END();

}


  1. Content of Makefile is as follows :

PROJECT = seven-segment-counter

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 is simple and requires no special configurations. Hence config.h file content will remain same as below :

#ifndef CONFIG_H

#define CONFIG_H

#define COMPILER AVR_GCC

#endif


Home <<Prev 6 Next>>