Hello, Alphanumeric- thank you for your reply- good to know that I’ve got the basics right. Because I want to drive 150 or 300 LEDs I’m using the current sensing capabilities of the Plasma 2040 to limit the current drawn by adjusting the brightness. Here’s my code:
import plasma
from plasma import plasma2040
from time import sleep
import gc
import micropython
#import machine
# Import helper for Analog
from pimoroni import Analog
NUM_LEDS = 300
FPS = 60
speed = 10
sleep_time = 0.1 # was: 0.25
offset = 0.0
brightness = 0.5
saturation = 1
num_reps = 100 # Number of times to repeat function
debug = False
# Maximum current
MAX_CURRENT = 1.5
# Define function to display current consumption
sense = Analog(plasma2040.CURRENT_SENSE, plasma2040.ADC_GAIN, plasma2040.SHUNT_RESISTOR)
led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT, rgbw=True)
led_strip.start(FPS)
NUM_PIXELS = int(NUM_LEDS / 10)
# Function to check current and adjust brightness accordingly
def check_current(bright, max_current):
current = sense.read_current()
if current <= max_current and brightness <= 0.99:
bright += 0.01
elif current > max_current:
bright -= 0.1
if debug == True:
print("Brightness =", bright, "Current (A) =", current, "A")
return bright
while True:
for i in range(NUM_LEDS):
for j in range(NUM_PIXELS):
pix_num = (i + (j * 10)) % NUM_LEDS
hue = (float(i) / NUM_LEDS)
# Adjust hue and set HSV values
offset = (offset + float(speed) / 20000.0) % 1
for k in range(5):
led_strip.set_hsv(pix_num + (k - 5), (hue + offset) % 1, saturation, brightness)
# Turn off trailing pixel
trailer = ((pix_num + NUM_LEDS) - 6) % NUM_LEDS
led_strip.set_hsv(trailer, 0, 0, 0)
gc.collect()
brightness = check_current(brightness, 2)
sleep(sleep_time)
gc.collect()
# Report on storage/memory usage
#mem_use = gc.mem_alloc()
#mem_free = gc.mem_free()
#print("Heap allocated to Python:", mem_use, ", available:", mem_free, "(bytes)")
#print("Reversing...")
# Reverse direction
for i in range(NUM_LEDS):
for j in range(NUM_PIXELS):
pix_num = (i + (j * 10)) % NUM_LEDS
hue = (float(i) / NUM_LEDS)
# Adjust hue and set HSV values
offset = (offset + float(speed) / 20000.0) % 1
for k in range(5):
led_strip.set_hsv(NUM_LEDS - (pix_num + k), (hue + offset) % 1, saturation, brightness)
# Turn off trailing pixel
trailer = ((2 * NUM_LEDS - (pix_num - 1))) % NUM_LEDS
led_strip.set_hsv(trailer, 0, 0, 0)
brightness = check_current(brightness, 2)
sleep(sleep_time)
gc.collect()
# Report on storage/memory usage
#print("Reversing back")
mem_use1 = gc.mem_alloc()
mem_free1 = gc.mem_free()
print("Heap allocated to Python:", mem_use1, ", available:", mem_free1, "(bytes)")
micropython.mem_info(1)
print("Reversing back...")
On running the code from Thommy the LEDs illuminate as per the first iteration only and these stay on. The shell responds thus when I attempt to stop the backend:
Unable to connect to COM5: could not open port 'COM5': PermissionError(13, 'Access is denied.', None, 5)
If you have serial connection to the device from another program, then disconnect it there first.
Process ended with exit code 1.
If I comment the final print()
:
# Report on storage/memory usage
#print("Reversing back")
mem_use1 = gc.mem_alloc()
mem_free1 = gc.mem_free()
print("Heap allocated to Python:", mem_use1, ", available:", mem_free1, "(bytes)")
micropython.mem_info(1)
#print("Reversing back...")
The code will run fine.
If I comment the block of code setting and reporting the allocated and free heap (and leave the final print()
commented:
# Report on storage/memory usage
#print("Reversing back")
#mem_use1 = gc.mem_alloc()
#mem_free1 = gc.mem_free()
#print("Heap allocated to Python:", mem_use1, ", available:", mem_free1, "(bytes)")
micropython.mem_info(1)
#print("Reversing back...")
I get the following:
stack: 556 out of 7936
GC: total: 228608, used: 8992, free: 219616
No. of 1-blocks: 91, 2-blocks: 22, max blk sz: 75, max free sz: 13257
GC memory layout; from 20008300:
00000000: h=MLhh..Dhh....Dh..DBDBh===BFB=.h====B=BBBBB.B=B.B=BBB.B=.B.B=Bh
00000400: ===DB=h===========h===================BBB.MDh=.h========h=======
00000800: ==========h=====================================================
00000c00: ==========h=====================================================
00001000: ==========h=hhhB...BDhDhh.hB..hDhDh.DB..B=.DBh==.DB.B=h=.h===...
00001400: .B..B=.BBB=Fh=======h========.DBh===BFFFh===..B=Bhh==h===h======
00001800: =====h===D.Bh=.FB=h===D.BF.h=B=h===FShSh.DhBBBB.DBh===h===.B=BBB
00001c00: h=.h===h===h===......................................h==========
00002000: ========...............................h====....................
00002400: ...........h========............................................
00002800: ........................h===================================h===
00002c00: ================================================================
00003000: =======.........................................................
(3 lines all free)
00004000: .F....F.........................................................
(206 lines all free)
00037c00: ................
NotImplementedError: opcode
In this case, stopping the backend from Thommy works OK with the response MPY: soft reboot
.
The gc.collect()
together with reporting on heap and the micropython.mem_info(1)
were inserted because I wondered if my problems were associated with memory exhaustion or fragmentation. You’ll see that the code is peppered with commented print()
statements- typically, uncommenting some of them will result in any of the three cases above.
In my case, “a little knowledge is a dangerous thing” and I’m hoping that my error(s) will be obvious to a practised eye.
Thank you for any suggestions offered!