2

I am trying to get the NodeMCU ESP8266 dev board to work with an HC SR04 Ultrasonic Sensor. I keep getting a reading of "0", which is not the reality.

I have the ground and 5v pins of the sensor hooked up to a 5v source, and the Echo and Trigger pins on GPIO pin 4 and 5. In theory, everything should be working, but I just keep getting "0". Perhaps there is something wrong with my code? See below:

import machine
import sys
import time
time.sleep(1) #Just for everything to settle down

while 1:

    pinTrigger = machine.Pin(5, machine.Pin.OUT) #defining the pins
    pinEcho = machine.Pin(4, machine.Pin.IN) #defining the pins

    pinTrigger.high()
    time.sleep(0.00001)
    pinTrigger.low()

    time.sleep(0.5)

    start = time.time()
    stop = time.time()

    while pinEcho ==0:
        start = time.time() #Starting the time when sending out the signal

    while pinTrigger ==1:
        stop = time.time() #Stopping the time when the signal comes back

    elapsed = stop-start #working out the time.

    distance = elapsed * 34000 #multiply by speed of sound to get distance

    distance = distance / 2 #divide by 2 becuase it was there and back

    print ("Distance : %.1f" % distance) 

    sys.exit()

Please help.

LukeVenter
  • 439
  • 6
  • 20
  • `while pinEcho ==0: start = time.time()` is very inefficient and you might miss the time window in which the pin is low. In such cases, one would use interrupts. (see http://docs.micropython.org/en/latest/wipy/reference/isr_rules.html). The first step to increase performance would be to replace the computation of the `start` variable by `pass` (i.e. do nothing), and then compute `start` when you're out of the `while` loop. Same for `stop`. The next thing: `time.time()` might have a too low accuracy. The speed of sound is incredibly high, and thus you would need to messure in the microseconds – Maximilian Gerhardt Feb 23 '17 at 14:08
  • range to get accurate results. If `time()` is in milliseconds, that might be too coarse. Print your `stop-start` to the console, if it is `0`, then your timer is not good enough. Again, you need to switch to interrupts, wait on the `FALLING_EDGE` event, then save the current time in microseconds, then wait for the `RISING_EDGE` on the echo pin, save the time, then compute the time difference. – Maximilian Gerhardt Feb 23 '17 at 14:10
  • What is `time.sleep(0.5)` for? Why do you make your code sleep 500 msec? – Mert Gülsoy Feb 24 '17 at 09:01
  • Have you looked at this thread on the micropython forum: http://forum.micropython.org/viewtopic.php?f=16&t=2436 ? – nekomatic Feb 24 '17 at 10:52
  • Thanks so much for all the help guys! @nekomatic - Are these libraries that I refer to in my main.py code, or is this the actual code itself? I'm just trying to figure all this out. – LukeVenter Feb 27 '17 at 08:25
  • There are three different offerings on page 3 of that forum thread; the ones from 'jpedrodias' and 'filipmar.mf' are intended to be saved as a Python module and imported into your code using e.g. `import ultrasonic`, but you could just copy and paste their code into yours. The code from 'dbalnaves' should work as is, although he notes it sometimes crashes (also note the indentation he uses is non-standard). All three look pretty similar though - the key appears to be the use of `time.ticks_us` for accurate timing. I think you should be able to get something working based on one of those. – nekomatic Feb 27 '17 at 11:10
  • Thanks so much, @nekomatic - I definitely need more experience here! Getting there. I found that with my original code, using time.ticks_us starts to give me a reading. The reading is strange, but I'm getting somewhere. I've noticed that it's either X, or 2X. So basically I'll get approximately 11, or approximately 22. Will try to figure it out. – LukeVenter Feb 27 '17 at 11:49
  • On further investigation, it's just giving me approx the same two readings all the time - think it's a timing issue. I'll revert back. :) – LukeVenter Feb 27 '17 at 12:07
  • Ok, there's a real problem. Even when I disconnect the sensor, I still get the same reading. :/ – LukeVenter Feb 27 '17 at 13:35

2 Answers2

1

Here is what solved the problem:

import machine
import utime


while True:
  trig=machine.Pin(5, machine.Pin.OUT)
  trig.off()//stop reading
  utime.sleep_us(2)
  trig.on()
  utime.sleep_us(10)
  trig.off()
  echo=machine.Pin(4, machine.Pin.IN)
  while echo.value() == 0:
    pass
  t1 = utime.ticks_us()
  while echo.value() == 1:
    pass
  t2 = utime.ticks_us()
  cm = (t2 - t1) / 58.0
  print(cm)
  utime.sleep(2)

Elsewhere on the internet they suggested that you put a resistor inbetween the echo and the pin on the NodeMCU board (ESP8266), This made the measurements trip out pretty badly. So right now I have it working 100% with 5v and Ground (to the HC-SR04) connected to my RPi GPIO, and the trigger and echo connected to the NodeMCU board pins.

Another thing to note is that I was doing readings at 1s, (last line of the code), changing that to 2 seconds made the code a lot more accurate.

Hope this helps someone.

Here's the diagram:

Working Diagram

LukeVenter
  • 439
  • 6
  • 20
  • I wouldn't advise people to connect a 5v-powered device to something which is only 3.3v-tolerant, but the general approach is very good. On my robot, I started with this code, then made it a separate function and added timeouts to each of the while loops. Mine is using a 1k resistor inline with the Echo pin. Seems pretty robust. – Alex Shroyer Jul 11 '17 at 14:27
  • So happy that this helped you. Would love to see your project! – LukeVenter Jul 13 '17 at 09:35
  • "while True: trig=machine.Pin(5, machine.Pin.OUT)" You are assigning the pin every time you loop. Make the pin assignments outside of your loop – Paul Allsopp Apr 23 '19 at 01:05
0

Take a look at this library to get it easier to work with HC-SR04 Sensor driver in micropython.

vaheeds
  • 2,594
  • 4
  • 26
  • 36