HC-SR04 Ultrasound Module and Tiny13 Example

1 post / 0 new
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The HC-SR04 ultrasound module is a truly great little device that is incredibly inexpensive and works well.

In This Thread there was a question asked about using this sensor with a Tiny13, and running the T13 at 1.2 MHz.

This Tutorial Post captures that answer as an example of using this module.


If one uses an Arduino Nano board, with a Mega328P, for example, one has enough memory to add a display to show the distance to the target that the ultrasound module is aimed at.

The T13 doesn't have enough memory or I/O pins to add a display, so the User Output is simply an LED.

As per the original design specification, if the module is aimed at an object that is <= 5 cm from the sensor, an LED turns on.


Many of the AVR micros' Timer/Counter modules can directly measure the width of a pulse.

One feeds the pulse in a given I/O pin, and the T/C counts clock pulses, beginning when the pulse goes high, and ending when the pulse goes low.

That makes it easy to measure the duration of a pulse, in hardware, quite accurately.


The T13 has a single T/C that doesn't have this capability, so one has to measure the ultrasound module's Ping Time using software.

The T13 can run at 20 MHz, which would make this project a little bit easier, but the original spec was to do this while running the micro at 1.2 MHz.


The following info describes one approach to doing this.

Other approaches certainly exist!





So, I was bored...  And I haven't tinkered in a while.

And I happen to have some T13's in the drawer.

And a couple of the HC-SR04 ultrasound modules.


So I thought I'd give it a try using the T13 at 1.2 MHz.


The goal is to use the T13, at 1.2 MHz, with the SR04 to turn on an LED if the target is <= 5 cm from the SR04 module.

(As per the OP's first post.)


First the lessons learned:

1) Why in the world would one run a time sensitive project at 1.2 MHz when the micro will run at 20 MHz?

The PING travels at about 343.2 meters/second, 20'C, dry air.

That is about 2.913 uS / mm of travel distance.

That means that in the time it takes the PING to travel 1 mm the micro will execute 3.497 clock cycles.

(2.913 uSec/mm  /  0.833 uSec/clock cycle) = 3.497 clock cycles / mm of Ping travel distance.


That just doesn't give one much processing power in which to time the pulse to the mm distance, (ignoring, for the moment, the inherent inaccuracies of the SR04 itself).


However, all is not lost.

One can measure the PING travel distance in cm's, instead of in mm's, by noting that one has 35 uSec / cm to work with, which gives one 42 clock cycles of processing time per each cm of PING travel distance.

That is lots better than 3.5 clock cycles!


If one ran the micro at 20 MHz, one would have 58 clock cycles / mm of PING travel distance, so measuring to the mm would be doable.

At 20 MHz one would also have 700 clock cycles per cm of PING travel, so that would be like using a super computer for the task!


Running the micro at 1.2 MHz is clearly tying one hand behind your back.

You can still perform the task, but it is a bit more challenging and less precise.


2) The T13 has a single Timer/Counter, and it doesn't have the input capture mode to allow it to easily measure a pulse width using the T/C hardware.

So, one is left with measuring the pulse width in software, which is certainly doable.

Typically, especially when referring to my coding, the hardware approach would be significantly more accurate with fewer code and loop and If/Then induced timing errors.


3) With the small amount of memory in the T13 one can't just throw a GLCD on the micro to read the PING travel distance, or in fact to display any debugging information.

Hence, as per the OP's original post, the output to detect an object is <= 5 cm from the sensor is merely an LED.


That said, I hooked up an LED and an SR04 to the T13, and then I added two more LEDs because a project can never have too many LEDs!


One LED flashes as a heartbeat to show that the micro is running, and that a new measurement is about to be taken.

One LED is the Target is <= 5 cm away indicator.

The third LED is turned on and off inside the timing loop, so that it can be tweaked for 35 uSec / Tic, which means each Tic count equals 1 cm of PING travel distance.

The O'scope image shows the 35 uSec Tic loop, from Rising Edge to Rising Edge of the pulse train.


The TIC timing loop is about 35 uSec.  It uses a software uSec delay counter, (not a Timer/Counter generated Tic), and was tuned to +/- 1 uSec in the delay.

The slow micro clock makes it harder to fine tune the loop timing, although I moved on before I started inserting NOP's to try to tweak it a bit further.


The (in)accuracy of the internal RC clock, and the loop timing jitter watching for the Echo Pulse to transition high, also add small errors.

But those are overwhelmed by the fact that the program is measuring the Ping Travel Distance in units of cm,  not mm.


4) The T13's have sat in the drawer for years.  I'm glad I finally had a reason to pull one out and do something with it.



There is a 0.1 uF "By-Pass" capacitor from V+ to Ground, partly hidden by one of the resistors.

Be sure to include this, as it is required for reliable operations of digital logic chips.


The Red &White wires, seen in the bottom right, go to a +5V DC power supply, (wall wart, in this case).


ALL PROJECTS, even simple ones such as this one, require a schematic diagram, even if it is just hand written on the back of a napkin!

This makes wiring the project up, coding it, and debugging one's code, SO much easier!





'File: Tiny13 SR04 Ultrasound V1.bas
'Carter   April 21, 2021

'This uses an ATTiny13 micro to drive an HC-SR04
'Ultrasound Module.
'If the distance to the target is < 5 it turns on an LED.
'SLOW micro clock, so measure distance in cm units, not mm units.
'No interrupts used.

'There is NO GLCD to show the range.
'This runs at 1.2 MHz as that is the Forum Question spec.
'The micro could run at 20 MHz for better time resolution
'and for more processing power...

'This is simplistic.
'The T13 has a single 8-Bit Timer/Counter which does
'not have built-in pulse width measuring capability,
'so that is done in SW.

