├── README.md ├── Schematic.png └── code.cpp /README.md: -------------------------------------------------------------------------------- 1 | Arduino car tachometer 2 | ============== 3 | 4 | Introduction 5 | ---- 6 | I'm currently driving an old Opel Astra without tachometer. I had a spare arduino and few LEDs, so I made a simple tachometer. I started by cut a 5cm x 1.5cm piece of an old credit cart, drilled 4 holes in it, painted it black and glued 4 LED diods to it. Then I soldered a 220ohm resistors to each positive LED pin and used a common ground. I connected them to arduino via 5x30cm jumpers and hid the arduino in a hole under the wheel. I connected the arduino data pin via voltage divider to the signal pin of the coil and used an old phone charger to power the arduino. In order to work I shared the phone charger and arduino's grounds. 7 | 8 | The first LED turns on when engine react 4000 rpm. Below 4000 rpm all LEDs are turned off. If there is Serial attached, it automatically emits rpm data(watch it realtime in arduino serial monitor). 9 | 10 | Demo 11 | ---- 12 | 13 | [Link to youtube video](https://www.youtube.com/watch?v=l8S7WWx-YB4&feature=youtu.be) 14 | 15 | [![Arduino tachometer demo](http://img.youtube.com/vi/l8S7WWx-YB4/0.jpg)](http://www.youtube.com/watch?v=l8S7WWx-YB4) 16 | 17 | Schematic 18 | ---- 19 | ![Schematic](https://raw.githubusercontent.com/deepsyx/arduino-tachometer/master/Schematic.png) 20 | 21 | Code 22 | ---- 23 | Check out the `code.cpp` file. 24 | 25 | Materials 26 | ---- 27 | - Arduino Uno 28 | - 4x LEDs 29 | - 5x 220ohm resistor 30 | - 1x 160ohm resistor 31 | - 10x 30cm jumpers 32 | - Old car phone charger 33 | - Longer wire to connect to coil 34 | - 1amp fuse (not included in schematics) 35 | 36 | Future ideas 37 | ---- 38 | - More LEDs 39 | - Log data (to phone or sd card) for analysis 40 | - Graphic visualization for phone 41 | -------------------------------------------------------------------------------- /Schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepsyx/arduino-tachometer/6f9248a49904b118b18cf34dcf53fcd4ca364c16/Schematic.png -------------------------------------------------------------------------------- /code.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SIMPLE ARDUINO CAR TACHOMETER 3 | */ 4 | 5 | 6 | const int DATA_PIN = 4; 7 | const int LED_GROUND_PIN = 8; 8 | 9 | const int PINS_COUNT = 4; 10 | const int LED_PINS[PINS_COUNT] = {9, 10, 11, 12}; 11 | const int LED_SWITCH_RPM[PINS_COUNT] = {4000, 4500, 5000, 5500}; 12 | const int REV_LIMITER_RPM = 5800; 13 | 14 | const int NUMBER_OF_CYLINDERS = 4; 15 | const int LED_UPDATE_INTERVAL = 200; 16 | 17 | /* 18 | * Last led state update time in ms, used to calculate the time from last update 19 | */ 20 | unsigned long lastUpdateTime = 0; 21 | 22 | /* 23 | * Amount of spark fires in a single interval 24 | */ 25 | volatile int sparkFireCount = 0; 26 | 27 | /* 28 | * Rpm value from last update 29 | * Used to average the last 2 rpms for smoother output 30 | */ 31 | int lastRpmValue = 0; 32 | 33 | /* 34 | * Blinking rev limiter state 35 | */ 36 | bool revLimiterOn = false; 37 | 38 | /* 39 | * 40 | */ 41 | void incrementRpmCount () { 42 | sparkFireCount++; 43 | } 44 | 45 | /* 46 | * Turns all leds on or off 47 | */ 48 | void setGlobalState(bool state) { 49 | for (int i = 0; i < PINS_COUNT; i++) { 50 | digitalWrite(LED_PINS[i], state); 51 | } 52 | } 53 | 54 | /* 55 | * Turn on leds, based on input rpm 56 | */ 57 | void setLedState(int rpm) { 58 | setGlobalState(LOW); 59 | 60 | // If rpm is over REV_LIMITER_RPM, all leds should be blinking at 200ms interval 61 | if (rpm > REV_LIMITER_RPM) { 62 | if (revLimiterOn) { 63 | setGlobalState(LOW); 64 | } else { 65 | setGlobalState(HIGH); 66 | } 67 | 68 | revLimiterOn = !revLimiterOn; 69 | return; 70 | } 71 | 72 | for (int i = 0; i < PINS_COUNT; i++) { 73 | if (rpm > LED_SWITCH_RPM[i]) { 74 | digitalWrite(LED_PINS[i], HIGH); 75 | } 76 | } 77 | } 78 | 79 | /* 80 | * Defines led pins as output, 81 | * turns all leds on for 500ms when started 82 | * attach to serial if available 83 | */ 84 | void setup() { 85 | // Define all led pins as outputs 86 | for (int i = 0; i < PINS_COUNT; i++) { 87 | pinMode(LED_PINS[i], OUTPUT); 88 | } 89 | 90 | pinMode(LED_GROUND_PIN, OUTPUT); 91 | digitalWrite(LED_GROUND_PIN, LOW); // Use pin 8 as ground for the leds 92 | 93 | setGlobalState(HIGH); 94 | delay(500); 95 | setGlobalState(LOW); 96 | 97 | pinMode(DATA_PIN, INPUT_PULLUP); 98 | attachInterrupt(1, incrementRpmCount, FALLING); 99 | Serial.begin(9600); 100 | } 101 | 102 | // 4 stroke engine fires every spark in 2 revolutions 103 | // so calculate at what degree interval sparks fires and divide 360 by it, 104 | // to find the number of fires per rotation 105 | const int FIRES_PER_REV = (360 / (720 / NUMBER_OF_CYLINDERS)); 106 | 107 | void loop() { 108 | if ((millis() - lastUpdateTime) > LED_UPDATE_INTERVAL) { 109 | 110 | // multiply the amount the spark fires in one interval by the number of intervals per 111 | // second, to find the amount in one second 112 | // then multiply the amount in one second by 60, to find the spark fires in one minute and 113 | // divide the result by the number of fires per revolution to find the rpm 114 | int currentRpm = (sparkFireCount * (1000 / LED_UPDATE_INTERVAL) * 60) / FIRES_PER_REV; 115 | 116 | // average the current and last rpm for smoother results 117 | int averagedRpm = (currentRpm + lastRpmValue) / 2; 118 | 119 | setLedState(averagedRpm); 120 | Serial.println(averagedRpm); 121 | 122 | sparkFireCount = 0; 123 | lastUpdateTime = millis(); 124 | lastRpmValue = currentRpm; 125 | } 126 | } 127 | --------------------------------------------------------------------------------