It’s hard work being a werewolf, and I don’t just mean cleaning blood stains out of the carpet or dealing with fleas in the house.

It’s this messy business of the full Moon. Most wall calendars and news sources, if they even mention Moon phases, there’s about a 50/50 chance that they’re off by a full day (explained on the “Moon Facts” page). You might be out at a fancy event wearing a rental tuxedo when things turn weird. There goes your deposit. So awkward.

The only way to get a correct Moon phase for your time and location is with math and science. Our Matrix Portal Moon phase clock lets you know where things stand right here and now, portraying the Moon’s phase more accurately than a printed calendar, and whether it’s currently in the sky or has set.

So now you can prepare. No tux! Stay home and put on a comfortable flannel shirt like werewolves do.

This project requires:

  • Adafruit Matrix Portal M4 board
  • Any of our 64x32 pixel “HUB75” (not NeoPixel) RGB LED matrices (other sizes are not supported by this code)
  • USB C cable
  • USB power supply with output of 2 Amps or more
  • WiFi internet access
  • An insatiable hunger for human flesh

This guide will get the software running on the bare Matrix Portal hardware. Mounting or supporting the clock in an enclosure or frame is left as an exercise to the reader.

Next we’ll connect the Matrix Portal board and LED matrix. Do not over-tighten the screws on the power terminals or they can shear off. This is best done in human form.


Folks love our wide selection of RGB matrices and accessories, for making custom colorful LED displays... and our RGB Matrix Shields...
Out of Stock
As technology changes and adapts, so does Adafruit. This  USB Type A to Type C cable will help you with the transition to USB C, even if you're still...
In Stock

You can use a USB C power supply or a USB micro B with a micro B to C adapter

The official Raspberry Pi USB-C power supply is here! And of course, we have 'em in classic Adafruit black! Superfast with just the right amount of cable length to get your Pi 4...
In Stock
Our all-in-one 5V 2.5 Amp + MicroUSB cable power adapter is the perfect choice for powering single-board computers like Raspberry Pi, BeagleBone, or anything else that's...
In Stock
As technology changes and adapts, so does Adafruit, and speaking of adapting, this adapter has a Micro B USB jack and a USB C...
In Stock

If you'd like your LEDs diffused, some acrylic may help

A nice whoppin' slab of some lovely black acrylic to add some extra diffusion to your LED Matrix project. This material is 2.6mm (0.1") thick and is made of special cast...
In Stock

Adafruit carries a number of 64x32 RGB LED Matrices, varying between the space between LEDs (pitch) and whether rigid or flexible. Choose your favorite - larger pitch means the display is larger, width and height-wise but with the same number of pixels, and larger may be easier to read further away. Smaller for near your desk, for example.

Bring a little bit of Times Square into your home with this sweet 64 x 32 square RGB LED matrix panel. These panels are normally used to make video walls, here in New York we see them...
In Stock
Bring a little bit of Times Square into your home with this sweet 64 x 32 square RGB LED matrix panel. These panels are normally used to make video walls, here in New York we see them...
Out of Stock
Bring a little bit of Times Square into your home with this sweet 64x32 square RGB LED matrix panel. These panels are normally used to make video walls, here in New York we see them on...
In Stock
Bring a little bit of Times Square into your home with this sweet 64x32 square RGB LED matrix panel. These panels are normally used to make video walls, here in New York we see them on...
In Stock
If you've played with multiplexed RGB matrices, you may have wondered "hey, could we possibly manufacture these on a thin enough PCB, so it's flexible?" and the...
In Stock
If you've played with multiplexed RGB matrices, you may have wondered "hey, could we possibly manufacture these on a thin enough PCB so it's flexible?" and the answer...
In Stock

Power Prep

The MatrixPortal supplies power to the matrix display panel via two standoffs. These come with protective tape applied (part of our manufacturing process) which MUST BE REMOVED!

Use some tweezers or a fingernail to remove the two amber circles.

Power Terminals

Next, screw in the spade connectors to the corresponding standoff.

  • red wire goes to +5V 
  • black wire goes to GND

Panel Power

Plug either one of the four-conductor power plugs into the power connector pins on the panel. The plug can only go in one way, and that way is marked on the board's silkscreen.

Board Connection

Now, plug the board into the left side shrouded 8x2 connector as shown. The orientation matters, so take a moment to confirm that the white indicator arrow on the matrix panel is oriented pointing up and right as seen here and the MatrixPortal overhangs the edge of the panel when connected. This allows you to use the edge buttons from the front side.


