Introduction: PyPortal Splatoon 2 Schedule Display

About: I like to make stuff.

Fun display of current and upcoming Splatoon 2 stages in Turf War and Ranked games, Ranked game type, and Salmon Run schedule using an Adafruit PyPortal. Cycle through the schedule by pressing on the touch screen. Backgrounds are randomly cycled for eye candy. The optional Amiibo stand is for Amiibotronics that spin Amiibos toward the screen when there are schedule changes.

The current stages are retrieved from made by @mattisenhower and time is synchronized from Adafruit IO.

This project is really easy if you just want to display the schedule on a PyPortal and use what I have. Basically you just have to update the configuration files for your network settings, Adafruit IO account information, and time zone.

The project gets slightly more involved if you want to customize further depending on how well you are with image programs and Python programming.

Adding the Amiibo animation is optional and will require quite a bit more of work with soldering and 3d printing.


The PyPortal is not as fast as your 1ms HDMI gaming monitor. The display takes a few seconds to finish drawing everything to the screen.



Optional Amiibtronic Build:

Step 1: Simple Portal Splatoon 2 Stages Display

Download the SplatSchedule project from GitHub. Create a in the src/conf directory with your information using the example in src/conf directory. Update in the same folder.

Create a backgrounds directory on the micro SD card at its root. Copy all bmp files from the project images directory into the backgrounds directory you just made. Insert the micro SD card into the PyPortal.

Install the SplatSchedule_[date].uf2 file from the firmware folder to the PyPortal by pressing the reset button on the back of the PyPortal twice quickly to open the Boot drive. Then copy the file over. The PyPortal will automatically reboot when the file is done copying. This firmware is CircuitPython 4.0.1 with the required Adafruit libraries built in.

Copy all files from the src directory onto your PyPortal and you should be good to go. The PyPortal should automatically reboot itself and startup.

The following are a quick explanation of the configuration files. - Each configuration should be self-explanatory. Replace SSID with your WiFi's SSID and so forth. You will need to grab your time zone from, eg. my time zone is Pacific/Honolulu.

# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it
# which would be not great. So, instead, keep it all in this one file and
# keep it a secret.

secrets = {
    'ssid': 'SSID',             # Keep the two '' quotes around the name
    'password': 'PWD',  # Keep the two '' quotes around password
    'timezone': "TIMEZONE",  # <a href="" target="_blank"></a>
    'aio_username': 'AIO_USERNAME',
    'aio_key': 'AIO_KEY',
    } - You only really need to update time_adjust to quickly get up and running. I didn't figure out a way to get that number timezone setting from so you will need convert your time zone adjustment into seconds. The rest of the settings should be self-explanatory.

