back
Written by Arthur Jensen — December 10th 2024

Data Collection with an IoT Device

Create a sketch that would simulate an existing natural system - look at physics, biology, and other natural sciences for good examples.
Collecting details on light and temperature at my local coffee shop.
Interpreting the Brief

For this project, I will be creating an internet-connected device that utilizes at least two sensors of my choosing to gather data within my home environment for a week. I will need to consider the device's installation location, power source, and any necessary mechanical components to interface with the sensors. Additionally, I will determine the data saving frequency, taking into account limitations like the maximum data points per feed on platforms such as AdafruitIO, and the type of data I need to store (repeated values or only changes). Following data collection, I will develop a sketch to access and visually represent this data. Finally, I will create a documentation page detailing the process, including images or videos of my IoT device in action, along with visuals or embeds of my P5.js sketch showcasing the data representation.

Using Our Previous Assignment's Code as a Foundation for This Project

This code is for an Arduino project where two sensors are used: a potentiometer (which measures how much a knob is turned) and a photocell (which measures the amount of light). The code does a few things: First, it connects to the internet using a service called Adafruit IO, which lets the Arduino send data online. In the setup() part, the code sets up communication and waits until the Arduino is connected to Adafruit IO. Then, in the loop() part, it constantly reads values from the potentiometer and photocell, prints those values to the screen, and sends them to Adafruit IO so they can be accessed remotely. Every 5 seconds, it repeats this process.

1#include "config.h"
2#define POTENTIOMETER_PIN A2
3#define PHOTOCELL_PIN A3
4
5AdafruitIO_Feed *potFeed = io.feed("knob-feed");
6AdafruitIO_Feed *photoFeed = io.feed("photo-feed");
7
8void setup() {
9  Serial.begin(9600);
10  while(! Serial);
11  // connect to io.adafruit.com
12  Serial.print("Connecting to Adafruit IO");
13  io.connect();
14  // wait for a connection
15  while(io.status() < AIO_CONNECTED) {
16    Serial.print(".");
17    delay(500);
18  }
19   Serial.println();
20   Serial.println(io.statusText());
21}
22
23void loop() {
24  // put your main code here, to run repeatedly:
25  io.run();
26  float potVal = analogRead(POTENTIOMETER_PIN);
27  float photoVal = analogRead(PHOTOCELL_PIN);
28  Serial.print("Sending pentiometer: ");
29  Serial.println(potVal);
30  potFeed->save(potVal);
31  Serial.print("Sending photoresistor: ");
32  Serial.println(photoVal);
33  potFeed->save(photoVal);
34  delay(5000);
35}
Written Code that connects my board with Adafruit IO.
Pivoting due to a Power Shut-Off

On Monday (Dec 9th), I was notified of a power shut off in my area that forced me change my direction of my project. I realized that I could still collect data but it will have to be at a coffee shop. I could collect data on the light and temperature within the environment. I can still connect my device to my laptop and keep it close to me while I work.

Creating Code to Measure Light & Temperature

This Arduino code uses two sensors: a temperature sensor (connected to pin A2) and a photocell (connected to pin A3), and sends their data to Adafruit IO. In the setup() section, the code starts communication with the computer and connects to Adafruit IO. In the loop() section, it continuously reads data from both sensors: the temperature sensor gives an analog reading, which is converted into a temperature in Celsius and then sent to Adafruit IO, while the photocell reading is used to determine how much light is present. The photocell value is displayed as a raw number, and based on its value, the code categorizes the light as "Dark," "Dim," "Light," "Bright," or "Very Bright." This data is also sent to Adafruit IO every 10 seconds. The serial monitor shows all the sensor readings to see what's happening in real time.

1#include "config.h"
2#define TEMP_PIN A2
3#define PHOTO_PIN A3
4AdafruitIO_Feed *lightFeed = io.feed("light-feed");
5AdafruitIO_Feed *tempFeed = io.feed("temp-feed");
6
7// Photocell Pin Variables
8const float Vref = 3.28;
9const int ADCResolution = 4095.0;
10float tempC;
11
12void setup() {
13  // Start Serial communication
14  Serial.begin(9600);
15  while (!Serial);
16
17  // Connect to Adafruit IO
18  Serial.print("Connecting to Adafruit IO");
19  io.connect();
20  // wait for a connection
21while(io.status() < AIO_CONNECTED) {
22Serial.print(".");
23delay(500);
24  }
25
26Serial.println();
27Serial.println(io.statusText());
28}
29
30void loop() {
31  // Read temperature sensor (TMP36)
32  io.run();
33  
34  float analogValue = analogRead(TEMP_PIN);
35  tempC = ((analogValue * Vref / ADCResolution) - 0.35) * 100.0;
36  float photoVal = analogRead(PHOTO_PIN);
37
38  // Print temperature readings
39  Serial.print("Analog Value (Temp): ");
40  Serial.println(analogValue);
41  Serial.print("Sending temp (C): ");
42  Serial.println(tempC);
43  tempFeed->save(tempC);
44  // Print photocell readings
45  Serial.print("Photocell Reading = ");
46  Serial.print(photoVal); // Raw ADC reading
47  if (photoVal < 10) {
48    Serial.println(" - Dark");
49  } else if (photoVal < 200) {
50    Serial.println(" - Dim");
51  } else if (photoVal < 500) {
52    Serial.println(" - Light");
53  } else if (photoVal < 800) {
54    Serial.println(" - Bright");
55  } else {
56    Serial.println(" - Very Bright");
57  }
58  lightFeed->save(photoVal);
59  // Delay before next loop iteration
60  delay(10000); // 10-second delay for readability
61} 
Written Code that connects my code for this assignment to Adafruit IO.
Graph of light-feed.
Light-Feed Graph: Values collected from Adafruit IO.
Values from light-feed
Light-Feed Values: Values collected from Adafruit IO.
Graph from temp-feed.
Temp-Feed Graph: Values collected from Adafruit IO.
Values from temp-feed.
Temp-Feed Values: Values collected from Adafruit IO.
Creating My Visual in P5.js to Represent Temperature and Light

