A quick and dirty vehicle entry/start sketch for Arduino
-
Quick and dirty sketch for the Elechouse PN532 board I have in I2C mode for starting the car. Or anything else you want to do really. Code mostly yoinked from elechouse PN532 examples folder, ringuid references yoinked from John's https://github.com/JohnMcLear/NFC_Ring_Arduino_Door_Lock
Suggestions, additions, changes?
#include <EEPROM.h> /**************************************************************************/ /*! This example will attempt to connect to an ISO14443A card or tag and retrieve some basic information about it that can be used to determine what type of card it is. Note that you need the baud rate to be 115200 because we need to print out the data and read from the card at the same time! */ /**************************************************************************/ int triggerPin1 = 2; int triggerPin2 = 3; int triggerPin3 = 4; // choose to SPI or I2C or HSU #if 0 #include <SPI.h> #include <PN532_SPI.h> #include "PN532.h" PN532SPI pn532spi(SPI, 10); PN532 nfc(pn532spi); #elif 0 #include <PN532_HSU.h> #include <PN532.h> PN532_HSU pn532hsu(Serial1); PN532 nfc(pn532hsu); #else #include <Wire.h> #include <PN532_I2C.h> #include <PN532.h> PN532_I2C pn532i2c(Wire); PN532 nfc(pn532i2c); #endif void setup(void) { pinMode(triggerPin1, OUTPUT); pinMode(triggerPin2, OUTPUT); pinMode(triggerPin3, OUTPUT); Serial.begin(115200); Serial.println("Hello!"); nfc.begin(); uint32_t versiondata = nfc.getFirmwareVersion(); if (! versiondata) { Serial.print(versiondata); Serial.print("PN53x key scanner board not online"); while (1); // halt } // Got ok data, print it out! Serial.print("Found key scanner board PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); // Set the max number of retry attempts to read from a card // This prevents us from waiting forever for a card, which is // the default behaviour of the PN532. nfc.setPassiveActivationRetries(0xFF); // configure board to read RFID tags nfc.SAMConfig(); Serial.println("Waiting for a valid card"); } void loop(void) { String ringUid; boolean success; uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) // Wait for an ISO14443A type cards (Mifare, etc.). When one is found // 'uid' will be populated with the UID, and uidLength will indicate // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength); if (success) { // Display some basic information about the card Serial.println("Found an ISO14443A card"); Serial.print(" UID Length: "); Serial.print(uidLength, DEC); Serial.println(" bytes"); Serial.print(" UID Value: "); for (uint8_t i = 0; i < uidLength; i++) { Serial.print(".."); Serial.print(uid[i], HEX); ringUid += String(uid[i], HEX); } Serial.println(ringUid + "\n"); if (ringUid == "xxxxxxxxxxx" || ringUid == "xxxxxxxxxxxx"){ // put your authorised UID in here Serial.println("PERMISSION GRANTED, DOOR UNLOCKED"); digitalWrite(triggerPin1, HIGH); // triggers unlock output for central locking delay(1000); // waits for a second digitalWrite(triggerPin1, LOW); // removes triggered output digitalWrite(triggerPin3, LOW); // Removes triggered alarm output } else if (ringUid == "xxxxxxxxxxxx"){ // put your authorised UID in herev Serial.println("PERMISSION GRANTED, SYSTEMS TRIGGER"); digitalWrite(triggerPin2, HIGH); // sets latching relay trigger on ie for ignition mode in car to allow button start - button start must disable reads until button turns engine off again delay(1000); // waits for a second digitalWrite(triggerPin2, LOW); // removes latching relay trigger digitalWrite(triggerPin3, LOW); // Removes triggered alarm output } else{ Serial.println("I'M AFRAID I CAN'T ALLOW THAT DAVE"); digitalWrite(triggerPin3, HIGH); // Trigger latching relay to alarm system delay(1000); // waits for a second } } }
-
Hi!
Could you tell me more about your relay starter? is for the ignition but for the central car start, how do you do?
And how you will plug your arduino for the supply? (12v of the batterie with a buck regulator?) -
Hi mate, the arduino will be powered by a small transistor regulator at 5 volts from the main car supply.
Switching for the ignition on is via latching relays of the type used in remote car start kits, they can be purchased seperately in high amperage rated units.
Cranking the engine at present will be done via a pushbutton under the dashboard to trip a high current relay. This could be added to another relay driven from the arduino (and do away with the pushbutton) at a later date but that will require a major re-think of the code contained therein to allow proper state switching. -
Okay, that is a really cool project :D
I thought on my first car starter prototype to a system drive hidden in the gear knob (with a realization clear plastic 3D printer). see a startup module that has just clipped driving (hands-free kit style).
But this project will wait for lack of time ^^' but maybe it can inspire some!
-
That's certainly an interesting idea you've got there!
So the reader unit would be inside the gear knob and car usage would be 'allowed' when the ring is present on the knob?
For mine because there is still the chance that you can switch off the car by accident I intend to place the reader in an out of the way position where I won't normally be putting my hands. I'm looking at possibly having two reader units, one on the door at the handle position and one up on the dashboard.
Though the reader units and the arduino modules are cheap enough that I could simply go with two of those, one complete unit for the door and one for the vehicle ignition. -
The gear knob reader juste allow the start of the car, a button are use for the starter.
But for more security i will use the ODB2 connexion for know the RPM of the car so you could stop the car only if it is in the stop state.
And off course, i use bistate relay for don't stop the car in case of a electronic problem.Why don't use a MSP430 chip ? it's compatible with the PN532 and the RC522 arduino library with energia. It's the cheapest solution and a ultra low power technology :)
You can make a wake-up button in the handle and use a little battery too (less wire so easier to connect). -
Interesting, I'll have to look into that one!
-
Ok, I finally got around to doing something more with my NFC Ring car starter. This is just a short proof of concept video showing the changing states via an RGB LED. I'll work on re-writing the code next so that I can do a little more with just a single ring inlay, and close the relay for the starter motor properly - at the moment as it's set up it pulses, I'll alter it so that a single inlay can change mode (on/off) and then start the engine when held.
-
Here are some pictures, including the ugliness of my wiring. :-)
-
Your ring or your reader work really fine, I have a PN532 reader from aliexpress (a clone for 14$) and the read is not effective (I have to rub the ring against the antenna to try to read). But maybe it's the ring tag.
What is the maximum current in your relay? I use a 30A relay because I don't know the instantaneous current to the contact closure, maybe you know that?
-
Hi @MrStein, the latching relay is 30v/3a for the contacts, it's triggering the vehicles relay switched ignition state so it should be fine for that. The momentary relay is 30v/5a, triggering the vehicle starter relay. It's bigger than the latching relay, but is the smallest had in my parts bin!
I have noticed that my Pn532 sometimes doesn't like to read one of my inlays and almost requires rubbing at times, but the other inlay works fine at a distance. -
This is awesome, keeping a close eye on this! :)
-
lol, thanks for the vote of confidence there!
I've modified the hardware side of things a little bit since I took those photos, adding a transistor to trigger the starter relay (the relay has a 12 volt coil and the arduino wasn't coping with that directly from an output) and a couple of filter capacitors for the regulator on the in and out sides to smooth things out a little, there were mild voltage fluctuations. Nothing major, but it's always a good idea to do that and keep things clean.
The starter output from D2 is now running through one side of the latching relay on to the trigger transistor for the momentary relay coil after I decided that the best way to lock out engine cranking was in hardware.
This way the starter can only be cranked once the vehicle ignition is switched on via the latching relay. D2 can still be triggered if software allows it, but it wont go any further than the latching relay if that relay is in the off state.
At the moment I'm investigating methods to trigger D2 and keep it high while the ring is present until the engine is running. This is getting a little trickier than I'd first planned and might end up needing an extra input from the vehicle to exit the engine cranking portion of the program when normal running is achieved.For those who are interested, in the main unit I'm using:
- Panasonic DS2E-SL2-DC5V latching relay
- LZ-12H-K momentary relay
- MPSA42 NPN transistor
- L7805CV regulator
- 10uF electrolytic capacitors, x2
- Microduino equivalent to Arduino Pro Mini 5V
- PN532 NFC board
This is basically all stuff that I had floating around in my parts bin for random projects, you can substitute for things you have as long as they're equivalent. The latching relay I bought for around $10 each from mouser, everything else is a leftover from something else! The Arduino portion of this could also be pretty much any arduino compatible board, I'm using the microduino because I had them and they were small and convenient. The Elechouse PN532 reader is in my opinion non-negotiable. They're the only board I've had real success with reading the rings, most others are far too picky and have trouble reading the rings.
Either way, this just shows that you can build something usable out of very little! Get cracking, people, there are projects waiting for you to build them!
-
Good job!
Don't forget some flyback diode (free wheel diode in french, I don't no how to say that in english ^^') for the discharge of the magnetic circuit of the inductance (relays). -
Oh yes, good catch @MrStein , I'll do that now. I had totally forgotten that one! (Usually it was me telling the apprentices to do that with relays!)
I usually refer to it as a clamping diode, flyback or free wheel diode is perfectly correct as well though. -
So, I've progressed a bit in the last 5 days - my code is still just as awful but I've got the prototype unit to the point where I've test installed it.
Following are some photos and a short video of the starter in action!First I removed the housing for the steering column and located the ignition barrel (I've done all this for other things previously)
Next look at the back of the barrel and find the wires coming out, this bundle is what you need to link into. I've hooked in after the connector into the main loom, I recommend you hook in before that though.
Tapping into the loom is fairly simple. This soldering is not my best, but it will hold for now. Upside down with a gas soldering iron in a cramped space is difficult.
Tape up the joins as you go, as neatly as possible. You really don't want to short out against other wires or metal parts of the car, it can cause all sorts of issues.
And here we are, this is the connector for the points I'm now going to be controlling from the car starter unit. The wire doesn't need to be excessively heavy because power is mostly switched via relays in this vehicle already.
-
And here is a short video of the starter in action!
-
so fricking awesome!! Have to get me one of these things sorted
-
Thanks @NFCringTom , I'm pretty pleased with how it's progressing! Next step will be to cut the prototype board down to make it a bit more manageable, house it in a plastic case and then decide where I'm going to put the actual unit!
Everyone should note that the steering lock is currently intact and so you still require the key in order to drive anywhere - I'm looking at options for removal, I'll see if I can retrofit an electric steering lock from something else and then remove the entire ignition barrel permanently.
On my other car this wont be an issue as it has never had a steering lock. -
I've got a minor code update, I've re-written it to reflect what it's actually doing and made it so that a single inlay can switch through all three states - on, cranking, off.
It's still extremely rough and ready and if anyone else wants to do it better then go for it, I'd welcome the input.int triggerPin1 = 2; int triggerPin2 = 3; int triggerPin3 = 4; int carRunState = 0; #include <Wire.h> #include <PN532_I2C.h> #include <PN532.h> PN532_I2C pn532i2c(Wire); PN532 nfc(pn532i2c); void setup(void) { pinMode(triggerPin1, OUTPUT); pinMode(triggerPin2, OUTPUT); pinMode(triggerPin3, OUTPUT); Serial.begin(115200); Serial.println("Hello! I'm a Car!"); nfc.begin(); uint32_t versiondata = nfc.getFirmwareVersion(); if (! versiondata) { Serial.print(versiondata); Serial.print("PN53x key scanner board not online"); while (1); // halt } // Got ok data, report state Serial.print("Reader Online, "); // Set the max number of retry attempts to read from a card // This prevents us from waiting forever for a card, which is // the default behaviour of the PN532. nfc.setPassiveActivationRetries(0xFF); // configure board to read NFC tags nfc.SAMConfig(); Serial.println("Waiting for a valid key"); } void loop(void) { String ringUid; boolean success; uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) // Wait for an ISO14443A type cards (NFC Ring, Mifare, etc.). When one is found // 'uid' will be populated with the UID, and uidLength will indicate // if the uid is 4 bytes (Mifare Classic) or 7 bytes (NFC Ring or Mifare Ultralight) success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength); if (success) { // Display some basic information about the card // Serial.print(" UID Length: "); Serial.print(uidLength, DEC); Serial.println(" bytes"); Serial.print(" UID Value: "); for (uint8_t i = 0; i < uidLength; i++) { Serial.print(".."); Serial.print(uid[i], HEX); ringUid += String(uid[i], HEX); } Serial.println(ringUid + "\n"); if (ringUid == "4db5e2b62880" || ringUid == "48fc02b62880" || ringUid == "4c9232b62880"){ Serial.println("Key accepted!"); } if ((ringUid == "4db5e2b62880" || ringUid == "48fc02b62880" || ringUid == "4c9232b62880") && (carRunState == 0)){ Serial.println("PERMISSION GRANTED, SYSTEMS ON"); digitalWrite(triggerPin3, HIGH); // sets latching relay trigger on for ignition mode in car to allow start delay(200); // waits briefly digitalWrite(triggerPin3, LOW); // removes latching relay trigger carRunState = carRunState++; } else if ((ringUid == "4db5e2b62880" || ringUid == "48fc02b62880" ||ringUid == "4c9232b62880") && (carRunState == 1)){ Serial.println("ENGINE CRANKING"); digitalWrite(triggerPin1, HIGH); // triggers output for engine starting delay(2000); // waits for a second digitalWrite(triggerPin1, LOW); // removes triggered output Serial.println("ENGINE CRANKING COMPLETE"); carRunState = carRunState++; } else if ((ringUid == "4db5e2b62880" || ringUid == "48fc02b62880" ||ringUid == "4c9232b62880") && (carRunState > 1)){ Serial.println("SYSTEM OFF, SLEEP TIME"); digitalWrite(triggerPin2, HIGH); // Trigger latching relay to reset for vehicle OFF delay(200); // waits briefly digitalWrite(triggerPin2, LOW); // Removes latching relay reset trigger delay(3000); carRunState = 0; } } }