HORIZONTE – Time Midterm

API Website/ Server : https://horizonte-api.herokuapp.com/

Github API Repository: https://github.com/lacouture100/Horizonte-API

Github project Repository: https://github.com/lacouture100/ITP-Time/tree/master/MidTerm

Introduction

My project is called Horizonte, a horizon clock that adjusts it’s color and light patterns in real-time according to its location and the current time of day. The clock itself is a device that provides a WiFi access point for remote configuration, and an autonomous network-based update feature, which allows the user to customize the clock’s parameters. I wanted to stray away from the sense of being precise, a rather lazy, and non-invasive way of letting you know what part of the day it is. I wanted to acknowledge the shift without precisely getting a sense of what exact moment it is. Consequently, The clock itself gradually shifts from one stage of the day to the next, taking around 5- 20 minutes to shift depending on the event, location, and date. The project uses an API that is based on the SuncalcJS library to acquire the time for each particular ‘sun event’ in the day, such as Dawn, Sunset, etc… For this particular project, at this stage at least, I am dealing with events that happen between Dawn and Dusk. Why? These are the first and last stages of sunlight, and if you are a fan of ” From Dusk till Dawn”, those are vampire-safe times.

This device is meant to be hung on the wall… Specifically, the lights would be pointed towards the wall, as to give a sensation of a “sky” inside a space.

Hardware Used

Power requirements

  • I used a 5V, 10A power supply for both the Arduino and the lights. Same as this one.

Software

  • Arduino IDE
  • NodeJS
  • Suncalc
  • Blender
  • Illustrator

Initial Proposal

Initial mockup idea
First sketches in pen and paper.
First sketches in pen and paper.

Light

I fortunately had a Neopixel strip around right from the start. I tested several colors, patterns, and rhythms in order to get a sense of how I could maneuver the light in the fashion I wanted, starting with something like the video below. Through the tests, I found that maintaining a 45-degree angle served my purpose better.

Testing the Neopixels against the wall

I mainly focused on gradients, however I also tried different approaches, as you can also see below.

Testing different lighting properties with the strips.

I quickly found myself struggling to acquire the control I needed, and after a week or two of trying to make my own gradients based off of Adafruit’s limited examples, I was running out of time to get the other things going. After looking for a while I ran into FastLED, a Neopixel control library developed for Arduino which boasts to be better than the original library. Their examples were very varied, complete, and allowed me to find a couple of useful scripts which I took apart to make my own. Specifically, I heavily relied on the ColorPalette example and the nblendPaletteTowardPalette function found in the docs. The code implemented in the clock goes through nine different gradients, transitioning in and out of them during the day.

The main function takes the following parameters:

  • A current time measure in order to determine which sun event should be activated
  • The start time for the current day loop. It resets at midnight.
  • each of the sun events in millis().
