Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # 2XLW BIG-ONE v2 - Loads of INPUTS/OUTPUTS
- # Tony Goodhew 31th May 2026
- import time
- from machine import Pin,I2C
- from pimoroni_i2c import PimoroniI2C
- from breakout_bme280 import BreakoutBME280
- from breakout_ltr559 import BreakoutLTR559
- import ahtx0
- from lsm6ds3 import LSM6DS3, NORMAL_MODE_104HZ
- from picographics import PicoGraphics, DISPLAY_PICO_DISPLAY_2, PEN_RGB332
- from pimoroni import RGBLED
- from pico_i2c_lcd import I2cLcd
- from breakout_trackball import BreakoutTrackball
- from neopixel import NeoPixel
- from ssd1306 import SSD1306_I2C
- from breakout_encoder import BreakoutEncoder
- from pimoroni import RGBLED, Button
- from DF2301Q_I2C import DFRobot_DF2301Q_I2C
- from qwstpad import QwSTPad
- from breakout_ioexpander import BreakoutIOExpander
- from aye_arr.nec import NECRemoteReceiver
- from aye_arr.nec.remotes import PimoroniRemote
- from random import randint
- import network
- import rp2
- import requests
- from secrets import WIFI_SSID, WIFI_PASSWORD
- rp2.country("GB")
- # SPI Display 2.0" set up 320x240 Pixels
- display = PicoGraphics(display=DISPLAY_PICO_DISPLAY_2, pen_type=PEN_RGB332, rotate=0)
- display.set_backlight(0.8)
- display.set_font("bitmap8")
- led = RGBLED(6, 7, 8)
- led.set_rgb(0,0,0) # Turn off the RGB LED
- width, height = display.get_bounds()
- # Display colours
- blk = display.create_pen(0, 0, 0) #0
- whi = display.create_pen(255,255,255) #255
- yel = display.create_pen(200,200,0) #216
- grn = display.create_pen(0,255,0) #28
- blu = display.create_pen(0,0,255) #3
- red = display.create_pen(255,0,0) #224
- mag = display.create_pen(255,0,255)
- cyn = display.create_pen(0,255,255)
- # SETUP Buttons = NOT used at the moment
- global KEY_A
- KEY_A = Pin(12,Pin.IN,Pin.PULL_UP)
- #KEY_B = Pin(13,Pin.IN,Pin.PULL_UP)
- #KEY_X = Pin(14,Pin.IN,Pin.PULL_UP)
- #KEY_Y = Pin(15,Pin.IN,Pin.PULL_UP)
- display.set_pen(blk)
- display.clear()
- display.set_pen(yel)
- display.text("Display 2.0 set up",5,5,310,scale = 3)
- display.update()
- # ====== Set up NeoPixelâ„¢ LEDs on GPIO 0 SKULL ============
- NUM_LEDS = 15 # No of Neopixels
- np = NeoPixel(Pin(0), NUM_LEDS) # Neopixels in SKULL
- # Neopixel Colours
- RED = (255,0,0)
- GREEN = (0,255,0)
- BLUE = (0,0,255)
- YELLOW = (255,255,0)
- CYAN = (0,255,255)
- MAGENTA = (255,0,255)
- WHITE = (255,255,255)
- BLACK = (0,0,0)
- WARM = (255,192,96)
- COOL = (96,192,255)
- codes =[(255,0,0),(0,255,0),(0,0,255),(255,255,0),(0,255,255),(255,0,255),(255,255,255),(0,0,0),(255,192,96),(96,192,255)]
- colours = [RED,GREEN,BLUE,YELLOW,CYAN,MAGENTA,WHITE,BLACK,WARM,COOL] # Neopixels 3 bytes
- col_names = ["RED","GREEN","BLUE","YELLOW","CYAN","MAGENTA","WHITE","BLACK","WARM","COOL"] # names
- col_p8 = [red,grn,blu,yel,cyn,mag,whi,blk] # Display 2.0 P8 - 1 byte
- def neofill(cc): # Skull colour fill
- for i in range(NUM_LEDS):
- np[i] = (cc)
- np.write()
- neofill(GREEN)
- np.write()
- # =========== END OF SKULL LED STRIP SET UP ================
- # =========== Set up 16 RGBW Neopixels on RING ==========
- # Number of LEDs in your ring
- RING_NO = 16
- # Global brightness limiter (0.0–1.0)
- BRIGHTNESS = 0.3 # 30% brightness
- # Data pin (change if needed)
- PIN_NUM = 38
- # Create RGBW NeoPixel object
- ring = NeoPixel(Pin(PIN_NUM), RING_NO, bpp=4) # bpp=4 = RGBW
- ring_cols = [(255, 0, 0, 0),(207, 0, 48, 0),(159, 0, 96, 0),(111, 0, 144, 0),(63, 0, 192, 0),
- (15, 0, 240, 0),(0, 33, 222, 0),(0, 81, 174, 0),(0, 129, 126, 0),
- (0, 177, 78, 0),(0, 225, 30, 0),(15, 240, 0, 0),(63, 192, 0, 0),
- (111, 144, 0, 0),(159, 96, 0, 0),(207, 48, 0, 0),
- ]
- def ring_clear():
- for i in range(RING_NO):
- ring[i] = (0, 0, 0, 0)
- ring.write()
- def apply_brightness(color):
- """Scale (R,G,B,W) by global brightness."""
- r, g, b, w = color
- return (
- int(r * BRIGHTNESS),
- int(g * BRIGHTNESS),
- int(b * BRIGHTNESS),
- int(w * BRIGHTNESS),
- )
- def ring_fill(rc): # Fills ring from ring_cols list
- # temp = ring_cols[rc]
- for i in range(16):
- ring[i] = apply_brightness(ring_cols[rc])
- ring.write()
- def ring_roll_cw():
- display.set_pen(blk)
- display.clear()
- display.set_pen(whi)
- display.text("Ring Roll CW",20,100,320,scale=4)
- display.update()
- for iz in range(15):
- pp = 0
- ii = 0
- tstep =iz/100.0
- if tstep >= 0.07: tstep = 0.065
- # print(tstep)
- for qq in range(15,-1,-1):
- ring_clear()
- ring[qq] = apply_brightness(ring_cols[ii])
- ring[(qq+1)%RING_NO] = apply_brightness(ring_cols[(ii-1)%RING_NO])
- ring[(qq+2)%RING_NO] = apply_brightness(ring_cols[(ii-2)%RING_NO])
- ring[(qq+3)%RING_NO] = apply_brightness(ring_cols[(ii-3)%RING_NO])
- ring.write()
- time.sleep(0.07-tstep)
- ring_clear()
- display.set_pen(blk)
- display.clear()
- display.update()
- def ring_roll_ccw():
- display.set_pen(blk)
- display.clear()
- display.set_pen(whi)
- display.text("Ring Roll CCW",20,100,320,scale=4)
- display.update()
- for iz in range(15):
- pp = 0
- ii = 0
- tstep =iz/100.0
- if tstep >= 0.07: tstep = 0.065
- for qq in range(15):
- ring_clear()
- ring[qq] = apply_brightness(ring_cols[ii])
- ring[(qq-1)%RING_NO] = apply_brightness(ring_cols[(ii-1)%RING_NO])
- ring[(qq-2)%RING_NO] = apply_brightness(ring_cols[(ii-2)%RING_NO])
- ring[(qq-3)%RING_NO] = apply_brightness(ring_cols[(ii-3)%RING_NO])
- ring.write()
- time.sleep(0.07-tstep)
- ring_clear()
- display.set_pen(blk)
- display.clear()
- display.update()
- #Flash a ring pixel to indicate connected
- ring_fill(7)
- ring.write()
- time.sleep(0.4)
- ring_clear()
- # === End of Neopixel RING set up ===
- # ====== IR ZAPPER RECEIVER set up ======
- # Constants IR receiver
- IR_RX_PIN = 1 # The pin to listen for IR pulses on
- # Color constants
- zRED = 255, 0, 0
- zGREEN = 0, 255, 0
- zBLUE = 0, 0, 255
- zCYAN = 0, 255, 255
- zMAGENTA = 255, 0, 255
- zYELLOW = 255, 255, 0
- zWARM = 255, 192, 96
- zWHITE = 255, 255, 255
- zCOOL = 96, 192, 255
- zBLACK = 0, 0, 0
- # Function called when a colour button is pressed
- def set_strip(colour):
- xx = codes.index(colour)
- print(colour,col_names[xx])
- for led in range(NUM_LEDS):
- np[led] =(colour)
- np.write()
- # print(f"Colour = #{colour[0]:02x}{colour[1]:02x}{colour[2]:02x}")
- r,g,b = colour
- temp_col = display.create_pen(r,g,b)
- display.set_pen(temp_col)
- display.clear()
- display.set_pen(blk)
- if xx == 7:
- display.set_pen(whi)
- display.text(col_names[xx],20,100,300,4)
- display.update()
- r = int(r * BRIGHTNESS)
- g = int(g * BRIGHTNESS)
- b = int(b * BRIGHTNESS)
- for pp in range(RING_NO):
- ring[pp] = (r,g,b,0)
- ring.write()
- def halt():
- global running
- running = False
- # Create the remote and setup up what each of the buttons will do
- remote = PimoroniRemote()
- remote.bind("1_RED", (set_strip, zRED), on_repeat=None)
- remote.bind("2_GREEN", (set_strip, zGREEN), on_repeat=None)
- remote.bind("3_BLUE", (set_strip, zBLUE), on_repeat=None)
- remote.bind("4_CYAN", (set_strip, zCYAN), on_repeat=None)
- remote.bind("5_MAGENTA", (set_strip, zMAGENTA), on_repeat=None)
- remote.bind("6_YELLOW", (set_strip, zYELLOW), on_repeat=None)
- remote.bind("7_WARM", (set_strip, zWARM), on_repeat=None)
- remote.bind("8_WHITE", (set_strip, zWHITE), on_repeat=None)
- remote.bind("9_COOL", (set_strip, zCOOL), on_repeat=None)
- remote.bind("0_RAINBOW", (set_strip, zBLACK), on_repeat=None)
- remote.bind("ANTICLOCK", (ring_roll_ccw), on_repeat=None)
- remote.bind("CLOCKWISE", (ring_roll_cw), on_repeat=None)
- remote.bind("OK_STOP", (halt))
- # Set up a receiver on the RX pin, using PIO 1 and SM 0, and bind the remote to it.
- receiver = NECRemoteReceiver(IR_RX_PIN, 1, 0)
- receiver.bind(remote)
- # ============= End of Zapper set up ====================================
- # ============ Set up LCD2004 on I2C bus 1 - GPIO 2 & 3 =======
- I2C_ADDR = 0x27
- I2C_NUM_ROWS = 4
- I2C_NUM_COLS = 20
- i2c1 = I2C(1, sda=machine.Pin(2), scl=machine.Pin(3), freq=400000)
- lcd = I2cLcd(i2c1, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)
- lcd.putstr("Hello, LCD set up")
- # Set up I2C Bus 0 - GPIO 4 & 5
- PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5, "baudrate": 100000}
- PINS_PICO_EXPLORER = {"sda": 20, "scl": 21, "baudrate": 100000}
- PINS_PICO = {"sda": 4, "scl": 5, "baudrate": 100000}
- i2c = PimoroniI2C(**PINS_PICO)
- # Connect I2C components to I2C Bus 0
- # Starting with Voice Recognition board
- '''
- https://nerdcave.xyz/docs/tutorials/gravity-offline-language-learning-voice-recognition-sensor/
- # Basic code to test the board
- # Say "Hello, Robot"
- # "Learn cmd word"
- # "Exit learning"
- # "Learn wake word"
- # "I want to delete"
- # "Delete cmd word"
- # "Delete all"
- Initial learned codes 23 March 2026
- COMMAND ID: 5 stop
- COMMAND ID: 6 red
- COMMAND ID: 7 green
- COMMAND ID: 8 blue
- COMMAND ID: 9 yellow
- COMMAND ID: 10 cyan
- COMMAND ID: 11 magenta
- COMMAND ID: 12 white
- COMMAND ID: 13 black
- '''
- def setup(sensor) -> None:
- """
- Set up the DFRobot DF2301Q sensor
- :param sensor: instance of DFRobot_DF2301Q_I2C
- :return: None
- """
- sensor.set_volume(7) # 10
- sensor.set_mute_mode(0) # 0
- sensor.set_wake_time(20) # 20
- def get_cmd_id(sensor) -> int:
- """
- Get the command id from the DF2301Q sensor
- :param sensor: instance of DFRobot_DF2301Q_I2C
- :return: int
- """
- command_id = sensor.get_cmdid()
- if command_id != 0:
- return int(command_id)
- # === End of VOICE SUPPORT ========================
- # === Set up the other I2C devices =============
- try:
- # Check sensors connected
- bme = BreakoutBME280(i2c, address=0x76)
- ltr = BreakoutLTR559(i2c)
- aht20 = ahtx0.AHT20(i2c)
- mov_sensor = LSM6DS3(i2c, mode=NORMAL_MODE_104HZ)
- #Set up TrackBall
- trackball = BreakoutTrackball(i2c)
- trackball.set_rgbw(0, 0, 0, 64)
- sensitivity = 2
- #Set up OLED display
- WIDTH = 128 # oled display width
- HEIGHT = 32
- # Advent SSD1306 and usual majority of displays
- oled = SSD1306_I2C(128,64,i2c)
- oled.fill(0)
- oled.show()
- # Rotary Encoder
- enc = BreakoutEncoder(i2c)
- STEPS_PER_REV = 24
- enc.set_led(0,0,0)
- enc.set_brightness(1.0)
- # enc.set_direction(BreakoutEncoder.DIRECTION_CCW) # Uncomment this to flip the direction
- # Qw/ST Pad
- qwstpad = QwSTPad(i2c, 0x21)
- # Voice recognition
- SLEEP_SECONDS = 2
- voice_sensor = DFRobot_DF2301Q_I2C(sda=4, scl=5)
- setup(sensor=voice_sensor)
- except RuntimeError:
- print("I2C connection problem!")
- # Check all I2C devices have been set up
- print('Scanning I2C bus.')
- devices = i2c.scan() # this returns a list of devices
- device_count = len(devices)
- if device_count == 0:
- print('No i2c device found.')
- else:
- print(device_count, 'devices found.') # Should be 10
- for device in devices:
- print('Decimal address:', device, ", Hex address: ", hex(device))
- # Report Bus 0 I2C items
- lcd.move_to(0,2)
- lcd.putstr("Items on I2C bus 0")
- lcd.move_to(8,3)
- lcd.putstr(str(device_count))
- # Wake up lux sensor - LTR559
- prox, a, b, c, d, e, lux = ltr.get_reading()
- time.sleep(0.5)
- # Procedure to draw enlarged text on SSD1306
- # using the built-in font
- def xtext(string,xx,yy,size):
- ln = len(string)
- oled.text(string,0,56,1) # Normal size string
- for yq in range(8):
- for xq in range(ln*8):
- px = oled.pixel(0+xq,56+yq) # Get pixel value
- if px == 1:
- oled.rect(xx+xq*size,yy+yq*size,size,size,1,1)
- oled.rect(0,56,ln*8,8,0,1) # Clear temp text area
- # Set up IO Expander add-on compenents and 3x'normal 10K pots' on ADC pins
- ioe = BreakoutIOExpander(i2c, address=0x18)
- ioe_button_pin = 2
- ioe.set_mode(ioe_button_pin, BreakoutIOExpander.PIN_IN_PU)
- state = ioe.input(ioe_button_pin)
- # Potentiometer - ADC input on IO Expander
- ioe_adc_pin = 10
- ioe.set_mode(ioe_adc_pin, BreakoutIOExpander.PIN_ADC)
- # Set up the 10 K potentiometers in a list on Pici ADC pins
- pots = [] # Empty list of potentiometers
- for i in range(3):
- pot = machine.ADC(i)# 0, 1 or 2
- pots.append(pot)
- # Function to get a number from the position of the potentiometer knob
- # Overcomes 'iffy zero' to true range 0 - 255 -- soft ends!
- def get_pot_no(adc, maxx):
- max2 = maxx + 6
- reading = pots[adc].read_u16()
- # Adjust low end
- reading = reading - 400
- if reading < 0:
- reading = 0
- result = int((max2 * reading)/(65535-400)) # rescale
- # Adjust top end
- if result > maxx:
- result = maxx
- return result # Send answer back to main program
- # set up RGB PWM LEDs on IO Expander
- # Setup colour control pins
- adj = 65500/256
- rd = 1
- green = 3
- blue = 5
- # Setup PWM timer
- # Settings to produce a 50Hz output from the 24MHz clock.
- # 24,000,000 Hz / 8 = 3,000,000 Hz
- # 3,000,000 Hz / 60,000 Period = 50 Hz
- divider = 8
- period = 60000
- ioe.set_pwm_period(period) # 50 Hz
- ioe.set_pwm_control(divider)
- # Setup PWM pins for RGBLED
- ioe.set_mode(rd, BreakoutIOExpander.PIN_PWM)
- ioe.set_mode(green, BreakoutIOExpander.PIN_PWM)
- ioe.set_mode(blue, BreakoutIOExpander.PIN_PWM)
- # Flash red LED - setup progress indicator
- ioe_LED_pin = 6
- ioe.set_mode(ioe_LED_pin, BreakoutIOExpander.PIN_OUT)
- for i in range(3):
- ioe.output(ioe_LED_pin, 1)
- time.sleep(0.2)
- ioe.output(ioe_LED_pin, 0)
- time.sleep(0.2)
- # == End of IO Exp set up =========
- # ===== Set up NeoPixelâ„¢ LEDs on GPIO 0 - in the SKULL bottle ======
- NUM_LEDS = 15 # No of Neopixels
- np = NeoPixel(Pin(0), NUM_LEDS)
- #=============================
- def tidy_up(): # Turn OFF the lights
- for i in range(NUM_LEDS): # SKULL
- np[i] = (0,0,0)
- np.write()
- oled.fill(0) # OLED
- oled.show()
- lcd.clear() # LCD
- enc.set_led(0,0,0) # Rot Enc
- trackball.set_rgbw(0,0,0, 0) # TB
- display.set_pen(blk) # Display 2
- display.clear()
- display.update()
- ring_clear() # RING
- ioe.output(rd, 0) # RGBLED on IO Exp
- ioe.output(green, 0)
- ioe.output(blue, 0)
- # ========== MENU PROCs ===================
- # ========== Environmental sensing ======
- def sensing():
- display.set_pen(blk)
- display.clear()
- display.set_pen(whi)
- display.text("Sensing",20,100,320,scale=4)
- display.update()
- running = True
- lcd.clear()
- lcd.move_to(3,0)
- lcd.putstr("Environmental")
- lcd.move_to(6,1)
- lcd.putstr("Sensing")
- lcd.move_to(1,2)
- lcd.putstr("On Coloured Screen")
- lcd.move_to(3,3)
- lcd.putstr("Menu: Button")
- display.set_pen(blk)
- display.clear()
- display.set_pen(yel)
- display.update()
- running = True
- while running:
- # Read the AHT20 sensors
- display.set_pen(blk)
- neofill(CYAN)
- oled.fill(0)
- xtext("AHT20",10,10,2)
- oled.show()
- display.clear()
- display.set_pen(yel)
- display.text("AHT20", 20,20, 220, scale=4)
- print("\nAHT20")
- display.set_pen(whi)
- print("Temperature: %0.2f C" % aht20.temperature)
- display.text("Temperature: %0.2f C" % aht20.temperature,20,70,220,scale = 2)
- print("Humidity: %0.2f %%" % aht20.relative_humidity)
- display.text("Humidity: %0.2f %%" % aht20.relative_humidity,20,120,220, scale =2)
- display.update()
- time.sleep(3)
- if ioe.input(ioe_button_pin) == 0:
- running = False
- break
- # Read the bme280 sensors
- neofill(RED)
- temperature, pressure, humidity = bme.read()
- temp = round(temperature,2)
- # Convert pressure to hPa
- pressurehpa = int(pressure / 100)
- display.set_pen(blk)
- display.clear()
- if ioe.input(ioe_button_pin) == 0:
- running = False
- break
- print("\nBME280")
- oled.fill(0)
- xtext("BME280",10,10,2)
- oled.show()
- display.set_pen(yel)
- display.text("BME280", 20,20, 220, scale=4)
- display.set_pen(whi)
- display.text("Temperature: "+str(temp)+" C",20,70,220,scale = 2)
- display.text("Humidity: "+str(int(humidity)) +" %",20,120,200,scale = 2)
- display.text("Pressure: "+str(pressurehpa)+" hPa",20,170,scale = 2)
- display.update()
- print("Temperature: "+str(temp)+" C")
- print("Humidity: "+str(int(humidity)) +" %")
- print("Pressure: "+str(pressurehpa)+" hPa")
- time.sleep(3)
- if ioe.input(ioe_button_pin) == 0:
- running = False
- break
- # Read LTR559
- neofill(BLUE)
- prox, a, b, c, d, e, lux = ltr.get_reading()
- lux = int(lux)
- oled.fill(0)
- xtext("LTR559",10,10,2)
- oled.show()
- display.set_pen(blk)
- display.clear()
- display.set_pen(yel)
- display.text("LTR559", 20,20, 220, scale=4)
- display.set_pen(whi)
- display.text("Lux: "+str(lux),20,70,220,scale = 2)
- print("\nLTR559\n"+str(lux),"LUX")
- display.update()
- time.sleep(3)
- if ioe.input(ioe_button_pin) == 0:
- running = False
- break
- # Read LSM6DS3
- neofill(MAGENTA)
- display.set_pen(blk)
- display.clear()
- display.set_pen(yel)
- display.text("LSM6DS3", 20,20, 220, scale=4)
- oled.fill(0)
- xtext("LSM6DS3",10,10,2)
- oled.show()
- ax, ay, az, gx, gy, gz = mov_sensor.get_readings()
- display.set_pen(whi)
- display.text("\nAccelerometer\nX:{}, Y:{}, Z:{}\n\nGyro\nX:{}, Y:{}, Z{}\n\n ".format(ax, ay, az, gx, gy, gz),20,70,220,scale = 2)
- display.update()
- time.sleep(3)
- if ioe.input(ioe_button_pin) == 0:
- running = False
- break
- tidy_up()
- # ========= Rotary Encoder Section ===========
- def hsv_to_rgb(h, s, v):
- # From CPython Lib/colorsys.py
- if s == 0.0:
- return v, v, v
- i = int(h * 6.0)
- f = (h * 6.0) - i
- p = v * (1.0 - s)
- q = v * (1.0 - s * f)
- t = v * (1.0 - s * (1.0 - f))
- i = i % 6
- if i == 0:
- return v, t, p
- if i == 1:
- return q, v, p
- if i == 2:
- return p, v, t
- if i == 3:
- return p, q, v
- if i == 4:
- return t, p, v
- # if i == 5:
- return v, p, q
- # === Lights routine ===
- def lights(r,g,b,position):
- # Colour the SKULL
- if (position < 0) or (position > 15):
- for i in range(NUM_LEDS):
- np[i] = (r,g,b)
- else:
- for i in range(NUM_LEDS):
- np[i] = (0,0,0)
- np[position] = (r,g,b)
- np.write()
- trackball.set_rgbw(r,g,b, 0)
- display.set_pen(blk)
- display.clear()
- led.set_rgb(0,0,0) # RGB LED
- xb = 100
- display.set_pen(red)
- display.text("R",15,53,310,scale = 3)
- display.rectangle(xb, 50, int(r*0.8), 30)
- display.set_pen(whi)
- display.text(str(r),60,58,310,scale = 2)
- display.set_pen(grn)
- display.text("G",15,103,310,scale = 3)
- display.rectangle(xb, 100, int(g*0.8), 30)
- display.set_pen(whi)
- display.text(str(g),60,108,310,scale = 2)
- display.set_pen(blu)
- display.text("B",15,153,310,scale = 3)
- display.rectangle(xb, 150, int(b*0.8), 30)
- display.set_pen(whi)
- display.text(str(b),60,158,310,scale = 2)
- c2 = display.create_pen(r,g,b)
- display.set_pen(whi)
- display.text("Mixed",15,203,310,scale = 3)
- display.set_pen(c2)
- display.rectangle(xb, 200, int(255*0.8), 30)
- # display.update()
- enc.set_led(r,g,b)
- r2 = int(r * adj /2)
- g2 = int(g * adj /2)
- b2 = int(b * adj /2)
- # RGB LED
- ioe.output(rd, r2)
- ioe.output(green, g2)
- ioe.output(blue, b2)
- if (position >= 0) and (position <= 14):
- temp_col = display.create_pen(r,g,b)
- display.set_pen(temp_col)
- display.circle(100+14*position,17,10)
- display.set_pen(c2)
- display.text("P",15,10,310,scale = 3)
- display.set_pen(whi)
- display.text(str(position),60,10,310,scale = 2)
- #==== Rot Enc Section =============
- def count_changed(count):
- print("Count: ", count, sep="")
- h = ((count % STEPS_PER_REV) * 360.0) / STEPS_PER_REV # Convert the count to a colour hue
- r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)] # rainbow magic
- lights(r,g,b,-1)
- r = int(r*BRIGHTNESS)
- g = int(g*BRIGHTNESS)
- b = int(b*BRIGHTNESS)
- w = 0
- for ptb in range(RING_NO):
- ring[ptb] =(r,g,b,w)
- ring.write()
- def rot_enc():
- display.set_pen(blk)
- display.clear()
- display.set_pen(whi)
- display.text("Rotary Encoder",20,100,320,scale=4)
- display.text("Turn the knob",20,180,320,scale=3)
- display.update()
- count = 0
- count_changed(count)
- enc.clear_interrupt_flag()
- colours = ["Red", "Light Red", "Orange", "Light Orange", "Yellow", "Lime", "Mid Green", "Bright Green", "Green",
- "Acid Green", "Light Cyan", "Cyan", "Blue Green", "Mid Blue", "Light Blue", "Bright Blue", "Blue", "Pinky Blue",
- "Bright Purple", "Mid-purple", "Magenta", "Bright Magenta", "Redish Magenta", "Blue Red"]
- print("\nTurn the Rotary Encoder\n")
- oled.fill(0)
- oled.text("Turn the Rotary",0,15,1)
- oled.text(" Encoder",0,32,1)
- oled.text("Button = MENU", 12,55,1)
- oled.show()
- lcd.clear()
- lcd.putstr("Turn Rotary Encoder")
- lcd.move_to(3,3)
- lcd.putstr("Menu: Button")
- while ioe.input(ioe_button_pin) == 1:
- if enc.get_interrupt_flag():
- count = enc.read()
- enc.clear_interrupt_flag()
- while count < 0:
- count += STEPS_PER_REV
- count_changed(count)
- print(" " + colours[count % 24])
- oled.fill(0)
- gap = (128 - 8 * len(colours[count % 24]))// 2
- oled.text(colours[count % 24],gap,25,1)
- oled.text(" Button = HALT", 0,55,1)
- oled.show()
- display.set_pen(yel)
- display.text(colours[count % 24],45,5,300,scale = 3)
- print(colours[count % 24])
- display.update()
- tidy_up()
- # End of Rot Enc ==============
- # === TrackBall section=====
- def track_ball():
- display.set_pen(blk)
- display.clear()
- display.set_pen(whi)
- display.text("Track Ball",20,100,320,scale=4)
- display.update()
- oled.fill(0)
- oled.show()
- print("Roll the trackball to change colour!")
- lcd.clear()
- lcd.putstr("Track Ball")
- lcd.move_to(0,1)
- lcd.putstr("Roll the ball")
- lcd.move_to(0,2)
- lcd.putstr("Col: U/D Bright: L/R")
- lcd.move_to(0,3)
- lcd.putstr("Press ball to halt")
- x = 0 # Controls Neopixel colours
- y = 10 # Controls brightness
- running2 = True
- while running2:
- state = trackball.read()
- if state[BreakoutTrackball.SW_PRESSED]:
- oled.fill(0)
- running2 = False # Out of loop at bottom
- elif state[BreakoutTrackball.LEFT] > sensitivity:
- oled.fill(0)
- x = x + 1
- if x == 8:
- x = 0
- elif state[BreakoutTrackball.RIGHT] > sensitivity:
- oled.fill(0)
- x = x - 1
- if x == -1:
- x = 7
- elif state[BreakoutTrackball.UP] > sensitivity:
- oled.fill(0)
- y = y - 1
- if y < 0:
- y = 0
- elif state[BreakoutTrackball.DOWN] > sensitivity:
- oled.fill(0)
- y = y + 1
- if y >10:
- y = 10
- elif state[BreakoutTrackball.SW_CHANGED]:
- pass
- oled.text("x = "+str(x),20,40,1)
- oled.text("y = "+str(y),20,55,1)
- oled.text(col_names[x],0,20,1)
- oled.fill_rect(100,62-y*6, 20, y*6, 1) # draw a solid rectangle
- for q in range(11):
- if (q == 5) or (q == 10):
- oled.hline(90,62-q*6,15,1) # Longer central tick
- else:
- oled.hline(95,62-q*6,10,1)
- oled.hline(90,62,30,1)
- r,g,b = colours[x]
- r = int(r /10 * y)
- g = int(g /10 * y)
- b = int(b /10 * y)
- oled.text(str(r),0,5,1) # Current RGB values
- oled.text(str(g),30,5,1)
- oled.text(str(b),60,5,1)
- lights(r,g,b,-1) # Values/ bar graphs on Color Display
- for i in range(NUM_LEDS):
- np[i] = (r,g,b)
- np.write()
- trackball.set_rgbw(r,g,b, 0)
- r = int(r*BRIGHTNESS)
- g = int(g*BRIGHTNESS)
- b = int(b*BRIGHTNESS)
- w = 0
- for ptb in range(RING_NO):
- ring[ptb] =(r,g,b,w)
- ring.write()
- oled.show()
- display.set_pen(whi)
- display.text("Track Ball",50,5,200,scale = 3)
- display.update()
- display.update()
- time.sleep(0.02)
- tidy_up()
- # =========== VOICE SYSTEM ==========
- def voice():
- display.set_pen(blk)
- display.clear()
- display.set_pen(whi)
- display.text("Voice Control",20,100,320,scale=4)
- display.update()
- SLEEP_SECONDS = 1
- lcd.clear()
- lcd.putstr("Voice Recognition")
- lcd.move_to(0,1)
- lcd.putstr("'Hello Robot'")
- lcd.move_to(0,2)
- lcd.putstr("Say a colour")
- lcd.move_to(0,3)
- lcd.putstr("'Stop' to HALT")
- print('Speak your commands:')
- running3 = True
- while running3:
- cmd_id = get_cmd_id(sensor=voice_sensor)
- if isinstance(cmd_id, int):
- if cmd_id == 5: # Stop
- print("Stop")
- oled.fill(0)
- running3 = False
- oled.show()
- for i in range(NUM_LEDS):
- np[i] =(0,0,0) # Clear the strip
- np.write()
- elif (cmd_id < 5) or (cmd_id > 13): # Out of range cmds
- pass
- else:
- p = cmd_id - 6
- print(col_names[p])
- oled.fill(0)
- oled.text(col_names[p], 0,0,1)
- oled.show()
- for i in range(NUM_LEDS):
- r,g,b = colours[p]
- np[i] =(r,g,b)
- np.write()
- enc.set_led(r,g,b)
- r2 = int(r * adj /2)
- g2 = int(g * adj /2)
- b2 = int(b * adj /2)
- # RGB LED
- ioe.output(rd, r2)
- ioe.output(green, g2)
- ioe.output(blue, b2)
- trackball.set_rgbw(r,g,b, 0)
- r3 = int(r*BRIGHTNESS)
- g3 = int(g*BRIGHTNESS)
- b3 = int(b*BRIGHTNESS)
- w3 = 0
- for ptb in range(RING_NO):
- ring[ptb] =(r3,g3,b3,w3)
- ring.write()
- display.set_pen(blk)
- display.clear()
- display.set_pen(col_p8[p])
- print(col_p8[p])
- display.text(col_names[p],20,100,320,scale=4)
- display.update()
- time.sleep(SLEEP_SECONDS)
- tidy_up()
- # === Potentiometer control - 3 in Pico ADCs for RGB colours ===
- # and 1 on IO Expansion for position
- def pots4():
- display.set_pen(blk)
- display.clear()
- display.set_pen(whi)
- display.text("4 Potentiometers",20,100,320,scale=4)
- display.text("Turn the pots",20,180,320,scale=3)
- display.update()
- lcd.clear()
- lcd.putstr("4 potentiometers")
- lcd.move_to(0,1)
- lcd.putstr("Twist the pots")
- lcd.move_to(0,3)
- lcd.putstr("Menu: Button")
- oldpos = 0
- oldtotal = 0
- for i in range(NUM_LEDS):
- np[i] = (0,0,0)
- np.write()
- while ioe.input(ioe_button_pin) == 1:
- led.set_rgb(0, 0, 0)
- oled.text("Turn the Pot",0,0,1)
- pot = ioe.input(ioe_adc_pin) // 4 # 10 bit resolution
- pos = int(pot * 14 /1023) # Range 0 - 14
- r = get_pot_no(0,255)
- g = get_pot_no(1,255)
- b = get_pot_no(2,255)
- r3 = int(r*BRIGHTNESS)
- g3 = int(g*BRIGHTNESS)
- b3 = int(b*BRIGHTNESS)
- w3 = 0
- lights(r,g,b,pos)
- display.update()
- # Ring
- for ptb in range(RING_NO):
- ring[ptb] =(0,0,0,0)
- ring[15-pos] = (r3,g3,b3,w3)
- ring.write()
- oled.text("Position: " + str(int(pos)),0,25,1)
- total = r+g+b
- if oldpos == pos and oldtotal == total:
- pass
- else:
- np[oldpos] = (0,0,0)
- oldpot = pos
- oldtotal = total
- np[pos] = (r,g,b)
- np.write()
- tidy_up()
- # ========================================
- # === Zapper - Aye Arr Remote and IR receiver =======
- def IR_zap():
- display.set_pen(blk)
- display.clear()
- display.set_pen(whi)
- display.text("IR Remote/Zapper",0,100,320,scale=4)
- display.text("Press some buttons",20,180,320,scale=3)
- display.update()
- global running
- lcd.clear()
- lcd.putstr("IR Zapper Control")
- lcd.move_to(0,1)
- lcd.putstr("(0) - (9) Colours")
- lcd.move_to(0,2)
- lcd.putstr("(CCW)-(CW) = Spin")
- lcd.move_to(0,3)
- lcd.putstr("(OK_STOP) to HALT")
- # Wrap the code in a try block, to catch any exceptions (including KeyboardInterrupt)
- try:
- receiver.start()
- running = True
- while running:
- # Decode any IR pulses received since the last time this was called.
- # This should be done as frequently as possible to avoid inputs feeling sluggish
- receiver.decode()
- # End the program by stopping any active systems
- finally:
- receiver.stop()
- for led in range(NUM_LEDS):
- np[led] =(0,0,0)
- np.write()
- time.sleep(0.1) # Short delay for the clear to take effect
- print("STOPPED")
- tidy_up()
- # === End of zapper proc ==============
- # ==== QUAKE Routine = Uses WiFi ==================
- def clean(): # Clear the screen to Black
- display.set_pen(blk)
- display.clear()
- display.update()
- # Routine to separate and extract data items from a single downloaded line
- def splitup(s):
- string = ""
- items = []
- for p in range(len(s)):
- c = s[p]
- # print(type(c))
- if c != chr(124):
- string = string + c
- else:
- items.append(string)
- string = ""
- items.append(string)
- # Extract date and time from second item
- dt = items[1]
- date = dt[0:10]
- ttime = dt[11:19]
- return(items,date,ttime)
- def quake():
- clean()
- display.set_pen(red)
- display.text("EarthQuake",80,120,300,3)
- '''
- display.set_pen(blu)
- display.text("Data from: https://earthquake.usgs.gov",70,400,480,2)
- display.text("Tony Goodhew, Leicester UK",120,450,480,2)
- '''
- display.update()
- lcd.clear()
- lcd.putstr("Earthquakes")
- lcd.move_to(0,3)
- lcd.putstr("Let it run: 0 - 9")
- time.sleep(1)
- display.set_pen(blk)
- clean()
- for p in range(35): # Shake Title routine
- display.set_pen(blk)
- display.rectangle(60,75,200,100)
- xx = randint(0,16)-8
- yy = randint(0,16)-8
- display.set_pen(red)
- display.text("EarthQuake",80+xx,120+yy,300,3)
- display.update()
- time.sleep(0.07)
- clean()
- display.set_pen(red)
- display.text("EarthQuake",80,120,3,3)
- display.update()
- time.sleep(0.6)
- clean()
- display.set_pen(red)
- display.text("Connecting to WiFi",10,30,300,3)
- display.update()
- # Activate WiFi
- wlan = network.WLAN(network.STA_IF)
- wlan.active(True)
- wlan.connect(WIFI_SSID, WIFI_PASSWORD)
- max_wait = 30
- while max_wait > 0:
- if wlan.status() < 0 or wlan.status() >= 3:
- break
- max_wait -= 1
- print("Waiting for Wi-Fi connection...")
- display.set_pen(yel)
- display.text("Waiting for Wi-Fi connection...",10,70,300,3)
- display.update()
- time.sleep(1)
- if wlan.status() != 3:
- raise RuntimeError("Network connection failed")
- else:
- print("Connected to Wi-Fi network.")
- print(wlan.ifconfig())
- clean()
- display.set_pen(grn)
- display.text("Connected to WiFi",50,20,300,3)
- display.set_pen(yel)
- display.text(" Processing",70,60,300,3)
- display.update()
- # ===== Main section of Quake ====
- # Access EarthQuake website and get first 10 lines
- response = requests.get("https://earthquake.usgs.gov/fdsnws/event/1/query?format=text&limit=10")
- # Separate into lines
- lines = []
- for x in response.content.splitlines():
- xs = str(x)
- # print(str(xs))
- lines.append(str(x))
- response.close()
- clean()
- events = []
- for i in range(1,11):
- k = splitup(lines[i]) # This does the major lifting using the proc above
- events.append(k)
- '''
- # List of items for information
- names = ['EventID', 'Time', 'Latitude', 'Longitude', 'Depth/km', 'Author', 'Catalog', 'Contributor',
- 'ContributorID', 'MagType', 'Magnitude', 'MagAuthor', 'EventLocationName', 'Date', 'Time']
- '''
- # Show recent event high-lights
- for i in range(10):
- clean()
- display.set_pen(cyn)
- k,date,ttime = events[i] # Fetch decoded quake data line
- display.text(date + " -- " + ttime,30,0,460,2)
- display.set_pen(yel)
- place = k[12]
- place = place[:-1] # remove final quote character
- display.text(place,0,40,290,2)
- lat = round(float(k[2]),3)
- long = round(float(k[3]),3)
- display.text("Lat/Lon: "+str(lat) + " "+ str(long),0,80,300,2)
- display.set_pen(grn)
- display.text("Magnitude: " + k[10],0,120,300,2)
- display.text("Type: " + k[9],0,140,300,2)
- deep = round(float(k[4]),3)
- display.text("Depth/km: "+ str(deep),0,160,300,2)
- display.set_pen(yel)
- display.text(str(i),300,190,100,4)
- display.update()
- time.sleep(3)
- clean()
- lcd.clear()
- print("\nDone")
- # ================ End of QUAKE =================
- # ==== Menu system on Qw/ST Pad - U, D, R and SSD1306 ====
- def show_menu(p,maxx):
- maxx = len(items) -2
- oled.fill(0)
- oled.text(">",0,30,1)
- oled.text(items[p-1],15,10,1)
- oled.text(items[p],15,30,1)
- oled.text(items[p+1],15,50,1)
- oled.show()
- def menu():
- maxl = len(items) -2
- p = 2
- show_menu(p,maxl)
- while True:
- buttons = qwstpad.read_buttons()
- if buttons['R']:
- while buttons['R']:
- buttons = qwstpad.read_buttons()
- return p
- elif buttons['U']:
- p = p - 1
- if p <= 1:
- p = 1
- show_menu(p,maxl)
- while buttons['U']:
- buttons = qwstpad.read_buttons()
- elif buttons['D']:
- p = p + 1
- if p >= maxl:
- p = maxl
- show_menu(p,maxl)
- while buttons['D']:
- buttons = qwstpad.read_buttons()
- else:
- pass
- #====== MAIN PROGRAM ======
- tidy_up()
- global items
- items = (" ","Track Ball", "Rotary Encoder","Sensing","4 Pots","IR Zapper","Voice",
- "Quake-WiFi","STOP"," ")
- run2 = True
- while run2:
- lcd.clear()
- lcd.putstr("Menu on SSD1306")
- lcd.move_to(0,1)
- lcd.putstr("Use U,D and R")
- lcd.move_to(0,2)
- lcd.putstr("on QW/ST Pad")
- q = menu() # Get value from menu system
- if q == 1: track_ball() # Track Ball
- elif q == 2: rot_enc() # Rotary Encoder
- elif q == 3: sensing() # Sensor stick
- elif q == 4: pots4() # IO Expander
- elif q == 5: IR_zap() # AYE ARR remote
- elif q == 6: voice() # Voice recognition
- elif q == 7: quake() # WiFi
- elif q == 8: run2 = False # STOP
- else: pass
- tidy_up()
Advertisement
Comments
-
- Full details of the project can be found on the Pimoroni.com website.
- https://blog.pimoroni.com/tonys-big-i2c-project/
- and
- https://forums.pimoroni.com/t/a-big-i-c-project/28891/4
- I hope you like it.
Add Comment
Please, Sign In to add comment