-
-
Save tdicola/2c42bfe534838b3c159c1b3cc3e58ac8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SSD1306 Sine Wave Message scroller | |
# This animates a message scrolling across a SSD1306 display in a sine wave. | |
# Currently written for SAMD21 MicroPython, but adjust how the I2C bus is | |
# defined to work with other ports. | |
# Author: Tony DiCola | |
# License: Public Domain | |
import machine | |
import math | |
import ssd1306 | |
import time | |
# Configure message that will scroll. | |
MESSAGE = 'Hello world this is a fun scroller!' | |
# Other configuration: | |
DISPLAY_WIDTH = 128 # Width of display in pixels. | |
DISPLAY_HEIGHT = 32 # Height of display in pixels. | |
FONT_WIDTH = 8 # Width of font characters in pixels. | |
FONT_HEIGHT = 8 # Height of the font characters in pixels. | |
AMPLITUDE = DISPLAY_HEIGHT - FONT_HEIGHT # Amplitude of sine wave, in pixels. | |
FREQUENCY = 2 # Sine wave frequency, how often it repeats across screen. | |
def main(i2c): | |
# Global state: | |
oled = ssd1306.SSD1306_I2C(DISPLAY_WIDTH, DISPLAY_HEIGHT, i2c) | |
pos = DISPLAY_WIDTH # X position of the starting character in the message. | |
message_len_px = len(MESSAGE) * FONT_WIDTH # Pixel width of the message. | |
# Build a lookup table of wavy Y positions for each column. This will speed | |
# up the main loop by not constantly computing Y positions. Remember characters | |
# can be drawn off screen to the left so increase the lookup table a bit to | |
# compute their Y positions too. | |
lookup_y = [0] * (DISPLAY_WIDTH+FONT_WIDTH) | |
for i in range(len(lookup_y)): | |
t = i / (DISPLAY_WIDTH-1) # Compute current 'time' as position along | |
# lookup table in 0 to 1 range. | |
# Use a sine wave that's offset to the range 0 to AMPLITUDE to compute | |
# each character Y position at a given X. | |
lookup_y[i] = int(((AMPLITUDE/2.0) * math.sin(2.0*math.pi*FREQUENCY*t)) + (AMPLITUDE/2.0)) | |
# Main loop: | |
while True: | |
# Clear the screen. | |
oled.fill(0) | |
# Move left a bit, then check if the entire message has scrolled past | |
# and start over from far right. | |
pos -= 1 | |
if pos <= -message_len_px: | |
pos = DISPLAY_WIDTH | |
# Go through each character in the message. | |
for i in range(len(MESSAGE)): | |
char = MESSAGE[i] | |
char_x = pos + (i * FONT_WIDTH) # Character's X position on the screen. | |
if -FONT_WIDTH <= char_x < DISPLAY_WIDTH: | |
# Character is visible, draw it. | |
# Look up the Y position in the previously computed lookup table. | |
# Remember the lookup table spans from all visible pixels and | |
# an extra FONT_WIDTH number of pixels on the left (so offset | |
# a bit when indexing into the table). | |
oled.text(char, char_x, lookup_y[char_x+FONT_WIDTH]) | |
oled.show() | |
# Run main function but first initialize I2C (with context manager to deinit). | |
with machine.I2C(machine.Pin('SCL'), machine.Pin('SDA')) as i2c: | |
main(i2c) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment