Help Needed: Text output from the Macropad RP2040

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Help Needed: Text output from the Macropad RP2040

Post by demsecure »

I received the Macropad and followed this guide:
https://learn.adafruit.com/macropad-hot ... oject-code
I'm on Windows 10.

I've had to alter several of the bundled macros because multiple windows computers refuse to output any text. eg: instead of [Keycode.CONTROL, Keycode.SHIFT, 't'] opening a previously closed tab, I need to use [Keycode.CONTROL, Keycode.SHIFT, Keycode.T]

I'd like to use the macropad for text insertion/expansion, but without the ability to export text, I'm dead in the water.

even something as simple ['test sentence'] causes the macropad to stop running.

Not sure what I'm doing wrong. I'm including a code sample that appears to be working for others, but not for me:

Code: Select all

# MACROPAD Hotkeys example: Multi-Keypress command Example

#from adafruit_hid.keycode import Keycode # REQUIRED if using Keycode.* values
#from adafruit_hid.keyboard import Keyboard # REQUIRED if using Keycode.* values
import usb_hid
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard import Keyboard

kbd = Keyboard(usb_hid.devices)
app = {                    # REQUIRED dict, must be named 'app'
    'name' : 'Example', # Application name
    'macros' : [           # List of button macros...
        # COLOR    LABEL    FLAG(Optional)  KEY SEQUENCE
        # 1st row ----------
        (0x200000, 'Chrome', [999], [Keycode.WINDOWS, 'chrome', Keycode.ENTER]), #ADDED - Note the extra list that contains the 999
        (0x000040, 'Reopen Tab', [Keycode.CONTROL, Keycode.SHIFT, 't']),
        (0x000000, '?', []),
        # 2nd row ---------
        (0x000000, '?', []),
        (0x000000, '?', []),
        (0x000000, '?', []),
        # 3rd row ----------
        (0x000000, '?', []),
        (0x000000, '?', []),
        (0x000000, '?', []),
        # 4th row ----------
        (0x000000, '?', []),
        (0x000000, 'test text', ['test sentance']),
        (0x000000, '?', []),
        # Encoder button ---
        (0x000000, '', []) #
    ]
}
Any help would be greatly appreciated.

User avatar
adafruit_support_carter
 
Posts: 29150
Joined: Tue Nov 29, 2016 2:45 pm

Re: Help Needed: Text output from the Macropad RP2040

Post by adafruit_support_carter »

What is the FLAG entry?

Code: Select all

            # COLOR    LABEL    FLAG(Optional)  KEY SEQUENCE
When it stops running, does it print out an error?

User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Re: Help Needed: Text output from the Macropad RP2040

Post by demsecure »

It just desplays "Code done running." on the display.

the second keycap is lit up blue, the first keycap flashes blue sporadically and the 11th key (bottom row middle) lights up white.

User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Re: Help Needed: Text output from the Macropad RP2040

Post by demsecure »

and...curiously.. my windows computer behaves as if the Ctrl key is being held down after I try to execute the "Reopen Tab" command above. eg: using my scroll wheel on the mouse causes Chrome to change the zoom level, not scroll the page.

User avatar
adafruit_support_carter
 
Posts: 29150
Joined: Tue Nov 29, 2016 2:45 pm

Re: Help Needed: Text output from the Macropad RP2040

Post by adafruit_support_carter »

"Code done running." on the display.
That means the code exited. Which it shouldn't, unless it hit an error. If it did hit an error, there would be an associated message above this.

Can you try going back to the original code from the guide so we can rule out it being anything with your modifications.
even something as simple ['test sentence'] causes the macropad to stop running.
Post the full line in your macro file where you tried this.

User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Re: Help Needed: Text output from the Macropad RP2040

Post by demsecure »

Code snippet -

Code: Select all

(0x000000, 'test text', ['test sentance']),
Can you try going back to the original code from the guide so we can rule out it being anything with your modifications.
That's what led me to make alterations. any code used that just used a alpha character such as:

Code: Select all

(0x000040, 'Private', [Keycode.CONTROL, 'N']),


from the "Windows Edge Default"
causes the error.
hope this helps!

User avatar
adafruit_support_carter
 
Posts: 29150
Joined: Tue Nov 29, 2016 2:45 pm

Re: Help Needed: Text output from the Macropad RP2040

Post by adafruit_support_carter »

Whats the text of the error message?

User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Re: Help Needed: Text output from the Macropad RP2040

Post by demsecure »

Windows Edge Code:

Code: Select all

