Tufty 2350 Documentation

And boom it is working, I believe the problem I had were it seemed bricked was because those two were actually touching at the time.

Just got the Tufty Stem kit and got a few of the basic apps to run just fine, even editing much of the code etc. But now I’m at the stage where I want to hook up the sensor stick or the controller, but I’m at a loss now with no supporting docs. There is some for them separately, but not sure how to integrate into Tufty scripts. Half the fun is finding out though!

Much as I dislike using AI it is pretty good with Python and MicroPython. I asked and got this back:

These are results for Pimoroni sensor stick Micropython example

AI Overview

The Pimoroni Multi-Sensor Stick contains three main I2C sensors: the BME280 (Temperature, Pressure, Humidity), LTR559 (Light and Proximity), and LSM6DS3 (Accelerometer and Gyroscope).

To run a MicroPython script, you’ll first need to download Pimoroni’s custom MicroPython UF2 file from the Pimoroni Pico GitHub and flash your Raspberry Pi Pico.

imageGitHub +2

BME280 & LTR559 Sensor Readings

The Pimoroni MicroPython firmware has built-in drivers for the BME280 and LTR559. You can read environmental and light data with the following example script:

Pimoroni

python

import time
from machine import Pin, I2C
from breakout_bme280 import BreakoutBME280
from breakout_ltr559 import BreakoutLTR559

# Set up I2C and initialize sensors
i2c = I2C(0, scl=Pin(5), sda=Pin(4))
bme = BreakoutBME280(i2c)
ltr = BreakoutLTR559(i2c)

while True:
    # Read environment, light, and proximity data
    temp, press, hum = bme.read()
    prox, _, _, _, _, _, lux = ltr.get_reading()
    
    print(f"Temp: {temp:.2f}C | Pres: {press/100:.2f}hPa | Hum: {hum:.2f}% | Lux: {lux}")
    time.sleep(1.0)

Use code with caution.

LSM6DS3 Accelerometer and Gyroscope

The LSM6DS3 sensor requires the lsm6ds3 library, which can be installed via Thonny’s ‘Manage Packages’ feature. Use this example to read movement data:

Pimoroni

python

import time
from machine import Pin, I2C
from lsm6ds3 import LSM6DS3

i2c = I2C(0, scl=Pin(5), sda=Pin(4))
sensor = LSM6DS3(i2c)

while True:
    accel = sensor.read_accelerometer()
    gyro = sensor.read_gyroscope()
    print(f"Accel: {accel} | Gyro: {gyro}")
    time.sleep(0.5)

Use code with caution.

  • Multi-Sensor Stick (BME280 + LTR559 + LSM6DS3) - Pimoroni

    Software. If you’re planning on using the Multi-Sensor Stick with Raspberry Pi Pico (or another RP2040/RP2350 microcontroller) the…

    image

    Pimoroni

  • Libraries and examples to support Pimoroni Pico add … - GitHub

    Pimoroni Pico Libraries and Examples. Welcome to the brave new world of Pico! This repository contains the C/C++ and MicroPython l…

    image

AI responses may include mistakes. Learn more

This last line is VERY IMPORTANT.

…why ask the AI?

I remember approx. a year ago that I got this up and running on a Pico with Pimoroni’s stock source code from Github…

This must be around the time, when they released the Presto, where the sensor stick was included…

The Tufty 2350 code for the sensor stick is here.
tufty2350/firmware/apps/sense/init.py at main · pimoroni/tufty2350 · GitHub

Just run the Sense App to see what it does.

I did up my own App to make use of the BME280 and display the readings numerically and graphically. Well sort of graphically? You’ll see what i mean if you run it. My coding skills are average at best, IMHO. What I’ve done can likely be done Bigger Better Faster =) but it is what it is. ;)

import time
import micropython
badge.mode(HIRES)
from badgeware import set_brightness
set_brightness(1.0)
BACKLIGHT_LOW = micropython.const(0.5)
BACKLIGHT_HIGH = micropython.const(1.0)
LUMINANCE_LOW = micropython.const(80)
LUMINANCE_HIGH = micropython.const(3072)  # 65535 to use the full range.
backlight = BACKLIGHT_LOW

def auto_brightness(previous: float) -> (float, float):
    luminance = badge.light_level()
    luminance_frac = max(0.0, float(luminance - LUMINANCE_LOW))
    luminance_frac = min(1.0, luminance_frac / (LUMINANCE_HIGH - LUMINANCE_LOW))
    backlight = BACKLIGHT_LOW + (luminance_frac * (BACKLIGHT_HIGH - BACKLIGHT_LOW))
    backlight_diff = backlight - previous
    backlight = previous + (backlight_diff * (1.0 / 8.0))
    return (luminance, backlight)

from breakout_bme280 import BreakoutBME280
from machine import I2C

temperature_sensor = BreakoutBME280(I2C())
last_ticks = badge.ticks

t = 0
p = 0
h = 0
A = 1
C = 1

