Manually Control Multiple HC-SR04

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
lawrenceyy
 
Posts: 108
Joined: Thu May 07, 2015 12:32 pm

Manually Control Multiple HC-SR04

Post by lawrenceyy »

I am building a quick project that consists of 5 sonar sensors and 5 fans. When something is in range of a sonar sensor the corresponding fan turns on. I am using a feather M4 express (with circuitpython) and there are not enough pins for each sonar sensor to take two. I was hoping to funnel all the echo signals into one pin to reduce pin usage. Since the adafruit_hcsr04 module won't let me assign the same echo pin to two sonar sensors, I have to do this the manual way. I would trigger sonar1 and wait for an echo, trigger sonar2 and wait for an echo, and so on. I am running into 2 problems:

1. So I have to do a while loop to measure the duration of the high signal from echo. The problem is that time.monotonic() does not give me enough resolution (about 300mm) since it only goes to two decimals. The adafruit module gives me a resolution of 10mm or so. Is there anyway to measure duration to the accuracy of microseconds?

2. I am currently testing the set up with two sonar sensors. The wiring follows this example https://learn.adafruit.com/assets/62761 except I have two sonars , with both echos connected to row 11. With one sonar I can get readings, but with two sonars, the echo signal does not seem to make it back to the M4. Is the signal flowing from one sensor's echo into another sensor's echo? I am not an electrical engineer. Maybe this just won't work. Is it possible for one pin to receive signals from multiple sources (one at a time)? Maybe be I should tie together all the trig pins to one pin on the M4 and leave the echo pins separated (essentially the inverse of what I am currently doing).

Thanks.
Last edited by lawrenceyy on Sun Apr 21, 2019 2:54 am, edited 2 times in total.

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Manually Control Multiple HC-SR04

Post by adafruit_support_mike »

1) The function micros() gives you a clock value in microseconds, and you can use that to get timestamps at the beginning and end of a pulse.

2) You can't connect the output from multiple sensors to the same pin without putting something else in between. Some of the sensors will try to hold the line's voltage high while others are trying to pull it low, and that isn't good for any of them.

User avatar
lawrenceyy
 
Posts: 108
Joined: Thu May 07, 2015 12:32 pm

Re: Manually Control Multiple HC-SR04

Post by lawrenceyy »

Thanks for the response. I forgot to mention that I am working in circuitpython.

Can you show me how to use micros()? Micros() by itself did not work. Time.micros() did not work. I tried importing pyb to use pyb.micros() but it is not a recognized module(https://test-circuitpython.readthedocs. ... y/pyb.html). Is there another micros() you are referring to? I only have the default adafruit libraries as of now.

This is my current code:

Code: Select all

import time
import board
import digitalio
import busio
import adafruit_ssd1306

i2c = busio.I2C(board.SCL, board.SDA)
display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c)

#setup up trig and echo as list so they can be expanded on
trig=[]
trig.append(digitalio.DigitalInOut(board.D5))
for i in range(len(trig)):
    trig[i].direction=digitalio.Direction.OUTPUT
    trig[i].value=False
echo=[]
echo.append(digitalio.DigitalInOut(board.D6))
for i in range(len(echo)):
    echo[i].direction=digitalio.Direction.INPUT
    echo[i].pull=digitalio.Pull.UP

time.sleep(2)

#get distance function
def get_distance(trig_index,echo_index):
    def_start=time.monotonic()
    trig[trig_index].value=True
    time.sleep(.00001)
    trig[trig_index].value=False
    while time.monotonic()-def_start<1 and echo[echo_index].value==False:
        pulse_start=time.monotonic()
    while time.monotonic()-def_start<1 and echo[echo_index].value==True:
        pulse_end=time.monotonic()

    try:
        pulse_duration=(pulse_end-pulse_start)
        dist=round(343000*pulse_duration/2.0)
    except:
        dist=-1
        pass
    return(dist)

#get distance and display on featherwing OLED
while True:
    try:
        dist_0=get_distance(0,0)
        display.fill(0)
        display.text(str(dist_0),0,0,1)
        display.show()
    except RuntimeError:
        display.fill(0)
        display.text('No Distance Reading',0,0,1)
        display.show()
        pass
    time.sleep(0.1)
Is setting an input pin to pull up only applicable if you are connecting it to a physical button where the circuit is open? In this case, can I leave the echo pin as a regular pin?

