Projects Research & Design Hub

Breathalyzer Links to Car’s Ignition System

Written by Julia Paglia

Using an NXP LPC802 MCU

To stop people from driving under the influence, it helps if their cars start only when their blood alcohol content is below the legal limit. In this article, learn how this York University student made a breathalyzer that’s built into a car’s ignition system—also known as an ignition interlock device. The system uses an NXP LPC802 MCU.

  • How to build a breathalyzer that’s built into a car’s ignition system,

  • What’s the difference between blood alcohol and alcohol levels?

  • How to select each component and what each does

  • How to develop custom software for the project

  • How to understand the conversion calculations

  • What are the future uses for this device?

  • NXP Semiconductors’ LPC802 MCU

  • MQ-3 gas sensor from SparkFun

  • Hitachi HD44780 LCD screen

  • NXP OM40000 development board

  • NXP MCUXpresso Version 11.1 IDE

  • NXP LPC802 SDK

Car accidents involving alcohol and drugs is the leading criminal cause of death in Canada. Despite the presence of programs such as RIDE and MADD—as well as the hefty legal deterrents—some people still find it easy to get behind the wheel after a few too many drinks. To truly prevent people from driving under the influence, their vehicles should start only if their blood alcohol content is below the legal limit. The context of my embedded system project reflects the provincial driving laws of Ontario. The system works similarly to the ignition interlock devices that are already mandated for some drivers through the Government of Ontario’s Ignition Interlock Program.

My project is a breathalyzer built into a car’s ignition system, also known as an ignition interlock device, using NXP Semiconductor’s LPC802 microcontroller (MCU). When a driver tries to start a car, the device prompts him or her to blow into an alcohol sensor. The device then measures the alcohol concentration in the driver’s breath, and converts it to a percentage of blood alcohol content. The car will turn on only if the driver’s BAC is within the province’s legal limit of 0.08%. Please note that the scope of this project does not cover the actual ignition of the vehicle. Instead, this ignition is represented in the prototype through the LED “headlights” on a model vehicle. More on its real-world applications is discussed later in the Future Uses section of this article.

Blood alcohol content (BAC) is the percentage of alcohol in a person’s bloodstream, used to measure the level of intoxication. In Ontario, someone is legally intoxicated if the BAC is above 0.08%. Drivers under the age of 22 are considered legally intoxicated at any BAC above 0.00%. Several factors can influence a person’s BAC, including the number of alcoholic drinks consumed, time elapsed since consumption, biological sex and body weight. Figure 1 outlines the various BAC ranges, along with the side effects and implications of reaching that level of intoxication.

FIGURE 1 – Spectrum of the experienced effects of each stage of intoxication, based on blood alcohol content (BAC) ranges

The easiest way to measure alcohol content is to obtain a breath alcohol reading and convert it into a blood alcohol level, so that’s exactly what I did. The ratio of breath alcohol to blood alcohol is 1:2100, meaning that for every 1mg of alcohol in a person’s breath, there are 2,100mg of alcohol per liter of blood. A BAC of 0.08% is equivalent to 800mg/L of blood alcohol, and 800/2,100 = 0.381mg/L of breath alcohol. Accordingly, the equation for converting breath alcohol to BAC is:

The MQ-3 is a semiconductor sensor that is particularly sensitive to alcohol. This module is composed of a tin dioxide (SnO2) layer for gas sensing, which is less conductive than pure air. When alcohol gas exists in the surrounding environment, the conductivity of the MQ-3 increases. The sensor uses its A0 pin to output a resistive analog signal that is dependent on the alcohol concentration present. The MQ-3 measures the amount of alcohol by measuring the resistance inside the sensor. Both of these properties are inversely proportional to one another. A higher concentration of alcohol in the air will result in a lower resistance within the sensor and a higher voltage output to the LPC802 MCU’s internal analog-to-digital converter (ADC).

