Add another line and type in Add a last line and type in Kevin at home

Wednesday, 25 January 2023

Hacking the Proform le Tour de France exercise bike

 Exercise bike part 2.  Investigating

TLDR:Incline and resistance can be controlled by the user.  The console sends messages to the control board using a RS485 protocol.  Values are sent using HEX, B0 to B9, C0-C6.  Resistance messages are prefaced by BAB6 and Incline by BAB4.  Response messages are prefaced by BAB5 and include a cadence value.

The exercise bike has a stout base and the bike sits on a pivot in the centre of this base.  There is a motor behind the pivot that extends or retracts a threaded screw, causing the bike to pivot forward 15 degrees or back 15 degrees. 

There is a flywheel behind the seat that is composed of inner rings of cast iron or steel, and an outer ring of anodized aluminum.  The flywheel is driven by a J profile poly v belt.  Tension is maintained on the belt by an idler wheel that is located close to the rear hub.  The rear pulley is not fixed, unlike some bikes (like Keisler) but allows you to freewheel and take a break from pedalling.  

Resistance is created by powerful magnets which are behind the seatpost.  They straddle the aluminum flywheel and are adjusted towards the wheel or away, creating an eddy current in the aluminum flywheel.  No physical contact and very quiet.  Adjustment of the magnets is performed by buttons on the handlebars that activate a small servo style motor.  Slick.  The magnet position can be changed by pressing the gear up or down button on the handle bars.  The bike has 26 "gears" which seem almost imperceptible but really increase the difficulty.  Gear 26 is a struggle when the bike is at zero incline, but at +15degree incline, gear 26 is almost impossible to turn over unless I stand up on the bike.

When you start riding, the bike console will cycle through Time, Distance, Speed, Pace, Watts and RPM. 

So how does it all work?  Is there a way to control the bike remotely?  What about the bluetooth connection?  Let's take a closer look...


There are two main interesting areas on the proform bike.  The upper console and the lower control board.



The lower control board has the power supply section, a number of inputs, some relays, power outputs to the control motors and a microcontroller.  The inputs are the small gauge wires.  There are 4 wires that connect to the console (blue/green/black/red), 5 wires that connect to the resistance motor (black/white/red/orange/blue), 3 wires that connect to the incline motor(green/black/red) and 2 to a reed switch on the crank (black/grey).  So the lower board seems to be in charge of adjusting the resistance and incline.  It also measures pedal revolutions (cadence) with a reed switch triggered by a magnet on the crank.  Importantly, it communicates with the upper console with the 4 wires.

The upper console:

Console circuit board

The console is the user interface of the bike.  It accepts and translates button presses, displays info about the speed, time, distance, watts, etc and communicates with the lower board.

I am interested in what ways the bike could be controlled beyond what is possible with the console and the iFit app.  

I tried listening to the bluetooth communications with Wireshark, but there was little to see there.  I tried connecting to the bluetooth via the NRF connect app, but the bluetooth services were not accessible.  Is the bluetooth secured somehow?  Beyond me at this point.

I decided to focus efforts on the four cables that go between the console and the lower control board.  Measuring the wires with a multimeter, I determined that the red was +9V, the blue was +3.3V, and the green and black were at ground.  So I hooked up my oscilloscope (Hitachi V212) to the wires and pressed some buttons...  And there was a signal on both the blue and green wires.  But, my oscilloscope is only 20MHz, analogue and can't store traces, so....

To my electronics box -- I tried to use my Bus Pirate as a logic analyzer, but it's resolution and sample size were too low.  So I ordered a knock off Logic Analyzer from Amazon and waited....

