Digital Voltmeter using Arduino

Introduction

            7-segment displays are most popular in panel meters, It can show direct numerical value on display, It’s cost is low and display size bigger than LCD’s. Lets interface four digit display, most of the time four digits are enough to display data.

Problem Statement

            We are making a Voltmeter using four digit 7-segment display, for this IC 74HC595 shift register is used instead of 7448 decoder, use of shift register gives few advantages such as you can display sign, few alphabets and control decimal point location.

7-Segment display types and its pin out

7-Segment Display Pin Diagram
7-Segment Display Pin Diagram

Based on the number we want to show on display prepare decoding table

7-segment Decoding
7-segment Decoding

Those segments we want to keep on make 1 and remaining 0.

Number dp G F E D C B A Hex Value
0 0 0 1 1 1 1 1 1 3F
1 0 0 0 0 0 1 1 0 06
2 0 1 0 1 1 0 1 1 5B
3 0 1 0 0 1 1 1 1 4F
4 0 1 1 0 0 1 1 0 66
5 0 1 1 0 1 1 0 1 6D
6 0 1 1 1 1 1 0 1 7D
7 0 0 0 0 0 1 1 1 07
8 0 1 1 1 1 1 1 1 7F
9 0 1 1 0 1 1 1 1 6F

Arduino Connection with 7-Segment Display

            To drive 7-segment display we used 74HC595 as Segment driver, you can use ULN2003 for driving common terminal, If the LED current is more, as we have used 1K Ohm resistor current stays in limit. We used three lines for driving segments and four for common terminal. At a time only one display is in on state.

Digital Voltmeter Circuit Diagram
Digital Voltmeter Circuit Diagram

Arduino Code for Voltmeter using 4-Digit 7-Segment Display

In program we have used TimerOne Library for Display scanning.

/*
     Digital Voltmeter using 4-Digit 7-segment Display
     www.circuits4you.com 
 */

#include <TimerOne.h>

//Define 74HC595 Connections with arduino
const int Data=7;
const int Clock=8;
const int Latch=6;

const int SEG0=5;
const int SEG1=4;
const int SEG2=3;
const int SEG3=2;

int cc=0;
char Value[4];

//Refer Table 4.1 7-Segment Decoding
const char SegData[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

//=============================================================
//                Setup
//=============================================================
void setup() {                
  // initialize the digital pin as an output.
  Serial.begin(9600);
  pinMode(Data, OUTPUT);
  pinMode(Clock, OUTPUT);
  pinMode(Latch, OUTPUT);  
  pinMode(SEG0, OUTPUT);  
  pinMode(SEG1, OUTPUT);  
  pinMode(SEG2, OUTPUT);
  pinMode(SEG3, OUTPUT);  
  
	//Initialize Display Scanner
        cc=0;
        Timer1.initialize(50000); // set a timer of length 100000 microseconds (or 0.1 sec - or 10Hz => the led will blink 5 times, 5 cycles of on-and-off, per second)
        Timer1.attachInterrupt( timerIsr ); // attach the service routine here
}
//=============================================================
//               Loop
//=============================================================
void loop() {
  char Volt[4];
  int Voltage=analogRead(A0);
  //To get fixed point decimal point we multiply it by 100
  Voltage = (500/1024.0) * Voltage;  //Scaling of 0 to 5V i.e. 0 to 1023 to 0 to 10 (in 10 steps)
  
  //Display Voltage on Segments
  sprintf(Volt,"%04d",Voltage);    //We get ASCII array in Volt
  Serial.println(Volt);  
  
  Value[0]=Volt[0] & 0x0F;    //Anding with 0x0F to remove upper nibble
  Value[1]=Volt[1] & 0x0F;    //Ex. number 2 in ASCII is 0x32 we want only 2
  Value[2]=Volt[2] & 0x0F;
  Value[3]=Volt[3] & 0x0F;  
  delay(200);
}

//=============================================================
//             Generates Bargraph
//=============================================================
void DisplayDigit(char d)
{
  int i;
  
 for(i=0;i<8;i++)    //Shift bit by bit data in shift register
 {
	if((d & 0x80)==0x80)
	{
	  digitalWrite(Data,HIGH);
	}
	else
	{
	  digitalWrite(Data,LOW);
	}
	d=d<<1;

        //Give Clock pulse
        digitalWrite(Clock,LOW);        
        digitalWrite(Clock,HIGH);
 } 
  //Latch the data
  digitalWrite(Latch,LOW);
  digitalWrite(Latch,HIGH);      
}
//===================================================================
//			TIMER 1 OVERFLOW INTTERRUPT FOR DISPALY
//===================================================================
void timerIsr()
{
	cc++;
	if(cc==5)  //We have only 4 digits
	{cc=1;}
	Scanner();
	TCNT0=0xCC;
}

//===================================================================
//		SCAN DISPLAY FUNCTION
//===================================================================
void Scanner()
{  
  switch (cc)    //Depending on which digit is selcted give output
  {
    case 1:
      digitalWrite(SEG3,HIGH);      
      DisplayDigit(SegData[Value[0]]);
      digitalWrite(SEG0,LOW);
    break;
    case 2:
      digitalWrite(SEG0,HIGH);
      DisplayDigit(SegData[Value[1]] | 0x80); //0x80 to turn on decimal point
      digitalWrite(SEG1,LOW);
    break;
    case 3:
      digitalWrite(SEG1,HIGH);
      DisplayDigit(SegData[Value[2]]);
      digitalWrite(SEG2,LOW);
    break;
    case 4:
      digitalWrite(SEG2,HIGH);    
      DisplayDigit(SegData[Value[3]]);
      digitalWrite(SEG3,LOW);      
    break;    
  }
}
//===================================================================

Result

            You can observe its output on serial terminal also, the display will show the voltage reading, apply voltage at ADC A0 pin using potentiometer. This code demonstrates how to multiplex multiple displays and concept of 7-segment display.

Leave a Reply