Michael McCaffrey
Published

Car crash adjusting art project

Art project that displays the number of Chicago car crashes in the past week by moving a model car across a road while flashing lights.

BeginnerShowcase (no instructions)20 hours55
Car crash adjusting art project

Things used in this project

Hardware components

Stepper Motor
Digilent Stepper Motor
×1
LED Strip, NeoPixel Digital RGB
LED Strip, NeoPixel Digital RGB
×1
Photon 2
Particle Photon 2
×1

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
Hot glue gun (generic)
Hot glue gun (generic)
Scissor, Electrician
Scissor, Electrician
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
10 Pc. Jumper Wire Kit, 5 cm Long
10 Pc. Jumper Wire Kit, 5 cm Long

Story

Read more

Code

Electronics demonstration

C/C++
converts the data from Chicago portal to a physical representation
No preview (download only).

Electronics demonstration

C/C++
converts the data from Chicago portal to a physical representation
No preview (download only).

Car Crash Art Project Code

C/C++
Pulls the number of car crashes in the past week from the Chicago Data Portal and moves a motor and lights up LEDs (headlights or taillights of a model car) in order to display the fluctuation in car crashes in the past week.
// This #include statement was automatically added by the Particle IDE.
#include <ArduinoJson.h>
#include "Particle.h"
#include <neopixel.h>
#include <Stepper.h>

SYSTEM_MODE(AUTOMATIC);

SerialLogHandler logHandler(LOG_LEVEL_INFO);
String jsonText = "";
JsonDocument doc;
int crashes = 0;
int oldCrashes = 4500;
int stepperRotation;
int button = D7;
int ledStrip = 2;
bool debounce = false;
int carDisplacement = 0;

const int stepsPerRevolution = 2048;

// Change the pins below to match your Argon set up
#define IN1 0
#define IN2 1
#define IN3 3
#define IN4 4 
#if (PLATFORM_ID == 32)
// MOSI pin MO
#define PIXEL_PIN SPI1
// MOSI pin D2
// #define PIXEL_PIN SPI1
#else // #if (PLATFORM_ID == 32)
#define PIXEL_PIN D2
#endif
Adafruit_NeoPixel strip(2, PIXEL_PIN, WS2812B);

#if (PLATFORM_ID == 32)
#define PIXELB_PIN SPI
#else
#define PIXELB_PIN MOSI
#endif
Adafruit_NeoPixel stripB(2, PIXELB_PIN, WS2812B);
Stepper myStepper(stepsPerRevolution, IN1, IN3 , IN2, IN4);

// setup() runs once, when the device is first turned on
void setup() {
    pinMode(button, INPUT_PULLUP);
    Particle.subscribe("hook-response/carCrash", handleEventResponse);  // Ensure this matches the event name in the webhook
    Serial.begin(9600);
    Serial.println("Subscribed to 'hook-response/carCrash'");
    myStepper.setSpeed(17);
    strip.begin();
    stripB.begin();

    time_t startTime = Time.now() - 604800;   // 7 days ago
    time_t endTime = Time.now();       // today

    // setup the time zone
    Time.zone(-5);

    // Format the time in the same format as what the database uses
    String strEndTime = Time.format(endTime, TIME_FORMAT_ISO8601_FULL);
    strEndTime = strEndTime.substring(0, strEndTime.length() - 6);  // Remove extra characters

    // Do the same for min
    String strStartTime = Time.format(startTime, TIME_FORMAT_ISO8601_FULL);
    strStartTime = strStartTime.substring(0, strStartTime.length() - 6);

    // Format the JSON string properly. It should look like:
    // {"minDate":"2023-03-13T14:11:11", "maxDate":"2023-03-14T14:11:11"}
    String data = "{\"minDate\":\"" + strStartTime + "\"";
    data += ", \"maxDate\":\"" + strEndTime + "\"}";

    // Publish data to trigger the webhook
    delay(10000);  // Give time for the webhook to be triggered
    Particle.publish("carCrash", data);
    delay(10000);
    Particle.publish("carCrash", data);
    Serial.println("Crashes in setup: " + String(crashes));
    
    for(int i = 0; i < 2; i++)
    {
        strip.setPixelColor(i, stripB.Color(0, 0, 0));
    }
    strip.show();
    for(int i = 0; i < 2; i++)
    {
        stripB.setPixelColor(i, strip.Color(0, 0, 0));
    }
    stripB.show();
    Particle.function("blink", run);
    myStepper.step(1600);
    myStepper.step(-800);
}

