Introduction: Marsmellow - a Mars Clock Which Gives Celestial Information

About: I am an electronics enthusiast who loves making projects with microcontrollers and microcomputers.

Have you ever looked into the vast open sky and wondered whether an Astronaut was there at that very moment in Space looking right at you? Or even wondered when the ISS (International Space Station) was directly over your head? Or what time was it on Mars?

Well...I have and in case you are anything like me here's something to keep you inspired during the quarantine!.

"Marsmellow" (Get it?) is a project which answers all these questions and more. The onboard Raspberry Pi calculates the exact MTC (Mars Coordinated Time), finds which Sol (Martian Days) is it and even what Season is it on Mars. It even finds the exact number of people in space at that very moment.

What's more is that a different colour LED lights up each time an Astronaut leaves Space, enters Space or whenever the ISS is over a specific location.

This project is also entered in the "Space" contest. If you liked the project it would mean a lot if you could vote for it.

Supplies

Hardware:

  • Any Raspberry Pi with onboard WiFi Cost : $40 - 50 (USD)
  • A NodeMCU (ESP8266). Cost : $6 (USD)
  • A 128 x 64 OLED display. (Something like this) Cost :$5 - 15 (USD)
  • A couple of LEDs. Cost: $1 (USD)
  • Some Jumper wires (Male-Female, Male-Male and Female-Female) Cost: $3 (USD)

Software requirements:

  • Arduino IDE
  • Python 3 IDLE on RPi
  • Adafruit account
  • IFTTT account

Others:

WiFi connection

  • Cardboard
  • White Glue or Epoxy glue
  • Sharp pair of Scissors
  • Paint
  • Curiosity (It might have killed the cat, but right now it's on Mars, alongside Opportunity and Spirit .) (Soon to be joined by Perseverance* . )

Step 1: The Answer of Life, Universe and Everything

The project is divided into two independent parts. Although both these parts could be combined and controlled by the Raspberry Pi this is done to make the project modular. I could simply remove the head and place it elsewhere with the spacesuit displaying Martian time.

The NodeMCU part controls the LED lights every time an event happens in Space and the Raspberry PI part controls the display to show Mars time, Sol and Martian Weather Information.

NodeMCU is a low-cost open-source IoT platform based on the ESP8266. It allows us to connect to the Internet and call various API ( Application Programming Interface) which is acts as an intermediary that allows two applications to talk to each other. The NodeMCU is connected to IFTTT (More on this later) which allows it to trigger an action via the Internet. (Here, light a LED)

The Raspberry Pi runs a Python 3 program calculates the time on Mars (MTC-Martian Coordinated Time) as well as the exact Sol(Martian Days). It also calls an API to find the Martian weather and the number of Astronauts in Space. All this information is then is displayed on an OLED display.

All calculations and algorithms are available on NASA's Mars24 Website. The Raspberry Pi uses these algorithms to calculate the time(MTC) and Sol on Mars.

The Mars weather information is obtained from NASA's Insight API which takes continuous weather measurements (temperature, wind, pressure) on the surface of Mars at Elysium Planitia, a flat, smooth plain near Mars' equator.

The number of people in space is obtained from Open Notify's API. All the information from the API's as well as the

Step 2: The Wiring

The connections are very simple and are as follows:

D6 of NodeMCU >>> Anode of Blue LED (+)

D7 of NodeMCU >>> Anode of Green LED (+)

D8 of NodeMCU >>> Anode of Red LED(+)

GND of NodeMCU >>>Cathode of all LEDs(-)

The three different LEDs show three different events occurring in space. The Blue LED lights up when the ISS is directly overhead, the Green when an Astronaut enters Space and the Red when an Astronaut leaves Space.

You could also use an RGB LED, but I used these instead.

Step 3: Adafruit.io Setup

Adafruit IO is a cloud service that makes data useful. It allows Online software to control hardware through controlling REST and MQTT APIs which NodeMCU calls.

MQTT, or message queue telemetry transport, is a protocol for device communication that can be used to publish or subscribe to a feed to send and receive feed data.

Follow the steps in the video above.

1) For this step, you would require an Adafruit account. After logging in to your account, go to Adafruit.io.

2) Click on "New dashboard" and enter a suitable name for your dashboard.

3) Doing so would open up a new dashboard. To add new elements, click on the "+" sign in the top-right side of the window.

4) Choose "Momentary Button" from the list of options and type in the parameters as shown in the video. Be sure to keep the feed names the same as shown in the video. Do this for all three feeds(Entry, Exit and ISS_overhead).

