I have written the routine for the ultrasonic rangefinder, tied to PWM modulation of a vibration motor. I have verified the PWM output using piscope.
I ended up using a slightly different ultrasonic sensor than the one I originally ordered.
I ordered this one:
I used this one (I had it onhand from my water level indicator) :
I did this because the LVEZ1 does not put out ttl by default which is what the pi needs. I tried building the inversion circuit, but for whatever reason that didn't work. I didn't have the exact right transistor, but it was a signal level pnp, so it should have worked.
In any case, the one I used can be made to output ttl without building the inversion circuit.
Code: Select all
import time import RPi.GPIO as GPIO import serial GPIO.setmode(GPIO.BOARD) #setup for PWM GPIO.setup(12, GPIO.OUT) #Define pin 12 as output p = GPIO.PWM(12, 25) #channel = 12 , frequency = 25 hz p.start(50) #50% duty cycle to start. should immediately change as the rangefinder reads upperdistance = 5000 #distance from sensor to max distance lowerdistance = 1000 # The distance to critical threshold indicating imminent collision maxbotix = serial.Serial("/dev/ttyAMA0",baudrate=9600,timeout=5) # other examples that didnt specify baudrate and timeout did not work for me while 1: maxbotix.flushInput() #clear buffer to get fresh values if you don't do this, you won't get responsive readings currdistance = maxbotix.readline(10) #Take ten characters worth of the serial buffer that accumulates since the flush stripstart = currdistance.find("R") #Look for the character "R", find out where it occurs in the string first stripend = stripstart + 5 #Define the end of the character length we need to grab the numeric info currdistance = currdistance[stripstart+1:stripend] #strip out the numeric info #print currdistance #comment this out after debugging currmm = float(currdistance) #Now make the info a number instead of a string # print currmm #comment this out after debugging percentmax = (upperdistance-(currmm-lowerdistance))/upperdistance*100 #calculate the percentage between 1000-5000mm to calculate duty cycle percentmax = int(percentmax) #convert to integer because rpi.gpio doesn't like duty cycle with more precision than 10ths of a percent. for this routine, precision of single percentages is fine if percentmax <0: p.ChangeFrequency(25) #The change frequency here is to revert from the near collision conditions when the frequency is changed to 1 p.ChangeDutyCycle(10)#This should never occur based on the math, but lets check our random errors if percentmax > 100: p.ChangeFrequency(1) #percentmax >100 happens when currmm is less than 1000 This indicates imminent collision. p.ChangeDutyCycle(50)# Frequency and duty cycle are changed to an alert mode rather than feathering the vibration if percentmax <100: p.ChangeFrequency(25) #The changefrequency here is to revert from near collision conditions when the frequency is changed to 1 p.ChangeDutyCycle(percentmax) #change duty cycle to percentage distance calculation #print percentmax #comment this out after debugging
I haven't tested it with the vibration motor, but with this complete, I just need to build the case and assemble things. Unfortunately, I also look like I'm stuck needing to put a power switch in as well.
Once I do the final assembly, I will put together an electrical schematic of the configuration and post here.
I'm about to enter a work cycle and will be somewhat sidelined for some time. Be assured that as time permits, I will continue to continue.
edit: For everyones reference, I have done some investigation into estimated power consumption.
The rpi 2 can be expected to consume 350 ma, the vibration motor up to 90 ma, and the rangefinder less than 5 ma. This means the battery will be good for only a few hours using a 1200 mah battery.
The bright side to all of this is that the recharging circuit can deliver 500ma. This means that the user can take the device out for a spin with the built in battery, or get an auxillary battery and go for a full day at a time easily.