Ultrasonic Distance Ranger#

Create a simple rangefinder that reports distance, measured in millimeters, to a real-time display.

Particle CLI#

Installation#

%%capture
!bash <( curl -sL https://particle.io/install-cli )

Utility functions#

import re
import subprocess

# regular expression to strip ansi control characters
ansi = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')

# decode byte string and strip ansi control characters
def decode_bytes(byte_string):
    if isinstance(byte_string, bytes):
        result = byte_string.decode("utf-8")
    return ansi.sub("", result)

# streamline call to the particle-cli
def particle(args, particle_cli="/root/bin/particle"):
    process = subprocess.run([particle_cli] + args,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
    process.stdout = decode_bytes(process.stdout)
    process.stderr = decode_bytes(process.stderr)
    return process

Login to Particle#

import getpass

# prompt for username and password
username = getpass.getpass(prompt="Username: ")
password = getpass.getpass(prompt="Password: ")

# attempt login
output = particle(["login", "--username", username, "--password", password])

# report results
if output.returncode:
    print(f"Return code = {output.returncode}")
    print(output.stderr)
else:
    print(output.stdout)
Username: ··········
Password: ··········
> Successfully completed login!

Select a device#

The following cell downloads a list of all user devices and creates a list of device names. Here we choose the first name in the list for the rest of this notebook. If this is not the device to be used, then modify this cell accordingly.

devices = [line.split()[0] for line in particle(["list"]).stdout.splitlines()]
device_name = devices[0]
print(particle(["list", device_name]).stdout)
jck_argon_01 [e00fce68eaceb1faa7cf7193] (Argon) is online

Project Hardware#

Grove Ultrasonic Ranger#

SeeedStudio description

The Grove Ultrasonic Ranger emits a sequence of eight short bursts of 40 kHz sonic signals, then measures duration until an echo is detected. The sonic signals are triggered by applying a 10 microsecond pulse to the GPIO pin connecting to the device. The duration until echo detection is returned as a pulse on the same GPIO pin. The pulse duration can be measured using the pulseIn() function of the standard Arduino or Particle API.

Grove 4 Digit Display#

Implementation#

Create Project#

print(particle(["project", "create", "--name", "myproject", "."]).stdout)
Initializing project in directory myproject...
> A new project has been initialized in directory myproject

Change working directory#

The Particle CLI assumes one is working in the top project directory.

%cd /content/myproject
/content/myproject

Add relevant libraries#

print(particle(["library", "add", "Grove_4Digit_Display"]).stdout)
> Library Grove_4Digit_Display 1.0.2 has been added to the project.
> To get started using this library, run particle library view Grove_4Digit_Display to view the library documentation and sources.

Create source file#

%%writefile src/myproject.ino

/* Grove 4 digit display */
const int pinCLK = D2;         /* display clock pin */
const int pinDIO = D3;         /* display data pin */
const int digits = 4;          /* display digits */

#include "Grove_4Digit_Display.h"
TM1637 tm1637(pinCLK, pinDIO);

/* Grove ultrasonic ranger */
const int pinULTRASONIC = D4;  /* ultrasonic ranger pin */

void setup() {
    /* setup display */
    tm1637.init();
    tm1637.set(BRIGHT_TYPICAL);
    tm1637.point(POINT_OFF);
}

void loop() {
    display(measureDistance(pinULTRASONIC));
    delay(100);
}

void display(unsigned int number) {
    for (int i = 0; i < 4; i++) {
        int digit = digits - 1 - i;
        tm1637.display(digit, number % 10);
        number /= 10;
    }
}

int measureDistance(int pin) {
    /* send a pulse */
    pinMode(pin, OUTPUT);
    digitalWrite(pin, LOW);
    delayMicroseconds(2);
    digitalWrite(pin, HIGH);
    delayMicroseconds(10);
    digitalWrite(pin, LOW);

    /* measure duration of response pulse in microseconds */
    pinMode(pin, INPUT);
    unsigned long duration = pulseIn(pin, HIGH);

    /* distance in mm = 0.344 mm/micro-sec` * duration / 2 */
    return(0.172*duration);
}
Overwriting src/myproject.ino

Compiling#

print(particle(["compile", "argon", "--saveTo", "myproject.bin"]).stdout)
Compiling code for argon

Including:
    src/myproject.ino
    project.properties

attempting to compile firmware
downloading binary from: /v1/binaries/5f95722fabefb30aacbc7337
saving to: myproject.bin
Memory use:
   text	   data	    bss	    dec	    hex	filename
   8440	    108	   1068	   9616	   2590	/workspace/target/workspace.elf

Compile succeeded.
Saved firmware to: /content/myproject/myproject.bin

Flash firmware#

print(particle(["flash", device_name, "myproject.bin"]).stdout)
Including:
    myproject.bin

attempting to flash firmware to your device jck_argon_01
Flash device OK: Update started

Flash success!