5) After creating the three "Momentary Buttons", note down your Username and the Adafruit IO Key as you would need this later. Make sure to keep this Secret key, umm secret...

Note: The Adafruit IO Key shown in the video is not secret anymore.

Step 4: Setting Up IFTTT

IFTTT ( If This Then That), is a web-based service that creates chains of simple conditional statements which are triggered by changes that occur within other web services. You can use the IFTTT website or it's android or IOS app to set it up. Follow the steps in the video above.

1)On IFTTT, click on your profile icon and then on "Create".

2)Click on "this". Then search for and select "Space". Choose "ISS passing over a specific location".Type in your location and then click "enter"

3) Now click on "that" and search for "Adafruit" on the search bar. Choose "Send IO data". Now choose the feed "ISS_overhead" which we created during the Adafruit.io dashboard setup. Type in "1" for "Data to Save".This tells Adafruit.io to send "1" to the feed every time the ISS is overhead and thus control the led.

4) Repeat this until you have created three applets connected to their appropriate feeds that are "Astronauts enter space" to the "Entry Feed" and "Astronauts exit space" to the "Exit Feed".

Step 5: Uploading the NodeMCU Code.

Upload the code into your NodeMCU using the Arduino IDE. Make sure to replace your Adafruit username and Adafruit IO Key in the code.

You would also need a couple of libraries:

ESP8266Wifi.h

"Adafruit_MQTT.h"

"Adafruit_MQTT_Client.h"

#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

#define ISS_overhead    D5
#define Entry           D6
#define Exit            D7


#define WLAN_SSID       "SSID"             // Your SSID
#define WLAN_PASS       "PASSWORD"        // Your password

//=================================================
#define AIO_SERVER      "io.adafruit.com"
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME    "YOUR ADAFRUIT.IO USERNAME" // Replace it with your Adafruit username
#define AIO_KEY         "YOUR ADAFRUIT.IO KEY"   // Replace with your AdafrProject Auth Key

//==================================================

// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);


//===========================Feeds=====================


//Setting up fields
Adafruit_MQTT_Subscribe ISS_Light = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/ISS_overhead"); // FeedNames
Adafruit_MQTT_Subscribe Entry_Light = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/Entry");
Adafruit_MQTT_Subscribe Exit_Light = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/Exit");

//=====================================================

void MQTT_connect();

//===================================================
void setup() {
  Serial.begin(115200);

  pinMode(ISS_overhead, OUTPUT);
  pinMode(Entry, OUTPUT);
  pinMode(Exit, OUTPUT);
  
  // Connect to WiFi access point.
  Serial.println(); Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.println("WiFi connected");
  Serial.println("IP address: "); 
  Serial.println(WiFi.localIP());
 

  // Setup MQTT subscription for onoff feed.
  mqtt.subscribe(&ISS_Light);
  mqtt.subscribe(&Entry_Light);
  mqtt.subscribe(&Exit_Light);
}

//=========================================================


void loop() {
  mqtt.ping();//This prevents from the NodeMCU to become inactive after some time
  MQTT_connect();
  

  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(20000))) {
    if (subscription == &ISS_Light) {
      Serial.print(F("ISS overhead light: "));
      Serial.println((char *)ISS_Light.lastread);
      int ISS_Light_State = atoi((char *)ISS_Light.lastread);
      digitalWrite(ISS_overhead,HIGH);
      delay(20000);//Light up for 20 seconds
      digitalWrite(ISS_overhead,LOW);
      
    }
    if (subscription == &Entry_Light) {
      Serial.print(F("Astronauts Entry Light: "));
      Serial.println((char *)Entry_Light.lastread);
      //int Entry_Light_State = atoi((char *)Entry_Light.lastread);
      digitalWrite(Entry,HIGH);
      delay(20000);
      digitalWrite(Entry,LOW);
    }
    if (subscription == &Exit_Light) {
      Serial.print(F("Astronauts Exit Light: "));
      Serial.println((char *)Exit_Light.lastread);
      //int Exit_Light_State = atoi((char *)Exit_Light.lastread);
      digitalWrite(Exit,HIGH);
      delay(20000);
      digitalWrite(Exit,LOW);}
  }

  
}




//===========================================================


void MQTT_connect() {
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);  // wait 5 seconds
    retries--;
    if (retries == 0) {
      // basically die and wait for WDT to reset me
      while (1);
    }
  }
  Serial.println("MQTT Connected!");
  
}

Upload the code and gaze into the sky.