Edit:

I did some additional testing and found that when I print the time.monotonic() values, only two decimals are shown. When I print the value of one timestamp minus another timestamp, I get six decimals. However, the resolution is about .002 seconds. As I move my hand away from the sensor, the echo duration change is very stepped, changing only at about each foot of distance. This makes sense because .002/2*343000 is 343 mm which is a little over a foot. The adafruit module gives me really fine resolution so I know it is not a hardware thing

I am reading this page (https://circuitpython.readthedocs.io/pr ... csr04.html) and I do not see any difference in the underlying method for getting echo duration. My monotonic() is in seconds while theirs seems to be in microseconds, strange.

User avatar
kevinjwalters
 
Posts: 1025
Joined: Sun Oct 01, 2017 3:15 pm

Re: Manually Control Multiple HC-SR04

Post by kevinjwalters »

An interpreted language isn't going to be good for accurate millisecond and sub-ms timing particularly on these slowish processors. I made same comment on CPX (slower, M0-based) on Crickit and HCSR04. I think Mike's comment on micros() was about C/Arduino sketch programming.

The adafruit_hcsr04 library will be using library calls which are implemented in hardware or compiled C code under the covers. There's an example of how to use that library in https://learn.adafruit.com/jack-o-theremin/circuit-python-code.

There's a second problem with timing with time.monotonic(). The return value is a 32bit floating point stored as a 30bit value. As time goes by the sub-second precision drops, e.g. time value will be something like 1.234567 for small values but 123456.7 for large ones. This is mentioned on second post on Making a time slicer which recommends use of time.monotonic_ns().

BTW, the classic HC-SR04 needs 5v power and has a 5v output. That 5v output is incompatible with inputs on the Feather M4 and will need reducing with a level shifter or some resistors making a potential divider.

User avatar
lawrenceyy
 
Posts: 108
Joined: Thu May 07, 2015 12:32 pm

Re: Manually Control Multiple HC-SR04

Post by lawrenceyy »

After looking at the M4's pinout page more closely, I think I have enough pins for each of the 5 sensors to take two pins if I use the SPI pins as digital IO. It is unfortunate that python on the m4 is not fast enough to do accurate time stamping.

Now that I have the whole thing setup, I am having an electrical problem. The sensors do good readings by default (bounces in a range of +/- 20mm), but when the distance condition is met for one sensor, and a fan (5v/.17A https://www.amazon.com/gp/product/B07KR ... UTF8&psc=1) is turned on, the sensors all start give poor readings (range increases to +/- 150mm). Currently, the sensor and the fan are all powered by the USB's 5v. Power to the fans are controlled by a mosfet. Do I need another 5v supply for the fans? How would I control a fan with a mosfet if the fan does not share the same ground?
Attachments
Capture2.PNG
Capture2.PNG (597.31 KiB) Viewed 675 times
Capture1.PNG
Capture1.PNG (399.48 KiB) Viewed 675 times

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Manually Control Multiple HC-SR04

Post by adafruit_support_mike »

It would be a good idea to move the fans to a separate power source.

All motors generate a lot of electrical noise, and that will inject all sorts of unwanted signal into sensor measurements.

User avatar
lawrenceyy
 
Posts: 108
Joined: Thu May 07, 2015 12:32 pm

Re: Manually Control Multiple HC-SR04

Post by lawrenceyy »

Good to know about the electrical noise. Let's say I go another power source. How do I enable/disable the fans? Would a mosfet still work or do I have to get a relay?

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Manually Control Multiple HC-SR04

Post by adafruit_support_mike »

The mosfet should still work. Just make sure you connect the GND lines between the two power sources.

User avatar
lawrenceyy
 
Posts: 108
Joined: Thu May 07, 2015 12:32 pm

Re: Manually Control Multiple HC-SR04

Post by lawrenceyy »

What? You can connect two different circuits like this? So the source pin on the mosfet would have to be connected to the ground of both power sources? What is this scenario called? I should read up on this.

User avatar
kevinjwalters
 
Posts: 1025
Joined: Sun Oct 01, 2017 3:15 pm

Re: Manually Control Multiple HC-SR04

Post by kevinjwalters »

On the library front, does creating two/five of the adafruit_hcsr04.HCSR04() not work? It uses PulseIn() to get an accurate measurement.

On the fan front, I can't see if you have a diodes across each fan? If these are not present (worth checking the fan specification to see if they are integrated) then you'll need them for back emf protection. See Arduino Lesson 13. DC Motors for an example, orientation of diode is very important.

User avatar
lawrenceyy
 
Posts: 108
Joined: Thu May 07, 2015 12:32 pm

Re: Manually Control Multiple HC-SR04

Post by lawrenceyy »

On the library front, does creating two/five of the adafruit_hcsr04.HCSR04() not work? It uses PulseIn() to get an accurate measurement.
It works. This is no longer an issue since I can harness more pins than I previously thought possible.
On the fan front, I can't see if you have a diodes across each fan? If these are not present (worth checking the fan specification to see if they are integrated) then you'll need them for back emf protection. See Arduino Lesson 13. DC Motors for an example, orientation of diode is very important.
Good call. I think the diode will solve some of my problems.

User avatar
lawrenceyy
 
Posts: 108
Joined: Thu May 07, 2015 12:32 pm

Re: Manually Control Multiple HC-SR04

Post by lawrenceyy »

2 general questions:

1. How do I see the names of the pins available to me on any given board? I have been referring to this site (https://circuitpython.readthedocs.io/en ... ght=board#) but it does not say.

2. Is there anyway to create a pin with all its attributes in one line? Currently, you have to choose the pin, direction, pull and value on different lines. I am looking for something like:

Code: Select all

pin=digitalio.DigitalInOut(board.D5,INPUT,UP)

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Manually Control Multiple HC-SR04

Post by adafruit_support_mike »

lawrenceyy wrote:What? You can connect two different circuits like this?
Sure.. it's done all the time.

Current can only flow around a loop, so if you only have one point of connection between two circuits, it's impossible for current to flow from one DC power source to another.

Voltage is measured between two points, so if you have a single point of connection between two circuits, they can both measure voltages relative to that point.
lawrenceyy wrote:So the source pin on the mosfet would have to be connected to the ground of both power sources? What is this scenario called? I should read up on this.
It's called a shared ground connection. More generally look into basic network analysis, get comfortable with voltage and current sources, then focus on Thèvenin's Theorem. That lays out the rules for circuits made of resistors and energy sources.

User avatar
lawrenceyy
 
Posts: 108
Joined: Thu May 07, 2015 12:32 pm

Re: Manually Control Multiple HC-SR04

Post by lawrenceyy »

So I added a diode to each fan and separated the fans from the sensors power-wise, and everything worked. That was with 3 fans and 3 sensors. To add the other two, I had to use pins A3, A4, A5, SCK, MOSI and MISO. When I go to save there is a runtime error: EXTINT channel already in use. What is causing this? I thought we could use the SCK, MOSI and MISO pin for GPIO (according to https://learn.adafruit.com/adafruit-fea ... 51/pinouts).

Code: Select all

import time
import board
import digitalio
import busio
import adafruit_ssd1306
import adafruit_hcsr04

#setup
i2c = busio.I2C(board.SCL, board.SDA)
display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c)
sonar=[]
sonar.append(adafruit_hcsr04.HCSR04(trigger_pin=board.A4, echo_pin=board.A3))
sonar.append(adafruit_hcsr04.HCSR04(trigger_pin=board.SCK, echo_pin=board.A5))
sonar.append(adafruit_hcsr04.HCSR04(trigger_pin=board.D11, echo_pin=board.D12))
sonar.append(adafruit_hcsr04.HCSR04(trigger_pin=board.D9, echo_pin=board.D10))
sonar.append(adafruit_hcsr04.HCSR04(trigger_pin=board.D5, echo_pin=board.D6))
fan=[]
fan.append(digitalio.DigitalInOut(board.MOSI))
fan.append(digitalio.DigitalInOut(board.MISO))
fan.append(digitalio.DigitalInOut(board.A0))
fan.append(digitalio.DigitalInOut(board.A1))
fan.append(digitalio.DigitalInOut(board.A2))
for i in range(len(fan)):
    fan[i].direction=digitalio.Direction.OUTPUT
Thanks for the help.

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Manually Control Multiple HC-SR04

Post by adafruit_support_mike »

I’m not sure how CircuitPython handles pin assignments.

Try posting over in the CircuitPython forum:

viewforum.php?f=60

The folks there will know the details better.

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”