Key Fob replacement for 2002 Ford using Particle Electron

The key fob on my 2002 Ford Fairlane broke and was no longer able to be used for wireless remote central locking. After dismantling the fob, it appeared that just the packaging and one of the switches was broken. I connected the switches (using a transistor for each switch) to be driven by a Particle Electron.

The original article (including all code, pictures, etc…) is on hackster.io: https://www.hackster.io/jeremy-gillbanks/key-fob-replacement-for-2002-ford-using-particle-electron-f3e8f0

/* App to replace 2002 Ford Fairlane Key Fob
*/
void setup() {
    pinMode(D2, OUTPUT);
    pinMode(D3, OUTPUT);
    pinMode(D4, OUTPUT);
    Particle.function("lock", lock);
    Particle.function("unlock", unlock);
    Particle.function("boot", boot);
} 

int lock(String command) {
    digitalWrite(D3, HIGH);
    delay(100);
    digitalWrite(D3, LOW);
    digitalWrite(D7, HIGH);
    delay(500);
    digitalWrite(D7, LOW);
    return 1;
}

int unlock(String command) {
    digitalWrite(D4, HIGH);
    delay(100);
    digitalWrite(D4, LOW);
    delay(100);
    digitalWrite(D4, HIGH);
    delay(100);
    digitalWrite(D4, LOW);
    digitalWrite(D7, HIGH);
    delay(500);
    digitalWrite(D7, LOW);
    return 1;
}

int boot(String command) {
    digitalWrite(D2, HIGH);
    delay(100);
    digitalWrite(D2, LOW);
    digitalWrite(D7, HIGH);
    delay(500);
    digitalWrite(D7, LOW);
    return 1;
}

void loop() {
}

If you attempt this project, please let me know!

Cheers

4 Likes

This is very cool. How are you calling the Particle functions?

A few constructive comments:

  1. You don’t need to use three different Particle functions. You can easily use a central one (let’s call it “command”) that takes various arguments (“unlock”, “lock”, and “boot”)
  2. Ideally you want Particle functions to execute as quickly as possible. To achieve this we suggest you use “flags”.
  3. See below for an example code (untested but should give you the general gist)
/* App to replace 2002 Ford Fairlane Key Fob
*/

#define COMMAND_UNKNOWN -1
#define COMMAND_NONE 0
#define COMMAND_LOCK 1
#define COMMAND_UNLOCK 2
#define COMMAND_BOOT 3

int command = COMMAND_NONE;

void setup() {
    pinMode(D2, OUTPUT);
    pinMode(D3, OUTPUT);
    pinMode(D4, OUTPUT);
    Particle.function("command", command);
} 

void loop() {
    if (command != COMMAND_NONE) {
        switch (command) {
            case COMMAND_LOCK:
                digitalWrite(D3, HIGH);
                delay(100);
                digitalWrite(D3, LOW);
                digitalWrite(D7, HIGH);
                delay(500);
                digitalWrite(D7, LOW);
                break;
            case COMMAND_UNLOCK:
                digitalWrite(D4, HIGH);
                delay(100);
                digitalWrite(D4, LOW);
                delay(100);
                digitalWrite(D4, HIGH);
                delay(100);
                digitalWrite(D4, LOW);
                digitalWrite(D7, HIGH);
                delay(500);
                digitalWrite(D7, LOW);
                break;
            case COMMAND_BOOT:
                digitalWrite(D2, HIGH);
                delay(100);
                digitalWrite(D2, LOW);
                digitalWrite(D7, HIGH);
                delay(500);
                digitalWrite(D7, LOW);
                break;
            default:
                Particle.publish("UNKNOWN_COMMAND", String(command));
        }
        command = COMMAND_NONE;
    }
}

int command(String command) {
    if (command == "lock") {
        command = COMMAND_LOCK;
    } else if (command == "unlock") {
        command = COMMAND_UNLOCK;
    } else if (command == "boot") {
        command = COMMAND_BOOT;
    } else {
        command = COMMAND_UNKNOWN;
    }
    return command;
}
5 Likes

Nicely done! Unfortunately, my solar panel I had hooked up to the battery didn’t get any sun for a while and I’ve bricked my Electron just like: Bug Bounty: Electron not booting after battery discharges completely

Once we get something on the bug bounty, I’ll be excited to implement these changes.

Cheers!

Oh noes! That’s frustrating. If you are up for it I can guide you through unbricking your device. First you need to purchase something like this (search “ST-Link” on eBay or Amazon): [eBay] [Amazon]

That is frustrating. The same thing happened to my solar panel powered Photon. The next thing you need to purchase is a battery protector that will disconnect the load when the battery voltage goes below a preset level. Search “battery protector” on Ebay.

