Freya - Networking
Made by Freya Yang
Made by Freya Yang
The goal of networking exercise is for the design and development of How’s the Weather project. We want to design and prototype an interactive IoT device that leverages real-time communication to create a shared emotional connection between friends. By combining tactile interaction with visual feedback, the project aimed to explore how everyday emotional check-ins can be enhanced through tangible, responsive design.
Created: December 15th, 2024
The goal of the How’s the Weather networking project was to design and prototype an interactive IoT device that leverages real-time communication to create a shared emotional connection between friends. By combining tactile interaction with visual feedback, the project aimed to explore how everyday emotional check-ins can be enhanced through tangible, responsive design.
Specifically, we sought to:
This connecting assignment is part of our prototype process. We started by connecting a basic pressure sensor to an LED light to test input-output functionality. After achieving reliable lighting control, we connected two devices via Particle Photon microcontrollers. When one user pressed the sensor on their device, the paired device lit up in real time, successfully achieving synchronized emotional communication.
During development, I ensured each light pattern for the weather states was separated into its own event. This allowed us to publish and test each event individually. However, when the same code was uploaded to the second device and tested, the devices failed to respond to each other. We suspected the issue was tied to the way events were titled and attempted to simplify the titles to numerical names for easier debugging. With assistance from our TA, we were able to successfully network the devices and ensure real-time communication. However, we encountered an additional issue with the sunny and cloudy patterns: they would only flash momentarily at the start of each event. To resolve this, we introduced millis() for timing control and added delays to simulate a longer-lasting light pattern. This approach successfully created the desired behavior for these two states, while the rain and thunderstorm effects required no further adjustment due to their existing functionality.
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
#include "Particle.h"
#include "neopixel.h"
SYSTEM_MODE(AUTOMATIC);
// Define pin and NeoPixel configuration for Photon 2
#if (PLATFORM_ID == 32)
#define NEOPIXEL_PIN SPI // Use MOSI for Photon 2
#else
#define NEOPIXEL_PIN D3 // Use D3 for other Particle devices
#endif
#define NUM_PIXELS 8 // Number of LEDs in the NeoPixel strip
#define PIXEL_TYPE WS2812B // Specify the NeoPixel type
// Pressure sensor pin
#define PRESSURE_PIN A0
// Create a NeoPixel object
Adafruit_NeoPixel strip(NUM_PIXELS, NEOPIXEL_PIN, PIXEL_TYPE);
void setup() {
strip.begin(); // Initialize NeoPixel strip
strip.show(); // Turn off all LEDs initially
Serial.begin(9600); // Debugging
// Subscribe to events from the Particle Cloud
Particle.subscribe("weatherEvent", weatherEventHandler);
}
// Function prototypes for weather effects
void thunderEffect();
void rainEffect();
void cloudyEffect();
void sunnyEffect();
// Function to publish weather events
void publishWeatherEvent(const char* eventName) {
String event = String("weatherEvent/") + eventName;
Particle.publish(event); // Publish the event with the prefix
weatherEventHandler(event.c_str(), ""); // Call event handler immediately
}
// Particle event handler
void weatherEventHandler(const char* event, const char* data) {
String eventString = String(event);
if (eventString == "weatherEvent/sunny") {
sunnyEffect(); // Call sunny effect function
}
else if (eventString == "weatherEvent/cloudy") {
cloudyEffect(); // Call cloudy effect function
}
else if (eventString == "weatherEvent/rainy") {
rainEffect(); // Call rainy effect function
}
else if (eventString == "weatherEvent/thunder") {
thunderEffect(); // Call thunder effect function
}
}
void loop() {
// Read the pressure sensor value
int pressure = analogRead(PRESSURE_PIN);
Serial.println(pressure); // Debugging the sensor value
// Determine weather event based on pressure level
if (pressure > 3600) {
publishWeatherEvent("thunder");
} else if (pressure > 2700) {
publishWeatherEvent("rainy");
} else if (pressure > 1800) {
publishWeatherEvent("cloudy");
} else if (pressure > 900) {
publishWeatherEvent("sunny");
} else {
strip.clear(); // Turn off LEDs when pressure is too low
strip.show();
}
}
// Thunder: Blue and yellow flash
void thunderEffect() {
for (int i = 0; i < NUM_PIXELS; i++) {
strip.clear();
if (i % 2 == 0) {
strip.setPixelColor(i, strip.Color(0, 0, 128)); // Dim blue
} else {
strip.setPixelColor(i, strip.Color(128, 128, 0)); // Dim yellow
}
strip.show();
delay(50);
}
strip.clear();
strip.show();
}
// Rain: Light dim blue light
void rainEffect() {
for (int i = 0; i < NUM_PIXELS; i++) {
strip.clear();
strip.setPixelColor(i, strip.Color(0, 0, 128)); // Dim blue
strip.show();
delay(100);
}
}
// Cloudy: Dim violet/lavender light
void cloudyEffect() {
static int brightness = 0;
static int direction = 5;
brightness += direction;
if (brightness >= 100 || brightness <= 0) {
direction = -direction;
}
uint32_t color = strip.Color(75 + brightness, 50 + brightness, 150 + brightness); // Dim lavender/violet
for (int i = 0; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, color);
}
strip.show();
delay(50);
}
// Sunny: Warm orange light
void sunnyEffect() {
static int brightness = 0;
static int direction = 5;
brightness += direction;
if (brightness >= 255 || brightness <= 50) {
direction = -direction;
}
uint32_t color = strip.Color(255, 140, 0); // Warm orange
for (int i = 0; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, color);
}
strip.show();
delay(50);
}
Click to Expand
#include "Particle.h"
#include "neopixel.h"
SYSTEM_MODE(AUTOMATIC);
// Define pin and NeoPixel configuration for Photon 2
#if (PLATFORM_ID == 32)
#define NEOPIXEL_PIN SPI // Use MOSI for Photon 2
#else
#define NEOPIXEL_PIN D3 // Use D3 for other Particle devices
#endif
#define NUM_PIXELS 8 // Number of LEDs in the NeoPixel strip
#define PIXEL_TYPE WS2812B // Specify the NeoPixel type
// Pressure sensor pin
#define PRESSURE_PIN A0
// This value will store the last time we published an event
long lastPublishedAt = 0;
// this is the time delay before we should publish a new event
int publishAfter = 10000;
// Create a NeoPixel object
Adafruit_NeoPixel strip(NUM_PIXELS, NEOPIXEL_PIN, PIXEL_TYPE);
void setup() {
strip.begin(); // Initialize NeoPixel strip
strip.show(); // Turn off all LEDs initially
Serial.begin(9600); // Debugging
// Subscribe to shared events
Particle.subscribe("weatherEvent/shared", weatherEventHandler);
}
// Function prototypes for weather effects
void thunderEffect();
void rainEffect();
void cloudyEffect();
void sunnyEffect();
// Function to publish weather events
void publishWeatherEvent(const char* eventName) {
String event = String("weatherEvent/shared/") + System.deviceID() + "/" + eventName;
Particle.publish(event); // Publish the shared event
weatherEventHandler(event.c_str(), ""); // Call event handler immediately for local effect
delay(1000);
}
// Particle event handler
void weatherEventHandler(const char* event, const char* data) {
String eventString = String(event);
Serial.println(eventString);
// Ignore events originating from this device
// if (eventString.indexOf(System.deviceID()) != -1) return;
// Parse the event name to determine the weather condition
if (eventString.endsWith("/sunny")) {
sunnyEffect();
} else if (eventString.endsWith("/cloudy")) {
cloudyEffect();
} else if (eventString.endsWith("/rainy")) {
rainEffect();
} else if (eventString.endsWith("/thunder")) {
thunderEffect();
}
}
void loop() {
// Read the pressure sensor value
int pressure = analogRead(PRESSURE_PIN);
// Serial.println(pressure); // Debugging the sensor value
// Determine weather event based on pressure level
if (pressure > 3600) {
publishWeatherEvent("thunder");
} else if (pressure > 2700) {
publishWeatherEvent("rainy");
} else if (pressure > 1800) {
publishWeatherEvent("cloudy");
} else if (pressure > 900) {
publishWeatherEvent("sunny");
} else {
strip.clear(); // Turn off LEDs when pressure is too low
strip.show();
}
}
// Thunder: Blue and yellow flash
void thunderEffect() {
for (int i = 0; i < NUM_PIXELS; i++) {
strip.clear();
if (i % 2 == 0) {
strip.setPixelColor(i, strip.Color(0, 0, 128)); // Dim blue
} else {
strip.setPixelColor(i, strip.Color(128, 128, 0)); // Dim yellow
}
strip.show();
delay(50);
}
strip.clear();
strip.show();
}
// Rain: Light dim blue light
void rainEffect() {
for (int i = 0; i < NUM_PIXELS; i++) {
strip.clear();
strip.setPixelColor(i, strip.Color(0, 0, 128)); // Dim blue
strip.show();
delay(100);
}
}
// Cloudy: Dim violet/lavender light
void cloudyEffect() {
static int brightness = 0;
static int direction = 5;
brightness += direction;
if (brightness >= 100 || brightness <= 0) {
direction = -direction;
}
uint32_t color = strip.Color(75 + brightness, 50 + brightness, 150 + brightness); // Dim lavender/violet
for (int i = 0; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, color);
}
strip.show();
delay(50);
}
// Sunny: Warm orange light
void sunnyEffect() {
static int brightness = 0;
static int direction = 5;
brightness += direction;
if (brightness >= 255 || brightness <= 50) {
direction = -direction;
}
uint32_t color = strip.Color(255, 140, 0); // Warm orange
for (int i = 0; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, color);
}
strip.show();
delay(50);
}
Click to Expand
The goal of networking exercise is for the design and development of How’s the Weather project. We want to design and prototype an interactive IoT device that leverages real-time communication to create a shared emotional connection between friends. By combining tactile interaction with visual feedback, the project aimed to explore how everyday emotional check-ins can be enhanced through tangible, responsive design.