Once my logic analyzer arrived, I was able to capture some useful data (once I was over the learning curve of Pulseview).  So I hooked up my analyzer to the console wires and pressed some gear and incline buttons while riding the bike (important: pedals must turn or the bike doesn't do anything!).   The first capture I got showed two data lines.  One went HIGH and at the same time the other went LOW.  Hmmmm...  Quick google search, maybe it is RS48...   Capture a few more sessions and analyze just one of the lines...


So, much confusion later, it turns out that the messages are indeed RS485 at a speed of 38400 baud, 8 bits, no parity, 1 stop bit and least significant bit first (LSB).  And then we can decode the messages from the lower control board to the console. Mostly a series of messages like this:

BAB6B1B0B6B0B1B0B5B0B0B2C4B6B68D8A
BAB5B1B0B3B0B0B0B2B0B0B0B0C1C18D8A
BAB5B1B0B3B0B2B0B1B0B2B0B0B0B0C1B78D8A
BAB5B1B0B3B0B0B0B2B0B0B0B0C1C18D8A
BAB5B1B0B3B0B2B0B1B0B2B0B0B0B0C1B78D8A
BAB5B1B0B3B0B0B0B2B0B0B0B0C1C18D8A
BAB5B1B0B3B0B2B0B1B0B2B0B0B0B0C1B78D8A
BAB5B1B0B3B0B0B0B2B0B0B0B0C1C18D8A
BAB5B1B0B3B0B2B0B1B0B2B0B0B0B0C1B78D8A
BAB5B1B0B3B0B0B0B2B0B0B0B0C1C18D8A
BAB5B1B0B3B0B2B0B1B0B2B0B0B0B0C1B78D8A
BAB5B1B0B3B0B0B0B2B0B0B0B0C1C18D8A
BAB5B1B0B3B0B2B0B1B0B2B0B0B0B0C1B78D8A
BAB5B1B0B3B0B0B0B2B0B0B0B0C1C18D8A

After a few more captures and decoding the signals I was able to decipher the communication protocol.  Messages are sent from the console to the control board twice per second while the bike is being ridden.

To change the incline, the following command would be sent:
0xBA, 0xB4, 0xB1, 0xB0, 0xB6, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB0, 0xB1, 0xC3, 0xB9, 0xC3, 0x8D, 0x8A
That would change the incline down one notch to -0.5. The important bytes are the second (0xB4) which indicates that the command is to change the incline and 12 to 15 (0xB1, 0xC3, 0xB9, 0xC3) which tell the console which level to shift to in absolute terms. There are 61 different codes(!) for bytes 12 to 15 corresponding to each half step in the incline of the bike.

To change the gear (resistance), this command would be sent:
0xBA, 0xB6, 0xB1, 0xB0, 0xB6, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB0, 0xB0, 0xB0, 0xC2, 0xB8, 0x8D, 0x8A
This would change the "gear" to #2. Note the important second byte (0xB6) indicating that a gear change is sent and bytes 12 to 15 indicate the level to move the resistance servo. I mapped out 22 levels for the gears, but the bytes are not sequential, unlike the incline levels so I believe there are many more levels of resistance possible (more on this later).

0xBA, 0xB5 prefaced messages are from the control board responding to the incline or resistance change or sending info about the current cadence of the rider.

 Pretty simple.  But with caveats... There are only certain values that are used by the console and control board for the incline and resistance and cadence data -- B0-B9, C0-C6.  I don't know what base that is, but okay, we'll deal with it.

With this knowledge, I have created a small Arduino circuit and sketch which is capable of controlling the incline and gears of the bike.

 



<code>


int incline = 30; //(levels from -15 to +15 by half increments. Index for zero is 30)
int gear = 0;

//these are the bytes for gear changes.
//bytes 12 to 15.  There could be more levels in between these, note the pattern of bytes for incline
//                       1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,   22
byte gearCommand1[] ={0xB0, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4};
byte gearCommand2[] ={0xC6, 0xB1, 0xB4, 0xB7, 0xC1, 0xC4, 0xB0, 0xB3, 0xB6, 0xB8, 0xC2, 0xC5, 0xB1, 0xB4, 0xB7, 0xC1, 0xC4, 0xC6, 0xB2, 0xB5, 0xB8, 0xC2};
byte gearCommand3[] ={0xB8, 0xB8, 0xB8, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB4, 0xB4, 0xB4};
byte gearCommand4[] ={0xB5, 0xB3, 0xB0, 0xC4, 0xC1, 0xB7, 0xB4, 0xB1, 0xC5, 0xC3, 0xB9, 0xB6, 0xB3, 0xB0, 0xC4, 0xC1, 0xB7, 0xB5, 0xB2, 0xC6, 0xC3, 0xB9};

//these are the bytes for incline changes
//note that "0" is number 31 below and changes are 0.5 degree increments on the bike
//                           1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61   
byte inclineCommand1[] = {0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3};
byte inclineCommand2[] = {0xC6, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xC1, 0xC2}; //what are the actual codes?...
byte inclineCommand3[] = {0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB7, 0xB7, 0xB7};
byte inclineCommand4[] = {0xB9, 0xB8, 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xB9, 0xB8, 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xB9, 0xB8, 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xB9, 0xB8, 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0, 0xC6, 0xC5, 0xC4};

byte inclineDownButton = 10;
byte inclineUpButton = 11;
byte gearDownButton = 9;
byte gearUpButton =8;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(38400);

  pinMode(inclineDownButton, INPUT_PULLUP); //
  pinMode(inclineUpButton, INPUT_PULLUP); //
  pinMode(gearDownButton, INPUT_PULLUP); //
  pinMode(gearUpButton, INPUT_PULLUP); //
}