Check nothing is impeding the board from plugging in firmly. If there's a plastic nub on the matrix that's keeping the Portal from sitting flat, cut it off with diagonal cutters

For info on adding LED diffusion acrylic, see the page LED Matrix Diffuser.

CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.

Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

Further Information

For more detailed info on installing CircuitPython, check out Installing CircuitPython.

Click the link above and download the latest UF2 file.

Download and save it to your desktop (or wherever is handy).

Plug your MatrixPortal M4 into your computer using a known-good USB cable.

A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.

Double-click the Reset button (indicated by the green arrow) on your board, and you will see the NeoPixel RGB LED (indicated by the magenta arrow) turn green. If it turns red, check the USB cable, try another USB port, etc.

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

You will see a new disk drive appear called MATRIXBOOT.


Drag the adafruit_circuitpython_etc.uf2 file to MATRIXBOOT.

The LED will flash. Then, the MATRIXBOOT drive will disappear and a new disk drive called CIRCUITPY will appear.

That's it, you're done! :)

To use all the amazing features of your MatrixPortal M4 with CircuitPython, you must first install a number of libraries. This page covers that process.

Adafruit CircuitPython Bundle

Download the Adafruit CircuitPython Library Bundle. You can find the latest release here:

Download the adafruit-circuitpython-bundle-version-mpy-*.zip bundle zip file, and unzip a folder of the same name. Inside you'll find a lib folder. The entire collection of libraries is too large to fit on the CIRCUITPY drive. Instead, add each library as you need it, this will reduce the space usage but you'll need to put in a little more effort.

At a minimum we recommend the following libraries, in fact we more than recommend. They're basically required. So grab them and install them into CIRCUITPY/lib now!

  • adafruit_matrixportal - this library is the main library used with the MatrixPortal.
  • adafruit_portalbase - This is the base library that adafruit_matrixportal is built on top of.
  • adafruit_esp32spi - this is the library that gives you internet access via the ESP32 using (you guessed it!) SPI transport. You need this for anything Internet
  • neopixel - for controlling the onboard neopixel
  • adafruit_bus_device - low level support for I2C/SPI
  • adafruit_requests - this library allows us to perform HTTP requests and get responses back from servers. GET/POST/PUT/PATCH - they're all in here!
  • adafruit_fakerequests.mpy  - This library allows you to create fake HTTP requests by using local files.
  • adafruit_io - this library helps connect the PyPortal to our free data logging and viewing service
  • adafruit_bitmap_font - we have fancy font support, and it's easy to make new fonts. This library reads and parses font files.
  • adafruit_display_text - not surprisingly, it displays text on the screen
  • adafruit_lis3dh - this library is used for the onboard accelerometer to detect the orientation of the MatrixPortal
Back up any existing code or files you want to keep from your Matrix Portal CIRCUITPY drive.

Most of the CircuitPython libraries used by this project were already recommended on the prior page…but there’s a couple extras needed as well. Here’s a complete list of all the prerequisite libraries…copy them into the lib folder on the CIRCUITPY drive:

  • adafruit_bitmap_font
  • adafruit_bus_device
  • adafruit_display_text
  • adafruit_esp32spi
  • adafruit_fakerequests
  • adafruit_io
  • adafruit_lis3dh.mpy
  • adafruit_matrixportal
  • adafruit_portalbase
  • adafruit_requests.mpy
  • neopixel.mpy

Now fetch the files for our Moon clock project from Github:

Unzip this file after downloading. Inside are two folders and one file: the fonts and moon folders and should be copied in the CIRCUITPY root directory. If you already have a fonts folder on your CIRCUITPY drive, copy the three .bdf files in there.

One additional file you’ll create or edit yourself — — is explained on the next page… holds your WiFi network credentials and other info. This file can be created or edited with any simple text editor you prefer.

If you already have this file on your Matrix Portal from prior projects…great!

If not, it should resemble what’s below, with the ssid and password lines. The corresponding values for these (after the colon) is in single-quotes.

The format of this file is super persnickety, every space and comma counts! If creating it for the first time, best to copy-and-paste the text below exactly, then change any items of interest (preserving quotation marks and such).

Latitude and longitude are optional but recommended. The clock can do IP geolocation (estimating your location using IP address), but having it here is more accurate and avoids another server query on startup. These values are floating-point numbers (in degrees and decimal fractions thereof) and should not be in quotes. For latitude, positive values are north, negative is south. For longitude, negative is west, positive is east.