int run(String param)
{
        Serial.println("Run function called");
        time_t startTime = Time.now() - 604800;   // 7 days ago
        time_t endTime = Time.now();       // today
        
        String strEndTime = Time.format(endTime, TIME_FORMAT_ISO8601_FULL);
        strEndTime = strEndTime.substring(0, strEndTime.length() - 6);  // Remove extra characters
    
        // Do the same for min
        String strStartTime = Time.format(startTime, TIME_FORMAT_ISO8601_FULL);
        strStartTime = strStartTime.substring(0, strStartTime.length() - 6);
    
        // Format the JSON string properly. It should look like:
        // {"minDate":"2023-03-13T14:11:11", "maxDate":"2023-03-14T14:11:11"}
        String data = "{\"minDate\":\"" + strStartTime + "\"";
        data += ", \"maxDate\":\"" + strEndTime + "\"}";
        
        Particle.publish("carCrash", data);
        
        delay(10000);
        Serial.println("Previous crash value: " + String(oldCrashes));
        Serial.println("New crash value: " + String(crashes));
        
        if(crashes >= oldCrashes)
        {
            Serial.println("crashes were greater than oldCrashes");
            for(int i = 0; i < 2; i++)
            {
                stripB.setPixelColor(i, stripB.Color(255, 255, 255));
            }
            stripB.show();
            for(int i = 0; i < 2; i++)
            {
                strip.setPixelColor(i, strip.Color(0, 0, 0));
            }
            strip.show();
        }
        else if(crashes <= oldCrashes)
        {
            Serial.println("crashes were fewer than oldCrashes");
            for(int i = 0; i < 2; i++)
            {
                strip.setPixelColor(i, strip.Color(255, 0, 0));
            }
            strip.show();
            for(int i = 0; i < 2; i++)
            {
                stripB.setPixelColor(i, stripB.Color(0, 0, 0));
            }
            stripB.show();
        }
        //RUN THROUGH THIS ON PAPER WITH MADE UP VALUES
        stepperRotation = crashes - oldCrashes;
        if(carDisplacement + (crashes - 4500) > 500)
        {
            Serial.println("car should be all the way to the right");
            myStepper.step(((500 - carDisplacement) * (-2)));
            carDisplacement = 500;
        }
        else if(carDisplacement + (crashes - 4500) < -500)
        {
            Serial.println("car should be all the way to the left");
            myStepper.step(((-500 - carDisplacement) * (-2)));
            carDisplacement = -500;
        }
        else
        {
            Serial.println("car should somewhere in the middle");
            myStepper.step(((crashes - oldCrashes) * (-2)));
            carDisplacement += (crashes - oldCrashes);
            Serial.println("stepper steps: " + String(((crashes - oldCrashes) * (-2))));
            Serial.println("crash difference: " + String((crashes - oldCrashes)));
        }
        //UPDATE LINE
        oldCrashes = crashes;
    delay(500);
    
    return 0;
}

void loop() 
{
    if(Time.hour() == 13 && debounce == false)
    {
        run("run");
        debounce = true;
    }
    else if(Time.hour() != 13 && debounce == true)
    {
        debounce = false;
    }
    delay(200);
}

void handleEventResponse(const char *event, const char *data) {
    // Print debug info to confirm that the event was received
    Serial.println("Event received!");

    // Print out the event and data received
    Serial.print("Event: ");
    Serial.println(event);
    Serial.print("Data: ");
    Serial.println(data);

    // Store the event data
    jsonText = String(data); 

    // Check if data is arriving as expected
    if (jsonText.length() == 0) 
    {
        Serial.println("No data received from webhook.");
    } else {
        Serial.print("Data received from webhook: ");
        Serial.println(jsonText);
    }
    crashes = atoi(data);
    Serial.println("crashes in handleEventResponse: " + String(crashes));
}

Credits

Michael McCaffrey
2 projects • 0 followers
I am a Computer Science major at Clemson University, and I love making projects that complement my hobbies!
Thanks to Mubeen.

Comments