'With this SLOW clock frequency, the Ping travels 1 mm
'every 3.497 clock cycles.
'So, this clock is too slow to measure the Ping travel
'distance in mm.
'Can, however, use 35 clock cycles / cm to measure it in cm.

'Program simply counts 35 uSec Tics from the start of
'the Echo Pulse until it goes low.
'Each Tic = 1 cm in Ping travel distance.
'Note, therefore, that Range to target  = Ping travel distance/2
'as the Ping travels both out and back.

'Ping Speed = 343.2 meters/second, 20'C, Dry air
'That gives 2.913 uSec / mm Ping travel time.

'This is a simplistic implementation.
'It measures Range to Target in cm, not mm.
'Loop timing was adjusted with O'scope.
'Loop overhead for entry/exit was ignored.
'If one desired more accuracy, then pick a micro
'with a T/C that can directly measure pulse widths
'and run the micro at a faster clock frequency!

'ATTiny13  5V  1.2 MHz (Int RC Osc)
'Set FUSES for Int 4.8 MHz Clock Source.
'PB0  LED 1
'PB1  Echo Signal, (Input)
'PB2  Trigger      (Output)
'PB3  NC
'PB4  LED 2

   $regfile = "attiny13.dat"      'Micro used
   $crystal = 1200000             '1.2 MHz,  Internal RC Osc

   $hwstack = 20                 'Hardware Stack    (24)
   $swstack = 10                 'Software Stack    (10)
   $framesize = 24               'Frame Space       (30)

   'Now Configure the Port's Pins for Input or Output mode.
   Config PortB.0 = Output       'LED1
   Config PortB.1 = Input        'Echo SIgnal
   Config PortB.2 = Output       'Trigger Signal
   Config PortB.3 = Output       'LED3
   Config PortB.4 = Output       'LED2

   LED1 Alias PortB.0             ' LED 1
   LED2 Alias PortB.4             ' LED 2
   LED3 Alias PortB.3             ' LED32
   Trig Alias PortB.2            'Trigger Signal
   EchoPin Alias PinB.1          'Echo Signal

    Dim LpCnt1 as Byte     'Loop Counter 1
    Dim PingDist as Word   'Ping Range x 2, out and back, mm
    Dim EchoSig as Byte    'Echo Signal Status, High or Low
    Dim PingCnt as Word    'Count of 1 cm, 35 uSec, Tics

   Waitms 50          'Hardware Startup Delay, (Not actually mSec!)

   Gosub SetClock     'Set Clock 1.2 MHz

   Gosub FlashLEDs    'Startup Flash LEDs

   Reset Trig        'Init Trigger Signal Low

   'Now set the Target Range, in cm,
   'If less than this then turn on the LED
   'NOTE: PingDist = TWICE the distance to the target, ie out and back, in cm
   'So to light up LED for target < 10 cm, PingDist = 20 cm
   'So to light up LED for target < 5 cm, PingDist = 10 cm (5 out, 5 back)
   PingDist = 10    '5  cm out, 5 cm back  = 5 cm target distance, 10 cm ping travel distance

   'Gosub Flash1Hz   'Test routine

   'Take a range measurement about once / second
   'Flash a heartbeat / taking a measurement LED
   'Turn ON the Target-in-range LED as indicated
   'Target range, in cm, is set above.

      Set LED1       'Heartbeat, taking a reading
      Waitms 100
      Reset LED1

      Gosub Ping     'Take a Range to Target measurement

      If PingCnt <= PingDist then
         'Target is within range, turn ON LED
         Set LED2
         Reset LED2
      End If

      Waitms 900

   Loop         'Forever

   'Use FUSES to set the micro to Int 4.8 MHz clock
   'Then run this to enable the Div / 4 to get a
   'clock of 1.2 MHz.
   clkpr = 128      'Enable Clock Prescale Register
   Clkpr = 2       'Clock Div / 4

   'Trigger a Ping
   'Watch for the Echo Signal to go High
   'Count 35 uSec Tics, (~ = 1 cm Ping travel)
   'On Exit have: PingCnt
   'Timeout at about 4 meters, 14 mSec, Ping Distance, out and back.

   'First fire the Trigger Pulse, > 10 uSec High
   Set Trig        'Trigger Pulse High
   Waitus 10      '
   Reset Trig     'Trigger Pulse Low

   'Now wait for Echo Signal to go high
   EchoSig = EchoPin
   While EchoSig = 0
      EchoSig = EchoPin

   'Now count 35 uSec Tics, each one = 1 cm Ping travel
   'Timeout at Range of 4 meters, 400 cm,  Tics = 400
   'Ignore loop overhead for the moment.
   PingCnt = 0
   EchoSig = EchoPin
   While EchoPin = 1
      Set LED3                   'Scope timing
      PingCnt = PingCnt + 1
      If PingCnt > 400 then
         Exit While
      End If
      Reset LED3                 'Scope timing
      Waitus 5
   Reset LED3                     'Force LED3 Off if Timeout

   'Flash the LEDs on startup
   For LpCnt1 = 1 to 5
     Set LED1
     Waitms 50
     Set LED2
     Waitms 50
     Set LED3
     Waitms 50
     Reset LED1
     Waitms 50
     Reset LED2
     Waitms 50
     Reset LED3
     Waitms 50
   Next LpCnt1

   'Flash an LED at ~ 1 Hz to test the clock.
   'Uses timed delays, not ISR.
      Set LED2
      Waitms 100
      Reset LED2
      Waitms 900
   Return      'Never





Give me a Ping, Vasili.

One Ping only, please.

(The Hunt for Red October)