void loop() {
  bool gearDown = digitalRead(gearDownButton);
  bool gearUp = digitalRead(gearUpButton);
  bool inclineDown = digitalRead(inclineDownButton);
  bool inclineUp = digitalRead(inclineUpButton);

  if (gearDown==LOW){
    gear = gear - 1;
    if (gear < 0){ gear = 0;}
    Serial.write(0xBA);
    Serial.write(0xB6);
    Serial.write(0xB1);
    Serial.write(0xB0);
    Serial.write(0xB6);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(0xB5);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(gearCommand1[gear]);
    Serial.write(gearCommand2[gear]);
    Serial.write(gearCommand3[gear]);
    Serial.write(gearCommand4[gear]);
    Serial.write(0x8D);
    Serial.write(0x8A);
    delay(500);
  }
  if (gearUp==LOW){
    gear = gear + 1;
    if (gear > 21){ gear = 21;}
    Serial.write(0xBA);
    Serial.write(0xB6);
    Serial.write(0xB1);
    Serial.write(0xB0);
    Serial.write(0xB6);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(0xB5);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(gearCommand1[gear]);
    Serial.write(gearCommand2[gear]);
    Serial.write(gearCommand3[gear]);
    Serial.write(gearCommand4[gear]);
    Serial.write(0x8D);
    Serial.write(0x8A);
    delay(500);
  }
  if (inclineDown==LOW){
    incline = incline - 1;
    if (incline < 0){ incline = 0;}
    Serial.write(0xBA);
    Serial.write(0xB4);
    Serial.write(0xB1);
    Serial.write(0xB0);
    Serial.write(0xB6);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(0xB1);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(inclineCommand1[incline]);
    Serial.write(inclineCommand2[incline]);
    Serial.write(inclineCommand3[incline]);
    Serial.write(inclineCommand4[incline]);
    Serial.write(0x8D);
    Serial.write(0x8A);
    delay(500);
  }
  if (inclineUp==LOW){
    incline = incline + 1;
    if (incline > 60){ incline = 60;} //max 60 entries in the incline array
    Serial.write(0xBA);
    Serial.write(0xB4);
    Serial.write(0xB1);
    Serial.write(0xB0);
    Serial.write(0xB6);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(0xB1);
    Serial.write(0xB0);
    Serial.write(0xB0);
    Serial.write(inclineCommand1[incline]);
    Serial.write(inclineCommand2[incline]);
    Serial.write(inclineCommand3[incline]);
    Serial.write(inclineCommand4[incline]);
    Serial.write(0x8D);
    Serial.write(0x8A);
    delay(500);
  }
}

</code>



Tuesday, 17 January 2023

Proform Tour de France exercise bike

Proform Tour de France Exercise bike

I bought a used Proform Tour de France exercise bike to replace a homemade version exercise bike.  Not knowing much about it I decided to take a leap of faith for the low used price of $400CAD (regular $1999?).  

ProForm Le Tour De France Indoor Cycling Stationary/Exercise/Spin Bike - iFit Enabled Side_Left
Proform Le Tour de France exercise bike.

I'm pleasantly surprised by the quality of the bike.  It seems sturdily built and allows very high resistance settings, something missing from my last bike.  It is very quiet when pedaling owing to its magnetic resistance, belt drive and narrow flywheel.  It has a nice incline function to enhance the experience, so I feel like I am actually going up a hill (or down).  Thankfully, it was in good condition and nothing was broken. 

The first task was to replace the seat.  I comes with a wide seat on a non standard mounting system.  So, I found a similar shaped rectangle of steel and welded on a length of scrap seatpost I had salvaged from an old bike. 

Old, original seatpost New welded seatpost Seatpost on bike


The other negative to me is the handlebars that came with the bike.  Very "gym" bike style -- my preference is for some nice road drop handlebars, but with the integrated incline and gear buttons, their replacement will be a bit more work.

My first few rides have been, well, a bit boring. I watch TV and try to keep my heart rate up for the duration.  But it leaves me wanting more and I think the capabilities of the bike are not fully exploited.  The bike has some Tempo and Interval Apps. But it seems all they do is set some targets for your watt output.  And you can program interval training limits into the bike too, but again it seems a bit simple.  There is a Bluetooth connection that allows the use of an iFit app but I'm not really up for the monthly subscription.  And it seems the iFit app is a bit like watching a movie of a bike ride.  It doesn't really take into account the effort you put into the workout.  

