Data Visualization
Design Challenge
Create an Internet-connected device using at least 2 sensors. The choice of sensors is up to you. This device will collect data in your house for a week. 
Then, you will create a sketch that will access the data and represent it visually.
Design tools used: p5.js javascript, Arduino ESP32
Ideation and concepts
I decided to use the TMP36 (temperature) sensor and the photocell (light) sensor for this project because I wanted to measure how many times I used our living room lamp and see the fluctuations in temperature. 
We have a heater in the home which works fine but since it is an older home, it tends to get really cold at night and early mornings. So these two sensors would tell me these important things. 
I placed the sensors next to our lamp and this video shows how it works to measure the light in the room. The temperature sensor also picks up the general temp in the room. 
The JS Sketch
Once the hardware was set up and collecting data, the information was sent to my feeds in Adafruit.io and I started to see how this was working. Here is the data the sensors started to pick up once it correctly set up. 
I am not entirely sure what these spikes mean. 
 I decided to have the TMP feed show me lines with varying stroke weights and the photo feed to show me circles with random colors and varying circle widths to indicate how much light it was picking up. I expected to see something like this, from going cold and dark to going warm and bright. 
Here's another example that I was expecting to see in my final sketch. This would represent what a morning looks like. The smaller lines indicate is was early and it is getting progressively warmer (once we turned on the heater). However, the light would have been turned on first before it go warm. 
Here's a more extreme example that I wasn't quite able to explain. It looks like the previous screen, but it shows more light in here. It might be when I was messing with the limit number, but it was interesting to note that the lines were beginning to fade away or become blocked by the circles. 
When I started to plug in the real time feeds to get the values, the TMP sensor was not being picked up correctly and only the photo sensor was showing up. It cycles through random colors really fast, so it looks like a strobe light. Even more interesting was the circles. They did not change size, only their color. 
Final Thoughts
Ultimately, I was not able to figure out how to properly visualize the data from these feeds to show what I was thinking of in the first place. However, it did help me understand how to send real-time data to a feed and use it to create interesting designs. I would like to figure out different ways to interpret data using different techniques, but this was really tough for me to understand in the first place. 
The P5.js Code
let baseTmpURL = "https://io.adafruit.com/api/v2/AntonioRenoj/feeds/tmp-feed";
let basePhotoURL = "https://io.adafruit.com/api/v2/AntonioRenoj/feeds/photocell-feed/";
let dataOption = "data";
let limitQuery = "limit=";
let limitNumber = 10;
let includeQuery = "include=";
tmpValues = [];
photoValues = [];

function setup() {
  createCanvas(600, 400);
  // Fetch data every 10 seconds
  setInterval(getTmpFeedData, 10000);
  setInterval(getPhotoFeedData, 10000);
}
function draw() {
  background(0);
  // Draw lines for TMP values
  if (tmpValues.length > 0) {
    tmpValues.forEach((value, i) => {
      let clampedValue = constrain(value, 0, 4095); // Ensure value is within range
      let strokeWidth = map(clampedValue, 0, 4095, 2, 10); // Minimum stroke width set to 2 for better visibility
      let xPosition = (width / limitNumber) * i + width / limitNumber * 0.5;
      let lineLength = map(clampedValue, 0, 4095, 20, height); // Minimum line length set to 20 for visibility
      stroke(173, 216, 230); // Light blue color
      strokeWeight(strokeWidth); // Set stroke thickness
      line(
        xPosition,
        height * 0.5 - lineLength / 2,
        xPosition,
        height * 0.5 + lineLength / 2
      ); // Draw vertical line
      console.log(`TMP Line ${i}: x=${xPosition}, length=${lineLength}, strokeWidth=${strokeWidth}`);
    });
  } else {
    console.log("No TMP values to draw.");
  }
  // Draw circles for Photo values
  if (photoValues.length > 0) {
    photoValues.forEach((value, i) => {
      let clampedValue = constrain(value, 0, 4095); // Ensure value is within range
      let diameter = map(clampedValue, 0, 4095, 20, height); // Minimum diameter set to 20 for visibility
      let xCenter = (width / limitNumber) * i + width / limitNumber * 0.5;
      let yCenter = height * 0.5;
      fill(random(255), random(255), random(255), 120); // Random translucent color
      noStroke(); // Ensure no outline for circles
      circle(xCenter, yCenter, diameter); // Draw circle
      console.log(`Photo Circle ${i}: x=${xCenter}, diameter=${diameter}`);
    });
  } else {
    console.log("No Photo values to draw.");
  }
}
function getTmpFeedData() {
  loadJSON(
    `${baseTmpURL}${dataOption}?${limitQuery}${limitNumber}&${includeQuery}value`,
    handleTmpData,
    handleTmpError
  );
}
function handleTmpData(data) {
  if (Array.isArray(data)) {
    console.log("TMP data received:", data);
    tmpValues = data.map((d) => parseInt(d.value) || 0); // Parse and fallback to 0 if invalid
    console.log("Parsed TMP values:", tmpValues); // Debugging TMP values
  } else {
    console.error("Invalid TMP data:", data);
  }
}
function getPhotoFeedData() {
  loadJSON(
    `${basePhotoURL}${dataOption}?${limitQuery}${limitNumber}&${includeQuery}value`,
    handlePhotoData,
    handlePhotoError
  );
}
function handlePhotoData(data) {
  if (Array.isArray(data)) {
    console.log("Photo data received:", data);
    photoValues = data.map((d) => parseInt(d.value) || 0); // Parse and fallback to 0 if invalid
    console.log("Parsed Photo values:", photoValues); // Debugging Photo values
  } else {
    console.error("Invalid Photo data:", data);
  }
}
function handleTmpError(error) {
  console.error("Error fetching TMP data:", error);
}
function handlePhotoError(error) {
  console.error("Error fetching photo data:", error);
}


Back to Top