HORIZONTE – Time Final

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. The clock 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.

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
  • Unreal Engine 4 (for visualizations)

Initial Proposal

Initial mockup idea

User Interaction

UI Re-design

FULL PROCESS

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.

Gradient and sky mood board in Miro

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.

HUGE THANKS TO:

  • Jeff Feddersen
  • Benjamin Light
  • Schuyler Devos

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

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

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