I'm visualizing cafe data with a dynamic sun graphic. The sun's color reflects the temperature: cooler temperatures make it blue, while warmer temperatures shift it towards red.To show light levels, the sun has rays that grow longer as more light enters the cafe, and shrink as light diminishes. This creates an intuitive visual representation of the cafe's environment.

My sketches for how I want to visualize my P5.js platform.
Creating Code for P5.js

This code visualizes live temperature and light data from Adafruit IO feeds. It fetches the latest data points every 5 seconds and uses them to draw a dynamic sun graphic. The sun's color changes based on the average temperature, shifting towards blue for colder temperatures and red for warmer ones. Additionally, the code draws black rays extending from the sun, with the length of the rays representing the average light intensity. Higher light values result in longer rays, providing an intuitive visual representation of the data.

1et baseTempFeedURL = "https://io.adafruit.com/api/v2/artjensen/feeds/temp-feed/";
2let baseLightFeedURL = "https://io.adafruit.com/api/v2/artjensen/feeds/light-feed/"; 
3let dataOption = "data";
4let limitQuery = "limit=";
5let includeQuery = "include=";
6let tempValues = [];
7let lightValues = []; 
8
9function setup() {
10  createCanvas(800, 800); 
11  noStroke();
12
13  // Fetch data every 5 seconds
14  setInterval(() => {
15    fetchTempData();
16    fetchLightData(); 
17  }, 5000);
18
19  // Initial data fetch
20  fetchTempData();
21  fetchLightData(); 
22}
23
24function draw() {
25  background(200, 225, 255); 
26
27  if (tempValues.length > 0 && lightValues.length > 0) { 
28    drawTemperatureCircle();
29  } else {
30    console.warn("No temperature or light values available for drawing.");
31  }
32}
33
34function drawTemperatureCircle() {
35  let centerX = width / 2;
36  let centerY = height / 2;
37  let circleSize = 150; 
38
39  // Calculate average temperature
40  let avgTemp = tempValues.reduce((sum, val) => sum + val, 0) / tempValues.length;
41
42  // Map temperature to color
43  let redValue = map(avgTemp, -20, 50, 0, 255); 
44  let blueValue = map(avgTemp, -20, 50, 255, 0); 
45
46  fill(redValue, 0, blueValue); 
47  ellipse(centerX, centerY, circleSize, circleSize);
48
49  // Calculate average light value
50  let avgLight = lightValues.reduce((sum, val) => sum + val, 0) / lightValues.length;
51
52  // Draw sun rays
53  stroke(0); // Black color for the rays
54  strokeWeight(4); // Thicker stroke weight
55  let rayLength = map(avgLight, 0, 1023, 50, 200); 
56  for (let angle = 0; angle < 360; angle += 30) { 
57    let x1 = centerX + cos(radians(angle)) * circleSize / 2;
58    let y1 = centerY + sin(radians(angle)) * circleSize / 2;
59    let x2 = centerX + cos(radians(angle)) * (circleSize / 2 + rayLength);
60    let y2 = centerY + sin(radians(angle)) * (circleSize / 2 + rayLength);
61    line(x1, y1, x2, y2);
62  }
63  noStroke();
64}
65
66async function fetchTempData() {
67  try {
68    let url = `${baseTempFeedURL}${dataOption}?${limitQuery}10&${includeQuery}value`;
69    let response = await fetch(url);
70
71    if (!response.ok) {
72      throw new Error(`HTTP error! status: ${response.status}`);
73    }
74    let data = await response.json();
75    tempValues = data.map((d) => parseFloat(d.value) || 0);
76    console.log("Temperature values:", tempValues);
77  } catch (error) {
78    console.error("Error fetching temperature data:", error);
79  }
80}
81
82async function fetchLightData() {
83  try {
84    let url = `${baseLightFeedURL}${dataOption}?${limitQuery}10&${includeQuery}value`; 
85    let response = await fetch(url);
86
87    if (!response.ok) {
88      throw new Error(`HTTP error! status: ${response.status}`);
89    }
90    let data = await response.json();
91    lightValues = data.map((d) => parseFloat(d.value) || 0); 
92    console.log("Light values:", lightValues);
93  } catch (error) {
94    console.error("Error fetching light data:", error);
95  }
96}
Written Code that illustrates the sun and rays on P5.js.
Written Code that illustrates the sun and rays.
Version 1: P5.js visual of sun with a dark blue circle and long sun rays.
Written Code that illustrates the sun and rays.
Version 2: P5.js visual of sun—dark purple circle and long sun rays one hour later
Reflection

Link to my P5.js:https://editor.p5js.org/This assignment challenged me to visualize environmental data in P5.js. A power outage forced me to adapt, shifting from collecting data at home with a potentiometer and photocell to gathering temperature and light data from a local coffee shop.Despite this, I successfully collected data using an Arduino with a temperature sensor and photocell, sending it to Adafruit IO. This highlighted the importance of flexibility when working with hardware.I visualized the data as a dynamic sun in P5.js, with color reflecting temperature and ray length indicating light intensity. This metaphor effectively conveyed the cafe's environment. This project deepened my understanding of IoT, data visualization, and iterative design. It also emphasized clear communication when explaining the project's evolution and visual representation.In the future, I would explore more complex and interactive visualizations. This was a valuable learning experience that broadened my technical and creative problem-solving skills.