screen.font = rom_font.ignore
screen.pen = color.white
h_color = screen.pen
p_color = screen.pen
background = color.rgb(60, 15, 10)
phosphor = color.rgb(246, 135, 4)

def get_reading():
    global t, p, h
    temperature, pressure, humidity = temperature_sensor.read()
    pressuremb = pressure / 100
    t = round(temperature)
    h = round(humidity)
    p = round(pressuremb)
    
get_reading()
time.sleep (0.5)
get_reading()
time.sleep (0.5)
min_temperature = t
max_temperature = t

def describe_humidity(h):
    global h_color
    if h < 30:
        description = "Low"
        h_color = color.red
    elif 30 <= h <= 60:
        description = "OK"
        h_color = color.green
    elif 60 < h < 80:
        description = "High"
        h_color = color.yellow
    elif h >= 80:
        description = "Very High"
        h_color = color.orange        
    return description

def describe_pressure(p):
    global p_color
    if p < 982:
        description = "Very Low"
        p_color = color.red
    elif 982 <= p < 1004:
        description = "Low"
        p_color = color.yellow
    elif 1004 <= p < 1026:
        description = "OK"
        p_color = color.green
    elif 1026 <= p < 1048:
        description = "High"
        p_color = color.blue
    elif p >= 1048:
        description = "Very High"
        p_color = color.orange
    return description

def draw_graph():
    global C
    if t <= 0:
        C = 0
    if t >= 13:
        C = 1    
    
    if C == 1:
        scaled_temp = int(t * 10)
        if scaled_temp <= 9:
            scaled_temp =9
        if scaled_temp >= 310:
            scaled_temp =310
        screen.pen = color.yellow
        screen.rectangle(9,89,116,19)
        screen.circle(9,98,9)
        screen.pen = color.green
        screen.rectangle(127,89,111,19)
        screen.pen = color.orange
        screen.rectangle(240,89,28,19)
        screen.pen = color.red
        screen.rectangle(270,89,44,19)
        screen.circle(310,98,9)    
    else:    
        scaled_temp = int((t * 5) + 160)
        if scaled_temp <= 9:
            scaled_temp =9
        if scaled_temp >= 310:
            scaled_temp =310
        screen.pen = color.blue
        screen.circle(9, 98, 9)
        screen.rectangle(12, 89, 92, 19)
        screen.pen = color.white
        screen.rectangle(106, 89, 53, 19)
        screen.pen = color.yellow
        screen.rectangle(161,89,58,19)
        screen.pen = color.green
        screen.rectangle(221,89,58,19)
        screen.pen = color.orange
        screen.rectangle(281,89,13,19)
        screen.pen = color.red
        screen.rectangle(296,89,15,19)
        screen.circle(310,98,9)
            
    scaled_humid = int(h * (320 / 100))
    if scaled_humid <= 9:
        scaled_humid =9
    if scaled_humid >= 310:
        scaled_humid =310
    humidity_text = describe_humidity(h)
    screen.pen = (h_color)
    screen.text(humidity_text,130,118)
    
    screen.pen = (color.red)
    screen.circle(9, 164, 9)
    screen.rectangle(12,155,82,19)
    screen.pen = (color.green)
    screen.rectangle(96,155,94,19)
    screen.pen = (color.yellow)
    screen.rectangle(192,155,62,19)
    screen.pen = (color.orange)
    screen.rectangle(256,155,55,19)
    screen.circle(310,164,9)
    
    screen.pen = (color.black)
    screen.circle((scaled_humid),164,9)
    screen.pen = (color.white)
    screen.circle((scaled_humid),164,5)
    screen.pen = (h_color)
        
    scaled_press = int((p - 960) * 3)
    if scaled_press <= 9:
        scaled_press =9
    if scaled_press >= 310:
        scaled_press =310
    pressure_text = describe_pressure(p)
    screen.pen = (p_color)
    screen.text(pressure_text,130,184) 
    
    screen.pen = color.red
    screen.circle(9, 230, 9)
    screen.rectangle(12,221,50,19)
    screen.pen = color.yellow
    screen.rectangle(64,221,62,19)
    screen.pen = color.green
    screen.rectangle(128,221,62,19)
    screen.pen = color.blue
    screen.rectangle(192,221,62,19)
    screen.pen = color.orange
    screen.rectangle(256,221,52,19)
    screen.circle(310, 230, 9)
    screen.rectangle(256,155,55,19)
    screen.circle(310,164,9)
    
    screen.pen = color.black
    screen.circle((scaled_temp),98,9)
    screen.circle((scaled_humid),164,9)
    screen.circle((scaled_press),230,9)
    screen.pen = color.white
    screen.circle((scaled_temp),98,5)
    screen.circle((scaled_humid),164,5)
    screen.circle((scaled_press),230,5)

def describe_month(month):
    if month == 1:
        description = "Jan"
    elif month == 2:
        description = "Feb"  
    elif month == 3:
        description = "Mar"
    elif month == 4:
        description = "Apr"              
    elif month == 5:
        description = "May"              
    elif month == 6:
        description = "Jun"              
    elif month == 7:
        description = "Jul"              
    elif month == 8:
        description = "Aug"              
    elif month == 9:
        description = "Sep"
    elif month == 10:
        description = "Oct"             
    elif month == 11:
        description = "Nov"              
    elif month == 12:
        description = "Dec"            
    return description