Step 6: Raspberry Pi Wiring

The connections are as follows:

5 Volt Pin of the RPi >>> VCC pin of the OLED display

GND Pin of the RPi >>> GND pin of the OLED display

SCL Pin of the RPi (GPIO 3) >>> SCL pin of the OLED display

SDA Pin of the RPi (GPIO 2) >>> SDA pin of the OLED display

Note: In case the wires are loose or there are some soldering problems the Python program gives out a "Remote I/O Error" message.

Step 7: Downloading the Python Libraries

Run the following commands into the Lx terminal. The Raspberry Pi code is written in Python 3 and thus we would be using "pip3" and "python3" commands. In case you want to use Python 2 simply use "pip" or "python" command instead.

sudo apt-get update

To install the Requests Module for python3 run:

sudo pip3 install requests

Now download and set up the Adafruit_SSD1306 library. This would be used to control the 128x32 I2C OLED display.

git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git
cd Adafruit_Python_SSD1306 
sudo python3 setup.py install 

Now download and set up the Adafruit_GPIO library to be able to control the GPIO(General Purpose Input Output) pins on the RPi.

git clone https://github.com/adafruit/Adafruit_Python_GPIO.git
cd Adafruit_Python_GPIO
sudo python3 setup.py install

Now you can proceed to coding the Pi

Step 8: Coding on the Raspberry Pi

The code is written in Python 3.Simply open the Python 3 IDLE on your RPi and run the code.

Remember to download the "Minecraftia-Regular Font" from here and extract the zip file. Also, download the Don't Panic Image from above. Remember to download both files into the same directory as the code.

#Imports Libraries
import datetime
import time

import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

import requests
import json 
import subprocess

# Raspberry Pi pin configuration:
RST = None     
# Note the following are only used with SPI:
DC = 23
SPI_PORT = 0
SPI_DEVICE = 0


# 128x32 display with hardware I2C:
disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST)

# Initialize library.
disp.begin()

# Clear display.
disp.clear()
disp.display()

# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = disp.width
height = disp.height
image = Image.new('1', (width, height))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)


padding = -1
top = padding
bottom = height-padding
x = 5

timeinprogram=0

# Alternatively load a different format image, resize it, and convert to 1 bit color.
start_image = Image.open('dontpanic.jpeg').resize((disp.width, disp.height), Image.ANTIALIAS ).convert('1')
# Display image.
disp.image(start_image)
disp.display()
time.sleep(4.2)
print("Don´t Panic!")
disp.clear()

def astronauts_in_space():
    r = requests.get("http://api.open-notify.org/astros.json")
    peopleinspace = r.json()['number']


def mars_nasa_api():
    f = "https://api.nasa.gov/insight_weather/?api_key=DEMO_KEY&feedtype=json&ver=1.0"
    data = requests.get(f)
    tt = json.loads(data.text)
    for i in tt:
     return tt[i]["Season"]

mars_season= mars_nasa_api().capitalize() #Capatilzes the first letter of the season

i=0
while i<1:

    if timeinprogram==43200:# Checks for Astronauts in Space every 12 hours/ 43200 hours
      astronauts_in_space()
    if timeinprogram ==43200: # Checks for season changes on mars every 12 hours / 43200 seconds
      mars_nasa_api()
      
      
    datetime.datetime.utcnow()
    time.time()

    def pretty_thousands(num):
        pretty_num = "{:,}".format(num)
        pretty_num = pretty_num.replace(',', ',')
        return pretty_num

 #Converting  Earth UTC date to sols
    tai_offset = 37     
    millis = 1000*time.time()
    jd_ut = 2440587.5 + (millis / (8.64*10**7))      
    jd_tt = jd_ut + (tai_offset + 32.184) / 86400
    j2000 = jd_tt - 2451545.0
    mars_sol = (((j2000 - 4.5) / 1.027491252) + 44796.0 - 0.00096)

 #Converting UTC to MTC (Martian Coordinated Time)
    mtc = (24 * mars_sol) % 24
    mtc_hours = int(mtc)
    mtc_minutes = int((mtc - mtc_hours)*60)
    mtc_seconds = int(((mtc - mtc_hours)*60 - mtc_minutes)*60)
    mtc_time = datetime.time(hour=mtc_hours, minute=mtc_minutes, second=mtc_seconds)
    Sol=(pretty_thousands(int(mars_sol)))
    Time=str(mtc_time)[0:8]
  
   # Load default font.
    #font = ImageFont.load_default()
   # Alternatively load a TTF font.  Make sure the .ttf font file is in the same directory as the python script!
   # Some other nice fonts to try: "http://www.dafont.com/bitmap.php" 

    font = ImageFont.truetype('Minecraftia-Regular.ttf', 8)


    # Draw a black filled box to clear the image.
    draw.rectangle((0,0,125,31), outline=25, fill=0)

    draw.text((x+10,top)  , str(Time)                 ,font=ImageFont.truetype('Minecraftia-Regular.ttf', 14), fill=255)  # Increased fontsize for Time
    draw.text((x+90,top+6) , "MTC"                    ,font=font, fill=255) 
    draw.text((x+4,top+15), "Sol :"                   ,font=font, fill=255)
    draw.text((x+30,top+16), str(Sol)                 ,font=font, fill=255)
    draw.text((x+80,top+16), str(mars_season)         ,font=font, fill=255)
    draw.text((x+7,top+23), "Astronauts :"            ,font=font, fill=255)
    draw.text((x+80,top+23), str(astronauts_in_space()) ,font=font, fill=255)
    
    
    # Display image.
    disp.image(image)
    disp.display()
    timeinprogram=timeinprogram+1

