Introduction: Chicago Clearance Rate Sculpture (Unfinished)

This is a computer engineering and sculpturing project by: Cedric Sandoval and Ewan McPhilliamy

The theme of this sculpture was Poison.

We are showing an arrest for the percentage of daily arrests/crimes committed. This shows poison as we depict the Chicago’s clearance rate. When clearance rate drops, support in police drop and crimes committed increase, poisoning our communities and making them unsafe. Having a high clearance rate means crimes are solved most of the time and the justice system is working as it should. We depict Chicago's low clearance rate and the poison that is to Chicago.

This is shown as a sculpture where there are criminal figurines on a belt that spins into a cop car and then the cop car goes away. If the clearance rate is high then the figures will all go through the car and be hidden behind a wall and if the clearance rate is low then the figures will not go through the car, showing that the criminals got away and the case wasn't solved.

Supplies

Materials used:

  • Argon Micro controller
  • 2 DC Motors
  • Servo motor
  • 5 led strip
  • 3D printer + PLA filament
  • Cardboard

Step 1: Micro Controller


The way the sculpture moves automatically is through data taken from the Chicago Data portal. I sorted through the data taken from a week ago taking the data from the last 24 hours at that point and found the ratio of arrests to non-arrest in the last 24 hours then if it reaches a certain threshold the motors move. The threshold number was chosen through the average clearance rate of lesser crimes (which are the main cases on the database).

When the code gets activated it moves the motors to turn the belt one time and then the servo with the car attached turns as well. Once everything moves into place the light will blink.

There are 3 different modes. One mode is when the percentage is less than 10 in which the code will not activate. The second mode activates if it is over 10 percent, but under 15 percent where the code will run normally. In the last mode if it is over 15 the belt will spin further and the lights on the cop car will blink faster to indicate more cases being solved.

After 24 hours the code will reset and run again.


The full code for the project:

#include <neopixel.h>