def describe_day(day):
    if day == 1:
        description = "st"
    elif day == 2:
        description = "nd"     
    elif day == 3:
        description = "rd" 
    elif day == 21:
        description = "st"      
    elif day == 22:
        description = "nd"  
    elif day == 23:
        description = "rd"
    elif day == 31:
        description = "st"
    else:
        description = "th"
    return description

def draw_battery():
    if badge.is_charging():
        battery_level = (badge.ticks / 20) % 100
    else:
        battery_level = badge.battery_level()
    pos = (275, 16)
    size = (32, 16)
    screen.pen = phosphor
    screen.shape(shape.rectangle(*pos, *size))
    screen.shape(shape.rectangle(pos[0] + size[0], pos[1] + 4, 2, 8))
    screen.pen = background
    screen.shape(shape.rectangle(pos[0] + 1, pos[1] + 1, size[0] - 2, size[1] - 2))
    width = ((size[0] - 4) / 100) * battery_level
    screen.pen = phosphor
    screen.shape(shape.rectangle(pos[0] + 2, pos[1] + 2, width, size[1] - 4))

def update():
    screen.pen = color.black
    screen.clear()
    
    global last_ticks
    if badge.ticks - last_ticks >= 2000:
        last_ticks = badge.ticks
        get_reading()
                    
    if badge.pressed(BUTTON_A):
        global A
        A = 1
    if badge.pressed(BUTTON_C):
        global C
        C = 1
        global min_temperature
        min_temperature = t
        global max_temperature
        max_temperature = t
        time.sleep(0.2)  
    if badge.pressed(BUTTON_UP):
        global A
        A = 0
        set_brightness(1)
        badge.caselights(1)
    if badge.pressed(BUTTON_DOWN):
        global A
        A = 0
        set_brightness(0)        
        badge.caselights(0)
    if A == 1:
        global backlight
        (luminance, backlight) = auto_brightness(backlight)
        set_brightness(backlight)
    if badge.held(BUTTON_B):
        screen.pen = color.white
        screen.text ("Battery", 5,9)
        screen.text("{:0.1f}V".format(badge.battery_voltage()), 100, 9)
        screen.text("{:0.0f}%" .format(badge.battery_level()), 160, 9)
    else:
        year, month, day, hour, minute, second, weekday = rtc.datetime()
        #print(f"{year:04d}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}")
        screen.pen = color.white
        if weekday == 0:
            weekday_text = "Mon"
        if weekday == 1:
            weekday_text = "Tue"
        if weekday == 2:
            weekday_text = "Wed"
        if weekday == 3:
            weekday_text = "Thu"
        if weekday == 4:
            weekday_text = "Fri"
        if weekday == 5:
            weekday_text = "Sat"
        if weekday == 6:
            weekday_text = "Sun"                      
        if hour == 0:
            time_text = f"{12}:{minute:02} AM"
        elif 0 < hour < 10:
            time_text = f"{hour:1}:{minute:02} AM"         
        elif 10 <= hour < 12:
            time_text = f"{hour:2}:{minute:02} AM"
        elif hour == 12:
            time_text = f"{hour:2}:{minute:02} PM"   
        elif hour >12:
            hour = hour - 12
            if hour <10:
                time_text = f"{hour:1}:{minute:02} PM"
            elif 10 <= hour < 12:
                time_text = f"{hour:2}:{minute:02} PM"
            elif hour == 12:
                time_text = f"{hour:2}:{minute:02} AM"

        screen.text(f"{time_text}  {weekday_text}  {describe_month(month)}  {day}{describe_day(day)}",5,9)

    #badge.battery_voltage()    
    #badge.is_charging()
    #badge.usb_connected()
    
    
    screen.pen = color.yellow
    if badge.usb_connected() == True:
        if badge.is_charging() == True:
            screen.text("+><-", 265, 9)
        else:
            screen.text("USB", 275, 9)
            
    if badge.usb_connected() == False:
        screen.text("{:0.1f}V".format(badge.battery_voltage()), 265, 9)
        
    #draw_battery()
    
    screen.pen = color.white
    screen.text("{:0.0f}°C" .format(t), 5, 52)
    screen.text("{:0.0f}%".format(h), 5, 118)
    screen.text("{:0.0f}mb".format(p), 5, 184)
    max_temperature
    if t >= max_temperature:
        max_temperature = t
    min_temperature
    if t <= min_temperature:
        min_temperature = t
    screen.pen = color.yellow
    screen.text(f"Min {min_temperature:.0f}", 110, 52)
    screen.text(f"Max {max_temperature:.0f}", 225, 52)    
     
    draw_graph()
    
    time.sleep(0.5)
    
run(update)

I was trying to help while on my way out with no time to look at my old code.