If you do not want to manually run the program on the Raspberry Pi each time it reboots,you can run the program each time the Raspberry Pi boots. We can do this by modifying the .bashrc file. With the .bashrc file, your python program will run when you log in (which happens automatically when you boot up and go directly to the desktop) and also every time when a new terminal is opened, or when a new SSH connection is made. Put your command at the bottom of ‘/home/pi/.bashrc’. The program can be aborted with ‘ctrl-c’ while it is running.

sudo nano /home/pi/.bashrc

Go to the last line of the script and add:

echo Running at boot 
sudo python /home/pi/marsmellow.py

The echo statement above is used to show that the commands in .bashrc file are executed on bootup as well as connecting to bash console.

Now reboot the Pi to hear the Pi speak at startup.

sudo reboot

Step 9: One Giant Leap ...

I decided to make the enclosure look like an Astronaut. The first step to make the astronaut is to make the helmet.

To make the helmet I simply took a piece of cardboard and cut it into a cube( 6x6x6 cm ) using the template above. I then cut a square piece out of one face of the cube. I covered this face with a translucent sheet to give it a look of a visor.

I painted the whole helmet light grey and gave it some streaks of dark grey. I then cut out small pieces of cardboard and stuck it around the helmet to give it some detailed effects. I also gave dots of red, green and blue to give the helmet a digital look.

The NodeMCU and the LEDs go inside the head of the astronaut.

Step 10: The Spacesuit

The torso is made out of multiple layers of cardboard glued together. On top of the torso, I stuck tiny pieces of cardboard to give it details.

The legs and hands are also cut out of cardboard and glued together. I painted them with light grey and used White glue to cover any holes in the sides. I later covered some areas with brown wrapping paper and painted it light grey to give it a spacesuit look. I also used aluminium foil as gloves to give a reflective\\look.

The head stores the NodeMCU and the oxygen tank in the back hold the Raspberry Pi.

Step 11: Assembling the Suit

“I like the cover," he said. "Don't Panic. It's the first helpful or intelligible thing anybody's said to me all day.”― Douglas Adams, The Hitchhiker's Guide to the Galaxy

The Raspberry Pi is attached behind the Astronaut using double tape. All the limbs are attached to the torso with Epoxy glue. The NodeMCU is powered by the Raspberry Pi which in turn is powered by a power bank.

The OLED also shows the time, Sol and season on Mars along with the current number of Astronauts in Space. The lights in the helmet light up any time an Astronaut enters or exits Space or whenever the ISS is overhead.

As soon as the program loads, a "Don't Panic" image is shown for exactly 4.2 seconds (a reference to The Hitchhiker's Guide to the Galaxy.) The LED's in the helmet light up whenever an Astronaut enters/exits Space or whenever the ISS is overhead.

The project works great and I have seen the LEDs light up several times a week. However, it's not every day that the ISS is over your head and you have got to be patient. Every time that I look at the Martian clock it inspires me to keep looking . It reminds me that each day is an opportunity to break boundaries, to do the impossible and to boldly go where no one has gone before.

In the future, I hope to add other features to include Martian windspeed, the average temperature on mars and it's a relative position to the Earth. I also want to improvise on the spacesuit and embed the OLED display into the suit.

Hope you liked this project. Feel free to comment down below for any suggestions or queries. Any inputs are appreciated.

Space Challenge

Participated in the
Space Challenge