The list of components used to build this ignition interlock device and where I purchased them are given in Table 1. The enclosure for this prototype system was a model motor vehicle built with Legos. This project also consisted of wires and a breadboard, which was eventually replaced with a PCB for the final product—and I will say, that was definitely an interesting first-time soldering experience for me. In addition, the NXP OM40000 development board can be powered by a laptop, so the power bank is optional for portability. I developed the project software in C language, using the NXP MCUXpresso Version 11.1 IDE and the NXP LPC802 SDK for reference to the MCU’s registers. A high-level overview of the hardware architecture, and the final, finished prototype in its initial “on” state are shown in Figure 2.

TABLE 1 – Components of the ignition interlock device, and their sources
FIGURE 2A – Overview of the hardware for the ignition interlock system. The high-level hardware architecture (top).
FIGURE 2B – A photo of the finished system prototype in its initial “on” state (bottom). A demonstration video of the project is posted on Circuit Cellar’s article materials webpage.

As with all engineering problems, it was crucial for me to break this problem into smaller sub-systems before integrating each part into one, complete system. This section describes the components of the LPC802 MCU that were used for this project, and the role that each one plays in the overall functionality of the device.

GPIO Inputs, Outputs, and Interrupts: The OM40000 board has a total of 20 LPC802 pins on the chip, 17 of which are GPIO pins. After accounting for the RESET and wires for programming, such as the Serial Wire Debugger and Clock (SWDIO and SWCLK), the user actually has 14 GPIO pins available. This project utilizes all 14 GPIO pins for its ignition interlock system. The details on how to use the GPIO registers and other registers on the LPC802 are given in the NXP LPC802 user manual and datasheet. The push button was set up as a GPIO input using the GPIO->DIRCLR[0] register, and further specified as a GPIO interrupt using SYSCON->PINTSEL[0]. An interrupt service routine (ISR) was configured to handle the push button as an interrupt, depending on the system’s state at the point of interruption.

The LCD screen and LED headlights were both set up as GPIO outputs using the GPIO->DIRSET[0] register. Since both LED headlights need to be on or off at the same time, I set them up in parallel, so I only needed one GPIO output pin. Turning the LEDs on required the use of the GPIO->SET[0] register, and turning them off made use of the GPIO->CLR[0] register. The setup and usage of the LED headlights is simple, but additional functionality was implemented using the Multi-Rate timer (MRT), which I will discuss later.

Compared to the simplicity of the LED GPIO usage, the LCD screen was much more complex to implement. This output occupies 11 GPIO pins on the LPC802. Table 2 is a list of each LCD pin, along with a brief description of its function and whether it is a GPIO output. A timing diagram for writing to the LCD screen is given in Figure 3. The digital pins D0-D7 determine the character that is printed to the display. More on this can be found in the HD44780 LCD datasheet.

TABLE 2 – List of LCD pins, which are connected as GPIO outputs, and their functions
FIGURE 3 – Timing diagram for setting/clearing the LCD pins to write to the display through GPIO. Threshold values for periods and delays are given in the legend. More details on this can be found in the HD44780 LCD datasheet.

Analog-to-Digital Converter (ADC): The ADC is a system on the LPC802 that converts an analog signal, such as an output from a sensor, into a digital one. This project uses the ADC to translate an analog output signal from the MQ-3 gas sensor. Any of the ADC pins can be used, but this particular system uses ADC_2 (also known as PIO0_15) to handle the analog signal.

When configuring and using the LPC802’s ADC, the following SYSCON registers provide these functionalities:

a) The ADC is powered with the PDRUNCFG register
b) The clock register is enabled with SYSAHBCLKCTRL0
c) ADCCLKSEL and ADCCLKDIV control the ADC clock
d) The SWM0->PINENABLE0 register is used to select an ADC pin to use
e) The channel selection and trigger settings are configured with ADC0->SEQ_CTRL[0]
f) The result data are read using the ADC0->DAT[2] register

