harbaum / upide

uPIDE is a simple IDE for Micropython
22 stars 6 forks source link

Add LEGO mindstorms example #4

Closed maarten-pennings closed 2 years ago

maarten-pennings commented 2 years ago

Like this IDE!

Could you maybe add some LEGO examples? For example a simple swirl

import hub
img=hub.Image('97531:86420:00900:02468:13579')
hub.display.show(img)

image

Or a counter

import hub,time

font = [ "99999:99999", "90090:99999", "99909:90999", "90909:99999", "00990:99999", "90999:99909", "99999:99909", "99909:00099", "99099:99099", "90999:99999" ]

def decdigits(num) :
    img=hub.Image( font[num//10] + ":00000:" + font[num%10] )
    hub.display.show(img)

for ix in range(100) :
    decdigits(ix)
    time.sleep_ms(200)

image

Thanks for the nice app.

harbaum commented 2 years ago

Ah, cool. Thanks for sharing some examples. I can add them easily. Do you have some nice (e.g. commented) examples you'd like me to include?

I would also accept pull requests.

maarten-pennings commented 2 years ago

You are right, here the second example with comments

# Import the low level hub module
import hub
# Import for time.sleep_ms
import time

# Font for the characters 0..9. 
# Each character is two stripes on the 5x5 display
font = [  
    "99999:99999", "90090:99999", "99909:90999", "90909:99999", "00990:99999", # chars 0,1,2,3,4
    "90999:99909", "99999:99909", "99909:00099", "99099:99099", "90999:99999"  # chars 5,6,7,8,9
]

# Puts `num` (must be 0..99) on the display
# The output is 90 rotated
def decdigits(num) :
    # Split num in two digits and lookup font
    char0 = font[num%10]
    char1 = font[num//10]
    # Create string from two chars with a space (empty stripe) in between
    str = char1 + ":00000:" + char0
    # Put `str` on display
    hub.display.show( hub.Image(str) )

# Demo of all numbers 0..99
for ix in range(100) :
    decdigits(ix)
    time.sleep_ms(200)
maarten-pennings commented 2 years ago

And here some getting started examples fragments

# See https://lego.github.io/MINDSTORMS-Robot-Inventor-hub-API/
import hub
import time

# Three ways to set the center button LED
print("LED")
hub.led(7) # orange
time.sleep(1)
hub.led(0,128,128) # R,G,B
time.sleep(1)
rgb=(64,0,64)
hub.led( rgb ) # R,G,B tuple
time.sleep(1)

# Do some beeps
print("SOUND")
hub.sound.volume(10) # 0..10
hub.sound.beep(freq=1000, time=100, waveform=hub.sound.SOUND_SIN) 
time.sleep_ms(200) # wait 100 for beep plus 100 pause
hub.sound.beep(1000,100) 
time.sleep_ms(200)
hub.sound.beep(500,100) 
time.sleep_ms(200)

# Run motor on port A
print("MOTOR")
m = hub.port.A.motor
print( '\n  '.join(dir(m)) ) # print all methods
m.run_at_speed(50) # -100..+100
time.sleep(1)
m.run_at_speed(0)
m.run_for_time(2000) # ms
time.sleep_ms(2500)
m.run_for_degrees(90,speed=20)
time.sleep(1)
m.run_to_position(270,speed=20)

# Color sensor on port F
print("COLOR")
c = hub.port.F.device
for _ in range(25) :
    print('  ',c.get()) #black=0, yellow=7, red=9 etc
    time.sleep_ms(500)

print("DONE")
harbaum commented 2 years ago

Done! Feel free to provide more examples.

maarten-pennings commented 2 years ago

Now that the MSHub is working, here an example that does not need peripherals plugged in.

# Import the MindStorms Hub module
from mindstorms import MSHub
# Import wait_for_seconds()
from mindstorms.control import wait_for_seconds

# Beep for welcome
hub = MSHub()
hub.speaker.beep()

# Font for the characters 0..9. 
# Each character is two stripes on the 5x5 display
font = [ 
    "99999:99999", "90090:99999", "99909:90999", "90909:99999", "00990:99999", # chars 0,1,2,3,4
    "90999:99909", "99999:99909", "99909:00099", "99099:99099", "90999:99999"  # chars 5,6,7,8,9
]

# Puts `num` (must be 0..99) on the display
# The output is 90 rotated
def decdigits(num) :
    # Split num in two digits and lookup font
    char0 = font[num%10]
    char1 = font[num//10]
    # Create string from two chars with a space (empty stripe) in between
    str = char1 + ":00000:" + char0
    # Put `str` on display
    hub.light_matrix.show( str )

colors = ['azure','blue','cyan','green','orange','pink','red','violet','white','yellow'] # 'black'

# Demo of all numbers 0..99
for ix in range(100) :
    # Status light maps "tens" to a color
    hub.status_light.on( colors[ix//10] )
    # Show the number 
    decdigits(ix)
    # Beep when ix ends with 9
    if ix%10==9 :
        hub.speaker.beep(note=100, seconds=0.02, volume=100)
    # Wait till next number
    wait_for_seconds(0.1)
harbaum commented 2 years ago

This demo fails for me with

digits_and_colors.py, line 29, in decdigits
AttributeError: 'LightMatrix' object has no attribute 'show'

This is with a pretty recent V1.14.0 on LEGO Learning System Hub

maarten-pennings commented 2 years ago

I'm surprised you got this far :-)

This is code for the MindStormsHub (MSHub) not the Spike Prime Hub (PrimeHub). You apparently have flashed your hub with the Spike Prime Firmware, I have flashed my hub with the Mindstorms firmware. Just install the other app from the windows appstore, connect the hub and it will ask the upload the firmware for that app. That is what I just did to change my Mindstorms hub to a spike hub.

What is surprising is that the from mindstorms import MSHub works with the spike hub; it is likely an alias for from spike import PrimeHub. The object returned by hub.light_matrix has type LightMatrix. If this class is from the spike package, it does not have show. If it is from the mindstorms package, the object does have the show method.

And it seems that Spike does not allow users to show their own image. So spike users must use the low-level script

maarten-pennings commented 2 years ago

I added a work-around for the missing show method. Tested the following script on Inventor and Spike.

# Import the MindStorms Hub module (works on Spike Prime too)
from mindstorms import MSHub
# Import wait_for_seconds()
from mindstorms.control import wait_for_seconds

# Beep for welcome
hub = MSHub()
hub.speaker.beep()

# Font for the characters 0..9. 
# Each character is two stripes on the 5x5 display
font = [ 
    "99999:99999", "90090:99999", "99909:90999", "90909:99999", "00990:99999", # chars 0,1,2,3,4
    "90999:99909", "99999:99909", "99909:00099", "99099:99099", "90999:99999"  # chars 5,6,7,8,9
]

# Puts `num` (must be 0..99) on the display
# The output is 90 rotated
def decdigits(num) :
    # Split num in two digits and lookup font
    char0 = font[num%10]
    char1 = font[num//10]
    # Create string from two chars with a space (empty stripe) in between
    str = char1 + ":00000:" + char0
    # Put `str` on display
    if hasattr(hub.light_matrix, 'show') :
        hub.light_matrix.show( str )
    else :
        # Robot Inventor has show() but Spike Prime not, so work-around
        for y in range(5) :
            for x in range(5) :
                level = int(str[y*6+x])*11
                hub.light_matrix.set_pixel(x,y,brightness=level)

# List of colors for the status light around the center button
colors = ['azure','blue','cyan','green','orange','pink','red','violet','white','yellow'] # 'black'

# Demo of all numbers 0..99
for ix in range(100) :
    # Print progress to console
    print(ix)
    # Status light maps "tens" to a color
    hub.status_light.on( colors[ix//10] )
    # Show the number 
    decdigits(ix)
    # Beep when ix ends with 9
    if ix%10==9 :
        hub.speaker.beep(note=100, seconds=0.02) # Inventor supports: volume=100
    # Wait till next number
    wait_for_seconds(0.1)
harbaum commented 2 years ago

Nice demo! Lego really managed to implement different versions for the otherwise identical hubs? What a mess. To avoid confusion all demos should imho run on both devices.