# MACROPAD Hotkeys example: Microsoft Edge web browser for Windows

from adafruit_hid.keycode import Keycode # REQUIRED if using Keycode.* values

app = {                      # REQUIRED dict, must be named 'app'
    'name' : 'Windows Edge', # Application name
    'macros' : [             # List of button macros...
        # COLOR    LABEL    KEY SEQUENCE
        # 1st row ----------
        (0x004000, '< Back', [Keycode.ALT, Keycode.LEFT_ARROW]),
        (0x004000, 'Fwd >', [Keycode.ALT, Keycode.RIGHT_ARROW]),
        (0x400000, 'Up', [Keycode.SHIFT, ' ']),      # Scroll up
        # 2nd row ----------
        (0x202000, '- Size', [Keycode.CONTROL, Keycode.KEYPAD_MINUS]),
        (0x202000, 'Size +', [Keycode.CONTROL, Keycode.KEYPAD_PLUS]),
        (0x400000, 'Down', ' '),                     # Scroll down
        # 3rd row ----------
        (0x000040, 'Reload', [Keycode.CONTROL, 'r']),
        (0x000040, 'Home', [Keycode.ALT, Keycode.HOME]),
        (0x000040, 'Private', [Keycode.CONTROL, 'N']),
        # 4th row ----------
        (0x000000, 'Ada', [Keycode.CONTROL, 'n', -Keycode.COMMAND,
                           'www.adafruit.com\n']),   # Adafruit in new window
        (0x800000, 'Digi', [Keycode.CONTROL, 'n', -Keycode.COMMAND,
                            'www.digikey.com\n']),   # Digi-Key in new window
        (0x101010, 'Hacks', [Keycode.CONTROL, 'n', -Keycode.COMMAND,
                             'www.hackaday.com\n']), # Hack-a-Day in new win
        # Encoder button ---
        (0x000000, '', [Keycode.CONTROL, 'w']) # Close tab
    ]
}
Same error. "code done running" on the screen and the computer behaves as if the Ctrl button is held down.

User avatar
adafruit_support_carter
 
Posts: 29150
Joined: Tue Nov 29, 2016 2:45 pm

Re: Help Needed: Text output from the Macropad RP2040

Post by adafruit_support_carter »

The above code should *not* be your code.py. Your code.py file should contain the main project code from here:
https://learn.adafruit.com/macropad-hot ... oject-code

The code you show above looks like a configuration file, which should be placed in the macros subfolder:
https://learn.adafruit.com/macropad-hot ... igurations
Same error. "code done running" on the screen and the computer behaves as if the Ctrl button is held down.
This is not an error. That is the normal message you'll see when code is done running. If you are getting that, it seems to indicate you are not running the actual project code. That code has a forever loop and should never exit. Or if it does, it with an actual error message.

User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Re: Help Needed: Text output from the Macropad RP2040

Post by demsecure »

Yes.. sorry I wasn't clear. Here's my code.py

Code: Select all

"""
A fairly straightforward macro/hotkey program for Adafruit MACROPAD.
Macro key setups are stored in the /macros folder (configurable below),
load up just the ones you're likely to use. Plug into computer's USB port,
use dial to select an application macro set, press MACROPAD keys to send
key sequences.
"""

# pylint: disable=import-error, unused-import, too-few-public-methods

import os
import displayio
import terminalio
from adafruit_display_shapes.rect import Rect
from adafruit_display_text import label
from adafruit_macropad import MacroPad


# CONFIGURABLES ------------------------

MACRO_FOLDER = '/macros'


# CLASSES AND FUNCTIONS ----------------

class App:
    """ Class representing a host-side application, for which we have a set
        of macro sequences. Project code was originally more complex and
        this was helpful, but maybe it's excessive now?"""
    def __init__(self, appdata):
        self.name = appdata['name']
        self.macros = appdata['macros']

    def switch(self):
        """ Activate application settings; update OLED labels and LED
            colors. """
        group[13].text = self.name   # Application name
        for i in range(12):
            if i < len(self.macros): # Key in use, set label + LED color
                macropad.pixels[i] = self.macros[i][0]
                group[i].text = self.macros[i][1]
            else:  # Key not in use, no label or LED
                macropad.pixels[i] = 0
                group[i].text = ''
        macropad.keyboard.release_all()
        macropad.pixels.show()
        macropad.display.refresh()


# INITIALIZATION -----------------------

macropad = MacroPad()
macropad.display.auto_refresh = False
macropad.pixels.auto_write = False