secrets = {
    'ssid'      : 'WiFi-Network-Name',
    'password'  : 'WiFi-Network-Password',
    'latitude'  : 32.711956,
    'longitude' : -117.160838

You can easily get your decimal latitude and longitude from Google Maps. Zoom in on your location and click on the map. The nearest address (and street view if available) will pop up at the bottom of the map, the information there includes latitude and longitude in exactly the format we need…you can just copy and paste those into the secrets file. Update: you might need to right-click the location to get the geographic coordinates now.

The code will relaunch any time there’s a change on the CIRCUITPY drive…so, after editing, the clock should start up on its own and you’ll see a splash screen after a few seconds.

If the clock does NOT start up, or shows the splash screen but then crashes: most likely the WiFi credentials are incorrect, or something is wrong with the file syntax…make sure every quote, comma and colon is there and in the right place.

On power-up, the clock will display a splash screen while it connects to the WiFi network and makes a couple of initial server requests for time and Moon data.

Time is provided by WorldTimeAPI, and astronomical data from the Norwegian Meteorological Institute. These two sources were chosen as they are free and do not require an account for access.

The orientation of the clock at startup determines how information is displayed — in a vertical “portrait” format, or horizontal “landscape” format.

Clock Operation Basics

With the clock set up horizontally (either hung or propped up with a stand or case), the current Moon phase (with percentage lit) is displayed on the left.

The current time and date are displayed on the right. Below this is an indication of the next moonrise or set…

A downward-pointing arrow (as shown above) indicates the next lunar event will be a moonset — that the Moon is currently above the horizon (in the sky) as seen from your position, regardless of phase.

An upward-pointing arrow indicates a moonrise is next — the Moon is currently below the horizon, not currently visible from your position, regardless of phase.

The time shown next to the arrow is when this next lunar rise or set event will occur. It can alternately be configured as a countdown, explained shortly.

The color of the time and arrow indicates whether this next event occurs in the a.m. hours (green) or p.m. (amber).

The rise and set times are for an “idealized” horizon. Hills or other local obstructions could have it rising a short time later or setting earlier.

All the same data is displayed when the clock’s in a vertical orientation, but the visibility of the Moon from your location is made more apparent.

When the Moon is above the local horizon (in the sky) the phase is shown at the top of the matrix.

And if the Moon is currently below the local horizon, the phase scoots to the bottom.

The Moon might still appear above the horizon for someone to the west of you, but the phase will be nearly the same. That’s how this game of cosmic billiards works.

The percentage shown is the amount of the lunar “disc” that’s currently illuminated, not the “age” of the current lunar month. So this will go from 0% (new Moon) to 100%* (full Moon) and back down to 0% (next new Moon) over the course of the lunar month. The lunar terminator — the line between light and dark — always moves right to left, like turning the pages of a book (that’s why it doesn’t bother reporting if the phase is waxing or waning — it’s easy to visualize).

* It’s normal some months that you’ll see this only go to 99.8 or 99.9 percent…the Moon’s never quite perfectly full from our position.

If the clock starts up in the wrong orientation…just tap the reset button and let it try again. Occasionally the accelerometer gets confused when grappling the clock to plug it in, or the “snap” of a USB cable being inserted.

Customizing the Clock Display

Some aspects of the clock display can be changed by editing the file in your text editor of choice. Starting around line 35, look for this section of code:

# CONFIGURABLE SETTINGS -------------------------------------

TWELVE_HOUR = True # If set, use 12-hour time vs 24-hour
COUNTDOWN = False  # If set, show time to next rise/set event

Change the value of TWELVE_HOUR to False (capitalized — Python is case sensitive) to have the clock display times in 24-hour military time.

Changing COUNTDOWN to True makes the clock show the time to the next rise/set event (hours and minutes), rather than the time of the event. Both modes are shown in the same HH:MM format, so COUNTDOWN mode may be confusing if you’re not familiar with the clock’s operation.

The startup splash screen images are inside the moon folder, named splash-0.bmpsplash-90.bmpsplash-180.bmp and splash-270.bmp — one image is selected on startup based on the Matrix Portal orientation. If you’ve settled on a position for installing your Moon clock but want the opposite splash image, you can just rename these files, e.g. swap the filenames on splash-0.bmp and splash-180.bmp (or 90 and 270). Or you can delete the splash images (they might be frightening to children) or substitute your own BMP files.

Matrix brightness is not currently adjustable. It’s just more than the microcontroller can handle.


The clock will periodically contact a time server to keep itself in sync. But if you observe the time drifting by more than a minute or two, you can have it sync more often.

Look for these lines in (in the “MAIN LOOP” section):

# Sync with time server every ~12 hours
if NOW - LAST_SYNC > 12 * 60 * 60:

Change the 12 to a smaller value…perhaps 6, or 3 if the time drift is really pronounced. This is the period (in hours) between clock updates. To avoid over-taxing the server, which they’re providing as a free service, don’t set this too low.

Interestingly, the clock will keep better time if powered from a computer’s USB port (which provides a steady 1.000 KHz reference pulse) than from a passive USB “wall wart.” Not always practical, of course…but if you have a free USB port on a NAS or other nearby system that runs 24/7, it’s something to consider.

Image credit: Rogério da silva Santana, Wikipedia

So what's the big deal? What’s wrong with the Moon phases on wall calendars? Surely those dates come from trusted sources! NASA, Almanacs and stuff!

The problems are many…some technical, some semantic…each alone may be minor, but there’s the potential for them to compound and really mix things up.

  • Most importantly, unless they explain their data sources, static media can’t take into account different time zones. At any given moment, the Moon’s phase appears nearly the same from anywhere on Earth (if it’s above the local horizon), but the time of day…and even the day itself…may vary. If a calendar is basing their phases on UTC time but you’re in North America, they might be reporting a lunar phase on on a Thursday while to you it’s still late Wednesday (this can happen in the other direction too).
  • Each day’s changeover at midnight doesn’t align with our semantic concept of a “night” — we tend to lump early morning hours with the prior day. So, if a lunar phase crossing occurs in the early hours after midnight (for a given time zone), it might be reported as Thursday, while we’re inclined to think of it as late Wednesday night…but, seeing Thursday on the calendar, we think “Thursday night” and could easily end up celebrating a “full” Moon that’s past its ideal freshness date.
  • What even is “full,” or any other phase of the Moon? It’s erroneous to think there’s a single night that the Moon is locked in “full,” because this is an analog system with celestial bodies in continual motion, and phase can change by several percent in a single 24-hour period. To the unaided eye, anything more than about 98% illumination of the lunar disc is pretty much indistinguishable from “full,” and you’ll get two to three successive nights that would qualify. Those dates on the calendar typically refer to an “instantaneous” phase crossing (and once again, for whatever time zone they’re using for reference). If at that moment the Moon is below the horizon (is on the opposite side of the planet from you, due to the Earth’s rotation), and if your definition of “full” is too narrow…have you really experienced a full Moon at all? Sometimes it’s okay to think of a phase as “ish.”
  • Sometimes just sloppy reporting…the instantaneous time of a phase crossing is sometimes improperly reported as the Moon rise time instead, and other slip-ups.

As you can see, it’s A Huge Ordeal, and that was the inspiration for making this clock. No more “do they mean Wednesday night or Thursday morning?” This is the Moon as it is right now.

Other Moon Factoids

  • We tend to think of the Moon as a nighttime phenomenon, but really it spends just as much time on the daylight side. During a new Moon, it rises and sets close to the same time as the Sun, the narrow crescent lost in the glare of the daylight sky.
  • The cycle of phases — the “lunar month” — is about 29.5 days long. It varies a bit due to the elliptical nature of orbits and that the Earth-Moon system is in turn orbiting the Sun.
  • If you really want to get lost in all the details, NASA’s Dial-A-Moon page is packed with information and nuance!
  • A lunar eclipse can only happen during the full Moon, but not all full Moons experience a lunar eclipse … the orbital planes of the Earth and Moon diverge by a few degrees. Correspondingly, a solar eclipse can only happen during the new Moon, but not all new Moons experience a solar eclipse. (WolfCop got this wrong, with a solar eclipse the day after a full moon, and I’m still bitter about it.)
  • Some full moons have special names — a “blue Moon” is an infrequent second full Moon in the same month, the “pink Moon” is usually the full Moon in April — but these are only names and are not actually descriptive of the Moon’s color. Sometimes atmospheric phenomena (smoke, etc.) can cast the Moon in varying hues, but it’s entirely unrelated to these names.

This guide was first published on Sep 23, 2020. It was last updated on Sep 23, 2020.