#define PIXEL_PIN D4
#define PIXEL_COUNT 5
#define PIXEL_TYPE WS2812B
Adafruit_NeoPixel car(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
Adafruit_NeoPixel lights(5,D5,WS2812B);


float tr = 0;
float count = 0;
float percent = 0;


int temp = 0; // a temporary variable for motor testing
int cycle = 0;
int timer = Time.now();
int start = Time.now();


bool move = false;


Servo myServo;
int motor = 3;


void setup() {
    car.begin();

    pinMode(motor, OUTPUT);
    myServo.attach(2);
    myServo.write(10);

    Serial.begin(9600);
    reseting();
    time_t startTime = Time.now() - 777600;
    time_t endTime = startTime + 86400;

    Time.zone(-6);  

    String strEndTime = Time.format(endTime, TIME_FORMAT_ISO8601_FULL);

    strEndTime = strEndTime.substring(0, strEndTime.length()-6);

    String strStartTime = Time.format(startTime, TIME_FORMAT_ISO8601_FULL);
    strStartTime = strStartTime.substring(0, strStartTime.length()-6);

    String data = "{\"minDate\":\"" + strStartTime + "\"";
    data += ", \"maxDate\":\"" + strEndTime + "\"}";


    move = true;
    delay(1000);

    Particle.publish("clearance", data);
    Particle.subscribe("hook-response/clearance", myHandler, MY_DEVICES);
}


void loop() {
    car.setBrightness(255);
    lights.setBrightness(150);
    if(Time.now() == start+86400)
    {
        reseting();
        start = Time.now();
        time_t startTime = Time.now() - 777600;
        time_t endTime = startTime + 86400;

        Time.zone(-6);  

        String strEndTime = Time.format(endTime, TIME_FORMAT_ISO8601_FULL);

        strEndTime = strEndTime.substring(0, strEndTime.length()-6);

        String strStartTime = Time.format(startTime, TIME_FORMAT_ISO8601_FULL);
        strStartTime = strStartTime.substring(0, strStartTime.length()-6);

        String data = "{\"minDate\":\"" + strStartTime + "\"";
        data += ", \"maxDate\":\"" + strEndTime + "\"}";

        move = true;
        delay(1000);

        Particle.publish("clearance", data);
        Particle.subscribe("hook-response/clearance", myHandler, MY_DEVICES);
    }
    percent = 0.14;
    if(timer<Time.now()-2)
    {
        if(percent<=0)
        {
            Serial.println("nothing");
        }
        else if(percent<0.10)
        {
            Serial.println("Low clearance");
        }
        else if(percent<=0.15)
        {
            if(temp>3)//a temporary if statement for motor testing 
            {
                move=false;
                temp=0;
            }
            if(move==true)
            {
            digitalWrite(motor, HIGH);
            delay(2000);
            digitalWrite(motor, LOW);
            delay(1000);
            for(int pos = 10; pos <= 170; pos++)
                {                               
                    myServo.write(pos);              
                    delay(15);                       
                }
            move=false;
            }
        blink();
        cycles(200);
        temp++;//temporary
        Serial.println("here");
        }
        else if(percent<1)
        {
            if(move==true)
            {
            digitalWrite(motor, HIGH);
            delay(5000);
            digitalWrite(motor, LOW);
            delay(1000);
            for(int pos = 10; pos <= 170; pos++)
                {                               
                    myServo.write(pos);              
                    delay(15);                       
                }
            move=false;
            }
            cycles(100);
        blink();
        }
    }
}
void myHandler(const char *event, const char *data) {
  String dataStr = String(data);
  Serial.println(dataStr);
  for(int i = 0;i<dataStr.length();i++)
  {
    if(dataStr[i]=='}')
    {
        count++;
    }   
    if(dataStr[i]=='u')
    {
        tr++;
    }
  }
  percent = (tr/count);
  Serial.println(percent);
  start = Time.now();
  timer = Time.now();
}
void blink()
{
    if(cycle==0)
    {
        car.setPixelColor(0, car.Color(255, 0, 0));     
        car.setPixelColor(1, car.Color(255, 0, 0));     
        car.setPixelColor(2, car.Color(0, 0, 255));     
        car.setPixelColor(3, car.Color(0, 0, 255));     
        car.setPixelColor(4, car.Color(0, 0, 255));
        car.show();
        cycle++;
    }
    else if(cycle==1)
    {
        car.setPixelColor(0, car.Color(0, 0, 255));     
        car.setPixelColor(1, car.Color(0, 0, 255));     
        car.setPixelColor(2, car.Color(255, 0, 0));     
        car.setPixelColor(3, car.Color(255, 0, 0));     
        car.setPixelColor(4, car.Color(255, 0, 0));
        car.show();
        cycle++;
    }
    else if(cycle==2)
    {
        car.setPixelColor(0, car.Color(255, 0, 0));     
        car.setPixelColor(1, car.Color(255, 0, 0));     
        car.setPixelColor(2, car.Color(255, 0, 0));     
        car.setPixelColor(3, car.Color(0, 0, 255));     
        car.setPixelColor(4, car.Color(0, 0, 255));
        car.show();
        cycle++;
    }
    else
    {
        car.setPixelColor(0, car.Color(0, 0, 255));     
        car.setPixelColor(1, car.Color(0, 0, 255));     
        car.setPixelColor(2, car.Color(0, 0, 255));     
        car.setPixelColor(3, car.Color(255, 0, 0));     
        car.setPixelColor(4, car.Color(255, 0, 0));
        car.show();
        cycle = 0;
    }
}
void cycles(int speed)
{
    for(int l = 0;l<5;l++){
        int count = 0;
        for(int i = l;count<5;i++){
            if(i<5)
            {
                lights.setPixelColor(i, lights.Color(255/(count*count+1),255/(count*count+1),255/(count*count+1)));
            }
            if(i>=5)
            {
                lights.setPixelColor(i-5, lights.Color(255/(count*count+1),255/(count*count+1),255/(count*count+1)));
            }
            count++;
        }
        lights.show();
        delay(speed);
    }
}


void reseting()
{
    car.setPixelColor(0, car.Color(0,0,0));
    car.setPixelColor(1, car.Color(0,0,0));
    car.setPixelColor(2, car.Color(0,0,0));
    car.setPixelColor(3, car.Color(0,0,0));
    car.setPixelColor(4, car.Color(0,0,0));
    car.show();
    for(int pos = 170; pos >= 10; pos--) 
    {                                    
        myServo.write(pos);              
        delay(15);                       
    }
    percent=0;
    delay(3000);
}

Step 2: Physical Sculpture(unfinished)

3D parts were printed so that the objects created can attach to the motors and servos

Step 3: Video