New_Ping.h library that runs on Photon and Electron won't run on a Boron

I have code that interfaces to a JSN-SR04T ultrasonic sensor and reports the height and number of gallons of water in a large storage tank that runs perfectly on a Photon and on an Electron, but won’t even flash to a Boron. The code - below - includes the New_Ping.h library file written by Tim Eckel. The errors that I get when I try to flash to a Boron are attached as a screenshot. When I queried Tim about the issue, he replied “The problem is the Boron (and all Gen 3 devices) not supporting the SparkIntervalTimer library (as the errors are noting). It seems even the latest version doesn’t support the Gen 3 devices.”

Can anyone suggest an alternative to the New_Ping.h library for this app?

Code:

// This #include statement was automatically added by the Particle IDE.
#include <New_Ping.h>
#include <Wire.h>

// Define variables:
int gallons;
int distance;
int height;
//int arraydistance;
int gap = 0; // Distance between sensor and maximum water level

#define trigPin 2
#define echoPin 3
#define MAX_DISTANCE 400
NewPing sonar = NewPing(trigPin, echoPin, MAX_DISTANCE);

void setup() {
    Serial.begin(9600); // Set the speed of the I2C port on the Photon and start it.
    Wire.begin();   
    Particle.function("Gallons", getGallons);
    Particle.function("Inches", getInches);
  }

// For MTWA:
// int depth [29] = {1480,1438,1396,1356,1316,1271,1226,1186,1146,1096,1046,1003,961,919,876,831,786,741,696,656,616,571,526,482,438,396,354,309,264};
// For Steve Swanberg:
int depth [67] = {919,905,891,877,863,849,836,822,808,794,780,766,752,738,724,710,696,682,668,654,641,627,613,599,585,571,557,543,529,515,501,487,473,460,446,432,418,404,390,376,362,348,334,320,306,292,279,265,251,237,223,209,195,181,167,153,139,125,111,97,84,70,56,42,28,14,0};

// Function to retrieve gallons
int getGallons(String command) { 
    distance = sonar.ping_in(); // In inches
    distance = distance - gap;
    height = 67 - distance;
    gallons = depth [distance];
    return gallons;
} // End getGallons Function

// Function to retrieve height

int getInches(String command) { 
    distance = sonar.ping_in(); // In inches
    distance = distance - gap;
    height = 67 - distance;
    gallons = depth [distance];
    return height;
} // End getInches Function

void loop() {

distance = sonar.ping_in();// In inches
distance = distance - gap;
height = 67 - distance; // Maximum height of water in tank
gallons = depth [distance];


if (distance <10) {
    Particle.publish ("Gallons","Error",60, PRIVATE);
    Particle.publish ("Inches","Error",60, PRIVATE);
  }

else {
    Particle.publish ("Gallons",String(gallons),60, PRIVATE);
    Particle.publish ("Inches",String(height),60, PRIVATE);
 }
  
delay(300000); // Take a measurement every 5 minutes
   
}

Hi Brian-

That sounds extremely frustrating. I can’t find a good replacement that works on Boron but I’ll look into it further.

Thanks Colleen.

@blshaw45, @Colleen, the new_ping library makes use of the SparkIntervalTimer library that uses the extra STM32 hardware timers available in the STM32F205 of the Photon and Electron. Unfortunately, there are not extra hardware timers in the nRF52840 used in the Boron.

There is and existing HC_SR04 v1.01 library on the WebIDE. It was written 5 years ago and relies on an ATOMIC_BLOCK and micros() to get an accurate distance. Using ATOMIC_BLOCK prevents other threads and interrupts from running so the library limits max time it ways on a pulse response. Used carefully, this library might work for you.

4 Likes

Thanks peekay123! Unfortunately, I have no idea what most of your info means, but the reference to the HC_SR04 library I do understand. I am awaiting arrival of a couple of new Borons and when they get here next week and I’ll recompile with that file. I’ll post the results here. If it works, your next few beers will be on me!!

1 Like

I created a new library to read a JSN-SR04 ultrasonic distance sensor accurately on Gen 3 Particle devices (Argon, Boron, B Series SoM, Tracker SoM using the nRF52840 MCU). It does so without ever disabling interrupts and it’s accurate to less than 0.3 cm even when using the BLE radio. It does not require any timer resources, which are scarce on the nRF52.

It’s completely non-blocking and you can theoretically measure a distance every 10 milliseconds with a range up to 1 meter. It only generates two MCU interrupts per measurement, and if the interrupt delayed by higher priority interrupts, or disabled interrupts, it does not affect the accuracy of the timing.

It requires a lot of GPIO (4 GPIO) and some RAM (2,080 bytes for the default maximum of 1 meter, reconfigurable). It uses the I2S (S is in sound, not I2C) peripheral on the nRF52 as a digital IO to DMA engine to accurately generate the TRIG and measure the ECHO pulse entirely in hardware without running code on the MCU.

Full documentation and more information in the Github repository

5 Likes