So, what to do with the bike? Can it be connected to Zwift? Could I write my own simple workouts for the bike?  Maybe upload a GPS file of my favorite ride? It might be time to look inside and see what makes it all tick.

Hacking the exercise bike

Thursday, 29 April 2021

Bye, bye, FM radio

 I have a Samsung A50 smart phone.  I used to listen to the radio while in the garden with some wired headphones and the Nextradio app.  One day, my phone announced an update which I dutifully downloaded and surprise, surprise the radio no longer works on my phone. 


Well, that sucks.  Permission has been elevated for FM steaming in Android 11 so Nextradio doesn't even attempt to work.  Nextradio is bankrupt so what are the chances of a fix for the FM tuner app?  And a search through the app store finds hundreds of "tuner" apps that are really just internet streaming apps.  Which use data or wifi.  And suck.  Why is this so hard?  Why does everything just get pushed to a pay model, or subscription.  How can my phone lose features through an update?  Have you ever taken your car to the mechanic for an oil change and then found that your radio or headlights don't work?   Of course you haven't.  How can tech suck so much?  And suck even more as time passes. 

I subscribe to Spotify.  I watch YouTube and Netflix.  But sometimes I just want some plain radio.  Which is now gone from my phone. So screw you Android/Samsung. I'm going old fashioned FM tuner in the garden from now on and wearing a pair of analog headphones.

Saturday, 20 February 2021

Philips Speechmike. Upgrade nightmare.

 I recently installed some windows updates on my wife's home office computer.  She does dictations with a Philips Speechmike USB microphone to Dragon dictate software.  The Philips microphone seems good quality but wasn't cheap ($400Cdn).  Upon reboot, I was greeted by a popup saying "new firmware available for your microphone" and the choice of "install now"or "later".  


Oh, I wish I had clicked "later"...  but I clicked "install now"...  So a dialog pops up with a green bar flashing back and forth urging me to not unplug the microphone as the upgrade can take several minutes.  So I wait.  And wait. And wait.  Then I notice that the Philips microphone software says that there is no microphone connected.  And the drop down menu to select the microphone cannot select the microphone model.  Troubleshooting suggestions are not helpful like saying the USB may not have enough power or that it might not like a specific port.  What the heck?  So I wait.  And wait. And wait.  Finally I bite the bullet and unplug the USB microphone and try plugging it back in with no result. 

The microphone is gone and doesn't show up as a device in Windows.  So I try it on a different computer with Linux.  No evidence of the microphone in dmesg. The USB functionality doesn't exist anymore.

So what happened?  Info is sparse online but it seems a failed upgrade can brick your device.  Who writes a firmware upgrade like this?  Is there no failsafe? I was relatively uninvolved in the upgrade (just click once), there were no warnings that this could ruin a $400 microphone.  Fortunately, my wife has an identical microphone that was not being used at work.   So once we plugged the new one in, the computer recognized it immediately indicating that it was not a driver issue caused by the update.

But is there a way to fix the old microphone?  The hardware still works, it seems as though just the firmware is missing or corrupt.

Opening the microphone reveals....  not much.  Some buttons, lots of test points, maybe a jtag connection.  Down at the bottom is the brains of the system, an NXP2364 chip.

Arm7 with on board flash, blah, blah, blah.  Not sure how Philips disabled the USB functionality with a bad firmware upgrade, but there you go.  
So, where to from here? I will try to access a windows 7 computer to see if older USB drivers magically fix the connectivity.  Maybe there is some way of forcing a firmware upgrade via some of the test points.  But seems unlikely...  so maybe this is just junk.


Wednesday, 26 September 2018

Aluminum can counter.

The Can Counter.

This is an old project I put together from old junk and parts I had lying around.  The motivation for this stems from my involvement in our local elementary school's bottle drive.  We collect cans and bottles from the local community to raise money for our school.  We sort the cans and bottles and then count them into bags.  Beer cans are 288 per bag, pop cans 288 per bag, plastic water bottles are 150 per bag and small juice boxes are 360 per bag.  Sometimes we can collect almost 10000 pop cans, beer cans, juice boxes and water bottles -- that is a lot of counting!

I've always hated the counting, so when I found a treadmill lying on the side of the road near our mailbox, I knew what I could make.  A can counter!  (As and aside, my neighbourhood isn't really so trashy, I think someone thought that maybe someone would want a free treadmill).
Free treadmill!

The can counter idea is simple - the cans are accelerated along the belt and then shot through a beam.  When a can breaks the beam, we know to count one can.  The beam is created by an LED shining on a photoresistor; an Arduino takes continuous analogue readings of the resistance.  When the resistance changes we assume that a can has broken the beam.

