Fiddling with sensors

Sending bytes is all fine and dandy but let’s add a sensor to the mix. The ultrasonic sensor HC-SR4 are cheap and plentiful so let’s make an NB-IoT enabled ultrasonic sensor in case you want to be alerted every time someone approaches your precious module. You wouldn’t want anyone stealing it so let’s get cracking.

The majority of these comes with four pins – one for power, one for ground, one for trigger and one for echo. The way they work is that you trigger a small pulse with the trigger pin, then wait for the response on the echo pin. The time it takes to respond corresponds with the measured distance. The time-to-distance conversion is usually printed in the data sheet. The quick solution is to measure the number of microseconds from the trigger pulse to the echo pulse and divide on 58. Arduino comes with a handy pulseIn() function for this purpose:

#define TRIGGER_PIN 7
#define ECHO_PIN 8

float measureDistanceCm() {
    digitalWrite(TRIGGER_PIN, LOW);
    delayMicroseconds(2);
    digitalWrite(TRIGGER_PIN, HIGH);
    delayMicroseconds(5);
    digitalWrite(ECHO_PIN,LOW);

    return pulseIn(ECHO_PIN,HIGH) / 58.0f;
}

There’s some variants of the same sensor with just three pins where there’s a single pin for echo and trigger – the code for this is similar:

#define ET_PIN 7

float measureDistanceCm() {
    pinMode(ET_PIN, OUTPUT);
    digitalWrite(ET_PIN, LOW);
    delayMicroseconds(2);
    digitalWrite(ET_PIN, HIGH);
    delayMicroseconds(5);
    digitalWrite(ET_PIN,LOW);
    pinMode(ET_PIN,INPUT);

    return pulseIn(ET_PIN,HIGH) / 58.0f;
}

If there’s nothing in front of the sensor it will send the echo pulse after 38ms, ie it will return a distance of 3800058 ~ 655 cm. Let’s handle that later and just look at the raw data first.

Start a blank sketch, run the ultrasonic code and print the measured distance via the Serial library:

void setup() {
  Serial.begin(115200);
  while (!Serial) ;
}

#define ET_PIN 7

float measureDistanceCm() {
    pinMode(ET_PIN, OUTPUT);
    digitalWrite(ET_PIN, LOW);
    delayMicroseconds(2);
    digitalWrite(ET_PIN, HIGH);
    delayMicroseconds(5);
    digitalWrite(ET_PIN,LOW);
    pinMode(ET_PIN,INPUT);

    return pulseIn(ET_PIN,HIGH) / 58.0f;
}

void loop() {
  float d = measureDistanceCm();
  Serial.println(d);
  delay(100);
}

Looking at the Serial Plotter we get quite some noise when the distance increases. Let’s first get rid of the invalid measurements in the measureDistanceCm function and skip invalid plots:

float measureDistanceCm() {
  pinMode(ET_PIN, OUTPUT);
  digitalWrite(ET_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(ET_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(ET_PIN,LOW);
  pinMode(ET_PIN,INPUT);

  float distance = pulseIn(ET_PIN,HIGH) / 58.0f;
  if (distance > 400) {
    return -1.0f;
  }
  return distance;
}

void loop() {
  // put your main code here, to run repeatedly:
  float d = measureDistanceCm();
  if (d >= 0) {
    Serial.println(d);
  }
  delay(100);
}

The serial plot looks a lot better now: