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.
Manually Control Multiple HC-SR04
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- lawrenceyy
- Posts: 108
- Joined: Thu May 07, 2015 12:32 pm
Manually Control Multiple HC-SR04
Last edited by lawrenceyy on Sun Apr 21, 2019 2:54 am, edited 2 times in total.
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Manually Control Multiple HC-SR04
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.
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.
- lawrenceyy
- Posts: 108
- Joined: Thu May 07, 2015 12:32 pm
Re: Manually Control Multiple HC-SR04
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:
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.
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)
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.
- kevinjwalters
- Posts: 1025
- Joined: Sun Oct 01, 2017 3:15 pm
Re: Manually Control Multiple HC-SR04
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.
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.
- lawrenceyy
- Posts: 108
- Joined: Thu May 07, 2015 12:32 pm
Re: Manually Control Multiple HC-SR04
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?
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 (597.31 KiB) Viewed 675 times
-
- Capture1.PNG (399.48 KiB) Viewed 675 times
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Manually Control Multiple HC-SR04
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.
All motors generate a lot of electrical noise, and that will inject all sorts of unwanted signal into sensor measurements.
- lawrenceyy
- Posts: 108
- Joined: Thu May 07, 2015 12:32 pm
Re: Manually Control Multiple HC-SR04
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?
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Manually Control Multiple HC-SR04
The mosfet should still work. Just make sure you connect the GND lines between the two power sources.
- lawrenceyy
- Posts: 108
- Joined: Thu May 07, 2015 12:32 pm
Re: Manually Control Multiple HC-SR04
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.
- kevinjwalters
- Posts: 1025
- Joined: Sun Oct 01, 2017 3:15 pm
Re: Manually Control Multiple HC-SR04
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.
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.
- lawrenceyy
- Posts: 108
- Joined: Thu May 07, 2015 12:32 pm
Re: Manually Control Multiple HC-SR04
It works. This is no longer an issue since I can harness more pins than I previously thought possible.On the library front, does creating two/five of the adafruit_hcsr04.HCSR04() not work? It uses PulseIn() to get an accurate measurement.
Good call. I think the diode will solve some of my problems.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.
- lawrenceyy
- Posts: 108
- Joined: Thu May 07, 2015 12:32 pm
Re: Manually Control Multiple HC-SR04
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:
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)
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Manually Control Multiple HC-SR04
Sure.. it's done all the time.lawrenceyy wrote:What? You can connect two different circuits like this?
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.
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.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.
- lawrenceyy
- Posts: 108
- Joined: Thu May 07, 2015 12:32 pm
Re: Manually Control Multiple HC-SR04
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).
Thanks for the help.
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
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Manually Control Multiple HC-SR04
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.
Try posting over in the CircuitPython forum:
viewforum.php?f=60
The folks there will know the details better.
Please be positive and constructive with your questions and comments.