Enginursday: Internet of Terror

Terrify your coworkers! Annoy your friends! How many people in upper management can I frighten without losing my job?

Favorited Favorite 1

In this Enginursday, I've repurposed a project I was using to light fireworks during the Fourth of July. Now I can't really tell you how I did that, but I had an airhorn lying around and figured I could hook that up and have a little fun. The concept is pretty simple: have an ESP32 host up a webpage, click a button on your phone on said webpage, and set off the airhorn! I'm pretty lazy and wanted to do things solderless, so I grabbed a Qwiic Relay and was off to the races. All I had to do was connect my airhorn-battery circuit up to the common and normally open connections on the relay, connect the relay to my ESP32 and add a LiPo to power my ESP32. The whole setup is one of the simplest things I've ever made, but oh boy is it super effective. Check the whole thing out below.

Beeper Setup

Beeper Setup

We just need to add some code for our web server to serve up our button. To do this, we configure our ESP32 as a soft access point, and have it serve up a button for our horn. We then attach our relay functions to our on and off URLs. Lines 69-78 are where our web interface is actually doing actions on the ESP32, so check in here if you want the ESP32 to do some other things on your button presses. Check out lines 17 and 18 to change your WiFi settings to something neat and super secret.

/******************************************************************************
  Horn.ino
  Example for controlling a relay using a webpage served by an ESP32
  by: Rui Santos
  Adapted for horn by: Andy England, SparkFun Electronics
******************************************************************************/

#include <WiFi.h>
#include <Wire.h>
#include "SparkFun_Qwiic_Relay.h"

#define RELAY_ADDR 0x18 // Alternate address 0x19

Qwiic_Relay relay(RELAY_ADDR);

// Replace with your network credentials
const char* ssid     = "HORN";
const char* password = "beepbeep1";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String hornState = "off";

void setup() {
  Wire.begin();
  Serial.begin(115200);
  relay.begin();

  relay.singleRelayVersion();

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.softAP(ssid, password);
  server.begin();
}

void loop() {
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the horn on and off
            if (header.indexOf("GET /horn/on") >= 0) {
              Serial.println("Horn on");
              hornState = "on";
              relay.turnRelayOn();
            } else if (header.indexOf("GET /horn/off") >= 0) {
              Serial.println("Horn off");
              hornState = "off";
              relay.turnRelayOff();
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>The Big Old Beeper</h1>");

            // Display current state, and ON/OFF buttons for our horn
            client.println("<p>Horn - State " + hornState + "</p>");
            // If the hornState is off, it displays the ON button
            if (hornState == "off") {
              client.println("<p><a href=\"/horn/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/horn/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Upload this to your ESP32 and you should see a WiFi hotspot with your chosen SSID pop up when looking for networks on a phone or other device. Go ahead and connect to it. If it's not popping up, open up a Serial connection at 115200 baud to try and see why your ESP32 is unhappy.

WiFi Hotspot

WiFi Hotspot

At this point your phone might tell you that there isn't an internet connection. This is fine, as we only need the ESP32 to serve up its own webpage. Once connected, open up a web browser and navigate to 192.168.4.1 (this is the default IP address, as occasionally the ESP32 has trouble hosting a DNS server). You should see a webpage like the one below.

Webpage

Horn Webpage

Now, hide the thing somewhere and scare some folks!


Comments 14 comments

  • FSJ Guy / about 5 years ago / 2

    Just when I thought IoT was only good for useless things like your fridge talking to the grocery store to order more milk when you run out!!

  • Ahhhh, it's been a while with the car horn prank. XD

    It's cool to see it now in IoT form. =P

  • Member #134773 / about 5 years ago / 2

    IMHO, it wouuld be a wise idea to have it "automatically" turn the horn off after some maximum number of seconds. You really don't want to come home to find that the neighbors have called 911 because of the racket...

    • Totally correct, but I really enjoyed being able to toot the thing for different periods of time. All you would need to do would be to add a delay and a call to relay.turnRelayOff(). Also, since the ESP32 is acting as a soft access point, you have to be kind of close to the thing to maintain decent WiFi signal strength.

      • Member #134773 / about 5 years ago / 3

        I learned long ago about the truth in Murphy's Law... so it's always good to have a "failsafe".

        On a different tangent, methinks you could use this for something "interesting" the evening of Oct. 31... ;-)

  • Jeff Haas / about 5 years ago / 2

    What, no video?!

    • You're just gonna have to take my word for it here, we were setting up to film and I went to test the horn and once the camera came on, the horn wouldn't turn off! I didn't want to actually deafen my coworkers so we decided against filming.

      The day prior I did come back to my desk, thinking I was the only one connected to the horn. @brambleton asked if I had just given the thing a toot and I said yea, nobody else can connect to it.

      Then he triggered the thing and I jumped about 3 feet out of my own body.

  • BerenV / about 5 years ago / 1

    Nice! IMO, the best setup of this type of prank is where it triggers off of an action of the person, whether it be them hitting a certain key on their keyboard, touching their screwdriver to something, or simply leaning back in their chair (think image processing...)

    • The old one was actually installed in a bar stool that would honk when you sat down on it! We've contacted our old horn supplier in an attempt to bring back the honky goodness, so keep your eyes peeled!

  • Member #536818 / about 5 years ago / 1

    The car horn prank revenge included an ignition coil connected under the driver's seat. I heard of this in 1966 from a guy whose first car was a model T Ford.

    • Nice post. I learn something more challenging on different blogs everyday. It will always be stimulating to read content from other writers and practice a little something from their store. I’d prefer to use some with the content on my blog whether you don’t mind. Natually I’ll give you a link on your web blog. Thanks for sharing.

Related Posts

Recent Posts

Halloween Hacking

SparkFun Spooktacular

Tags


All Tags