Pixelblaze w/HC-SR04 Distance Sensor

I was done with work early today, so instead of digging in to the backlog of Useful and Important Projects, I decided to take a quick look at what might be done with this very timing dependent ultrasonic distance sensor. Thought it might be fun for proximity based interactive toys and art and such. Source code below the video.

I hooked the sensor to GPIO 4 & 5 on a Pixelblaze 2, and used the “Performance test framework” from the library to figure out workable delays.

There’s also a function that detects what model Pixelblaze the pattern is running on (2+, 3 or nano) based on capacitance on the “orange LED” GPIO pin. It works on every Pixelblaze I’ve tried it on, but is definitely not guaranteed. It may break with firmware revisions. Interesting to know that you can do that though.

I’d planned to use it to adjust delay based on CPU speed, but didn’t have a PB3 around that I could solder random things to, so it just sets the color of the LEDs based on PB model…

/*
Read approximate distance from an HC-SR04 Ultrasonic sensor using GPIO

MIT License

ZRanger1 6/7/2021
*/

var triggerPin = 4;
var echoPin = 5;
pinMode(triggerPin,OUTPUT);  
pinMode(echoPin,INPUT);  

var sensorTimer = 999;
var maSize = 6;
var aIndex = 0;
var avgBuffer = array(maSize);

// maxIterations controls the maximum measurable distance. On a 
// Pixelblaze2, 1500 is about 1.5 meters.  Minimum measurable distance is
// about 15cm (6 inches), determined to some extent by the Pixelblaze's
// execution speed. 
var maxIterations = 1500;   

// retrieve the Pixelblaze type so someday we can set delay times.
// appropriately.
var hw = getHardwareType();

// something like 1.8ms measured delay on PB2.  TBD - Will
// need to increase delay time on PB3
function delay() {
  ;
}

// average the last <maSize> readings to get rid of some
// of the noise and stabilize our distance reading.
function avgNewReading(dist) {
  var r = 0;
  avgBuffer[aIndex] = dist;
  aIndex = (aIndex + 1) % maSize;
  for (var i = 0; i < maSize; i++) {
    r += avgBuffer[i];
  }
  return r / maSize;
}

// Attempt to detect the Pixelblaze variant the pattern is
// currently running on, based on differences in capacitance 
// returned by touchRead on the "orange LED" GPIO Pin (GPIO12)
//
// Returns: 0 - Pixelblaze 2, 1 - Pixelblaze 3, 2 - Pixelblaze Nano
function getHardwareType() {
  var hw = 0;   // default to pb2
  
  var e = touchRead(12);
  if (e == 0) { hw = 2; }
  else if (e >= 0.99) hw = 1;
  
  return hw;
}  

// send a brief pulse on the trigger pin to start the sensor
function triggerSensor() {
  digitalWrite(triggerPin,LOW);
  delay();
  digitalWrite(triggerPin,HIGH);
  delay();
  delay();
  digitalWrite(triggerPin,LOW);  
}

// wait for the sensor to receive an echo.  Length of the
// wait time determines distance.  It times out in about 38ms
function readSensor() {
  var t = 0;
  // wait for echo pin to go high, indicating that we've
  // started listening.
  while (!digitalRead(echoPin)) {
    if (t++ > 100) break;
  }
  
  // measure how long it takes for echo pin to return to low
  // this will give us a rough distance estimate.
  t = 0;
  while(digitalRead(echoPin)) {
    // if we hit timeout, set the echo pin to LOW
    // to reset the hardware, which otherwise can get stuck
    if (t++ >= maxIterations) {
      pinMode(echoPin,OUTPUT);
      digitalWrite(echoPin,LOW);
      pinMode(echoPin,INPUT);
      break;
    }
  }
  return t / maxIterations;
}

export var distance;
export function beforeRender(delta) {
  sensorTimer += delta;
  
  if (sensorTimer > 50) {
    triggerSensor();
    distance = readSensor();
    distance = avgNewReading(distance);
    sensorTimer = 0;
  }
}

// Display red for pb2, green for pb3, blue for nano, moving lit area of pixels 
// down the strip according to distance sensor reading.
export function render(index) {
  h = hw * 0.3333; // color according to Pixelblaze type.
  s = 1
  v = abs((index / pixelCount) - distance) < 0.1;
  hsv(h, s, v)
}
2 Likes

interesting, and cool. I have to look, but I think I have a bunch of these

which are similar but only use 1 pin instead of 2. I’ll have to see if I can adapt this to work.

Looks like a good “garage backup space indicator” among other simple uses.

2 Likes

Only having one signal line would be a definite improvement. But darn it, you made me look at the seeedstudio store! All the strange and wonderful sensors! And I’ve wanted a Bus Pirate for a while. There goes the monthly electronic project budget…

1 Like

If only I made a commission on all of the cool stuff I find that other people buy… :slight_smile:
I could afford to buy more myself.

BTW, the m5stack store also has a bunch of nifty sensors, and I agree with Ben, they often seem underpriced, compared to other sources. Between these two sources, you can find so much “plug and program” stuff.

1 Like