Strange behavior of test code

Greetings,

I am experimenting with a sonic proximity sensor and I am using some demo code from the internet. The original demo project had a servo, that is why you will see a deg variable. Here is the code:

#define TRIG_PIN A0
#define ECHO_PIN A1

#include <NewPing.h>

#define MAX_DISTANCE 300
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE); 
char dist[3];
String output = "";

void setup() {
  pinMode (TRIG_PIN, OUTPUT);
  pinMode (ECHO_PIN, INPUT);
  Serial.begin(9600);
  Serial.println("===== Ultrasonic sonar =====");
}

void loop() { 
  // scan right to left
  for (int deg = 10; deg < 170; deg+=5) {
    //myServo.write(deg);
    delay(300);
    displaySonar();
  }

  // scan left to right
  for (int deg = 170; deg > 10; deg-=5) {
    //myServo.write(deg);
    delay(300);
    displaySonar();
  }
}

void displaySonar() {
  int distance = sonar.ping_cm(); 
  delay(30);
  if (distance < 0) distance = 0; 
  
  sprintf(dist,"%3d",distance);
  Serial.print("Range:");
  Serial.print(dist);
  Serial.print("cms/");
  for (int dloop = 0; dloop < distance/4; dloop++) {
    Serial.print("-");
  }
  Serial.println("=");
}

This code works and is printing:

===== Ultrasonic sonar =====
Range: 43cms/----------=
Range:  0cms/=
Range:  0cms/=
Range:  0cms/=
Range: 42cms/----------=
Range: 42cms/----------=
........

The problem I encounter is when I want to remove the loops (I have no servo and I want to use the sensor part of the demo only)

#define TRIG_PIN A0
#define ECHO_PIN A1

#include <NewPing.h>

#define MAX_DISTANCE 300
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE); 
char dist[3];
String output = "";

void setup() {
  pinMode (TRIG_PIN, OUTPUT);
  pinMode (ECHO_PIN, INPUT);
  Serial.begin(9600);
  Serial.println("===== Ultrasonic sonar =====");
}

void loop() { 
  delay(300);
  displaySonar();
}

void displaySonar() {
  int distance = sonar.ping_cm(); 
  delay(30);
  if (distance < 0) distance = 0; 
  
  sprintf(dist,"%3d",distance);
  Serial.print("Range:");
  Serial.print(dist);
  Serial.print("cms/");
  for (int dloop = 0; dloop < distance/4; dloop++) {
    Serial.print("-");
  }
  Serial.println("=");
}

After this, I only get this output:

===== Ultrasonic sonar =====
===== Ultrasonic sonar =====
===== Ultrasonic sonar =====
===== Ultrasonic sonar =====
===== Ultrasonic sonar =====
===== Ultrasonic sonar =====
===== Ultrasonic sonar =====
===== Ultrasonic sonar =====
.........

Why is this looping the setup()? Why does removing the loops break the program? How do I fix this.

Frankly, I have no idea.

Some help, please?

Oops.

char dist[3];

sprintf(dist,"%3d",distance);

Why do you use sprintf at all?

%3d places a minimum of 3 digits in dist. Your dist variable is only 3 chars long so no space for the terminating nul character. The result is a buffer overflow and after that all bets on the the behaviour of the code are of. Sometimes it works and the smallest change makes it fail.

Whandall:
Why do you use sprintf at all?

That's a very good question. I should actually think when I copy/paste from demos... And yes, removing it fixed everything.

sterretje:
Sometimes it works and the smallest change makes it fail.

So it's an unhandled exception/fault? Is there an indicator for these (besides the setup() loop)?

So it's an unhandled exception/fault?

It's an eight bit microcontroller - there is no MMU.

And regarding the usage of sprintf/snprintf:

those are very versatile and can be extremely useful,
but the are quite big and for printing a simple int absolutely overkill.

Your original sketch uses 5.894 bytes Flash and 276 bytes RAM.

A modified version of your sketch uses only 3.118 bytes Flash and 210 bytes RAM.

#include <NewPing.h>

const byte triggerPin = A0;
const byte echoPin = A1;
const int maxDistance = 300;

NewPing Sonar(triggerPin, echoPin, maxDistance);

void setup() {
  Serial.begin(250000);
  Serial.println(F("===== Ultrasonic sonar ====="));
}

void loop() {
  displaySonar();
  delay(300);
}

int displaySonar() {
  int distance = Sonar.ping_cm();
  if (distance < 0) {
    distance = 0;
  }
  Serial.print(F("Range: "));
  Serial.print(distance);
  Serial.print(F(" cm /"));
  for (int dloop = 0; dloop < distance / 4; dloop++) {
    Serial.write('-');
  }
  Serial.println(F("="));
  return distance;
}