1

I'm new to pico, only using arduinos before. I'm trying to make a simple rotary encoder program that displays a value from 0-12 on an 0.96 oled display, and lights up that many leds on a strip. I wanted to try out using multiple cores, as interrupts made the leds not run smooth when I had them just cycling (everything would be paused while the encoder was being turned)

However, when I run this program, aside from the encoder being bouncy, the pico would crash maybe 30 seconds into running the program, making a mess on the display and stopping the code. I feel like there's some rule of using multiple cores that I completely ignored.

Here's the code:

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import _thread
import utime
import neopixel

#general variables section
numOn = 0

#Encoder section
sw = Pin(12,Pin.IN,Pin.PULL_UP)
dt = Pin(11,Pin.IN)
clk = Pin(10,Pin.IN)
encodeCount = 0
lastClk = clk.value()
lastButton = False

#Encoder thread
def encoder(): #don't mind the indentation here, 
               #stackoverflow kinda messed up the code block a bit.
while True:
    #import stuff that I shouldn't need to according to tutorials but it doesn't work without
    global encodeCount
    global lastClk
    global clk
    import utime
    
    if clk.value() != lastClk:
        if dt.value() != clk.value():
            encodeCount += 1
        else:
            encodeCount -= 1
        if encodeCount > 12:
           encodeCount = 0
        elif(encodeCount < 0):
           encodeCount = 12
    lastClk = clk.value()
    print(encodeCount)
    utime.sleep(0.01)

_thread.start_new_thread(encoder,())

#LED section
numLed = 12
ledPin = 26
led = neopixel.NeoPixel(machine.Pin(ledPin),numLed)

#Screen Section
WIDTH = 128
HEIGHT = 64
i2c = I2C(0,scl=Pin(17),sda=Pin(16),freq=200000)
oled = SSD1306_I2C(WIDTH,HEIGHT,i2c)

#loop
while True:
    for i in range(numLed):
        led[i] = (0,0,0)
    
    for i in range(encodeCount):
        led[i] = (100,0,0)
    led.write()

    #Display section
    oled.fill(0)
    oled.text(f'numLed: {numOn}',0,0)
    oled.text(f'counter: {encodeCount}',0,40)
    oled.show()

I'm probably doing something stupid here, I just don't know what. Also, any suggestions on simply debouncing the encoder would be very helpful. Any help would be appreciated! Thanks!

Update: The code above bricked the pico, so clearly I'm doing something very very wrong. _thread start line stopped it from crashing again, so the problem is there.

  • neopixls are notoriously sensitive to timing, dont know if thats you issue or not – pm100 Feb 20 '22 at 23:25
  • Consider using the Pico's PIO functionality for interfacing with the rotary encoder and / or the LEDs. Maybe checking out the quadrature encoder and apa102 example projects could be a good place to start. https://github.com/raspberrypi/pico-examples/tree/master/pio. More information about PIO can be found in the rp2040 datasheet or in online tutorials. – Partial Science Aug 23 '23 at 11:38

1 Answers1

-2

Same issue with very similar code on a Raspberry Pico W. I specify the 'W' because my code works without crashing on an earlier Pico.

I'm wondering if the low level networking functions might be using the 2nd core and causing a conflict.

I'm adding thread locking to see if passing a baton helps, the link below has an example, eg:

# create a lock
lck= _thread.allocate_lock()

# Function that will block the thread with a while loop
# which will simply display a message every second
def second_thread():
    while True:
        # We acquire the traffic light lock
        lck.acquire()
        print("Hello, I'm here in the second thread writting every second")
        utime.sleep(1)
        # We release the traffic light lock
        lck.release()
Tom
  • 1
  • Do you consider your answer post to actually provide a solution to the question at the top of this page? I do not get that impression. Please [edit] to make the answer according to [answer] more obvious. – Yunnosch Dec 26 '22 at 17:19