Introduction: CompSculpt Drug Overdose Visualization



This project was a collaborative effort between the sculpture class and the physical computing lab at Lane Tech. This project drew data from data.cdc.gov about the amount of drug overdose cases in the United States. The code would get data for drug overdose cases in the U.S each month starting from January 2015, then add all of it together once a year has passed. It will then compare it to the amount of drug cases there were last year and attempted to spin a motor up and down if the amount of drug overdose cases were less or more. The motor is attached to a pulley system on the back of the sculpture, which pulled a figure up and down a hill.


The end result was not satisfactory. It didn't end up working at the end. I think it was because I did a poor job gluing the cardboard onto the motor, and the motor ended up spinning without the pulley. Additionally, if I had spent more time on mounting the lights, the project would be more brighter, as there were meant to be strips between the hills.

Supplies

Cardboard

Stepper Motor and ULN2003 Driver

Breadboard

Wires

Fishwire

LED Strip

Argon

Step 1: Create Webhook to Get Data

Step 2: Make an Algorithm to Respond to the Data

This was my code for the app I made in Particle's Web IDE to respond to the code. Include the Stepper and neopixel library for the app.

// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>


// This #include statement was automatically added by the Particle IDE.
#include <Stepper.h>


const int stepsPerRevolution = 256;


#define PIXEL_PIN D6
#define PIXEL_COUNT 4
#define PIXEL_TYPE WS2812B


#define IN1 2
#define IN2 3
#define IN3 4
#define IN4 5


Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);


Stepper myStepper(stepsPerRevolution, IN1, IN3, IN2, IN4);
Stepper myStepper2(stepsPerRevolution, IN1, IN3, IN2, IN4);


unsigned long prevTime = 0;
int od = 0;
int altVar = 0;
int interval = 1000; // the time it takes until it gets data from the next month starting January 2015 (in milliseconds) Typically the delay interval would be 1 day if the project were to run for a full day


//used for seeing how many times the stepper spun up/down
int down = 0; 
int up = 0;
bool end = false;


int odInYear = 0;
int monthCount = 0;


void setup() {

    strip.begin();

    strip.show();

    myStepper.setSpeed(17);

    Serial.begin(9600);
    Serial.println("Start");


    Particle.subscribe("hook-response/odTest", singleValueHandler);
}


void loop() {
    unsigned long currTime = millis();

    strip.setBrightness(255);
    strip.setPixelColor(0, strip.Color(255, 0, 0));
    strip.setPixelColor(1, strip.Color(255, 0, 0));
    strip.setPixelColor(2, strip.Color(255, 0, 0));


    strip.show();


    if(currTime - prevTime >= interval && end == false) //timed action that loops through every month from January 2015
    {
        prevTime = currTime;

        int mins = currTime/interval;
        Serial.println("Minutes elapsed: " + (String)mins);
        String data = "{\"month\":\"" + timeToMonth(currTime) + "\"";
        data += ", \"year\":\"" + (String)timeToYear(currTime) + "\"}";

        Particle.publish("odTest", data);

    }

    delay(1000);
}


void singleValueHandler(const char *event, const char *data) { //data cuts off after september 2023 as of february 2024

    Serial.println("Handler begins ------ ");

    od = atoi(data);

    Serial.println((String)od);



    odInYear += od;
    monthCount++;

    if(monthCount >= 12)
    {
        monthCount = 0;

        if(odInYear >= altVar)
        {
            altVar = odInYear;

            strip.setBrightness(255);

            strip.show();

            myStepper.step(stepsPerRevolution);
            myStepper2.step(stepsPerRevolution);
            delay(5000);

            Serial.println("Spin clockwise");

            Serial.println("Times spun UP: " + (String)up);
            Serial.println("Times spun DOWNL " + (String)down);
        }
        else if(altVar > odInYear)
        {
            altVar = odInYear;

            strip.setBrightness(122);

            strip.show();

            myStepper.step(stepsPerRevolution);
            myStepper2.step(stepsPerRevolution);
            delay(5000);

            Serial.println("Spin counterclockwise");

            Serial.println("Times spun UP: " + (String)up);
            Serial.println("Times spun DOWN: " + (String)down);
        }
        odInYear = 0;
    }

    Serial.println("Handler ends ------ ");
}


String timeToMonth(int aTime) //returns month of the year based on time since program ran
{
    int monthInt = aTime/interval;
    String month = "";
    while(monthInt > 12)
    {
        monthInt -= 12;
    }
    if(monthInt == 1) {month = "January"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 2) {month = "February"; /*Serial.println("Month: " + month + " " + monthInt); */return month;}
    if(monthInt == 3) {month = "March"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 4) {month = "April"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 5) {month = "May"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 6) {month = "June"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 7) {month = "July"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 8) {month = "August"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 9) {month = "September"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 10) {month = "October"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 11) {month = "November"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}
    if(monthInt == 12) {month = "December"; /*Serial.println("Month: " + month + " " + monthInt);*/ return month;}

    //check if anything went wrong
    else if(monthInt < 1){return "monthInt < 12, " + (String)monthInt;}
    else {return "monthInt > 12, " + (String)monthInt;}
}
int timeToYear(int aTime) //returns year depending on time elapsed since flashed
{
    int monthInt = aTime/interval;
    int year = 2015;
    int yearSince2015 = monthInt/12;
    if(yearSince2015 > 0 && !(monthInt%12 == 0))
    {
        year += yearSince2015;
        //Serial.println("Year: " + (String)year);
    }
    if(monthInt%12 == 0)
    {
        year += (monthInt/12) - 1;
    }
    return year;
}

Step 3: Construct the Physical Components

This was the step that I struggled in. Originally, my first draft of the project was to use a rubber band and wrap it between two steppers to create linear motion. However, I found that it snapped too frequently, and tried to implement a pulley system on the back of our structure. At first, it moved smoothly when something lighter like a piece of tape was attached, but when I glued the figure that we were going to be pulling, the motor was not able to turn.