Scott Phan
Published

Wildfire Data Visualization

The sculpture is a moving physical sculpture that represents and displays wildfire data.

IntermediateShowcase (no instructions)79
Wildfire Data Visualization

Things used in this project

Hardware components

Adafruit NeoPixel Digital RGB LED Strip 144 LED, 1m White
Adafruit NeoPixel Digital RGB LED Strip 144 LED, 1m White
×1
Photon 2
Particle Photon 2
×1
ULN2003 28BYJ-48 4-Phase Stepper Motor with 5V Drive Board
×1
Timing Belt and Pulley Wheel
×1
5v DC Power Supply and Barrel Jack Adapter
×1
Jumper wires (generic)
Jumper wires (generic)
×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
Breadboard, 170 Pin
Breadboard, 170 Pin
Protoboard
Hot glue gun (generic)
Hot glue gun (generic)
Cardboard

Story

Read more

Schematics

Circuit Diagram

Code

Final Sculpture Firmware

C/C++
This is the firmware for the fully completed electronics.
// 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>

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

// Include Particle Device OS APIs
#include "Particle.h"

// Let Device OS manage the connection to the Particle Cloud
SYSTEM_MODE(AUTOMATIC);

SerialLogHandler logHandler(LOG_LEVEL_INFO);

#define IN_1 10
#define IN_2 7
#define IN_3 6
#define IN_4 5

const int stepsPerRevolution = 1019;

int position;
int next;

int startDay;

Stepper myStepper(stepsPerRevolution, IN_1, IN_3 , IN_2, IN_4);

#define LED_COUNT 18

Adafruit_NeoPixel strip(LED_COUNT, SPI, WS2812B);
int row;

int lights[6][3] = {{0, 6, 12},
                    {1, 7, 13},
                    {2, 8, 14},
                    {3, 9, 15},
                    {4, 10, 16},
                    {5, 11, 17}};

String jsonText = "";
JsonDocument doc;
int numFires;

// setup() runs once, when the device is first turned on
void setup() {
    waitFor(Particle.connected, 5000);
    
    //ambee is the name of the webhook that pulls data from ambee API
    Particle.subscribe("hook-response/ambee", handleEventResponse, MY_DEVICES);
    
    startDay = Time.day();
    
    myStepper.setSpeed(17);
    position = 0;
    next = 0;
    
    row = 0;
    strip.begin();
    
    Particle.publish("ambee");
}

void handleEventResponse(const char *event, const char *data)
{
    jsonText = String(data);
    
    retrieveValues();
}

void retrieveValues()
{
    DeserializationError error = deserializeJson(doc, jsonText.c_str());
    if (error)
    {
        return;
    }
    
    JsonArray fires = doc["data"];
    numFires = fires.size();
}

void loop() {
    //next two for loops for setting which rows turn on and off
    row = numFires;
    for(int i = 0; i < row; i++){
        for(int j = 0; j < sizeof(lights[i]); j++){
            strip.setPixelColor(lights[i][j], 255, 69, 0);
        }
    }
              
    for(int i = row; i < 6; i++){
        for(int j = 0; j < sizeof(lights[i]); j++){
            strip.setPixelColor(lights[i][j], 0, 0, 0);
        }
    }
    
    //correction for problem in lighting the first neopixle
    if(row >= 1 && row <= 5)
        strip.setPixelColor(0, 255, 69, 0);
        
    //next two for loops for burning fire effct
    for(int i = 5; i < 75; i++){
        strip.setBrightness(i);
        strip.show();
        delay(10);
    }
    
    for(int i = 75; i > 5; i--){
        strip.setBrightness(i);
        strip.show();
        delay(10);
    }
    
    //spins the stepper based on the length of the array 
    next = numFires;
    if(next != position){
        myStepper.step((next - position) * stepsPerRevolution);
        position = next;
    }
    
    //calls API every new day to get new fire data
    if(startDay != Time.day()){
        Particle.publish("ambee");
        startDay = Time.day();
    }
}

Neopixel Firmware Test

C/C++
This is the firmware that is used to test if the neopixels work.
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

// Include Particle Device OS APIs
#include "Particle.h"

#define LED_COUNT 18

Adafruit_NeoPixel strip(LED_COUNT, SPI, WS2812B);

SYSTEM_MODE(AUTOMATIC);

SerialLogHandler logHandler(LOG_LEVEL_INFO);

void setup() {
    
  for(int i = 0; i < LED_COUNT; i++){
        strip.setPixelColor(i, 255, 69, 0);
    }
    strip.begin();
}

void loop() {
    for(int i = 5; i < 75; i++){
        strip.setBrightness(i);
        strip.show();
        delay(10);
    }
    
    for(int i = 75; i > 5; i--){
        strip.setBrightness(i);
        strip.show();
        delay(10);
    }
}

Stepper Motor Firmware Test

C/C++
This is the firmware that is used to test if the stepper motor works.
// This #include statement was automatically added by the Particle IDE.
#include <Stepper.h>

#include "Particle.h"

SYSTEM_MODE(AUTOMATIC);

SerialLogHandler logHandler(LOG_LEVEL_INFO);

#define IN_1 10
#define IN_2 7
#define IN_3 6
#define IN_4 5

const int stepsPerRevolution = 2048;

int position;
int next;

Stepper myStepper(stepsPerRevolution, IN_1, IN_3 , IN_2, IN_4);

void setup() {
    myStepper.setSpeed(17);
}

void loop() {
    myStepper.step(stepsPerRevolution);
    delay(200);
    myStepper.step(-stepsPerRevolution);
    delay(200);
}

Credits

Scott Phan
3 projects • 0 followers

Comments