Introduction: Stick2Cane - Never Lose Your Walking Cane

About: Sucks at soldering, [hopefully] compensates with coding.
The problem

This is for someone who has balance problems, only needs a walking cane during an episode, and can physically walk away from the cane quite a distance before it's actually needed (oops). The idea is to attach a transmitter to the cane, and let the patient carry a receiver that beeps/vibrates/etc. when it's out of range.

The solution

Use a simple 433/415MHz kit (MX-FS-03V / MX-05V or similar):

  • Patient carries receiver (+ arduino + buzzer/vibrator) in a pocket/bag.
  • The transmitter is attached to the walking cane (no arduino, only a 555-based oscillator. Thanks to @steveastrouk for telling me an oscillator was needed because the MX-FS-03V couldn't drive a DC signal).

The idea is to detect whether what we're getting is signal or noise, regardless of what signal exactly - as long as it's coherent and the signal/noise ratio is high enough.

At the moment, the transmitter is attached to the cane with an elastic bandage (see photo). I'm still thinking of ways to make it look less "sick", though ;). Suggestions are welcome.

On the receiver side - I've managed to make it mighty small by reprogramming a MilCandy. It's a really small arduino-based "appliance" (i.e. comes pre-programmed). What a MilCandy usually does is fun, but pretty limited (although it's great as a "lesson 1" pitch to kids), but once you reprogram it (needs an FTDI), it has a lot to offer for such a tiny box (a rechargeable battery + charger circuit and even an analog input for reading battery level, red/green leds, a button, and even a built-in light sensor - what a pleasant surprise).

Of course - any Arduino-ish controller will do. I also have an Arduino Micro based version of it (see soap dish photos).

Step 1: A History of Fails

Feel free to skip this step. I'm just documenting how I got to this specific solution.

TL;DR: although this project succeeded, I doubt if I'll ever use 433/315MHz kits for anything serious (at least not the simple ones). The RF noise the Arduino itself generates (especially if connected to and[/or] transmitting serial) makes these things rather useless IMHO. Specifically - Arduino Micro is the much worse (and while we're at it: the Micro also takes a mighty long time to reset. There. Got it off my chest).

In the beginning, it worked

There was a working prototype (see photo). It had a different algorithm, but it worked.

Then I got back home, built it again (see Tupperware photo), it worked, but with lots of false detection (detected signal where there wasn't any), but I've managed to fine-tune stuff and it worked.

Then came the Arduino Micro

Then I tried a smaller receiver based on an Arduino Micro (see soap-dish photo), and it all went wrong: the thing could only detect signal if it was a few Cm from the transmitter (and even then it was a bit uncertain).

So I started doing some "organic debugging"(TM): I've connected the piezo buzzer straight to the data pin of the receiver, and started listening - the thing was making a lot of RF noise: even when the transmitter was off.

Even out in the fields (away from anything electric).

It got better when I told it to stop using the Serial, but still - you can listen to the attached sound (before / after I turn on the transmitter, and once it gets 20-30cm away from the transmitter).

For reference, I've built a circuit with only the receive and a piezo buzzer on the data pin. You can listen to the attached sound (before / after I turn on the transmitter, and while I [noisily] walk away ~2m).

So I decided to go mainstream

I started thinking: maybe the whole idea of not having an Arduino on the transmitter side is stupid. Maybe libraries like VirtualWire or RadioHead are there to get anything at such a low signal/noise level. So I tried a simple "Hello" example between an Arduino as transmitter and the Arduino Micro as receiver, got no reception. Switched between the Large Arduino and the Micro, Nada.

Did I burn my receiver?

After a few experiments even the "Tupperware prototype" (the one that used to work) became a lot worse. So I've decided I've damaged the receiver. Maybe during all these experiments, a transmitter sketch was uploaded to the wrong machine and sent signal to the receiver's data. Not sure it matters (if you know the answer, please comment), but when you don't know whether you've burned the only receiver you've got or not - it really sucks.

So I've ordered a few more RF kits [and waited...]

When the new kits arrived - nada. I couldn't get the VirtualWire example to work. So I've searched the forum and found someone with a similar problem (my emphasis):

I bought this kit and using VirtualWire had it working perfectly ... Then suddenly it stopped working. ... I used to get lots of noise coming through... now there's nothing.

and there's an answer saying:

USB Power source are very bad. Try powering by battery.Small distance between rx and tx are not good.Small distance to PC is not good (they are like a hf jammer).

So I tried to debug stuff without using serial or external power

As a "cordless debugging tool" I tried to use an I2C LCD, but the problem was to get it to work on battery power (a serial cable to either a PC or even wall socket jams the rf badly), but I only had an old Arduino (I'll order some modern ones soon) with a manual USB/battery selection jumper, and it wasn't trivial to get the I2C LCD monitor work while in "battery" mode (if you have similar problems, here's a howto I wrote).


Once I got the LCD problem out of the way, I wrote a version of stick2cane that presented the histogram (see algorithm later on. It's much simpler than the previous one). The trick was to see the histograms visually and study them. No amount of serial debugging could provide such insights (unless you import csv or json via serial - an idea for a future project ;) ).

Step 2: Transmitter (cane Side)


  • 1 x 433/415MHz rf kit (e.g. MX-FS-03V / MX-05V. If you're using a Milcandy receiver, you'll need a Grove kit.
  • 1 x 555 timer
  • 2 x 1㏀ resistor
  • 1 x 10µF capacitor
  • 1 x 0.01µF capacitor

As you can see in a photo (of an early prototype), there's a 555-based oscillator driving a 50Hz signal to the transmitter via the blue lead.

In the last photo we can see that this can be packed real tight.

Step 3: Receiver (patient Side)

The code is here.

Pin definitions are a good checklist for the components you'll need to connect to your Arduino. If you're not using a MilCandy, just write the relevant pins where it says "begin pin definitions" in the code.

What you need to connect is a button, red and green leds (or other "bad/good" indicators), a buzzor (or vibrator), and - of course - the receiver that matches the transmitter you've used in the previous step.

Connecting the receiver on board

If you don't use a grove receiver, you can stick it into the header of your arduino (see photo) or into the breadboard (see soap dish photo). It has 4 pins: Gnd, 2xdata, Vcc. What you do is stick into analog pins (say 2-5), then in the setup you send LOW to 2, HIGH to 5 (fake Gnd/Vcc), and you get signal on pins 3,4.


MilCandy has a built-in rechargeable battery, which is cool, but the downside is that if you charge it, it turns on (no matter what the power switch says), and since the electricity generates RF noise, it would go to "no signal" mode and start beeping. The way around it was to decide that it always restarts in mute mode (can be toggled by the button). In order to alert the user to the fact that mute mode is on, the led (whether red or green) flashes. The receiver box is also covered with a sticker that tries to convey all this info (see graphic file).

Why it works

After all I've been through, I'm not exactly sure ;)

Essentially, I take 64 samples of RF data, take the most significant 4 bits and create a histogram: how many samples had such a value (out of 16 rough options).

As expected, there are usually many samples that return 0 (or the lowest 16th of possible values). When there's signal, we see lots of values in a specific slot. In some rare cases it becomes a bit fuzzy (some values in the nearest slots to the largest one), but if you add up the largest slot and its neighbors (if any, and not including the 0 slot), the value should be above MIN_REQUIRED_PEAK (from my experience, 38 is above "room noise level"). This used to be controllable with a potentiometer, but best is not to give patients ways to make stuff stop working, so 38 it is, and here we are.