SysTick Timer: The SysTick timer is exactly what it sounds like—a system timer, which is considered to be the main timer for the LPC802 MCU. It counts down from a large number with a maximum of 24 bits, provided in the SysTick configuration. In this project, SysTick runs at an FRO frequency of 12MHz, with a down-count value of 12 million ticks, resulting in an interrupt frequency of 1Hz. At the point of each SysTick interrupt, new ADC values are added to the buffer responsible for the analog signal filtering. This is discussed later in this article in the section CUSTOM COMPONENTS. The SysTick timer is the simplest of all timers on the LPC802, so I decided that it was the best choice for handling the ADC buffer values while the system is running.

Multi-Rate Timer (MRT) and Pulse-Width Modulation (PWM): The Multi-Rate timer consists of two channels, each with its own 31-bit timer, running in parallel with SysTick. This project uses the MRT repeat mode, though one-shot and bus stall modes are also available. The MRT CTRL register enables interrupts for repeat mode, whereas the INTVAL register loads a value into the MRT channel after each cycle. In this project, the MRT channel 0 is set up with a frequency of 1kHz and is used for pulse-width modulation on the LEDs. Channel 1 has a frequency of 125MHz and is used to create an 8s delay while ADC values are being collected and stored. At each interrupt, the ADC average is calculated, converted into a meaningful BAC value and displayed on the LCD screen for the user.

Channel 0 was set up to run pulse-width modulation for the LED headlights with a duty factor of 0.2 (80%). This means that when turned on, the LEDs are set high for 80% of their period and low for 20%, giving the appearance that they are 80% as bright as they would be with just a straight voltage signal. As previously mentioned, the channel 0 IRQ frequency was set to 1kHz, making the transition between pulses undetectable with the naked eye. Since the LEDs represent vehicle headlights in the context of this project, I set the duty factor to 80% as a safety measure for the drivers, because they should not be driving with high beams on. But this implementation also provides the opportunity for scalability in future applications, since the LEDs can be switched out for a motor to be activated with PWM (pulse-width modulation).

In addition to the LPC802-specific components, I designed and developed custom software systems for the purpose of this project. Although the following system aspects were designed for an ignition interlock device, their concepts and implementations can be applied to other embedded systems and software projects.

State Machine: The ignition interlock system was designed as a state machine to schedule the execution of various messages on the LCD screen (Figure 4). The SysTick and MRTs are configured in State 2, after the first button interrupt. After configuration, both timers are constantly running for the remainder of states while the system is on. As a result, it was necessary to keep track of the current state of the system and schedule the next state according to the timers and the system’s interactions with the surrounding environment.

FIGURE 4 – State diagram for the ignition interlock system, from the moment the device turns on until it reaches a final message state (State 7 or State 10)

Analog Signal Filtering for the ADC Rolling Average: I implemented and tested a series of analog signal filtering solutions to determine the best approach to achieving the most accurate BAC conversions. I kept track of the rolling average of ADC readings by storing the 10 most recent values in a first-in-first-out (FIFO) data structure. In this case, I used a global array to act as my buffer for the system. As previously mentioned, the filter was set up using the SysTick timer, with an interrupt every 1 second. During each interrupt, two ADC readings are added to the buffer array. I decided that an array is the most efficient data structure for this implementation, because it allows the system to get and set element entries in constant time, O(1). Updating values in the buffer is the core functionality of tracking the 10 most recent ADC readings.

I chose this filtering implementation because it resulted in the least variance in ADC values relative to the target value, when tested against three other options over a period of 20 seconds. Throughout my testing, I found that increasing the time between adding new values to the buffer allowed the measurements to be taken over a longer period, and thus, resulted in less outliers and a more accurate average.

The chosen solution still fills the initial buffer array in 5 seconds, which is within the duration of the 8 second MRT channel 1 interrupt. This allowed me to lengthen the duration of ADC data collection for the buffer, while still ensuring that there were 10 values available for the next rolling average calculation. Although a simple rolling average filter was implemented specifically for this project, its applications extend to any device that uses analog inputs or outputs. Analog signal filtering is crucial in the realm of embedded systems, because it provides an accurate and measurable way for systems to interact with the real world.

