Thursday, March 20, 2014

50. Robotics with PiBot. V - Decision Making based on Ultrasound

This is hopefully the first in a series of coding exploits where I get to make the PiBot do what I want it to do!

I was so excited that the PiBot actually started doing what I wanted, that I just had to make a video and publish it.  I will replace this one with a better one when I get an improved version.

Here's how the distance sensor works:
In the above picture, you can see the Elec-Freaks HC-SR04 Ultrasonic Ranging module at the font of the PiBot.  There are two cylindrical eye-like components, the one on the left being the transmitter and the one on the right is the receiver.  Think of these as being a speaker and a microphone respectively.  The transmitter emits sound in a conical shape, ±30 wide:
The specification of the HC-SR04 claims that distances can be measured with an accuracy of up to 3mm from 2cm to 300cm.

There are 4 pins, VccTrigEcho and Gnd.  The timing chart below shows that when a 10µs, 5V pulse is sent to the Trig pin, this initiates a trail of 8 pulses (generated by the piezoelectric crystal, the shiny oblong component between the two 'eyes') allowing the transmitter to emit this signal in a burst of sound pulses.  The pulses are emitted with a frequency of 40kHz, making the duration of each 'high', 400µs.  This frequency is classed as ultrasound as the human ear can only hear frequencies between 20Hz and 20kHz (my personal upper limit is more like 10kHz).  See HERE for a rough test. This train of pulses causes the Echo pin to go from low to high.

The 40kHz sound signal will of course travel at the speed of sound, in a conical shaped beam, and any reflective object in its path will cause the sound to be reflected back towards the HC-SR04.  When the sensor 'eye' detects the reflected sound wave, the Echo pin will return to low.  If there is no object to reflect the sound, the Echo pin will return to low after 38ms.  The time for which the Echo pin is high is an indicator of the distance to the reflective object:
distance  = s.t/2
where s is the velocity of sound in air (343ms-1 or 1234 kmh-1 in dry air at 20C) and t is the TTL (time to live) of the high signal on the Echo pin.  The distance is divided by 2 because the object distance is half of the total round-trip distance covered by the sound pulse.

After the initial 10µs, 5V pulse, we wait for at least 100ms before it is repeated.  The resulting distance can be calculated every 500 milliseconds or so, keeping the PiBot up-to-date on its distance from obstacles in its path.

After struggling with the Python code a bit, and getting some help from the PiBot Team, I finally understand that the bot.getUltrasonicDistance() quantity I was reading was in fact of the data type list. On making my variable dist equal this quantity (making this variable also a list) I then used the first element of the list, dist[0] in the program, which is of the data type int.

Here's the script:

The problem area had been between lines 41 and 53.  This sets up a loop of 300 iterations to read the ultrasound transceiver's distance, and I set it up so that if the distance to any obstacle is 15cm or more, the green lights come on and it's full steam ahead (192, 192).  If the distance is less than 15cm, the red lights come on, and the left hand wheel reverses direction (-192, 192), turning the bot through an angle and away from the obstacle - then it's back to full steam ahead with the green tail lights.

After this loops 300 times (this doesn't take very long), the wheels stop and the blue lights come on, in reverse order, to indicate the end of the movement.

Lines 44 and 45 have been split from one long line which wouldn't all fit into the width allowed above.  This combined statement removes the square brackets which were enclosing the value of distance displayed on the terminal, by converting dist[0] to a string, and using the string method .replace to change firstly the [ to a space, and then the ] to a space.

The time.sleep(0.1) statement is quite important as it regulates the speed at which things happen within the loop, in this case, it introduces a delay of 0.1 seconds each time.

And - it works!  So now my SD card won't be getting as much of a bashing as it was!

No comments:

Post a Comment