Honk, Honk! Automating the Counting of Car Horns to Tell a Story About Road Safety | Field Test by David S. Joachim
(Originally published on October 4. 2018)
The honking is driving me crazy. When we moved into our home in Pelham, N.Y., two years ago, we knew we were choosing a busy street — Boston Post Road, a part of U.S. Route 1, which traces the path of the colonial-era postal route from New York to Boston. The street has a double-yellow line and is a conduit between two major highways, the Hutchinson River Parkway and Interstate 95.
Soon after we moved in, though, we noticed a problem. The road pattern on our side of the street, traveling eastbound from the Hutch to I95, narrows from two lanes to one lane just before traffic reaches my house (see oncoming traffic ⬆️ and map ⬇️). The speed limit is 30 miles per hour, but that doesn't stop motorists from speeding up to battle for the lead position as they approach the merge into one lane. This dangerous game of chicken often results in near-misses, punctuated by drivers leaning on their horns. It's quite jarring when it happens, I can tell you.
My local government, the Village of Pelham Manor, was responsive after I called attention to the problem. Local officials added signs warning eastbound motorists of the approaching merge. That has helped, but the problem persists. We still hear close calls all the time.
Village records show no accidents at that intersection, so the officials say they can't justify further intervention. The trouble is, I haven't been able to prove how treacherous that stretch of road is. My evidence is purely anecdotal. I'd love quantitative proof, but who has the time to sit by the road for hours at a time, listening for car horns and tallying the honks?
A computer does, that's who! I got to wondering: What if I could assemble a few circuits and write some code that would listen for instances of honking and keep a running count with time stamps? What if I equipped this box with its own storage media and power supply and made it small enough to affix to a utility pole or other permanent object by the side of the road? What if I made several of these sound sensors and placed them at multiple locations along Boston Post Road, to test whether near-accidents are truly more frequent in front of my house than they are down the road from me, as I suspect?
My hypothesis is that this sound sensor could be programmed to distinguish a car horn from other loud noises and that the resulting data would tell a story about the potential danger of a traffic pattern before tragedy strikes.
The hardware components prove to be rather simple, inexpensive and adaptable, but I didn't know that at the beginning. I didn't even know where to start, so I consulted several people with varying levels of expertise. They included Rick Lehrbaum, a longtime technology journalist and the founder of a website called DeviceGuru; Jason Hillman, a nephew with an engineering degree; SparkFun Electronics customer support; and Professor Dan Pacheco of Syracuse University, the instructor for this course. After cross-checking their advice and reading about (somewhat) similar do-it-yourself projects, I purchased the following equipment from SparkFun ⬇️:
The Arduino Uno is the brains of the operation. It's a flexible microcontroller board that can be expanded with various input devices (temperature, moisture and sound sensors, for example) and output devices (LED lights, speakers and storage cards, for instance). Code, in the form of "sketches," is written using open-source software running on a standard computer and then uploaded to the Arduino Uno over a USB cable. The sketches give the Arduino Uno and the add-on devices their instructions. The Uno is powered by the USB cable from a computer or by a 9-volt battery.
A breadboard is used to create prototypes, or temporary circuits, without having to solder. The existence of this product was welcome news to me.
The SparkFun Sound Detector is a simple microphone with three outputs. "With headers" means it comes with pins attached to add to the breadboard, again to avoid soldering. Thank goodness.
The Qwiic OpenLog is a data-storage device that uses microSD cards. The Qwiic cable connects the OpenLog device to the Arduino Uno. The 9V battery holder is meant to provide a portable power supply to my car-horn sensor. The jumper wires are used to create circuits between the Arduino Uno and the add-on "shields" for electric current and data transfer. And the resistors add resistance to the electrical current, to slow it down in small increments.
I decided to wait before buying a smaller breadboard to miniaturize the device and a case to protect it from the elements. First I had to see if I could make a prototype do something. Anything.
My first challenge was that I knew nothing about building circuits. Zero. I must have been absent the day they taught that in elementary science class. After reviewing several dozen schematics to try to understand the basics of delivering power to the breadboard, and after hours of missteps, frantic text messages and curse words, I finally managed to run power to the breadboard using a 9-volt battery. This felt miraculous. The LED light on the sound detector is responding to my voice here. ⬇️
Then, to simplify things, I tried to run power to the breadboard using the Arduino as a daisy-chained intermediary, and that worked too. The Arduino is powered by my laptop via USB here. ⬇️
Next I needed to connect the Qwiic OpenLog microSD device to the system (it's the small device in the bottom-right corner with the LED light activated ⬇️). I was able to get power to it, but because the online instructions didn’t match the printing on the device, I had to guess about which wires to connect for the data input and output. The instructions had the TX connected to the RX, and the RX connected to the TX, indicating to me that those were the input and output wires for the data collection. I moved on, comfortable that I’d have a chance later to figure out which was which. A mistake like that wouldn't be fatal in the same way that mixing up the positive and negative power wires might be.
The next step was to get acquainted with the concept of "sketches," which are the mini-programs that tell the hardware what to do. They're open source and created inside the Arduino Integrated Development Environment (IDE). Eventually I'll need the equipment to perform a series of operations — listen for sound, identify a car horn and record the honk to the storage device. But first, baby steps.
To my frustration, even the simplest built-in sketches (like the "Blink" program that lights up an LED for defined increments of time ⬇️) wouldn't load onto the Arduino Uno. The code was compiled correctly, as was confirmed by the Arduino IDE's code-checker, but for some reason it couldn't be sent to the board. The error message wasn't helpful. I reinstalled the Arduino IDE software, thinking that maybe the directory paths got messed up when I moved folders around, but still nothing.
Poking around an Arduino forum, I learned that a preference setting called "Show verbose output during: upload" wasn't checked by default in this software but needed to be checked to prevent such an error. So I checked it. That cleared up some of the problem — I could now see the port that the board was connected to, but the Arduino still wouldn’t accept my sketches.
To troubleshoot further, I took out my wife's laptop and duplicated the setup I had with my laptop. Success! The board was visible on the serial port, and the code for the "Blink" sketch uploaded successfully to the board, causing the LED indicator light to blink for one second, turn off for one second, and then repeat.
Now that I was able to upload sketches successfully, it was time to see what I could make the sound detector do. On the advice of Professor Pacheco, I read a healthy chunk of a book called "Arduino Workshop: A Hands-On Introduction." This crash course gave me the coding basics and helped me understand the syntax of sketches. With this foundation, I could analyze pieces of code on public forums with the hope of finding the right combination of instructions to make my project work.
I then went back to basics by consulting the SparkFun Sound Detector Hookup Guide, which instructed me reconfigure my wiring:
(Sound Detector → Arduino)
GND → Supply Ground
VCC → Power supply voltage between 3.5 and 5.5 Volts
Gate → Pin 2
Envelope → A0
Then I loaded the sample sketch on that page, which is meant to demonstrate two sound detector modes: The gate output, a binary indicator, registers "high" when sound is present and "low" when it detects no sound, with the "high" condition triggering an LED to light up; and the envelope output, which measures the amplitude of a sound and then sends the numerical level to a serial monitor that is part of the Arduino IDE software.
Ultimately I'll want the envelope to deliver information about the intensity of sound to my microSD card rather than light up an LED. But for now the on-board serial monitor software is sufficient to collect and present the output, because my laptop is connected to and providing power to the board.
So that code would hopefully take care of the input side of things. Now I needed to replace the output instructions in my sketch so that, rather than merely light up an LED, the data about the intensity of sudden sounds would be sent to the serial monitor.
I found some code that seemed suited for that operation on a site called TheoryCircuit, on a project page for a device designed to "amplify the sounds of door knocks, claps, voice or any other sounds loud enough to [be] picked up" by the SparkFun Sound Detector. After pasting the output portion of that sketch into my sketch and then making some fixes to the code so that it wouldn't conflict with my existing code, I was able to get the serial monitor to report instances of loud sounds. When I clapped near the microphone, the serial monitor would read out, "Knock Knock." ⬇️
Next I found a project on GitHub in which a developer created a decibel-level meter with a numerical output to an LCD screen. I modified her sketch to send a time-stamped notification to the serial monitor whenever the microphone picked up a noise above 80 decibels. That's the low end of the intensity range for car horns; they can go as high as 110 dB at close proximity. The modified sketch seemed to work. ⬇️
I found other promising sketches, too, like one entitled "Measure Sound/Noise Level in dB with Microphone and Arduino." But this one and others like it required additional hardware, in this case a "low voltage audio power amplifier." It's possible that I do need such a device to make up for the low power of what one commenter called a "cheap little microphone." That chipset is sold by Texas Instruments for just 80 cents. But I didn't have time to complicate the project, so I moved on.
In fact, at this point, with time running out, I made the executive decision to simplify the project further by setting aside the OpenLog microSD component, relying instead on the serial monitor to present the output on my laptop.
Now I was almost ready to take my prototype outside to the street. First, I conducted a few tests indoors by clapping and screaming close to the microphone. Each sound burst was reported successfully in the serial monitor.
So it was time to go outside. ⬇️
As soon as I set myself up on the sidewalk and started the initial test, I knew something was wrong. The serial monitor was going off constantly. I turned it up to 90 dB, in an attempt to decrease the microphone's sensitivity, and it still kept going off. Then I tried 100 dB and even 150 dB. Same problem. ⬇️
The most suspicious thing about the number pattern, to me, was that the output readings weren't fluctuating, whereas the noise on Boston Post Road fluctuates widely. ⬇️
Even back inside the house, the serial monitor was scrolling like a gas pump.
As I was rebooting, I noticed that the ground wire into the breadboard had come loose, which might have explained the malfunctioning code. Upon reboot, the mic was much less sensitive, logging only my claps but not any ambient sound.
I went back outside with settings at 80 dB, this time on my porch steps, about 40 feet from the road, rather than on the sidewalk ⬇️. For one thing, I wanted to see just how sensitive the microphone was. For another, I had noticed during my earlier test that the local police were taking an interest in what I was doing, and at this stage I didn't want to hassle.
Now, ordinary ambient road noise wasn't registering in the serial monitor. That was a good sign. I thought it made sense at that point to stick around to see what did register, and to await my first honking horn.
I clapped my hands to give myself a "start" timestamp of 16:49:32.997 p.m., and then I waited.
From there I manually recorded any loud noise I heard, giving a 1 to any sound that was picked up by the serial monitor, and a 0 to any loud sound that I heard but wasn't picked up by the serial monitor.
For the next two hours or so, between around 5 p.m. and 7 p.m., here's what I recorded manually:
Multiple cars passing: 0
City bus: 0
City bus: 0
Heavy truck: 0
Double-long city bus: 0
Big diesel school bus: 0
Tricked-out Honda Civic with no muffler: 0
Utility truck: 0
Ridiculously loud double city bus: 0
Acorn hitting gutter directly above: 0
Giant Pepsi truck: 0
Double city bus on this side of street: 0
UPS 18-wheeler: 0
Short honk, opposite side of street: 0
Screaming brat on sidewalk: 0
Loud bang as truck passed (triggered LED light but no tally): 0
Cawing bird of prey (I think): 0
Convertible with radio blaring: 0
Car transport carrying multiple vehicles (triggered LED light numerous times but no tally): 0
Loud UPS truck: 0
Frustrated, I texted my wife, who was heading home from a birthday party with my kids. I asked her to honk on my signal as she pulled up the driveway. And that's what she did ⬇️.
First honk: 0
Second honk: 0
Third honk: 0
Then she said, "Want me to honk again?"
I replied, "No, that's OK."
To my shock, my voice, at a moderately loud tone, set off the terminal monitor. From this I theorize that proximity matters a lot, and that it's quite possible that an amplifier may, indeed, be needed to detect honks from dozens of feet away.
Working from the premise that proximity was important, I moved to my backyard for a more controlled test of whether the terminal monitor would report an instance of a honking horn from close range ⬇️.
At this point, I figured that I would start again at 80 dB and then move up 10 dB each time to see where the sensitivity of the microphone kicked in. As it turned out, the 80 dB threshold worked: Two honks generated three hits. Then 90 dB, 100 dB and 110 dB also generated two or three hits each for two honks of about a second in duration.
So I decided to go up to 200 dB and then work my way down, to see if the microphone was merely picking up any loud sound or if it would filter out sounds that were too loud to be car horns. No hits at 200 dB, none at 190 dB or 180 dB or 170 dB or 160 dB. But then at 150 dB I got one hit for two honks. And then I got two hits for two honks at 140 dB ⬇️.
Unconvinced by the findings of that test, a couple of days later I started again with another controlled test in the backyard. I figured I would start again at 80 dB and then go up 10 dB each time to see where the sensitivity kicked in. It turned out, 80 dB worked. It recorded three hits for two honks ⬇️.
Then 90 dB, 100 dB and 110 dB also generated two or three hits each for two honks each of about one second in duration.
So then I decided to go to 200 dB and work my way down. I recorded nothing at 200 dB, nothing at 190 or 180 or 170 or 160. But then at 150 dB I got one hit for two honks ⬇️.
And then I recorded two hits for two honks at 140 dB and lower ⬇️.
This series of field tests seemed to suggest that my improvised honk detector was at least able to listen for sounds, count each sound burst within a range of intensities and reject sound bursts outside of that range.
Was this the right range? Was the code really measuring decibels with any precision? I can't be sure without further testing. But the system's ability to isolate and memorialize sound bursts within a set range felt like a genuine success, and perhaps the beginning of something useful.
The concept of an electronic sensor that can listen for a certain kind of sound event and collect data about that event is a commercial reality — witness ShotSpotter Inc., the vendor whose gunshot detector listens for the acoustic signature of gunfire. It's used by law enforcement across the country and was the basis of an investigative project by The Washington Post.
The commercial success of ShotSpotter, together with my small success in cobbling together a device that would listen for car horns, tells me that my approach may be viable.
But I suspect that I would need to calibrate the device to be much more precise in identifying the particular signature of a car horn while also accounting for differences among horn types.
This would mean adding capabilities to the device, such as an amplifier and a separate device to isolate frequency. Then I would want to fine-tune the code and the positioning of resistors to regulate the current. Through testing, testing and more testing, I'd seek to find the optimal combination of settings to minimize missed car horns as well as false positives. To be a viable product, it should either always work or at least have a very low, and predictable, failure rate.
Finally, to tell the story about the potential danger of the traffic pattern in front of my house, I'd want to miniaturize the device, attach a battery and microSD reader, and weatherproof it. This way it could operate independently for many hours at a time. Then I'd want to duplicate the system at least two more times, I think, so that I could run three of these devices concurrently at different sections of Boston Post Road in Pelham. One possible test would have the three devices listening for at least 12 hours, from around 6 a.m. to 6 p.m., to account for the morning and evening rushes.
Once the device is proved reliable, it could be applied to any number of traffic situations in all kinds of settings, for use by journalists to report on the potential hazards or by local governments to take steps to prevent accidents. ▪️