void ChangePalettePeriodically_bottom(unsigned long startMillis,
                                      unsigned long currentMillis,
                                      long interval1,
                                      long interval2,
                                      long interval3,
                                      long interval4,
                                      long interval5,
                                      long interval6,
                                      long interval7,
                                      long interval8,
                                      long interval9
                                     ) {
Gradient using FastLED
Seeing the individual sections on the two strips

In terms of wiring and connections, it was pretty straightforward. I used an Arduino MKR 1010 since it had an esp32. From previous research, I knew it had more ram than the Arduino Nano, which was my other option. I hooked a couple of 470-ohm resistances to the input line of each Neopixel Strip. I also added two 470 microfarads capacitors in series. The Adafruit Uberguide for powering Neopixels suggests a 1000 microfarad capacitor, however, I did not have one. All of this was powered by a 5V, 10A power supply. Here’s the schematic below.

Horizonte Schematic

Color

First Gradient display made with Miro

In order to represent the horizon, or at least my view of it, I would have to decide on a color palette to use. I started out doing something like the image below, which gave me a general sense of where to go.

However, the more I observed the sky the more I could not help but think about what makes each sun stage so unique beyond it’s time. What makes a sunset different than a sunrise? The color? Not really. However, it is different, it feels different. So I felt unsatisfied with my above diagram and expanded it towards the one below.

Gradient and sky mood board in Miro

This one was much better. It made me feel each of the sun events way better and get a more complete sense of the transitions throughout the day. Throughout my observation I also came to the conclusion most of these gradients were two-toned, and in some cases even three, which gave path to the notion of using 2 led strips instead of one.

Finally, after having all of my hardware and LED libraries at hand, I added the FastLED color table to see what I would have to code in order to get these gradients. Image Below. Link to the FastLED color diagram here.

Gradient, FastLED color-code diagram, and sky mood board in Miro

Calculation

My first idea was to make a gradient that would go across the strip, and it would have a fish-lens type of sphere that would travel along the strip throughout the day. However, after working on it for a while and trying out different approaches, I did not quite achieve the effect I wanted. Because even though I could create a custom gradient and modify its position, I did not clearly see a way to make it happen in runtime. So after deciding whether I should invest more time in it in the moment, I changed my strategy. I would show the horizon and it’s particular stage in its entirety, without giving away what passed and what came next.

The calculations made in order to acquire the effect were not so difficult to adapt. However after attempting to do some of them onboard the Arduino, I came to the conclusion ( thanks to Jeff for this one) it was better to make the Arduino as dumb as possible. I would send everything calculated from the Node server I set up and the Arduino would just set the HTTP response body as the parameters for the lights and time synchrony. They were : Which time to turn on and off the device, how long it would take in each of the solar stages, and what time scale would I be following: local or UTC? The first two were easy: Suncalc gave them to me already, I just had to pass it into milliseconds in order for the Arduino to calculate everything in the same scale.

User Interaction

At first I played around with the idea of two or three simple buttons hidden away, maybe even a small OLED screen? (I think I’ve broken 10 of them already) I used Miro app to swiftly design how the user interface would work in terms of what appeared on the screen, what input or option did the user have, and what would happen in the device while all of this happened.

Apparently, the initial idea of maybe having a couple of buttons or a screen was not as straightforward as I thought, at which point Jeff directed me towards the possibility of creating an access point with the Arduino and make the UI and UX in there. Amazing. So that’s what I went for. I used the AP_SimpleWebServer example from the WiFiNINA series of examples to set up my own thing.

The Horizon Hotspot

WiFi Hotspot connected!
Web UI for the Horizonte Clock

In the images above you can see the hotspot being created by the clock, and how the interface is presented. I managed to send some JS in the site in order to grab the local time, GMT, and also modify the CSS to make it look a bit better. Somehow flex doesn’t work all the way, though I might be overlooking something. You can find the code for this one in the “Access point” tab in the Main Sketch. Anyways, once the hotspot is on, you input the credentials for a WiFi network around you, as well as your latitude and longitude. These lase two will later make part of the request for the server in order to get accurate times.

The API, the request, the data

After having seen Tom Igoe’s Connected Devices and Networked Interaction class last semester, I felt fairly confident that making my own API was the way to go in order to access the data at any given time from any device and also to control it. Manipulating the data and processing it before sending it to any device was a priority. I decided to make it in NodeJS since I wanted to keep the possibility of incorporating JS into the web client open. I also mounted it on Heroku, which probably isn’t the best option for continuous communication such as WebSockets but works fine for HTTP requests. As I said before, even though my idea was to keep it as real-time as possible the idea of being a couple of seconds or even minutes off track didn’t mean much. The API consists of two routes: /sun and /now. /sun ill return all of the times for each sun event according to UTC. /now will return the current time.

The data is presented as a JSON file. So everytime we make a request, the server writes an updated JSON file which is sent to the Arduino. You can see the JSON formatted below.

Server console log

To made the request to the server I used the WiFi Web Client example from the Arduino IDE, and later saved it as a JSON using the ArduinoJson library.

Arduino Serial Log connecting to the hotspot, receiving the data, and updating it’s value to the current time.

This allowed me to access each key-value in the JSON easily, and save it to set the parameters in our Neopixels lights function. Below you can see a glimpse of how it went for saving the data for Dawn. I later expanded this to include an SD card in order to save the dat and access it later in case I did not have an internet connection. Mostly as a fail-proof asset.


int dawnR, dawnG, dawnB;
long dawnMillis;
JSONVar myDataObject;

JSONVar apiSunTimesRequest(JSONVar myDataObject) {
  // assemble the path for the GET message:
  String path = "/sun";

  // send the GET request
  Serial.println("making GET request");
  httpclient.get(path);

  // read the status code and body of the response
  int statusCode = httpclient.responseStatusCode();
  String response = httpclient.responseBody();
  Serial.print("Status code: ");
  Serial.println(statusCode);
  Serial.print("/sun Response: ");
  Serial.println(response);

  //Write the Data to the SD Card
  writeToSD(response);

  // parse the string into a JSONVar object:
  myDataObject = JSON.parse(response);

  dawnMillis = myDataObject["dawn"]["time"]["ms"];
  
  // Set the color for each event
  dawnR = myDataObject["dawn"]["color1"]["r"];
  dawnG = myDataObject["dawn"]["color1"]["g"];
  dawnB = myDataObject["dawn"]["color1"]["b"];
   
    return  myDataObject;
  }
}

