# Getting valid input from Ultrasonic range finder

(I am posting this question here since I feel that the issue is a part of my lacking understanding of the electronics, and not a )

I am trying to monitor the feed hopper for my pellet furnace. I had a Seed Studio Ultrasonic range finder lying about

I used an example script to get started, and set up some simple "error correcting" before setting it up by the hopper.

Everything works generally as it should. I am running into two issues though;

1. I need to point the Ultrasonic Sensor into the hopper in a way so that the cone sees the sides of the hopper as little as possible.

2. I get much bigger spikes in my data (a factor of 1000 bigger) after mounting the sensor than while testing in my office. How do I solve this? do I need another sensor, or should I filter it out in the code as bad reads?

Additional questions: I am aware that Ultrasonics can be affected by particles in the air and temperature. should I consider another sensor?

Sample Data:

* = potentially a hit on another surface than the pellets in the hopper

44              2018-10-17 11:08:39
33              2018-10-17 11:24:40 *
41              2018-10-17 11:25:00
49              2018-10-17 12:01:03
42              2018-10-17 12:01:23
36              2018-10-17 13:41:49 *
340376          2018-10-17 13:43:09 ???
40              2018-10-17 13:43:29
33              2018-10-17 14:06:50 *
40              2018-10-17 14:07:10
32              2018-10-17 14:56:13 *
40              2018-10-17 14:56:33
30              2018-10-17 15:24:35 *
39              2018-10-17 15:24:55
32              2018-10-17 15:56:57 *
41              2018-10-17 15:57:17
35              2018-10-17 16:34:59 *
41              2018-10-17 16:35:39
33              2018-10-17 17:33:42 *
41              2018-10-17 17:34:02
49              2018-10-17 18:00:44
41              2018-10-17 18:04:44
49              2018-10-17 18:11:25
42              2018-10-17 18:12:25
52              2018-10-17 18:39:46
44              2018-10-17 18:40:06
36              2018-10-17 18:57:48 *
42              2018-10-17 18:58:08
69              2018-10-17 19:39:10
41              2018-10-17 19:39:30
68              2018-10-17 19:41:10
41              2018-10-17 19:41:30
48              2018-10-17 21:22:16
41              2018-10-17 21:27:56
48              2018-10-17 23:55:45
340385          2018-10-18 00:00:26 ???
45              2018-10-18 00:00:46
36              2018-10-18 00:31:48 *
44              2018-10-18 00:32:08
36              2018-10-18 01:02:49 *
44              2018-10-18 01:03:09
52              2018-10-18 06:28:29
44              2018-10-18 06:35:09
37              2018-10-18 07:48:54 *
44              2018-10-18 07:49:34
340395          2018-10-18 08:13:15 ???
46              2018-10-18 08:13:35


Here is the essential part of my code (Complete code on Github):

#function to calculate deviation between current and previously read value
def deviation(x,y):
diff = abs(float(x)-float(y))
avg = (float(x)+float(y))/2
return (diff/avg)

distance = int(round(duration*34000/2))
if (dev > allowableError):
#save last entry, only if deviation is big enough.
saveData(distance)
print str(distance) + "\t\t" + str(datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S'))


It is likely related to the overall system latency.

The problem is that on a raspberry, or similar linux system (and also applies to platform with an OS), you have a kernel that schedule the tasks (all the other programs running).

While your program may seem to execute continuously on your while (1), the system actually needs to execute other tasks, and can at any moment hang your program.

User-space programs have usually the lowest priority, unless otherwise specified.

What happens, is that sometimes, your program is not executed quickly enough as the system is busy handling other things, and thus time goes by between the time the pin is actually set to 1 and the program will check on it.

There are some way to bypass this issue, but it requires kernel level driver that can control and read the pins with lower latency but is fairly (very) complex to do to some non-kernel driver programmer.

To mitigate the problem, you can try to run the program with a higher execution priority. This will probably help, but may not totally solve the issue.

You can also add a software filtering to ignore those mistaken issues.

Another option, perhaps the best, if your raspberry has several CPU Core, would be to reserve a core for your program alone, so it wouldn't be interrupted

Overall, the best solution would be to use an Arduino like device to control the sensor, and then communicate to the raspberry through SPI or I2C. As the Arduino doesn't have a kernel to or the need to run over tasks, you will have much more accurate measurements on the timings.

• Thank you for the answer. I actually started off with and arduino, and switched since i didn't want a whole computer in the furnace room... It's a 1st gen pi, so dedicating a core isout of the question. I will consider going down the arduino path again, but maybe just start off with software filtering first of all. – Jonas Stumph Stevnsvig Oct 18 '18 at 11:47
• Try at least to increase the process priority, that should be fairly easy. – Damien Oct 18 '18 at 11:52
• Corner reflectors (inadvertent patterns in your pellets) will respond to off-main-lobe energy, and confuse the measurement. – analogsystemsrf Oct 19 '18 at 4:41
• @analogsystemsrf I have considered using an array of ir leds and an opposing array of light sensors, to get a vague indication of the level instead. Is that a better approach? – Jonas Stumph Stevnsvig Oct 19 '18 at 10:00