You da man Rick!! Of course, not being anywhere near as savvy as you - or most everybody else on this forum - much of what you said in your post is completely greek to me. So I have a few questions:

  • Should your library be a simple one-for-one replacement for the New_Ping library or am I going to have to modify my code as well?
  • Will your library also work on a Photon or only Gen 3 devices?
  • Does your statement regarding “a range of up to one meter” mean that that is the maximum range, period, on the maximum range that would allow a 10 millisecond turn-around time?

Whatever clarification you can offer will be greatly appreciated.

BTW, I have tweaked my code a little bit, but it still uses the New_Ping library because it is currently running on a Photon:

// This #include statement was automatically added by the Particle IDE.
#include <New_Ping.h>

// Define variables:
int gallons;
int distance; // Distance from sensor to bottom of tank
int height; //. Height of water in the tank
int gap = 4; // Distance between sensor and maximum water level

#define trigPin 2 // 10 on breadboard
#define echoPin 3 // 9 on breadboard
#define MAX_DISTANCE 400
NewPing sonar = NewPing(trigPin, echoPin, MAX_DISTANCE);

void setup() {
    Particle.function("Gallons", getGallons);
    Particle.function("Inches", getInches);
  }

int depth [70] = {500,493,486,479,471,464,457,450,443,436,429,421,414,407,400,393,386,379,371,364,357,350,343,336,329,321,314,307,300,293,286,279,271,264,257,250,243,236,229,221,214,207,200,193,186,179,171,164,157,150,143,136,129,121,114,107,100,93,86,79,71,64,57,50,43,36,29,21,14,7};

// Function to retrieve gallons
int getGallons(String command) { 
    distance = sonar.ping_in(); // Inches to top of water
    distance = distance - gap; // Adjust for air gap between top of water and sensor
    gallons = depth [distance];
    return gallons;
} // End getGallons Function

// Function to retrieve height
int getInches(String command) { 
    distance = sonar.ping_in(); // Inches to top of water
    distance = distance - gap;
    height = 70 - distance; // Inches above bottom of tank
    return height;
} // End getInches Function

void loop() {

distance = sonar.ping_in();// Inches to top of water
distance = distance - gap;
height = 70 - distance; // // Inches above bottom of tank
gallons = depth [distance];

if (distance <10) {
    Particle.publish ("Gallons","Error",60, PRIVATE);
    Particle.publish ("Inches","Error",60, PRIVATE);
  }

else {
    Particle.publish ("Gallons",String(gallons),60, PRIVATE);
    Particle.publish ("Inches",String(height),60, PRIVATE);
 }
  
delay(60000); // Take a measurement every 5 minutes
   
}

HI,

No is a not simple replacement and you have to modify your code.
You can give a try with this one: Particle Web IDE
but this is just a simple/dirty/fast :see_no_evil: modification of rickkas7 simple example.

no just Gen 3 devices

sorry but I don't know the answer for this question :slight_smile:

Hope that's gonna help some how
Best,
Arek

1 Like

Thanks Arek!!

Nope, but for a longer range you'd need to donate more RAM for the measurement.

That's answered in the GitHub repo's ReadMe :wink:

Hi yet again Rick. As I think you already know, I am not a professional in this arena. I’m simply the only person in my community who can read binary. Beyond that, I know very little about any of this stuff, so here I go again asking for help.

I read your readme file on Github and I need to better understand the following: "Particle Gen 3 devices are not 5V tolerant because the nRF52840 MCU is not! Be sure to use a level shifter on the ECHO output from the JSN-SR04 to the GPIO on the Particle device, or you will likely permanently damage the pin on the Particle device.

Also note that since you need 5V you will not be able to power the sensor off the LiPo battery unless you use an external boost converter. If you are powered by USB, you can power the sensor from the VUSB bin."

I wanted to power the JSN-SR04 off the VUSB pin (tried powering it off 3.3 volt in conjunction with a Photon but it was unreliable; 5 volts made it very happy). But, per your readme, I must include a level shifter which will - if I understand correctly - convert 5 volt to 3 volt so as to not damage the Boron. Is that all correct? But I found this comment about the 74AHCT125 elsewhere on line (74AHCT125 - Quad Level-Shifter (3V to 5V) [74AHCT125] : ID 1787 : $1.50 : Adafruit Industries, Unique & fun DIY electronics and kits): “It is good for shifting from a low voltage logic signal (3.3v, say) up to a 5V logic signal. It can’t shift down from 5V to 3.3V.” Huh?

If you are powering by USB, you can use VUSB as an output, which will be a 4.8 to 4.9V, which is high enough for the JSN-SR04.

However, the ECHO pin from the sensor will exceed the 3.3V maximum of the Boron (nRF52840).

This is one way, using the SN74LVC1T45:

It’s also possible to a 74AHCT125, which is available in a breadboard-friendly PDIP package.

It’s also possible to use a MOSFET transistor.

1 Like

Would I be correct that the same concern about voltage would apply to an Argon if we were to switch to WiFi?

The 3.3V limitation is true for all Gen 3 devices (Argon, Boron, B Series SoM, and Tracker SoM) using the nRF52840 MCU.

The STM32F205 MCU in the Photon, P1, Electron, and E Series is 5V tolerant on most pins and doesn’t need a level-shifter, except on A3 and A6.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.