Introduction: Circuit Playground Express and Ultrasonic Distance Measurement in Makecode

The Adafruit Circuit Playground Express is a sensor-packed development board which supports four languages: block-based MakeCode (similar to MIT's Scratch), MakeCode javascript, CircuitPython and C. The HC-SR04 is an inexpensive distance sensor based on a pair of ultrasonic transducers with a straightforward TTL interface. This is a simple example demonstrating distance measurement in MakeCode inspired by the BBC micro:bit example.

The Adafruit board must be the express version to use Makecode, the classic version only supports C.

There's now an extended version of this article on Adafruit Learn: Distance Measurement with Ultrasound.

Step 1: Connecting the HC-SR04 to the CPX Board

The common HC-SR04 boards are designed for 5V TTL voltage levels. Since the advent of CMOS many circuits started using 3.3V levels including the Adafruit CPX board, this can create compatibility problems. The guide to Adafruit CPX Pinouts states:

All of the GPIO pads are 3.3V output level, and should not be used with
5V inputs. In general, most 5V devices are OK with 3.3V output though.

This creates a requirement to reduce the voltage from the Echo output of the HC-SR04 rather than simply directly connecting all of the sensor's pins to the CPX board. The easiest way to reduce a single voltage is to use two resistors as a potential divider. The example shown uses two equal resistors to halve the voltage. 2.5V is clearly lower than 3.3V but this is high enough to work. The sum of the two resistors should be above 1 kiloohm to keep within the current limits of the sensor.

In the breadboard example everything is connected directly to the CPX board apart from the Echo output which goes through the two 2.2 kiloohm resistors. The CPX input A1 pin connects in the middle of this pair. The connections are:

  • Black: Gnd (row 21) to GND and row 1 is connected to ground too.
  • Red: Vcc (row 24) to VOUT.
  • Green: Echo (row 22) to potential divider (row 11, a pair of 2k2 resistors across row 6 and row 1).
  • White: divided voltage (row 6) to A1.
  • Yellow: Trig (row 23) to A2.

A0 can be used as an output for the sensor's Trig pin if you want the surprise of hearing the trigger pulses. The CPX board has A0 hard wired up to its small speaker.

For comparison: the Raspberry Pi has the same 3.3V limitation on GPIO inputs; many of the Arduino boards like the Uno are 5V tolerant for inputs, allowing direct connection of this sensor.

The standard HC-SR04 will appear to work at 3.3V but apparently is far less accurate. There are versions of it sold as 3.3V tolerant. There's a detailed discussion on some of the variations of this sensor board on David Pilling's HC-SR04 page.

Step 2: MakeCode

The sample MakeCode is shown above and is also available as a published project.

The code is a simple loop sending a pulse to A1 output pin and then measuring the pulse on A2 input pin with the Makecode pulse in pin block. The division by 58 converts the timed value into centimetres and this value is then show on the neopixels up to a value of 30cm. The distance is also represented by a short beep with frequency between 50Hz (0.25cm) and 10kHz (50cm). The distance is also logged but this is only visible if you are using the Windows 10 app version of Makecode.

It's not clear if this sensor has a maximum measuring rate or a required pause after the Echo pulse before the next measurement. If it does then the code has a minor flaw as it's relying on the console log as a delay if the distance is out of range for the beep to occur.

The value of 58 or 58.2 is often seen in example code. It's worth exploring where this "magic" number comes from. The Echo high pulse duration represents the time for the first detected reflection. The speed of sound varies mainly with temperature and to a far lesser degree by humidity. The chirp travels to the target and is reflected back, its journey is twice as long as the distance. 58 represents an assumption that the speed of sound is 1000000 / 58 * 2 / 100 = 344.8 metres per second. 344.8m/s would equate to a 21.6 degrees celsius (70.8 fahrenheit), 40% relative humidity day.

Step 3: Moving Target Video

The video (animated gif) shows the sensor measuring the distance to a moving piece of paper and indicating this via the number of NeoPixels illuminated. The paper doesn't move far enough away to light up the tenth NeoPixel.

Step 4: A Look at the Pulses

A logic analyser can be used to look at communication between the CPX board and sensor. It can also be connected to the ultrasonic transmitter to see the high frequency chirp but won't work on the unamplified receiver output. A basic logic analyser cannot show the full detail of the analogue voltages as it makes everything appear square. There are some examples of what the signal really looks like on David Pilling's HCSR04 page.

The screenshot on the left shows three distance measurements. The screenshot on the right is one of the measurements zoomed in showing:

  • Trig (yellow): the pulse requesting the sensor to make a measurement
  • Tx Pulses (blue): the actual burst of eight pulses which constitue the ultrasonic chirp
  • Echo (green): the sensor's output measured by the logic analyser as 858 microseconds.

The 858 microseconds divided by 58 gives 14.8cm. The target was placed at 15.0cm which suggests this can be very accurate. The voltage thresholds on the logic analyser may differ by a tiny amount compared to the CPX board.

The TX Pulses can be used to determine the audio frequency. Using a higher resolution trace made at 25MHz (not shown), measuring seven pulses from the leading edge for best accuracy gives 173.24 microseconds, 7 / 173.24 * 1000 = 40.41kHz, clearly in the ultrasound range.