Measuring engine RPM with Arduino

You can measure engine RPM using the negative terminal of the coil, however you need to isolate the 12v circuit of the coil, from the 5v levels used in the Arduino. This can be done using an optical isolator circuit as detailed below.

The following schematic shows how to connect the circuit:

RPM Module Schematic

Assembly List

The following components, or their equivalent are required to build the RPM module.

Label Part Type Properties
4n25 DIP – 6 pins package DIP (Dual Inline) [THT]; hole size 1.0mm,0.508mm; true; chip label IC; pins 6; pin spacing 300mil
Arduino Arduino Uno (Rev3) type Arduino UNO (Rev3)
C1 Ceramic Capacitor package 100 mil [THT, multilayer]; capacitance 100nF; voltage 6.3V
C2 Ceramic Capacitor package 100 mil [THT, multilayer]; capacitance 100nF; voltage 6.3V
D1 Rectifier Diode package 300 mil [THT]; type Rectifier; part # 1N4001
D2 Zener Diode package Melf DO-213 AB [SMD]; breakdown voltage 5.1V; type Zener; power dissipation 0.5W; part # 1N4732A
R1 390 Ω Resistor package THT; tolerance ±5%; bands 4; resistance 390Ω; pin spacing 400 mil
R2 4.7k Ω Resistor package THT; tolerance ±5%; bands 4; resistance 4.7kΩ; pin spacing 400 mil

Example Code

volatile unsigned long timePointsOpen, timePointsClosed, lastChange;
volatile unsigned int numBangs;

void pointsOpening(){
    unsigned long t;
    t = millis();
    if (lastChange > 0){
        timePointsClosed += (t - lastChange);
    lastChange = t;

void setup(){
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);

void loop(){
  // Number of coil pulses
  numBangs = 0;
  attachInterrupt(0, pointsOpening, RISING);
  numBangs = ((60000/50)*numBangs)/2;
  Serial.print("RPM: ");

Arduino Megasquirt Library

This driver provides access to the MegaSquirt ECU with a level of abstraction above the MegaSquirt serial interface, enabling users with no knowledge of the MegaSquirt commands to access the register data easily without caring about the underlying communication required.

The MegaSquirt is a low cost engine control unit with support for fueling, ignition and idle control.


The MegaSquirt is connected to the Arduino using the RS232 output on the MegaSquirt, a MAX232 chip, and the Serial interface on the arduino board.


#include >MegaSquirt.h<
void setup(){
 byte status;
 String signature;
 switch (status){
   Serial.print("MegaSquirt Signature: ");
   Serial.println(" FAILURE: Communication Timeout");
   Serial.println(" FAILURE: Communication Overflow");
   Serial.println(" FAILURE: Unknown Error"); 

String revision;

 uint16_t uptime;

 MegaSquirtData registers;
 byte regTable[MS_TABLE_LENGTH];


 Serial.println(registers.lambda1()/10,DEC )


You can download the ZIP file to import into the IDE here, or you can fork your own.

Arduino LIS331 Library

The LIS331HH is an ultra low-power full-scale three axis MEMS linear accelerometer.  The device also features ultra low-power operational modes that allow advanced power saving and smart sleep to wake-up functions.  I wrote a library for Arduino that provides an object oriented interface to these devices using the I2C bus.

The project is hosted on GitHub here and is licensed under the GPL.


You can download the ZIP file to import into the IDE here, or you can fork your own.


Be sure to include the LIS331 and Wire libraries in your project first.

setPowerStatus(int status);

Set the power saving status of the device, options are: LR_POWER_OFF, LR_POWER_NORM, LR_POWER_LOW1, LR_POWER_LOW2,LR_POWER_LOW3

setXEnable(bool enable)

Enable or disable X axis

setYEnable(bool enable)

Enable or disable Y axis

setZEnable(bool enable)

Enable or disable Z axis

string lis.getXValue(int16_t &value);

Reads the X value and assigns it to value.

string lis.getYValue(int16_t &value);

Reads the Y value and assigns it to value.

string lis.getZValue(int16_t &value);

Reads the Z value and assigns it to value.


You can download an example project here.

DHT Support for Loguino

The DHT range of sensors provide a cheap way to grab temperature and humidity information. The sensors are not fast, (250ms per query) but have a good price and require only a single digital pin to use.  Kyle had a few sitting around, so I added loguino support for them.

Arduino ELM327 Library

The ELM327 IC is a multi-function OBD2 Interpreter that can be used to query information about most relatively new vehicles.  The ELM327 connects to the vehicle using the OBD2 port, and provides an RS232 Interface.   I recently purchased an OBD2 shield form SparkFun which uses an ELM clone, the STN1110.  I wanted to add OBD2 support to Loguino, but first I needed to be able to communicate using the ELM protocol.

Subsequently I created a the ELM327 class, which contains both high level and low level methods to get information from the controller.  The low level class is used to send arbitrary commands to the ELM chip, there are two main methods,

  • getBytes which requests a specific PID and parses the returned bytes into an array of values.
  • runCommand which sends an arbitrary command to the ELM device, and parses the output into a buffer which contains the response from the ELM.

The high level class provides methods to gather metrics from the controller, each method parses the response from the ELM device into the actual value.  The following code illustrates how to use the class:

#define ELM_TIMEOUT 9000
#define ELM_BAUD_RATE 9600
#define ELM_PORT Serial3

byte status;
Elm327 Elm;
if (status != ELM_SUCCESS){
    Serial.print("Error: ");
int temp;
Serial.print("OBD2 Coolant Temperature: ");
if (status  == ELM_SUCCESS)
    Serial.println ("Pass");
    Serial.print(" Value: ");
    Serial.print("Error: ");

byte values[2];
if (status == ELM_SUCCESS){
    Serial.print("Elm returned: ");
    Serial.print(values[0], HEX);
    Serial.print(" ");
    Serial.println(values[1], HEX);
    Serial.print("Which is: ");
    Serial.print(((values[0]*256)+values[1])/4, DEC);
    Serial.println(" RPM");
    Serial.print("Error: ");

char data[20];
Serial.print("Current version is: ");

Feature requests, bugs, suggestions and other feedback always appreciated.

NMEA Library for Arduino

NMEA 0183 (National Marine Electronics Association) is the communication standard for devices used in marine environments as an aid to navigation. The most common use outside of marine environments is for GPS devices, which use NMEA to broadcast their position.

I wrote this library for Loguino in order to provide global positioning metrics to the logger. For Loguino 2.0 I needed to simplify the build, which means moving non-core libraries into their own packages, a lot of people also use the libraries on their own without Loguino, so it’s about time this was the case.

The code is available on GitHub, under the GPL.


You can download the ZIP file to import into the IDE here, or you can fork your own.


bool addChar(const char c)

Add a character from the gps stream. Returns True when a valid NMEA sentence has been completed. Generally you want to loop through all the data in the serial buffer and call addChar with the output of until it returns true. At which point you can interrogate the NMEA object to determine if the fix is valid and then grab the location information if required.

bool validFix()

Returns true when the GPS has a valid fix.

string gps.getCourse()

Returns the course in degrees.

string getSpeed()

Returns the speed in Knots.

string getLatitude()

Returns the latitude.

string getLongitude()

Returns the longitude

string gps.getDate()

Returns the date as a string.

string gps.getTime()

Returns the time as a string.


You can download an example project here.