It was all breadboarded and then put in a fancy box.  The trick was to build physical guides for the cans to get them to line up in single file and to get the belt driving at a reasonable speed.


It actually works pretty well as you can see in the video.  Total budget was about $5 - I had to buy a belt to connect the motor.  Everything else I had lying around.

The video shows that the cans can be counted as fast as you feed them.  Much faster than by hand.  And it is quite reliable -- certainly counting cans manually, people get distracted and miscount.

Some problems with the counter which I couldn't be bothered to resolve.
1.  The motor is an old furnace fan motor, maybe from the 60's.  I might have been 1/3h.p. once but now is about 1/100 h.p.  So it can barely drive the treadmill and tends to stall.  I guess I could buy a motor, but that would increase my budget!  I think it puts some big emf spikes into the circuit too, which tends to mess up the LCD display sometimes.  Oh well, the price was right on the motor (free).
2.  If the cans are really, really close together, they might count as one instead of two.  But I think some creative coding could probably figure that out.  Or maybe a mechanical solution to introduce a gap to separate close cans.
3.  It can't count plastic bottles at all.  The beam break system doesn't work with plastic; it sees right through it, or counts the bottom, then the label, then the lid -- three bottles where there is only one!  Tightening the code to count only variations that last for a certain time might work.  Or add another beam from the side and compare values or a different colour that sees plastic better or.... I don't know, it would require more research than I care to do for a free, low budget project.
4. The hopper to feed the bottles onto the belt never really worked.  But then again, the budget was low ($5) so I didn't use anything other than scraps of plywood or cardboard for the hopper.  Again, a bit of money and time and it could have a pretty effective hopper.  I envision a top feed hopper with a powered paddle at the bottom to agitate the cans and feed them onto the belt! 

Friday, 22 June 2018

Protecting Our Cherries from the Birds!



I didn't see many bees in the fruit trees this spring, but I guess they must have been visiting the flowers because we have a bumper crop ripening on the tree.

Ripening red cherries that need protection from birds
Cherries ripening June 22, 2018.


Of course, the birds are a real threat to edible fruit (robins seem to be the worst).  The tree is about 8m high and I'd be happy for the birds to eat the high, out of reach fruit, leaving the lower fruit for me.  But, I know that they will peck, sample and destroy all the cherries if given a chance.  So what to do?...

Previous years I tried aluminum pie plates, scarecrows, CDs, holographic tape, scare eyeballs and blue survey tape to try to scare the birds.  The performance of these options was poor to say the least.

The best solution was using a motion sensitive sprinkler to scare the birds.  It worked but wasn't ideal.  The motion detector really didn't see the birds and the only way to scare the birds from the fruit was to dial up the sensitivity to the photocell to enable the sprayer to work constantly.  The water use was excessive and the deterrent not terribly effective.  Also, the sprinkler used a fair number of 9v batteries.

Last year I decided to make my own sprayer deterrent.  I attached an irrigation solenoid valve to an impact sprinkler head and then I programmed an Arduino Pro Mini to activate the valve every 60 seconds.   I also built a photocell into the circuit to ensure the system only fired during the day -- the birds aren't a problem at night!  The new system worked well, but was only effective on the lower branches of the tree because the sprinkler was stationed close to the ground.  And the birds figured out the timing of the valve and would attack in the lull periods immediately following the sprinkler activation!  Smart birds!  The whole system was powered by adapter, so I saved a few batteries.  And the activation time of the sprinkler was shorter, so water usage was less than before.  But it still needed improvement.

This year I decided to upgrade, and added a second impact sprinkler/solenoid valve.  I've built a tower of irrigation pipe with sprinklers at 2m and 4m levels aimed into the tree.  The Arduino code now fires the sprinklers independently and at random intervals.  The lower sprinkler and upper sprinkler are also randomly chosen to fire randomly.

Electronic bird deterrent setup.  Solenoid and impact head triggered by Arduino circuit
Irrigation valve and sprinkler head.

So far the birds seem to have trouble figuring out the cycle and the cherries are ripening nicely without bird losses.  The sprinklers use about 250ml each activation.  So daily use should be about 100 to 150litres.  I figure that I might water the tree anyway so this water goes to good use making larger, juicier fruit. 

Future improvements might be to reduce firing frequency during certain times, because feeding pressure seems to be higher in the mornings and evenings, mid day sprinkler activations could be reduced.  I intend to etch some boards and build a few more as I've got 4 more cherry trees on our property that are unprotected.  This year is looking like a bumper crop, so much so that the kids are going to set up a stand to sell some cherries.