configuration = {
    'battle_schedule_url': '',
    'salmon_schedule_url': '',
    'time_service': '',
    'time_service_strftime': '&fmt=%25Y-%25m-%25d+%25H%3A%25M%3A%25S.%25L+%25j+%25u+%25z+%25Z',
    # Adafruit IO strftime is %Y-%m-%d %H:%M:%S.%L %j %u %z %Z see for decoding details
    # See for full options

    'time_adjust': -36000,  # hours in seconds
    'touchscreen_touch_throttle': 2,
    'sd_mount_directory': '/sd',
    'background_images_directory': '/sd/backgrounds/',
    'background_timeout': 900,  # 900 = 15 minutes
    'schedule_change_timeout': 180,  # 180 = 3 minutes
    'schedule_refresh': 43200,  # 43200 = 12 hours

    # If you built the turntable stage, set to True
    'enable_turntable': False,

    # The follow are optional and used for testing and debuggin
    # 'debug': False,
    # 'disable_wifi': False,
    # 'use_test_files': False,
    # 'test_battle_schedule_file': '/test_battle_schedule.json',
    # 'test_salmon_schedule_file': '/test_salmon_schedule.json'

That's all there is to getting a PyPortal Splatoon 2 Schedule display. Read on if you want to customize a background and/or tweak text placement.

Step 2: Background Customization

Included in the SplatSchedule project is a GIMP project file used to create the backgrounds. Use this as an example if you like using GIMP. Or use your favorite image editor to make backgrounds. Follow some of the guidelines below to help you make backgrounds that are displayable.

The stage backgrounds were grabbed from Inkipedia.

As mentioned earlier, the PyPortal is not fast at rendering the display. To help cut down on what the PyPortal has to process, place static text on the background.

Backgrounds must be 320x240 pixels in size and in bitmap format. I saved the backgrounds in 24-bit format as 16-bit looked horrible and 32-bit had a blue tinge to them.

That is pretty much it for backgrounds. The next step describes text font and placement.

Step 3: Font Customization

Read Custom Fonts for CircuitPython Displays for creating your own custom fonts.

I used fonts from @frozenpandaman found at

Place fonts according to the directory specified in in the src/conf directory. The default location is in /fonts/.

Update for which font to use, color, and placement coordinate for text. - Should be self-explanatory.

configuration = {
    'fonts_directory': '/fonts/',

    # text: (font, color, (x, y))
    'text_battle_time_slot': ('Splatoon2-18.bdf', 0xFFFFFF, (10, 18)),
    'text_battle_regular_stage_a': ('Splatoon2-18.bdf', 0xFFFFFF, (65, 66)),
    'text_battle_regular_stage_b': ('Splatoon2-18.bdf', 0xFFFFFF, (65, 86)),
    'text_battle_ranked_rule_name': ('Splatoon2-24.bdf', 0xF54910, (65, 108)),
    'text_battle_ranked_stage_a': ('Splatoon2-18.bdf', 0xFFFFFF, (65, 129)),
    'text_battle_ranked_stage_b': ('Splatoon2-18.bdf', 0xFFFFFF, (65, 149)),
    'text_salmon_time_slot': ('Splatoon2-18.bdf', 0xFFFFFF, (65, 191)),
    'text_salmon_stage': ('Splatoon2-18.bdf', 0xFFFFFF, (65, 211))


Try not to use more than 3 fonts for the issues noted below.

Use your image editor to help you find the coordinates of where you want to place text so that you are not just wildly guessing. Usually the pointer tool of image editing software will have its x and y coordinates displayed somewhere in the editor, most of the time in the status bar.


The more fonts you use, the longer the PyPortal takes to startup as all the fonts used are loaded up during setup.

Bitmap fonts take up lots of space and will eat into PyPortal's onboard storage space.

You can create a fonts directory on the micro SD card and point there (eg. /sd/fonts/), but I've run into a weird problem where the same font will run from the onboard storage but not work from the micro SD card. I could not resolve what the issue was about loading from an SD card.

Step 4: Read on to Build Amiibtronics Display

The next bunch of steps are for building the DJ Turntable Amiibotronic stage display.

You can stop here if you just want the PyPortal for displaying the Splatoon 2 schedules.

Step 5: PyPortal I2C 3.3V

I found the onboard Real Time Clock (RTC) stops ticking if you connect a 5V I2C device. I think this is due to the RTC has pull-ups to 3.3V. Then adding a 5V I2C device that has its own pull-ups to 5V throws off the RTC.

There is a jumper near the ports on the side of the PyPortal to select the voltage output ports. See Adafruit Pinouts for reference.

Cut/scrape away the little itty bitty trace connecting the center pad to the 5V pad. ***Important*** Cut/scrape away from the ribbon cable!

Use a multi-meter to check that there is no continuity between the center pad and 5V pad. Also check that the port voltage pin has no continuity to the 5V pad.

Solder a little solder bridge from the center pad to the 3V pad.

Use a multi-meter to check the continuity of the center pad to the 3V pad. Check that there is no inadvertent connection with the 5V pad too.

Step 6: Power Connector - Wiring PyPortal

We will power the PyPortal by connecting directly to the 5V bus instead of using the PyPortal's micro USB port.

The wire that comes with the JST RCY connector is too big to squeeze through the Adafruit PyPortal enclosure. You will need to solder smaller 24AWG wire to the PyPortal and then to the JST RCY connector. Use the conventional colors of red for positive and black for ground for the wires.

Strip and tin the ends of the 24AWG wires. Snip the end to just the size of the 5V solder pad (the pad we just disconnected in the previous step).

Tin the 5V pad and solder the red wire to the pad. Then carefully bend the wire to go between the I2C port and D3 port.

Tin the ground pin of the D3 port (the top pin) and solder the black wire to it. Bend this wire to follow the red wire.

Step 7: Power Connector - Adding Connector End

Trim the wires attached to the male end of the JST RCY to a reasonable length, like an inch or two. I chose the male end to make the connector consistent with the side ports.

Slip on head shrink tubing on the wires before solder splicing them together.

Solder the connector wires to the wires we soldered in the previous step.

Shrink the tubing into place.

Step 8: Disconnect Onboard Speaker

We will connect external speakers and need to disconnect the onboard speaker. See Speaker and Speaker Connector for reference.

There are two solder pads connected by an itty bitty trace to the left of the onboard speaker. Cut/scrape away that tiny little trace.

Use a multi-meter to check that the two pads are no longer connected to eachother.

Step 9: Speaker Pigtail Connector

The speaker connector is a pain to get to when the PyPortal enclosure is on. We will make a connector pigtail so that we can easily connect/disconnect external speakers.

Solder a male 2-Pin JST PH connector to the end of a female Molex Picoblade connector. Make sure you have the wires soldered to the correct terminal for the matching female JST PH connector.

The smallest shrink tubing I had was still too big so I ended up hot gluing the tubing to the male connector.

Step 10: Assemble Adafruit's PyPortal Enclosure

Assemble the acrylic PyPortal enclosure according to the enclosure's instructions.

The power plug should be able to fit out of the side.

Attach the speaker pigtail connector we made earlier. Do this now as trying to connect this later will be difficult.

Step 11: PCA9685 Wire Harness - Rearrange 4-Pin JST PH Connector Wires

You can skip this step if you are fine with the color order of wires on your wired female 4-pin JST PH connector.

I used a hobby knife to lift the locking tab and slide out the wires. I rearranged the colors to match the voltage pinout of the PyPortal.

I could have left the white and yellow wire alone but I like yellow as SCL since yellow and SCL have the letter 'L' in them.

The order of color is black, red, white, and yellow (GND, VCC, SDA, SCL).

The top pin is the ground pin, so make sure when you attach the connector to the PyPortal the ground wire is connected to the top pin.

Step 12: PCA9685 Wire Harness - 6P Dupont Connector End

Strip the ends of the wired female 4-pin JST PH connector.

Crimp female DuPont connectors to the end.

Insert the wires in the correct order to match the header on the PCA9685 module.

The order I have is GND, skip, SCL, SDA, VCC, skip.

Step 13: PCA9685 Wire Harness - Rearrange 4-Pin JST PH Connector Wires

As with the earlier step, rearrange the wire colors of the wired 3-pin JST PH connector to match the pins of the PyPortal 3-pin ports. The order from top down is GND, VCC, D3.

On the opposite end of the connector crimp female DuPont connectors.

We won't be using the GND and VCC wires but put them in a 2P case, just incase for future use.

Step 14: PCA9685 Wire Harness - Connect 3-Pin JST PH Wire to 6P Dupont Connector

Insert the D3 signal wire from the wired female 3-pin JST PH connector from the previous step into the 6P DuPont connector from an earlier step.

The wire should connect between GND and SCL.

Step 15: Print Amiibotronic Display Parts

Download PyPortal Splatoon 2 Stage 3D files from Thingiverse.

Print the STL files.

Description of the files:

  • PyPortalSplatoonStage.stl - Bottom part of the display to hold the electronics, servos and speakers.
  • PyPortalSplatoonRiser.stl - Piece to raise the PyPortal to the reasonable height that matches the Amiibos.
  • PyPortalSplatoonTurnTableBottom.stl - Bottom of the turn table that interfaces with the servo horn for turning. I tried making the turn table one piece but the recess for the servo horn doesn't come out so well even with print support.
  • PyPortalSplatoonTurnTableTop.stl - Top part of the turn table since I split the turn table into two pieces.

I should've printed the stage in white had I known my kids were gonna plaster their Splatoon stickers on it. I picked gray because that's what DJ turn tables usually come in from what I have seen.

I also printed with supports but you really don't need to for the stage speaker holes.

Step 16: Tap USB Mounting

Use a 4-40 bottom tap to thread the USB breakout board mount. The mount is the little block with 2 holes.

Use a sharp hobby knife to cut away plastic runout.

Step 17: Tap Servo Mount

Use the mounting screws that are packaged with the MG90S servos to "tap" threads into the servo mounting blocks. Well this is more like grooving the holes for the screws.

Cut out any runout if that happens.

Step 18: Tap Riser

Use a 4-40 tap to cut threads into the 4 riser screw holes on the bottom.

Use a hobby knife to cutaway runout.

Step 19: Mount USB Power Port

Use 1/4" 4-40 screws to hold down the USB breakout board.

Step 20: Mount PCA9685 Module

There are 4 holes in the center of the stage that line up with the mounting holes of the PCS9685 module. Use those holes for 12mm M2.5 screws, 6mm nylon standoffs, washers and nuts. I only had 6mm on hand but any height standoff will work as long as you have long enough screws.

I did not incorporate standoffs into the print because the header pins on the bottom are too close to the mounting holes. There is not enough space to reliably print a standoff with thick enough wall that would not interfere with the bottom of the header.

Step 21: Mount Servos

Mount the servos into the servo mounts. The servos only fit one way with the wires facing the center of the stage.

Connect the servos to the PCA9685 module. Connect the left servo when looking at the bottom to port 0 and the right servo to port 1.

Ensure the servos are correctly wired to the PCA9685 module, the colors of the servo wires should match up with the module (black/brown for ground).

Step 22: Prepare Servo Horn

The servo horns are not flat on top and need to be level to fit properly into the turntable bottoms.

Use sandpaper to flatten the top of the double sided servo horn. You'll know when it is flat when all the shininess is gone.

Step 23: Mount Turntable Amiibo Holder

Place the servo horn onto the servo. The orientation of the horn does not matter.

Place the turntable bottom onto the servo horn. The servo horn should fit nicely into the recess on the bottom of the turntable.

Place the turntable top on top and screw into place with an 8mm M2 screw.

Repeat for the second servo.

You could crazy glue the turntable pieces together if you wish. I didn't since my tube of glue dried out. Turntable still works without it.

Step 24: Mount Speakers

Use 10mm M3 screws, washers and nuts to mount the speakers in place.

The wires should be facing toward the sides.

I'll admit, I had a hard time getting the nuts on the inside of the screws near the top of the stage. What helped is having a bent nose needle pliers to hold the nuts in place while screwing.

Step 25: Tie Down PyPortal

I liked the look of the Adafruit PyPortal Desktop Stand Enclosure Kit and figured just cable tie the PyPortal to the riser.

The enclosure legs should fit in the grooves on the top of the riser. The fit is not a tight fit and may have some wiggle room but that won't matter.

Insert cable ties in the rear slots of the riser. The rear of the riser is near the oval opening. Do not tight the ties all the way yet, leave room for the legs of the enclosure to slide in.

Slip the enclosure legs into the loops.

Tighten the cable ties to hold the enclosure legs in place. Do not overtighten.

There are slits towards the front of the riser if you want to tie down the front'ish side of the legs. You'll need to chain the cable ties to reach around. I found that I didn't need to do this as the two cable ties in the back were sufficient to hold the PyPortal in place.

Step 26: PCA9685 Power Connection

Use wires to connect VCC and GND from the USB breakout board to the PCA9685 module. Stick to convention and use red for VCC and black for GND.

Strip and tin one side of the wires. Trim the tinned end to the size of the solder pad of the USB breakout board.

Solder the wires to the USB breakout board.

Strip the other end of the wires and insert them into the screw terminal block of the PCA9685 module. Make sure VCC from the USB goes to the VCC of the terminal block.

Step 27: PyPortal Power Connector

Solder on the JST RCY connector to the USB break out.

Strip and tin the ends of the wires if needed. Mine came stripped and tinned so could just solder into place.

Step 28: Speaker Connector

Trim the speaker wires as they are quite long. I trimmed mine down to about 5 to 6 inches (you could go shorter since attaching a wired connector).

The speakers are 4-ohms each and the PyPortal works with 8-ohm speakers. You will have to wire the speakers in series so that the PyPortal sees 8-ohms.

Solder one speaker's black wire to the other speaker's red wire. Don't forget to slip on heat shrink tubing first.

Then solder a wired female 2-pin JST PH connector to the remaining speaker wires. Chances are the wires of the connector will be red and black too, so just match those up. Also, the colors should match with the colors of the picoblade molex connector pigtail we made earlier.

Step 29: Attach PyPortal Riser

Place the riser with the PyPortal on top of the stage.

Use 1/2" 4-40 screws and washers to hold the riser from an earlier step to the top of the stage.

Ensure that the slot on the riser lines up with the slot on the stage before screwing down.

Step 30: Connect 6P DuPont Connector Harness

Connect the 6P DuPont Connector Harness we made earlier to the PCA9685 module. Make sure the connector connects the correct wires to the module.

Step 31: Connect the Connectors

Push up the JST PH and RCY connectors through the slot next to the PCA9685 module and out through the riser up top.

Connect the female connectors to their respective male connector.

Pull down wire slack into the stage to make the backside of the PyPortal nice and tidy.

Step 32: Organize Wires

The wires in the stage will be a mess.

Bunch up your wires nicely together and hold them together with something.

I used Velcro wrap. The wrap is wide that you can cut in half down the middle and make skinnier straps.

Step 33: Decorate

I didn't plan for this step. My kids had a sticker book and plastered some stickers on it. Had I known, I would've printed the stage in white to match the outline of the splatter sticker. I still like it, I think they did a nice job of decorating.

Step 34: Thank You

That is it for the project. Hookup a USB cable and attach to a USB power supply. I hope you enjoyed this Instructable. Thank you for reading it.

I would also like to thank the following:

Adafruit for Adafruit IO

@mattisenhower for Splatoon that provides the schedule data

@frozenpandaman for the Splatoon Fonts

Fandom Contest

Participated in the
Fandom Contest