Often - it transpires - humans and robots just don't get along. Something about one being infinitely more clever than the other. And to make matters worse, most machines equipped with even an ounce of "advanced" intelligence supposedly like nothing more than to totally annihilate the world, and generally cause misery for humans (just like their human counterparts, on second thought). This is all according to the seminal, and totally academic study on artificial intelligence - The Terminator. It's been peer reviewed on Rotten Tomatoes... so it must all be irrefutably true.
And for any fledging robot, when that terrifying moment finally arrives, when a muscle-man from Austria comes at you with all kinds of blunt and sharp instruments (often found suspiciously, not to say rather conveniently, nearby), they must recognise that they are being... well... properly whacked. With a gardener’s fork. Or an iron pipe. Or maybe even with an enormous sword of the barbarian variety. And before an expensive robot limb is left ingloriously dangling, it's probably best to register the blows, so that some over-the-top response can be fashioned up. Rapidly. Like a deadly laser beam that defies the laws of physics (sensible). Or - more drastically - a tactical nuke concealed up the robot's nostrils (less sensible, and probably terminal). Think: Skynet.
But none of this is possible without a way to identify physical shocks; sudden movements of the body. And because there's always a danger of Terminator sequel #<insert random 0-65,536 integer here> being released to the unsuspecting public, let's be quick with the solution. Let's get our robot working with a cheap and cheerful tilt / vibration sensor.
You don't want to be the tool without the tooling:
- A Raspberry Pi 3, running Raspbian OS
- A SW-520D tilt / vibration sensor
- Erm, that's it. Can't think of anything else. Nukes and lasers, not required. For now.
Chequered history:
Building Rosie 2.0 - naturally - assumes that there is a Rosie 1.0. For that reason, casting your eyes over the organised chaos that was Rosie and Rosie Patrol is highly recommended.And then, there's also been the first few episodes of Rosie 2.0:
Bit by byte:
- Connect the SW-520D tilt / vibration sensor to the Raspberry Pi using designated GPIO pins. Hopefully the sensor was bought as a module. If not, you will need to solder a pull-up resistor.
- Play around (official scientific term) with the sensor using Python. Can we get it to recognise any movement?
- At this point, you're likely to have experienced a bad bout of bouncing, aka Switch Bouncing. You can attempt to tackle it in software or hardware.
- Ah yes. A real-life crash test. Steer a seemingly innocuous object into something (accompanying sound effects compulsory). And see if you can detect the moment of the impact. We used a toy pram, obviously.
You ain't seen nothing yet:
Quite frankly, our brains are still hurting from the last episode, in which we attempted to - uncharacteristically for us - make use of a sophisticated Inertial Measurement Unit (IMU) to actually measure the tilt of a device. We had to use accelerometers, and (semi-)understand gravity and trigonometry, to build something that allowed us to measure tilt angles. Old friend Pythagoras made a return. So did his mischievous cousin Hypotenuse. What a rave! What a night.Now that's all very useful (and it really is when it comes to robot navigation) but what if we just want to detect sudden vibrations experienced by our robot hero? A collision with a stray wall perhaps. Or from being picked up by an oversized man in film star shades, and shaken vigorously like cheap plastic maracas bought in Poundland (yes, they're sold next to toilet plungers which are less acceptable to shake on the dance floor). We'd definitely like to know about it when such an event unfolds (the physical shocks, not the bit about dancing with toilet plungers). And using a sophisticated IMU for this simple task seems a little too... well... unnecessary.
Isn't there a simpler way?
Thankfully for us, there is. It's called a tilt (or sometimes, vibration) sensor. It's crude. It really does sound like a pair of maracas when you shake the tube-shaped device. It might not work terribly well in all cases, but it might just do the job here.
Put on a sombrero. Some banda music. It's time to get groovy with some tilt sensors.
Detail:
Did we say it's crude? Oh yes it is. And here's some proof.SW-520D is a rudimentary tilt / vibration sensor - the kind that you could even explain to your great grandma using two biscuits and a biscuit jar (use of denture during demo is strictly optional). It's because, the moment you Google its workings, you soon realise that despite its sophisticated-sounding alphanumerical code name, all it does is play ballgames. Specifically, the unit houses two conductive balls that opens and closes the circuit depending on the positions the two balls end up in (basically a ballsy switch). And clearly the balls will move around when the sensor is shaken with enough force, or tilted.
Yes, we did think this as well. The term "tilt sensor" is slightly misleading - as it doesn't help you work out precise angles like the IMU, or even orientation. Moving on.
And because it's basically no more sophisticated than a switch - as we'd expect - it simply supplies a HIGH or LOW logic signal as its output depending on the results of its internal ball action. Additionally, detecting a HIGH to LOW, or LOW to HIGH change in itself might not be so useful. It might just be that your robot has steered itself onto an incline, or onto a bank. But if the state is repeatedly changing in a short space of time - something is probably not quite right. There's probably a whiff of robot-killer aftershave in the air. You will need be on red alert.
Other than the 3.3V and Ground (0V) connections to power the SW-520D, you'll only require the one GPIO pin for the sensor's logic signal output.
SW-520D Pin | Pi GPIO Pin | Description |
---|---|---|
GND (Ground) | Any 0V Ground (e.g. 6, 9, 14, 20, 25, 30, 34, 39) | 0V (Ground) |
DO | 16 (BCM 23) | Signal output from SW-520D |
VCC | Any 3.3V (e.g. 1 or 17) | Used to power the sensor using 3.3V |
It's worth noting that we used a sensor module... which has the pull-up resistor pre-soldered in to ensure we have the correct voltage for HIGH and LOW signals. This means that the unit is ready to be used directly with the Pi. If you unfortunately have just the sensor itself, you will need to get yourself a resistor. Furthermore, some people appear to use a capacitor / resistor combination as well in their circuitry to act as a low pass filter of some sort to address the symptoms of switch bounce. More on this later.
All cabled properly? Some electronics aficionados like to use LEDs or buzzers to demonstrate their new sensors. Not us. We like to go straight into Python and see what we can do with it. Let's use IPython - our favourite way of testing Python code interactively.
ipython3
There really isn't much to interacting with simple HIGH and LOW signals that appear at a GPIO pin (especially since we've been playing around with a lot more interesting protocols like 1-Wire, SPI, and I2C lately). But here's a reminder of what to do.
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(23, GPIO.IN)
We've use this a million times before. We first import the GPIO library, set mode to BCM (so that we can address the pin using BCM numbering 23), and configure it as an input pin. Simply put: the pin should now be receiving HIGH or LOW signals depending on what the balls are doing in the sensor.
Are we interested in what the signal is? Not particularly for this exercise. You might be, if you are trying to detect known changes to the sensor's tilt. For example, from moving from upright to sideways, there should - in theory - always be a change in the signal from HIGH to LOW... and the datasheet informs us that this could happen at 10 or 45 degrees depending on sensor orientation. No, we just want to detect sudden shakes, not a gentle steer.
You could write your own routine to poll a change in the state of the signal. But why bother when there is a wait_for_edge() method in the GPIO library that alerts you when the signal changes. Feeding it a parameter of GPIO.BOTH means that we'll be monitoring for HIGH to LOW or LOW to HIGH changes.
while True: if GPIO.wait_for_edge(23, GPIO.BOTH): print("a shake, not a steer!")
Run this, and you'll find yourself in a horribly infinite loop, but one in which an alert is raised when the sensor is roughed up a bit.
Incidentally, wait_for_edge() is a blocking method... meaning you'll want to run this as a separate thread to ensure your code can be doing something else in the meantime. Or you could use one of the alternative GPIO library methods, like event_detected().
If you ran the code, you're probably quite surprised by the sensitivity of the sensor. A couple of innocuous shakes appear to lead to lots of spurious signals being generated - which is a by-product of the mechanical ball game taking place inside the sensor. And the infamous effects of Switch / Contact Bounce. After all, no switch transitions perfectly between OPEN / CLOSE states due to the mechanical components involved. Unfortunately, systems expecting certainty aren't great at dealing with these imperfections.
There could be both a hardware and software solution. More electronic circuitry (such as a low-pass filter created using an additional resistor and capacitor) could be used to mask the effects of these spurious signals... or you could do it programmatically in Python. Let's do the latter, and use the set of non-blocking event_detected() methods instead, and provide it with the bouncetime parameter of 250ms. This should now ignore further signals for 250ms. It's probably not the most sophisticated way of de-bouncing the switch, but it'll do for now.
GPIO.add_event_detect(23, GPIO.BOTH, bouncetime=250) while True: while not GPIO.event_detected(23): pass print("a shake, not a steer!") GPIO.remove_event_detect(23) # Manually remove event detection when finished
This will desensitise the output somewhat; as there should now be a minimum of 250ms between the signal changes register. It does also mean any legitimate "shakes" of an extremely vigorous nature will now not be registered so representatively. We have effectively created a low-pass filter - similar to what a RC Filter with a resistor / capacitor combo would have done.
Moment of truth.
Mount the unspectacular rig onto anything that moves, and you can now steer the creation into an immovable, impassable obstruction of death and destruction. Or failing that, use a toy pram and a sofa.
Here's our Pi and sensor positioned inside this particular research vehicle. Watch as it dramatically crashes into the furniture like a trailer from Fast and the Furious 65.
If you are planning to recreate this monumental footage, you might need to adjust the orientation of the sensor... as the way it is facing appears to make it more responsive to forces encountered from specific directions.
Here's our Pi and sensor positioned inside this particular research vehicle. Watch as it dramatically crashes into the furniture like a trailer from Fast and the Furious 65.
If you are planning to recreate this monumental footage, you might need to adjust the orientation of the sensor... as the way it is facing appears to make it more responsive to forces encountered from specific directions.
Sorry to disappoint. We did say this wasn't going to be epic as the one on the IMU.
Nonetheless hopefully you've become acquainted with yet another sensor that does something different. And this one might just save your robot from total destruction.
Nonetheless hopefully you've become acquainted with yet another sensor that does something different. And this one might just save your robot from total destruction.
Comments
Post a Comment