apiSunTimesRequest(myDataObject);

Form

I went though several iterations in order to get to a form which satisfied my thirst for a minimal horizon representation. I used blender in order to get a dimensionality and feel for what a wanted, and later used Illustrator in order to create the necessary shapes to later cut the shape with wood.

I quickly discarded the circle idea, and rather went for a more “horizon” kind of look. Such as this one taken by NASA:

https://www.abc.net.au/news/image/4688718-3x2-940x627.jpg

When I was satisfied with my 3D model, I decided to makes some illustrator sketches to start building the form . The construction would consist of several wooden layers attached together to achieve the required volume. The ‘Front Side’ , or show side, would have no markings on it, the remaining layers would be the main structure. These would be cut with laser to acquire the best precision possible, and would also allow me to design the frame in order to contain the components out of view.

I also started drawing out possible angles and the necessary depth of the volume, translating into how many layers of wood I would need. I decided on six layers of wood, each with a depth of 6mm. As you can see below, my idea was to make a 45 degree angle in the middle layers in order to place the lights on top

Very illustrative explanation of the position of the lights on the device. Side view above and front view below.
Initial measurements and making Pythagoras proud.
Final calculations.

So at first I just played around with the shape of each of the layers on top of each other:

Playing around.
Displaying each individual layer below the whole structure.

Getting a feel on how I would fit the components inside. As a minimum, the leanest slice would at least have to have 2.6 cms, So that was the measure I used as the scale for the other slices.

Thought about some text on it. Well, maybe not.
Getting there. You can see the cuts for this prototype below.
First attempts failed.
First attempts failed.

After several failed cuts, designs, and a lot of illustrator, I finally arrived at the design below, which divided each of the 5 “out-of-view” pieces to be cut into three separate pieces, each one with a hole for wooden dowels.

The current prototype design.
Current prototype exploded view display.
Current prototype exploded view display.

Production

The Strips

The strips come in a silicon enclosure, so I cut it off to have more access to the strip itself. The enclosure is so nice I actually felt sad about having to cut it. Besides, it cost a lot.

Both strips spread out.
The silicone enclosure is so nice.
Cutting the strips!

I then made a little jig in order to be able to keep my lights a distance away while I still worked on them from my computer. See it below:

Lighting jig solder.
The lighting jig in action.

The structure

First approaches:

Failed design:

Testing the different angles for my lights’ placement using the router table.
Failed print #2
Not as accurate as planned….
Observe the 45 degree angle on the right vs the uncut version on the left.

After 3 different failed cuts, I arrived at this design. Look at that beauty:

So smooth.
This time I kept the pieces together. I would glue them and then take them away.
Clearing the path inside.
Some glue to keep it all together.
It stands by it’s own. Proud parent here.

Putting it all together

I pasted the strips on the device using double-sided tape, and also sent the connecting cables inside the frame to the Arduino compartment as you can see below.

The power,GND, and input cables crawling into the frame.
Fitting the cables from the lights to the Arduino through the frame.
IT LOOKS GOOD!
Gorgeous, the strips fit perfectly. Maybe I should trim the cables though.
Drilling the hole for the power supply plug.
All of it fits snuggly into place.
Debugging the device.

Finishing it up

So….How does it look?

Horizonte.

Behind the Scenes:

What’s missing?

  • Decide on a pattern to set the time and stick with it. Be it UTC or local time.
  • Actually see it throughout the day, a whole run.
  • Implement a failsafe in case there is no internet, or the user inputs the password incorrectly.

Future development

  • Design a more complete Web UI.
    • Customize color on the device from a web customizable gradient.
    • Allow fade control.
  • Design my schematic and board in Eagle. Simplifying and cutting size.
  • Integrate other visualizations based around the concept of a horizon, astronomical horizon, etc.
  • Adjust the shape so it fits my slimmed-out idea.
  • Include an on/off button.
  • Incorporate node-geo-tz – geographical timezone lookup package
    • Scrape Instagram for current color palettes in images and location?

HUGE THANKS TO:

  • Jeff Feddersen
  • Benjamin Light
  • Schuyler Devos