The system was calibrated using a bottle of hand sanitizer with an ethanol content of 68%. Translating this gas concentration of 0.68mg/L in air to blood, the expected BAC level was: (0.68) × (0.21) = 0.14%. After the sensor’s analog output was filtered and I obtained an ADC average for the buffer’s current elements, I normalized the average value and converted it into a BAC percentage. I derived the conversion equation to be:

Through the LinkServer debugger built into the MCUXpresso IDE, I was able to determine the ADC information below from the result bits in the ADC0->DAT[2] register. The remainder of values specific to alcohol thresholds was obtained from the MQ-3 datasheet:

A sample calculation is given below as an example of how this equation behaved during the testing phase of the project when I calibrated the system using the 68% ethanol sanitizer. The ADCAVG value observed through the debugger during this stage of testing was 2,394, so the experimental result was calculated to be:

As noted above, the theoretical BAC level for these conditions was expected to be 0.14%. After testing the BAC conversion formula with multiple ADC averages, I observed experimental values that consistently matched the expected one. When testing the device with human alcohol consumption (the fun part, when I got to take shots in the name of science), I used an online calculator to estimate my BAC percentage based on my body type, alcohol type and time elapsed. I took a 1.5oz. shot of 33% liquor and measured my BAC after 1 hour. The calculator gave an estimate of 0.03%, which was the same BAC that was reported on the project prototype under these conditions.

Although this project was simply meant to be a prototype, several future implementations and enhancements could work in the context of drunk driving prevention. Given the shift of vehicles to remote starting, this type of system could be built directly into the key, to give the driver a more portable device to work with. It could also be linked to the driver’s phone, to automatically order an Uber or call a taxi if the driver consents. In addition, a fingerprint sensor could be added to the system to ensure that the person driving the car is the same person who is breathing into the breathalyzer. This option would also help minimize how many people try to cheat the device.

Current implementations of this type of system force the drivers to sporadically blow into the sensor as they are driving, and if their BAC readings ever exceed the legal limit, the vehicle would shut down. Since this method has already been partially integrated into society, it seems reasonable to continue using it. This functionality can be further enhanced by setting up the sensor to passively measure the drivers’ BAC without their having to stop to blow into it. The existing timers used for this project already have the potential to be expanded for these specifications, and this application also would be much more convenient for the average driver.

Ontario’s Ignition Interlock Program is currently mandated for individuals who have previously been convicted of impaired driving. However, this prototype is meant to model a more proactive approach to combating drunk driving by incorporating these devices into the standard vehicle. The whole premise of embedded systems is to accomplish a simple task effectively. Preventing a motor vehicle from starting when the driver is impaired is a seemingly simple task, but it could mean the difference between life and death for more than just the driver. 


Source Code:

Demo Video:

Datasheets and User Manuals:
The following are links to the PDF files for the LPC802 user manual as well as the datasheets for the LPC802, the MQ-3 gas sensor, and the HD44780 LCD screen.

Mathematical References:
These are resources used for the deriving the conversion formula from the MQ-3 analog output signal into a meaningful BAC percentage.

Additional Background References:
Below are references to background details about Ontario’s Ignition Interlock Program.

Eric Electronic Technology |
Digi-Key Electronics Canada |
Mouser Electronics |
NXP Semiconductors |
Sparkfun |


Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.

Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article
+ posts

Julia Paglia is fourth-year Computer Engineering student at York University. Although her background is primarily focused on the software side of the industry, she says that her Computer Engineering has allowed her to explore areas of design and development from both software and hardware perspectives (

Supporting Companies

Upcoming Events

Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2024 KCK Media Corp.

Breathalyzer Links to Car’s Ignition System

by Julia Paglia time to read: 13 min