My panel is charging a 12 V. gel cell. When we have a long stretch of cloudy weather, the battery protector will cleanly disconnect the Photon when the battery goes below 11.2 V and automatically reconnect it when it goes back above 12.2 V. No more dead microprocessors.

I’ve just ordered an ST-Link off eBay, but unfortunately, it will only arrive in early March! China is somehow very far away from Australia.

But I’m definitely keen to find out what to do once it arrives!

That’s an excellent idea! Do you recommend something like this: https://www.sparkfun.com/products/10617?

The Electron already has a fuel gauge. The issue is that there is no easy way to “hard cutoff” the battery when the voltage drops below safe levels. The lipo battery looks to already have some protection circuitry (it’s usually hidden under the yellow tape) but I guess it’s not optimized for the Electron. Ideally you’d have something that would cut the battery off at voltage X and then turn it back on at voltage X + ε where ε is just some positive value to add a bit of hysteresis.

No, I'm talking about something like this: http://www.ebay.com/itm/Battery-Protector-Voltmeter-Combo-Meter-0-200V-0-400A-Car-Motor-Boat-Motorhome-/162102273341?hash=item25be0c653d:g:A2IAAOSwU9xUUlbA

The one I got was a PCB kit from these guys: http://www.onstatetech.com/products/products.htm

Unfortunately they don't seem to be selling it on Ebay anymore.

That's exactly what the battery protector does. It has pots to select the low cutoff voltage and the reconnect voltage. I have mine set to disconnect the Photon from the 12 V gel cell when it gets down to 11.2 V. Later on when the sun returns and resumes charging the battery, it will reconnect when it gets back to 12.2 V, which is about the 50% point for gel cells.

This kills two birds with one stone. The battery is protected from deep discharging, which will kill a gel cell in short order, and the Photon is protected from its tendency to commit hari kiri when its input voltage slowly sags below 3v3.

1 Like

I finally got an ST-Link off eBay!

Could you please guide me through unbricking my device? I haven’t had any luck in finding an easy to follow set of instructions.

Thanks in advance Harrison!

The instructions are here, in the section “Programming the boot loader”

https://docs.particle.io/faq/particle-tools/jtag/

1 Like

@rickkas7 that's a great set of instructions! But I'm having a small problem implementing them. I seem to keep getting this error when I go to program the bootloader:

program /Users/Jeremy/Downloads/bootloader-electron.bin verify 0x08000000

target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
** Programming Started **
auto erase enabled
stm32x device protected
failed erasing sectors 0 to 0
embedded:startup.tcl:454: Error: ** Programming Failed **
in procedure 'program' 
in procedure 'program_error' called at file "embedded:startup.tcl", line 510
at file "embedded:startup.tcl", line 454

I'm not really sure what this means as I've never gotten quite this low-level before. I've already implemented the previous command:

flash protect 0 0 0 off

So I'm not sure why it keeps saying that the stm32 device is protected. Unless I'm reading that completely wrong! Any chance you could please give me a hand? Thanks!

That should have worked. Try doing

flash info 0

and see if the sector actually unprotected.

You could also try:

flash erase_sector 0

It should behave the same, but it’s a reasonable test to see what happens.

Thanks for the help @rickkas7!

Here's the result from both of those commands:

> flash erase_sector 0
  flash erase_sector bank_id first_sector_num last_sector_num

Result:

> flash info 0        
Device Security Bit Set
#0 : stm32f2x at 0x08000000, size 0x00100000, buswidth 0, chipwidth 0
	#  0: 0x00000000 (0x4000 16kB) not protected
	#  1: 0x00004000 (0x4000 16kB) not protected
	#  2: 0x00008000 (0x4000 16kB) not protected
	#  3: 0x0000c000 (0x4000 16kB) not protected
	#  4: 0x00010000 (0x10000 64kB) not protected
	#  5: 0x00020000 (0x20000 128kB) protected
	#  6: 0x00040000 (0x20000 128kB) protected
	#  7: 0x00060000 (0x20000 128kB) protected
	#  8: 0x00080000 (0x20000 128kB) protected
	#  9: 0x000a0000 (0x20000 128kB) not protected
	# 10: 0x000c0000 (0x20000 128kB) not protected
	# 11: 0x000e0000 (0x20000 128kB) not protected
STM32F2xx - Rev: unknown (0x2007) 

I'm not exactly sure what to make of this. I can see that using 'flash protect 0 0 0 off' disables the protection to 0x00000000, but I'm not sure what the rest of it is, or what it is used for.

Additionally, after running the bootloader command, I get the same error as mentioned in previously.