martedì 8 luglio 2014

Giochiamo con il Sensore HC-SR04


(il data sheet lo potete trovare QUI)

Un  preambolo su questo sensore... per quanto ho potuto appurare su inet le prime versioni non erano molto a buon mercato (sensori ultrasonici per misurare le distanze... poi I prezzi sono scesi e l'altro giorno me ne sono arrivati da Hong Kong due esemplari a 3,4 euro in tutto, spese di spedizione incluse!)

prima nota dolente ho letto che spesso (1 su 10) se ne trovano di difettosi tra le “cinesate” ed uno dei miei due ogni tanto sbarella... ma pazienza l'altro funziona bene

comunque vi consiglio di dare un occhiata anche QUI su AMAZON.

Guardando il manuale del sensore e girando per internet (per esempio qui QUI) ho fatto questo schema di cablaggio




con la solita resistenza da 1Khom per portare il segnale da 5v a 3,3 senza bruciare il Raspberry

L'alimnetazione da 5V l'ho presa direttamente dal Raspberry.

La versione 0 del sorgente lo ammetto l'ho scopiazzata, tanto per testarne il funzionamento e ve la riporto qua con qualche mio commento in piu da cui si capisce come funziona il sensore
(si manda segnale al pin “Trigger” e poi si legge il tempo che il pin “Echo” sta “Alto(1-ON)”
questo tempo è proporzionale alla distanza percorsa da un pacchetto di ultra-suoni a 44 Khz [da non confondere con la qualita di 44Khz dei CD, che è quella di campionamento, Teorema di Shannon insomma i cd riproducono al massimo frequenze di 22Khz perche tanto il nostro orecchio non sente suoni piu acuti (leggi); )

<pre>[Omissis]... </pre>
La seconda versione (v1) riprende la prima e la estende con settaggi di variabili al posto di codici cablati a programma, e per la gestione corretta della struttura (gestione errori etc)

<pre>[Omissis]... </pre>

La terza versione (v3) introduce la gestione di problemi tipo l'interruzione del segnale (magari per rottura del cavetto) tra sensore e raspberry, e la gestione di una distanza massima entro cui ci si aspetta il sensora debba funzionare (questo per evitare di aspettare inutilmente secondi se davanti al sensore non c'e' nulla)
La versione v3 ha avuto un parto travagliato per la gestione delle operazioni di interi in phyton... che restituisce sempre un intero e non un float... cmq la sera dopo, a mente lucida è stato risolto tutto.





import time
import RPi.GPIO as GPIO

# use the values of the GPIO pins, and not the actual pin number
# so if you connect to GPIO 25 which is on pin number 22, the
# reference in this code is 25, which is the number of the GPIO
# port and not the number of the physical pin
GPIO.setmode(GPIO.BCM)

# remember to change the GPIO values below to match your sensors
Trig_pin = 17 # GPIO output = the pin that's connected to "Trig" on the sensor
Echo_pin = 27 # GPIO input = the pin that's connected to "Echo" on the sensor

ON = 1
OFF = 0

#shoudln't need to changed these values unless you have a specific need to do so.
MAX_SENSOR_DISTANCE = float(500) # Maximum sensor distance can be as high as 500cm,
# no reason to wait for ping longer than sound takes
# to travel this distance and back.
US_ROUNDTRIP_IN = 146 # Microseconds (uS) it takes sound to travel round-trip 1 inch (2 inches total),
# uses integer to save compiled code space.
US_ROUNDTRIP_CM = 57 # Microseconds (uS) it takes sound to travel round-trip 1cm (2cm total),
# uses integer to save compiled code space.

#max_cm_distance = float(60)


#_maxEchoTime = (min(max_cm_distance, MAX_SENSOR_DISTANCE) / 17000);
#* US_ROUNDTRIP_CM + (US_ROUNDTRIP_CM / 2) *1000; # Calculate the maximum distance in uS.

#print min(max_cm_distance, MAX_SENSOR_DISTANCE) /17
#print min(max_cm_distance, MAX_SENSOR_DISTANCE) /1700
#print min(max_cm_distance, MAX_SENSOR_DISTANCE) /17000
#print _maxEchoTime*17000

def NewPingConvert(echoTime, conversionFactor):
return (echoTime + conversionFactor / 2) / conversionFactor


def reading(sensor,max_cm_distance):
max_cm_distance=float(max_cm_distance)
_maxEchoTime = (min(max_cm_distance, MAX_SENSOR_DISTANCE) / 17000);

if sensor == 0:
# point the software to the GPIO pins the sensor is using
# change these values to the pins you are using
# GPIO output = the pin that's connected to "Trig" on the sensor
# GPIO input = the pin that's connected to "Echo" on the sensor

GPIO.setup(Trig_pin,GPIO.OUT)
GPIO.setup(Echo_pin,GPIO.IN)
GPIO.output(Trig_pin, GPIO.LOW)

# found that the sensor can crash if there isn't a delay here
# no idea why. If you have odd crashing issues, increase delay
time.sleep(0.3)

# sensor manual says a pulse ength of 10Us will trigger the
# sensor to transmit 8 cycles of ultrasonic burst at 40kHz and
# wait for the reflected ultrasonic burst to be received
# to get a pulse length of 10Us we need to start the pulse, then
# wait for 10 microseconds, then stop the pulse. This will
# result in the pulse length being 10Us.
# start the pulse on the GPIO pin
# change this value to the pin you are using
# GPIO output = the pin that's connected to "Trig" on the sensor
GPIO.output(Trig_pin, ON) #True

# wait 10 micro seconds (this is 0.00001 seconds) so the pulse
# length is 10Us as the sensor expects
time.sleep(0.00001)

# stop the pulse after the time above has passed
# change this value to the pin you are using
# GPIO output = the pin that's connected to "Trig" on the sensor
GPIO.output(Trig_pin, OFF) #False

# listen to the input pin. 0 means nothing is happening. Once a
# signal is received the value will be 1 so the while loop
# stops and has the last recorded time the signal was 0
# change this value to the pin you are using
# GPIO input = the pin that's connected to "Echo" on the sensor
signaloff = time.time()
signal0 = signaloff + _maxEchoTime

while (GPIO.input(Echo_pin) == OFF and signaloff <= signal0):

signaloff = time.time()
if GPIO.input(Echo_pin) == ON:

# listen to the input pin. Once a signal is received, record the
# time the signal came through
# change this value to the pin you are using
# GPIO input = the pin that's connected to "Echo" on the sensor
signalon = signaloff
signal0 = signalon + _maxEchoTime

while (GPIO.input(Echo_pin) == ON and signalon <= signal0):

signalon = time.time()

if GPIO.input(Echo_pin) == OFF:
# work out the difference in the two recorded times above to
# calculate the distance of an object in front of the sensor
timepassed = signalon - signaloff


# we now have our distance but it's not in a useful unit of
# measurement. So now we convert this distance into centimetres
# if you take 340 m/sec (approximate speed of sound through air)
# and convert to cm/sec you get 34000 cm/sec.
# For pulse-echo, the sound travels twice the measured distance so
# you need to divide the conversion factor by 2 so you get 17000 cm/sec.
# When you multiply by the measured time, you get distance from the
# transducer to the object in cm.
# The speeds of sound used in the formulas are approximations.
# The actual speed of sound through air varies with temperature and
# (to a lesser extent) with humidity (and a little due to other factors).
distance = timepassed * 17000

else:
distance = 'Out Of Range'


else:
distance = 'No Start Echo'

# return the distance of an object in front of the sensor in cm
return distance

else:
print "Incorrect usonic() function varible."

def barra_da_num(myNum):
sOut = '#'
n = 1

while (n < myNum and n < 120):
n += 2
sOut += '#'
return sOut
try:

#here you put your main loop or block of code
#print reading(0,80)
myDist = reading(0,80)
while ( myDist > 6):
myDist = reading(0,80)
print '#' + str(myDist) + barra_da_num(myDist)

except KeyboardInterrupt:
# here you put any code you want to run before the program
# exits when you press CTRL+C
#print "\n", counter # print value of counter
print "\nuscito per pressione tasti CTRL+C"

#except:
# this catches ALL other exceptions including errors.
# You won't get any error messages for debugging
# so only use it once your code is working
# print "Other error or exception occurred!"

finally:
# we're no longer using the GPIO, so tell software we're done
GPIO.cleanup() # this ensures a clean exit