HC-SR04 & 8×7 Segment Display

Ok, the next tutorial.

The HC-SR04 is an ultrasonic sensor. It needs four wires:
Vcc, Ground, Trigger and Echo. There are no additional components necessary.

Before we start, here are some important details:
The speed of ultrasonic is 343 m/s. To measure a distance from 1m, it’s need round about 6 milliSeconds (actually there are two meter, one meter to the destination and one meter back).

So we need a special time for one measurement cycle and we are not able to make as many measurements per second as we want.
The HC-SR04 datasheet shows us the measurement cycle and the cycle time.

HC-SR04_datasheet

The cycle time must be less than 16 Hz.

Here is an example for a measurement function:

void Eyes_measurement() {
  digitalWrite(Eyes_Trigger,LOW);        // to be sure the Trigger is down
  delayMicroseconds(2);
  digitalWrite(Eyes_Trigger,HIGH);       // start a measurement
  delayMicroseconds(10);
  digitalWrite(Eyes_Trigger,LOW);        
  pulsdauer = pulseIn(Eyes_Echo,HIGH);   // get the result
  distance = pulsdauer / 58;             // value in cm
}

You can print the value with Serial.print().

But in this tutorial, I will show you, how you can combine the HC-SR04 and the 8×7 Segment Display.
This is not so easy, you need some know how about timer and interrupts. You will get this informations here: Basics – timer interrupts, and here: 8×7 Segment Display.

Some Details:

IMAG0197_1  2014-07-22 19.13.01  2014-07-22 19.17.37 2014-07-22 19.15.03

 

The code:

We need three ports for the display (port 5,6,7) and two ports for the HC-SR04 (port 9,10). In this example, we can use 5V Vcc for both elements.
We define the numbers to display (value[] without dot, valuedot[] the same numbers, but with dot).
The first difficult place is the timer setup.
We need a timer to control the display. This is without timer interrupt not possible. And, we need an additional timer for our measurement.
We use timer2 to control the display. There are no changes necessary.
To control the measurement, we use timer1 (this is the 16Bit timer). Only with this timer it’s possible to generate a frequency less then 16 Hz!
But this is no robot, why so often measure? I reduce the measurement frequency to 1 Hz.

 

Every one second (1 Hz!), the subroutine Eyes_measurement() will be running. The result will be be stored in the global variable distance.

In the loop() we cut the distance value in the individual digits.
Thats all.

 

The source code:

const int clock = 7; //SCK
const int latch = 5; //RCK 
const int data = 6;  //DIO

byte Eyes_Trigger = 10;    // I use a brown cable
byte Eyes_Echo = 9;
float pulsdauer,distance;


byte value[] =   {B11000000,  //0
                  B11111001,  //1
                  B10100100,  //2
                  B10110000,  //3
                  B10011001,  //4
                  B10010010,  //5
                  B10000010,  //6
                  B11111000,  //7
                  B10000000,  //8
                  B10010000,  //9
                  B11111111,  //nothing
                  B10111111}; //-

byte valuedot[] ={B01000000,  //0.
                  B01111001,  //1.
                  B00100100,  //2.
                  B00110000,  //3.
                  B00011001,  //4.
                  B00010010,  //5.
                  B00000010,  //6.
                  B01111000,  //7.
                  B00000000,  //8.
                  B00010000,  //9.
                  B01111111,  //nothing
                  B00111111}; //-


// digits count from left to right --- B00000001 = left digit, B10000000 = right digit
byte digit[] ={B00000001,B00000010,B00000100,B00001000,B00010000,B00100000,B01000000,B10000000};
byte ii = 0;

byte v0, v1,v2,v3,v4,v5,v6,v7;
byte vvalue = value[0];



void setup() {
  pinMode(Eyes_Trigger, OUTPUT);
  pinMode(Eyes_Echo, INPUT);  
  Serial.begin(9600); 
  pinMode(clock, OUTPUT);
  pinMode(latch, OUTPUT);
  pinMode(data, OUTPUT);
  
  cli();//stop interrupts
  //set timer2 interrupt at 980Hz
  TCCR2A = 0;// set entire TCCR0A register to 0
  TCCR2B = 0;// same for TCCR0B
  TCNT2  = 0;//initialize counter value to 0
  OCR2A = 255;//(must be <256) --> 16000000 / (prescaler*255) = 980 Hz
  TCCR2A |= (1 << WGM01);
  TCCR2B |= (1 << CS01) | (1 << CS00);   //prescaler = 64
  TIMSK2 |= (1 << OCIE2A);  
  
  //set timer1 interrupt at 1Hz
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  //OCR1A = 1562;              // = 10Hz, must be less than 16 Hz!!!
  //OCR1A = 3125;              // =  5Hz, must be less than 16 Hz!!!
  OCR1A = 15625;               // =  1Hz, must be less than 16 Hz!!!
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS12) | (1 << CS10);  //prescaler = 1024
  TIMSK1 |= (1 << OCIE1A);        

 sei();  //allow interrupts      
 v0=v1=v2=v3=v4=v5=v6=v7=10;   
} 

ISR(TIMER2_COMPA_vect){      
  ii++;   
  if (ii==8) ii=0;   
  if (ii==0) { vvalue = v0; }   
  else if (ii==1) { vvalue = v1; }       
  else if (ii==2) { vvalue = v2; }   
  else if (ii==3) { vvalue = v3; }   
  else if (ii==4) { vvalue = v4; }   
  else if (ii==5) { vvalue = v5; }   
  else if (ii==6) { vvalue = v6; }   
  else if (ii==7) { vvalue = v7; }   
  digitalWrite(latch,LOW);   
  shiftOut(data,clock,MSBFIRST,B11111111);   
  shiftOut(data,clock,MSBFIRST,B11111111);   
  digitalWrite(latch,HIGH);    
  digitalWrite(latch,LOW);   
  shiftOut(data,clock,MSBFIRST,digit[ii]);   
  if (ii == 5)     
    shiftOut(data,clock,MSBFIRST,valuedot[vvalue]);   //use a digit with dot
  else     
    shiftOut(data,clock,MSBFIRST,value[vvalue]);   
  digitalWrite(latch,HIGH); 
} 

ISR(TIMER1_COMPA_vect) {   
  distance = Eyes_measurement(); 
} 

float Eyes_measurement() {  
  float distance;   
  digitalWrite(Eyes_Trigger,LOW);   
  delayMicroseconds(2);   
  digitalWrite(Eyes_Trigger,HIGH);   
  delayMicroseconds(10);   
  digitalWrite(Eyes_Trigger,LOW);   
  distance = pulseIn(Eyes_Echo,HIGH,30000);            
  distance = distance / 58;     
  return distance; 
} 

float x; 

void loop() {   
  x = distance-int(distance);   
  if (distance >=100.00) {
    v3=int(distance/100);                
    v4=int(distance/10) - 10;}
    
  if (distance >= 10.00 && distance < 100.00) {
    v3=10;
    v4=int(distance/10);}

  if (distance < 10.00) {
    v3=10;
    v4=10; }
    
  v5=int(distance)%10;
  v6=int(x*10);
  v7=int((x*100))%10;  
} 

Advertisements

One thought on “HC-SR04 & 8×7 Segment Display

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s