diff --git a/micropython/examples/tufty2040/battery.py b/micropython/examples/tufty2040/battery.py new file mode 100644 index 00000000..c881c262 --- /dev/null +++ b/micropython/examples/tufty2040/battery.py @@ -0,0 +1,81 @@ +# This example reads the voltage from a battery connected to Tufty 2040 +# and uses this reading to calculate how much charge is left in the battery. + +from picographics import PicoGraphics, DISPLAY_TUFTY_2040 +from machine import ADC, Pin +import time + +display = PicoGraphics(display=DISPLAY_TUFTY_2040) + +display.set_backlight(0.8) + +# set up the ADCs for measuring battery voltage +vbat_adc = ADC(29) +vref_adc = ADC(28) +vref_en = Pin(27) +vref_en.init(Pin.OUT) +vref_en.value(0) +usb_power = Pin(24, Pin.IN) # reading GP24 tells us whether or not USB power is connected + +# Reference voltages for a full/empty battery, in volts +# the values could vary by battery size/manufacturer so you might need to adjust them +# Values for a Galleon 400mAh LiPo: +full_battery = 3.7 +empty_battery = 2.5 + +# set up some colours to draw with +WHITE = display.create_pen(255, 255, 255) +BLACK = display.create_pen(0, 0, 0) +GREY = display.create_pen(190, 190, 190) +GREEN = display.create_pen(0, 255, 0) +RED = display.create_pen(255, 0, 0) + +display.set_font("bitmap8") + +while True: + # The voltage reference on Tufty means we can measure battery voltage precisely, even when batteries are low. + # Enable the onboard voltage reference + vref_en.value(1) + + # Calculate the logic supply voltage, as will be lower that the usual 3.3V when running off low batteries + vdd = 1.24 * (65535 / vref_adc.read_u16()) + vbat = ( + (vbat_adc.read_u16() / 65535) * 3 * vdd + ) # 3 in this is a gain, not rounding of 3.3V + + # Disable the onboard voltage reference + vref_en.value(0) + + # Print out the voltage + print("Battery Voltage = ", vbat, "V", sep="") + + # convert the raw ADC read into a voltage, and then a percentage + percentage = 100 * ((vbat - empty_battery) / (full_battery - empty_battery)) + if percentage > 100: + percentage = 100 + if percentage < 0: + percentage = 0 + + # draw the battery outline + display.set_pen(BLACK) + display.clear() + display.set_pen(GREY) + display.rectangle(0, 0, 220, 135) + display.rectangle(220, 40, 20, 55) + display.set_pen(WHITE) + display.rectangle(3, 3, 214, 129) + + # draw a green box for the battery level + display.set_pen(GREEN) + display.rectangle(5, 5, int((210 / 100) * percentage), 125) + + # add text + display.set_pen(RED) + if usb_power.value() == 1: # if it's plugged into USB power... + display.text("USB power!", 15, 90, 240, 4) + + display.text('{:.2f}'.format(vbat) + "v", 15, 10, 240, 5) + display.text('{:.0f}%'.format(percentage), 15, 50, 240, 5) + + display.update() + time.sleep(0.5) diff --git a/micropython/examples/tufty2040/buttons.py b/micropython/examples/tufty2040/buttons.py new file mode 100644 index 00000000..e17ef0cc --- /dev/null +++ b/micropython/examples/tufty2040/buttons.py @@ -0,0 +1,76 @@ +# This example shows you a simple, non-interrupt way of reading Tufty 2040's buttons with a loop that checks to see if buttons are pressed. + +import time +from pimoroni import Button +from picographics import PicoGraphics, DISPLAY_TUFTY_2040 + +display = PicoGraphics(display=DISPLAY_TUFTY_2040) + +display.set_backlight(1.0) +display.set_font("bitmap8") + +button_a = Button(7, invert=False) +button_b = Button(8, invert=False) +button_c = Button(9, invert=False) +button_up = Button(22, invert=False) +button_down = Button(6, invert=False) + +WHITE = display.create_pen(255, 255, 255) +BLACK = display.create_pen(0, 0, 0) +TEAL = display.create_pen(0, 255, 255) +MAGENTA = display.create_pen(255, 0, 255) +YELLOW = display.create_pen(255, 255, 0) +RED = display.create_pen(255, 0, 0) +GREEN = display.create_pen(0, 255, 0) + +WIDTH, HEIGHT = display.get_bounds() + +while True: + if button_a.is_pressed: # if a button press is detected then... + display.set_pen(BLACK) # set pen to black + display.clear() # clear display to the pen colour + display.set_pen(WHITE) # change the pen colour + display.text("Button A pressed", 10, 10, WIDTH - 10, 3) # display some text on the screen + display.update() # update the display + time.sleep(1) # pause for a sec + + elif button_b.is_pressed: + display.set_pen(BLACK) + display.clear() + display.set_pen(TEAL) + display.text("Button B pressed", 10, 10, WIDTH - 10, 3) + display.update() + time.sleep(1) + + elif button_c.is_pressed: + display.set_pen(BLACK) + display.clear() + display.set_pen(MAGENTA) + display.text("Button C pressed", 10, 10, WIDTH - 10, 3) + display.update() + time.sleep(1) + + elif button_up.is_pressed: + display.set_pen(BLACK) + display.clear() + display.set_pen(YELLOW) + display.text("Button up pressed", 10, 10, WIDTH - 10, 3) + display.update() + time.sleep(1) + + elif button_down.is_pressed: + display.set_pen(BLACK) + display.clear() + display.set_pen(GREEN) + display.text("Button down pressed", 10, 10, WIDTH - 10, 3) + display.update() + time.sleep(1) + + else: + display.set_pen(BLACK) + display.clear() + display.set_pen(RED) + display.text("Press any button!", 10, 10, WIDTH, 3) + display.update() + + time.sleep(0.1) # this number is how frequently Tufty checks for button presses diff --git a/micropython/examples/tufty2040/pride_badge.py b/micropython/examples/tufty2040/pride_badge.py new file mode 100644 index 00000000..b50237fa --- /dev/null +++ b/micropython/examples/tufty2040/pride_badge.py @@ -0,0 +1,90 @@ +# A name badge with customisable Pride flag background. + +from picographics import PicoGraphics, DISPLAY_TUFTY_2040 + +display = PicoGraphics(display=DISPLAY_TUFTY_2040) + +WIDTH, HEIGHT = display.get_bounds() + +# List of available pen colours, add more if necessary +RED = display.create_pen(209, 34, 41) +ORANGE = display.create_pen(246, 138, 30) +YELLOW = display.create_pen(255, 216, 0) +GREEN = display.create_pen(0, 121, 64) +INDIGO = display.create_pen(36, 64, 142) +VIOLET = display.create_pen(115, 41, 130) +WHITE = display.create_pen(255, 255, 255) +PINK = display.create_pen(255, 175, 200) +BLUE = display.create_pen(116, 215, 238) +BROWN = display.create_pen(97, 57, 21) +BLACK = display.create_pen(0, 0, 0) +MAGENTA = display.create_pen(255, 33, 140) +CYAN = display.create_pen(33, 177, 255) + +# Uncomment one of these to change flag +# If adding your own, colour order is left to right (or top to bottom) +COLOUR_ORDER = [RED, ORANGE, YELLOW, GREEN, INDIGO, VIOLET] # traditional pride flag +# COLOUR_ORDER = [BLACK, BROWN, RED, ORANGE, YELLOW, GREEN, INDIGO, VIOLET] # Philadelphia pride flag +# COLOUR_ORDER = [BLUE, PINK, WHITE, PINK, BLUE] # trans flag +# COLOUR_ORDER = [MAGENTA, YELLOW, CYAN] # pan flag +# COLOUR_ORDER = [MAGENTA, VIOLET, INDIGO] # bi flag + +# Change this for vertical stripes +STRIPES_DIRECTION = "horizontal" + +# Change details here! Works best with a short, one word name +NAME = "Hel" +PRONOUNS = "She/they" + +# Change the colour of the text (swapping these works better on a light background) +TEXT_COLOUR = WHITE +DROP_SHADOW_COLOUR = BLACK + +# Draw the flag +if STRIPES_DIRECTION == "horizontal": + stripe_width = round(HEIGHT / len(COLOUR_ORDER)) + for x in range(len(COLOUR_ORDER)): + display.set_pen(COLOUR_ORDER[x]) + display.rectangle(0, stripe_width * x, WIDTH, stripe_width) + +if STRIPES_DIRECTION == "vertical": + stripe_width = round(WIDTH / len(COLOUR_ORDER)) + for x in range(len(COLOUR_ORDER)): + display.set_pen(COLOUR_ORDER[x]) + display.rectangle(stripe_width * x, 0, stripe_width, HEIGHT) + +# Set a starting scale for text size. +# This is intentionally bigger than will fit on the screen, we'll shrink it to fit. +name_size = 20 +pronouns_size = 20 + +# These loops adjust the scale of the text until it fits on the screen +while True: + display.set_font("bitmap8") + name_length = display.measure_text(NAME, name_size) + if name_length >= WIDTH - 20: + name_size -= 1 + else: + # comment out this section if you hate drop shadow + DROP_SHADOW_OFFSET = 5 + display.set_pen(DROP_SHADOW_COLOUR) + display.text(NAME, int((WIDTH - name_length) / 2 + 10) - DROP_SHADOW_OFFSET, 10 + DROP_SHADOW_OFFSET, WIDTH, name_size) + + # draw name and stop looping + display.set_pen(TEXT_COLOUR) + display.text(NAME, int((WIDTH - name_length) / 2 + 10), 10, WIDTH, name_size) + break + +while True: + display.set_font("bitmap8") + pronouns_length = display.measure_text(PRONOUNS, pronouns_size) + if pronouns_length >= WIDTH - 60: + pronouns_size -= 1 + else: + # draw pronouns and stop looping + display.set_pen(TEXT_COLOUR) + display.text(PRONOUNS, int((WIDTH - pronouns_length) / 2), 175, WIDTH, pronouns_size) + break + +# Once all the adjusting and drawing is done, update the display. +display.update() diff --git a/micropython/examples/tufty2040/retro_badge.py b/micropython/examples/tufty2040/retro_badge.py new file mode 100644 index 00000000..5f3ff12f --- /dev/null +++ b/micropython/examples/tufty2040/retro_badge.py @@ -0,0 +1,152 @@ +# A retro badge with photo and QR code. +# Copy your image to your Tufty alongside this example - it should be a 120 x 120 jpg. + +from picographics import PicoGraphics, DISPLAY_TUFTY_2040 +from pimoroni import Button +import time +import jpegdec +import qrcode + +display = PicoGraphics(display=DISPLAY_TUFTY_2040) +button_c = Button(9, invert=False) + +WIDTH, HEIGHT = display.get_bounds() + +# Uncomment one of these four colour palettes - find more at lospec.com ! +# Nostalgia colour palette by WildLeoKnight - https://lospec.com/palette-list/nostalgia +LIGHTEST = display.create_pen(208, 208, 88) +LIGHT = display.create_pen(160, 168, 64) +DARK = display.create_pen(112, 128, 40) +DARKEST = display.create_pen(64, 80, 16) + +# 2bit Demichrome colour palette by Space Sandwich - https://lospec.com/palette-list/2bit-demichrome +# LIGHTEST = display.create_pen(233, 239, 236) +# LIGHT = display.create_pen(160, 160, 139) +# DARK = display.create_pen(85, 85, 104) +# DARKEST = display.create_pen(33, 30, 32) + +# CGA PALETTE 1 (HIGH) - https://lospec.com/palette-list/cga-palette-1-high +# LIGHTEST = display.create_pen(255, 255, 255) +# LIGHT = display.create_pen(85, 254, 255) +# DARK = display.create_pen(255, 85, 255) +# DARKEST = display.create_pen(0, 0, 0) + +# Change your badge and QR details here! +COMPANY_NAME = "sciurus cybernetics" +NAME = "M. 'TuFTy'" +BLURB1 = "RP2040 plus 320x240 TFT LCD" +BLURB2 = "Nuts From Trees collector" +BLURB3 = "Will work for peanuts" + +QR_TEXT = "pimoroni.com/tufty2040" + +IMAGE_NAME = "squirrel.jpg" + +# Some constants we'll use for drawing +BORDER_SIZE = 4 +PADDING = 10 +COMPANY_HEIGHT = 40 + + +def draw_badge(): + # draw border + display.set_pen(LIGHTEST) + display.clear() + + # draw background + display.set_pen(DARK) + display.rectangle(BORDER_SIZE, BORDER_SIZE, WIDTH - (BORDER_SIZE * 2), HEIGHT - (BORDER_SIZE * 2)) + + # draw company box + display.set_pen(DARKEST) + display.rectangle(BORDER_SIZE, BORDER_SIZE, WIDTH - (BORDER_SIZE * 2), COMPANY_HEIGHT) + + # draw company text + display.set_pen(LIGHT) + display.set_font("bitmap6") + display.text(COMPANY_NAME, BORDER_SIZE + PADDING, BORDER_SIZE + PADDING, WIDTH, 3) + + # draw name text + display.set_pen(LIGHTEST) + display.set_font("bitmap8") + display.text(NAME, BORDER_SIZE + PADDING, BORDER_SIZE + PADDING + COMPANY_HEIGHT, WIDTH, 5) + + # draws the bullet points + display.set_pen(DARKEST) + display.text("*", BORDER_SIZE + PADDING + 120 + PADDING, 105, 160, 2) + display.text("*", BORDER_SIZE + PADDING + 120 + PADDING, 140, 160, 2) + display.text("*", BORDER_SIZE + PADDING + 120 + PADDING, 175, 160, 2) + + # draws the blurb text (4 - 5 words on each line works best) + display.set_pen(LIGHTEST) + display.text(BLURB1, BORDER_SIZE + PADDING + 135 + PADDING, 105, 160, 2) + display.text(BLURB2, BORDER_SIZE + PADDING + 135 + PADDING, 140, 160, 2) + display.text(BLURB3, BORDER_SIZE + PADDING + 135 + PADDING, 175, 160, 2) + + +def show_photo(): + j = jpegdec.JPEG(display) + + # Open the JPEG file + j.open_file(IMAGE_NAME) + + # Draws a box around the image + display.set_pen(DARKEST) + display.rectangle(PADDING, HEIGHT - ((BORDER_SIZE * 2) + PADDING) - 120, 120 + (BORDER_SIZE * 2), 120 + (BORDER_SIZE * 2)) + + # Decode the JPEG + j.decode(BORDER_SIZE + PADDING, HEIGHT - (BORDER_SIZE + PADDING) - 120) + + # Draw QR button label + display.set_pen(LIGHTEST) + display.text("QR", 240, 215, 160, 2) + + +def measure_qr_code(size, code): + w, h = code.get_size() + module_size = int(size / w) + return module_size * w, module_size + + +def draw_qr_code(ox, oy, size, code): + size, module_size = measure_qr_code(size, code) + display.set_pen(LIGHTEST) + display.rectangle(ox, oy, size, size) + display.set_pen(DARKEST) + for x in range(size): + for y in range(size): + if code.get_module(x, y): + display.rectangle(ox + x * module_size, oy + y * module_size, module_size, module_size) + + +def show_qr(): + display.set_pen(DARK) + display.clear() + + code = qrcode.QRCode() + code.set_text(QR_TEXT) + + size, module_size = measure_qr_code(HEIGHT, code) + left = int((WIDTH // 2) - (size // 2)) + top = int((HEIGHT // 2) - (size // 2)) + draw_qr_code(left, top, HEIGHT, code) + + +# draw the badge for the first time +badge_mode = "photo" +draw_badge() +show_photo() +display.update() + +while True: + if button_c.is_pressed: + if badge_mode == "photo": + badge_mode = "qr" + show_qr() + display.update() + else: + badge_mode = "photo" + draw_badge() + show_photo() + display.update() + time.sleep(1) diff --git a/micropython/examples/tufty2040/squirrel.jpg b/micropython/examples/tufty2040/squirrel.jpg new file mode 100644 index 00000000..8d1b2c9e Binary files /dev/null and b/micropython/examples/tufty2040/squirrel.jpg differ