# Set up displayio group with all the labels
group = displayio.Group()
for key_index in range(12):
    x = key_index % 3
    y = key_index // 3
    group.append(label.Label(terminalio.FONT, text='', color=0xFFFFFF,
                             anchored_position=((macropad.display.width - 1) * x / 2,
                                                macropad.display.height - 1 -
                                                (3 - y) * 12),
                             anchor_point=(x / 2, 1.0)))
group.append(Rect(0, 0, macropad.display.width, 12, fill=0xFFFFFF))
group.append(label.Label(terminalio.FONT, text='', color=0x000000,
                         anchored_position=(macropad.display.width//2, -2),
                         anchor_point=(0.5, 0.0)))
macropad.display.show(group)

# Load all the macro key setups from .py files in MACRO_FOLDER
apps = []
files = os.listdir(MACRO_FOLDER)
files.sort()
for filename in files:
    if filename.endswith('.py'):
        try:
            module = __import__(MACRO_FOLDER + '/' + filename[:-3])
            apps.append(App(module.app))
        except (SyntaxError, ImportError, AttributeError, KeyError, NameError,
                IndexError, TypeError) as err:
            pass

if not apps:
    group[13].text = 'NO MACRO FILES FOUND'
    macropad.display.refresh()
    while True:
        pass

last_position = None
last_encoder_switch = macropad.encoder_switch_debounced.pressed
app_index = 0
apps[app_index].switch()


# MAIN LOOP ----------------------------

while True:
    # Read encoder position. If it's changed, switch apps.
    position = macropad.encoder
    if position != last_position:
        app_index = position % len(apps)
        apps[app_index].switch()
        last_position = position

    # Handle encoder button. If state has changed, and if there's a
    # corresponding macro, set up variables to act on this just like
    # the keypad keys, as if it were a 13th key/macro.
    macropad.encoder_switch_debounced.update()
    encoder_switch = macropad.encoder_switch_debounced.pressed
    if encoder_switch != last_encoder_switch:
        last_encoder_switch = encoder_switch
        if len(apps[app_index].macros) < 13:
            continue    # No 13th macro, just resume main loop
        key_number = 12 # else process below as 13th macro
        pressed = encoder_switch
    else:
        event = macropad.keys.events.get()
        if not event or event.key_number >= len(apps[app_index].macros):
            continue # No key events, or no corresponding macro, resume loop
        key_number = event.key_number
        pressed = event.pressed

    # If code reaches here, a key or the encoder button WAS pressed/released
    # and there IS a corresponding macro available for it...other situations
    # are avoided by 'continue' statements above which resume the loop.

    sequence = apps[app_index].macros[key_number][2]
    if pressed:
        if key_number < 12: # No pixel for encoder button
            macropad.pixels[key_number] = 0xFFFFFF
            macropad.pixels.show()
        for item in sequence:
            if isinstance(item, int):
                if item >= 0:
                    macropad.keyboard.press(item)
                else:
                    macropad.keyboard.release(-item)
            else:
                macropad.keyboard_layout.write(item)
    else:
        # Release any still-pressed modifier keys
        for item in sequence:
            if isinstance(item, int) and item >= 0:
                macropad.keyboard.release(item)
        if key_number < 12: # No pixel for encoder button
            macropad.pixels[key_number] = apps[app_index].macros[key_number][0]
            macropad.pixels.show()
and the Windows Edge Macro, which sits in the macros folder per the project instructions.

Code: Select all

# MACROPAD Hotkeys example: Microsoft Edge web browser for Windows

from adafruit_hid.keycode import Keycode # REQUIRED if using Keycode.* values

app = {                      # REQUIRED dict, must be named 'app'
    'name' : 'Windows Edge', # Application name
    'macros' : [             # List of button macros...
        # COLOR    LABEL    KEY SEQUENCE
        # 1st row ----------
        (0x004000, '< Back', [Keycode.ALT, Keycode.LEFT_ARROW]),
        (0x004000, 'Fwd >', [Keycode.ALT, Keycode.RIGHT_ARROW]),
        (0x400000, 'Up', [Keycode.SHIFT, ' ']),      # Scroll up
        # 2nd row ----------
        (0x202000, '- Size', [Keycode.CONTROL, Keycode.KEYPAD_MINUS]),
        (0x202000, 'Size +', [Keycode.CONTROL, Keycode.KEYPAD_PLUS]),
        (0x400000, 'Down', ' '),                     # Scroll down
        # 3rd row ----------
        (0x000040, 'Reload', [Keycode.CONTROL, 'r']),
        (0x000040, 'Home', [Keycode.ALT, Keycode.HOME]),
        (0x000040, 'Private', [Keycode.CONTROL, 'N']),
        # 4th row ----------
        (0x000000, 'Ada', [Keycode.CONTROL, 'n', -Keycode.COMMAND,
                           'www.adafruit.com\n']),   # Adafruit in new window
        (0x800000, 'Digi', [Keycode.CONTROL, 'n', -Keycode.COMMAND,
                            'www.digikey.com\n']),   # Digi-Key in new window
        (0x101010, 'Hacks', [Keycode.CONTROL, 'n', -Keycode.COMMAND,
                             'www.hackaday.com\n']), # Hack-a-Day in new win
        # Encoder button ---
        (0x000000, '', [Keycode.CONTROL, 'w']) # Close tab
    ]
}
as I said in my original post, the macropad works. I can send key commands to perform functions and shortcuts, but I can't sent plain text. In the code above for Edge, I'd have to change

Code: Select all

(0x000040, 'Private', [Keycode.CONTROL, 'N']),
to

Code: Select all

(0x000040, 'Private', [Keycode.CONTROL, Keycode.SHIFT, Keycode.N]),
to get a new, private window in either Edge or Chrome. But I can't send something like "test sentence"

Hope this is clear.

User avatar
adafruit_support_carter
 
Posts: 29150
Joined: Tue Nov 29, 2016 2:45 pm

Re: Help Needed: Text output from the Macropad RP2040

Post by adafruit_support_carter »

Same error. "code done running" on the screen and the computer behaves as if the Ctrl button is held down.
Look above this output and see if there is more text with an actual error message.

User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Re: Help Needed: Text output from the Macropad RP2040

Post by demsecure »

The only place I see the output is the screen of the macropad. I can tell there is some text above, but I have no way to scroll the macropad screen. Is there a way to see the output in an editor like Mu, Thonny or Visual Studio Code?

User avatar
adafruit_support_carter
 
Posts: 29150
Joined: Tue Nov 29, 2016 2:45 pm

Re: Help Needed: Text output from the Macropad RP2040

Post by adafruit_support_carter »

Oh, OK, sorry, didn't realize you were reading that from the MacroPad OLED screen. It's probably scrolling out of view on that small display.

Yep, can see more by connecting to the serial console. Mu is probably the easiest for this. Just click the "Serial" button in the toolbar at the top. This will open a new window. You can drag that window up so it shows more lines. You should see the same serial output in that window.

User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Re: Help Needed: Text output from the Macropad RP2040

Post by demsecure »

able to get the output from Mu.
Traceback (most recent call last):
File "code.py", line 141, in <module>
AttributeError: 'NoneType' object has no attribute 'write'

Code done running.
Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

Press any key to enter the REPL. Use CTRL-D to reload.

Adafruit CircuitPython 7.0.0-alpha.5 on 2021-07-21; Adafruit Macropad RP2040 with rp2040


if/else code from from code.py that includes line 141:

Code: Select all

sequence = apps[app_index].macros[key_number][2]
    if pressed:
        if key_number < 12: # No pixel for encoder button
            macropad.pixels[key_number] = 0xFFFFFF
            macropad.pixels.show()
        for item in sequence:
            if isinstance(item, int):
                if item >= 0:
                    macropad.keyboard.press(item)
                else:
                    macropad.keyboard.release(-item)
            else:
                macropad.keyboard_layout.write(item)
    else:
        # Release any still-pressed modifier keys
        for item in sequence:
            if isinstance(item, int) and item >= 0:
                macropad.keyboard.release(item)
        if key_number < 12: # No pixel for encoder button
            macropad.pixels[key_number] = apps[app_index].macros[key_number][0]
            macropad.pixels.show()
line 141 is : macropad.keyboard_layout.write(item)

so looks as if that's where it's failing

code.py in it's entirety:

Code: Select all

"""
A fairly straightforward macro/hotkey program for Adafruit MACROPAD.
Macro key setups are stored in the /macros folder (configurable below),
load up just the ones you're likely to use. Plug into computer's USB port,
use dial to select an application macro set, press MACROPAD keys to send
key sequences.
"""

# pylint: disable=import-error, unused-import, too-few-public-methods

import os
import displayio
import terminalio
from adafruit_display_shapes.rect import Rect
from adafruit_display_text import label
from adafruit_macropad import MacroPad


# CONFIGURABLES ------------------------

MACRO_FOLDER = '/macros'


# CLASSES AND FUNCTIONS ----------------

class App:
    """ Class representing a host-side application, for which we have a set
        of macro sequences. Project code was originally more complex and
        this was helpful, but maybe it's excessive now?"""
    def __init__(self, appdata):
        self.name = appdata['name']
        self.macros = appdata['macros']

    def switch(self):
        """ Activate application settings; update OLED labels and LED
            colors. """
        group[13].text = self.name   # Application name
        for i in range(12):
            if i < len(self.macros): # Key in use, set label + LED color
                macropad.pixels[i] = self.macros[i][0]
                group[i].text = self.macros[i][1]
            else:  # Key not in use, no label or LED
                macropad.pixels[i] = 0
                group[i].text = ''
        macropad.keyboard.release_all()
        macropad.pixels.show()
        macropad.display.refresh()


# INITIALIZATION -----------------------

macropad = MacroPad()
macropad.display.auto_refresh = False
macropad.pixels.auto_write = False

# Set up displayio group with all the labels
group = displayio.Group()
for key_index in range(12):
    x = key_index % 3
    y = key_index // 3
    group.append(label.Label(terminalio.FONT, text='', color=0xFFFFFF,
                             anchored_position=((macropad.display.width - 1) * x / 2,
                                                macropad.display.height - 1 -
                                                (3 - y) * 12),
                             anchor_point=(x / 2, 1.0)))
group.append(Rect(0, 0, macropad.display.width, 12, fill=0xFFFFFF))
group.append(label.Label(terminalio.FONT, text='', color=0x000000,
                         anchored_position=(macropad.display.width//2, -2),
                         anchor_point=(0.5, 0.0)))
macropad.display.show(group)

# Load all the macro key setups from .py files in MACRO_FOLDER
apps = []
files = os.listdir(MACRO_FOLDER)
files.sort()
for filename in files:
    if filename.endswith('.py'):
        try:
            module = __import__(MACRO_FOLDER + '/' + filename[:-3])
            apps.append(App(module.app))
        except (SyntaxError, ImportError, AttributeError, KeyError, NameError,
                IndexError, TypeError) as err:
            pass

if not apps:
    group[13].text = 'NO MACRO FILES FOUND'
    macropad.display.refresh()
    while True:
        pass

last_position = None
last_encoder_switch = macropad.encoder_switch_debounced.pressed
app_index = 0
apps[app_index].switch()


# MAIN LOOP ----------------------------

while True:
    # Read encoder position. If it's changed, switch apps.
    position = macropad.encoder
    if position != last_position:
        app_index = position % len(apps)
        apps[app_index].switch()
        last_position = position

    # Handle encoder button. If state has changed, and if there's a
    # corresponding macro, set up variables to act on this just like
    # the keypad keys, as if it were a 13th key/macro.
    macropad.encoder_switch_debounced.update()
    encoder_switch = macropad.encoder_switch_debounced.pressed
    if encoder_switch != last_encoder_switch:
        last_encoder_switch = encoder_switch
        if len(apps[app_index].macros) < 13:
            continue    # No 13th macro, just resume main loop
        key_number = 12 # else process below as 13th macro
        pressed = encoder_switch
    else:
        event = macropad.keys.events.get()
        if not event or event.key_number >= len(apps[app_index].macros):
            continue # No key events, or no corresponding macro, resume loop
        key_number = event.key_number
        pressed = event.pressed

    # If code reaches here, a key or the encoder button WAS pressed/released
    # and there IS a corresponding macro available for it...other situations
    # are avoided by 'continue' statements above which resume the loop.

    sequence = apps[app_index].macros[key_number][2]
    if pressed:
        if key_number < 12: # No pixel for encoder button
            macropad.pixels[key_number] = 0xFFFFFF
            macropad.pixels.show()
        for item in sequence:
            if isinstance(item, int):
                if item >= 0:
                    macropad.keyboard.press(item)
                else:
                    macropad.keyboard.release(-item)
            else:
                macropad.keyboard_layout.write(item)
    else:
        # Release any still-pressed modifier keys
        for item in sequence:
            if isinstance(item, int) and item >= 0:
                macropad.keyboard.release(item)
        if key_number < 12: # No pixel for encoder button
            macropad.pixels[key_number] = apps[app_index].macros[key_number][0]
            macropad.pixels.show()

User avatar
demsecure
 
Posts: 14
Joined: Tue Apr 19, 2016 11:19 am

Re: Help Needed: Text output from the Macropad RP2040

Post by demsecure »

and in looking over the code, I don't see anywhere (either in code.py or test.py) where
"from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS" in imported

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”