Pidog does not run in Idle3

I am relatively new to Raspberry pi and started with developing python projects through idle3. I built the Pidog and have been able to run the examples through a command window with commands like “sudo python3 9_howling.py”.

Now I am interested in modifying the code so I opened 9_howling.py in idle3 and ran it but a large number of exceptions occurred. Is there something I need to do?

When you run the example code using IDLE3, you may encounter errors.

You used sudo (administrator privileges) to execute the program in the command window (sudo python3 9_howling.py), while IDLE3 runs with standard user permissions by default. This could result in insufficient hardware access permissions (such as for motors and sensors), causing exceptions.

Therefore, we still recommend executing the code in the command window.

Thanks for clearing that up. I am running now through the command window.

I am now working through the TTS with espeak and getting an error

ModuleNotFoundError: No module named ‘pidog.tts’

Can you help me find pidog.tts?

Could you please confirm the following:

Were all the library codes installed correctly?

Did you encounter any error messages during the installation?

If you received any errors, please send us a screenshot. This will greatly help us analyze and resolve the issue for you.

We also recommend that you carefully follow the tutorial to reinstall all libraries before running the example code again.

Helpful Link:
Installation Guide: 5. Install All the Modules(Important) — SunFounder PiDog Kit 1.0 documentation

I re installed all of the modules per your instructions and it took several attempts till pidog.tts was installed. The forum provided some minor installation commands that seemed to work

TTS with Espeak and Pico2Wave problem - Robotic kit for Raspberry Pi - Sunfounder Forum

Now when I run any TTS or STT example I receive

Failed to open file: “/sys/class/drm/card1/device/vendor”

When I look for

arecord -l

No CAPTURE Hardware Devices are listed.

Also, when I run sudo python3 stt_vosk_stream.py

Which version of PiDog do you currently have? Please send a photo of the Robot HAT for us to confirm.

If it is a PiDog V1 product:
The USB microphone we provide needs to be plugged into the Raspberry Pi’s USB port. Then, run the command arecord -l to check if the USB microphone device can be detected.
If it is not recognized, try plugging the USB microphone into a different USB port on the Raspberry Pi, and run the arecord -l command again to check.

If it is a PiDog V2 product:
The Robot HAT has a built-in microphone.

I believe it is Version 2.

Your product is the PiDog V1 version.

The Robot HAT for PiDog V1 does not have a built-in onboard microphone, which is why the command did not detect any microphone device.

However, our PiDog V1 product does include a USB microphone. From the photos you provided, it appears that the USB microphone is not connected to the Raspberry Pi’s USB port.

We recommend that you locate the USB microphone in the product packaging and plug it into the Raspberry Pi’s USB port for recognition.

I found the USB mic in the box. I did not see any steps for installing during the assembly process!

arecord -l identifies

card 4: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]

I run

arecord -D plughw:4,0 -f S16_LE -r 16000 -d 3 test.wav

and test.wav file is created. But when I run aplay test.wav no audio plays out.

I run alsamixer and select F6 then default: 4 USB PnP Sound Device

F3 [Playback] Audio Gain Control 00

F4 Mic varied level from 00 to 100 with multiple steps in between

Reboot the Raspberry Pi a couple of times.

Still no audio.

I can get audio when I run aplay angry.wav so it must be something with the Mic audio input.

After trying multiple times I noticed the mic was muted in the upper right corner of the window! When I unmute it then I could record mic audio although it was very low volume

How do I properly end a python program?

When I Ctrl-C and my_dog.close()

and then run the program again I get:

Traceback (most recent call last):
File “/usr/lib/python3/dist-packages/gpiozero/pins/pi.py”, line 411, in pin
pin = self.pins[info]
~~~~~~~~~^^^^^^
KeyError: PinInfo(number=29, name=‘GPIO5’, names=frozenset({‘WPI21’, ‘BOARD29’, ‘BCM5’, 5, ‘GPIO5’, ‘J8:29’, ‘5’}), pull=‘’, row=15, col=1, interfaces=frozenset({‘’, ‘spi’, ‘gpio’, ‘uart’, ‘dpi’, ‘i2c’}))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/home/pidog4a/pidog/Bill/PiDog_1.py”, line 10, in
my_dog = Pidog()
^^^^^^^
File “/usr/local/lib/python3.11/dist-packages/pidog/pidog.py”, line 131, in init
utils.reset_mcu()
File “/usr/local/lib/python3.11/dist-packages/robot_hat/utils.py”, line 155, in reset_mcu
pin = Pin(“MCURST”)
^^^^^^^^^^^^^
File “/usr/local/lib/python3.11/dist-packages/robot_hat/pin.py”, line 96, in init
self.setup(mode, pull, active_state)
File “/usr/local/lib/python3.11/dist-packages/robot_hat/pin.py”, line 134, in setup
self.gpio = OutputDevice(self._pin_num)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/lib/python3/dist-packages/gpiozero/devices.py”, line 108, in call
self = super().call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/lib/python3/dist-packages/gpiozero/output_devices.py”, line 74, in init
super().init(pin, pin_factory=pin_factory)
File “/usr/lib/python3/dist-packages/gpiozero/mixins.py”, line 75, in init
super().init(*args, **kwargs)
File “/usr/lib/python3/dist-packages/gpiozero/devices.py”, line 553, in init
pin = self.pin_factory.pin(pin)
^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/lib/python3/dist-packages/gpiozero/pins/pi.py”, line 413, in pin
pin = self.pin_class(self, info)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/lib/python3/dist-packages/gpiozero/pins/lgpio.py”, line 126, in init
lgpio.gpio_claim_input(
File “/usr/lib/python3/dist-packages/lgpio.py”, line 755, in gpio_claim_input
return _u2i(_lgpio._gpio_claim_input(handle&0xffff, lFlags, gpio))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/lib/python3/dist-packages/lgpio.py”, line 458, in _u2i
raise error(error_text(v))
lgpio.error: ‘GPIO busy’

Which example code are you running? In theory, you can stop and exit the program by pressing Ctrl+C.

If the example is not properly closed, you can run the command ps aux | grep python3 to check the running process ID. Then execute sudo kill -9 [process_id] to terminate that process before running the example code again.

Alternatively, you can restart the system and then run the example code.

I do not want to stop with Ctrl-C, I want the program to end based on a specific voice command.

I found still running:
root 2281 51.6 0.6 1063384 55064 ? Sl 10:38 0:15 python3 PiDog_251207C.py

After kill it I was able to run the code again.

How would I release or kill the program within the python code so I do not need to do this afterwards?

Apologies if I’ve misunderstood your question.

I believe you’ve written your own code? But hitting ctrl-c terminates the program, leaves the gpio busy and needs a kill command to restart? My best guess is that you’ve not trapped the ctrl-c in your program, so it exits before it can execute the my_dog.close().

If so, just copy the last few lines of any Sunfounder example, regards keyboard handling to the end of your code.

However, your actual final requirement is to capture a voice command to terminate. The code would be basically the same, but capturing the voice command instead of ctrl-c then do a clean dog close.

Sorry if I’ve missed the point!

Thanks. you are right on, I am writing my own code and I want to terminate program based on a voice command through vosk.

When the terminate command is detected I exit the while loop in Voice_Command()

if name == “main”:
try:
Voice_Command()
except KeyboardInterrupt:

This block is executed when Ctrl-C is pressed

print(“Script Ctrl-C terminated by user.”)
except Exception as e:

Catches any other potential exceptions

print(f"\033[31mERROR: {e}\033[m")
finally:

This block “always” runs before program terminated

print(“PiDog hardware released.”)
my_dog.close()

When I say the terminate command I get:

Terminate Command Received

PiDog hardware released.
Stopping and returning to the initial position …
Quit
pidog4a@raspberrypi:~/pidog/Bill $

Then I run the program again and it blows up!

pidog4a@raspberrypi:~/pidog/Bill $ sudo python3 PiDog_251207C.py
Traceback (most recent call last):
File “/usr/lib/python3/dist-packages/gpiozero/pins/pi.py”, line 411, in pin
pin = self.pins[info]

KeyError: PinInfo(number=29, name='GPIO5', names=frozenset({5, 'BCM5', '5', 'WPI21', 'J8:29', 'BOARD29', 'GPIO5'}), pull='', row=15, col=1, interfaces=frozenset({'', 'uart', 'spi', 'i2c', 'gpio', 'dpi'}))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/pidog4a/pidog/Bill/PiDog_251207C.py", line 15, in <module>
my_dog = Pidog()
^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/pidog/pidog.py", line 131, in __init__
utils.reset_mcu()
File "/usr/local/lib/python3.11/dist-packages/robot_hat/utils.py", line 155, in reset_mcu
pin = Pin("MCURST")
^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/robot_hat/pin.py", line 96, in __init__
self.setup(mode, pull, active_state)
File "/usr/local/lib/python3.11/dist-packages/robot_hat/pin.py", line 134, in setup
self.gpio = OutputDevice(self._pin_num)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 108, in __call__
self = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/gpiozero/output_devices.py", line 74, in __init__
super().__init__(pin, pin_factory=pin_factory)
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 75, in __init__
super().__init__(*args, **kwargs)
File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 553, in __init__
pin = self.pin_factory.pin(pin)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 413, in pin
pin = self.pin_class(self, info)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/gpiozero/pins/lgpio.py", line 126, in __init__
lgpio.gpio_claim_input(
File "/usr/lib/python3/dist-packages/lgpio.py", line 755, in gpio_claim_input
return _u2i(_lgpio._gpio_claim_input(handle&0xffff, lFlags, gpio))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/lgpio.py", line 458, in _u2i
raise error(error_text(v))
lgpio.error: 'GPIO busy'

Unfortunately I don’t have a pidog currently available to verify, (its rpi4 is currently repurposed to control my astrophotography rig) but I have also used vosk and python code, which from memory, looks identical to yours, and it exited cleanly.

I’ve published various programs for pidog here on this forum and on Facebook, and I don’t remember having that same problem. I’ll try to see if I can remember a bit more of what I did, for any subtle differences.

But memory is not what it was :wink:

Probably better to await Sunfounder…

The key issues seem to be:

  1. Termination logic timing – When exiting the Voice_Command() loop, the finally block or my_dog.close() may not fully release all resources (especially GPIO pins).
  2. Incomplete release by my_dog.close() – The MCURST pin (used for MCU reset) might not be explicitly released, causing a “GPIO busy” error when reinitializing.
  3. Exception handling coverage – Voice-triggered exit may bypass certain cleanup paths.

Solutions to try:

Option 1 – Manually release the MCURST pin in finally:

from robot_hat import Pin
import lgpio

if __name__ == "__main__":
    my_dog = None
    mcu_reset_pin = None
    try:
        mcu_reset_pin = Pin("MCURST")
        my_dog = Pidog()
        Voice_Command()
    except KeyboardInterrupt:
        print("Script terminated by user.")
    except Exception as e:
        print(f"ERROR: {e}")
    finally:
        print("Releasing hardware...")
        if my_dog:
            my_dog.close()
        if mcu_reset_pin:
            try:
                # Try freeing via lgpio as fallback
                lgpio.gpio_free(mcu_reset_pin._pin_num)
            except:
                pass
        print("Cleanup done.")

Option 2 – Force release on startup (if still getting “busy” errors):

import lgpio
import time

def release_busy_gpio():
    try:
        handle = lgpio.gpiochip_open(0)
        busy_gpio = 5  # MCURST is GPIO5 (BCM)
        if lgpio.gpio_is_claimed(handle, busy_gpio):
            lgpio.gpio_free(handle, busy_gpio)
            print(f"Released GPIO{busy_gpio}")
        lgpio.gpiochip_close(handle)
    except Exception as e:
        print(f"GPIO release failed: {e}")

# Run before initializing Pidog
release_busy_gpio()
time.sleep(0.5)

my_dog = Pidog()

Try these and let me know if the “GPIO busy” error disappears when restarting the program.

1 Like

I tried Option 1
It does not make it past command: mcu_reset_pin = Pin(“MCURST”)

It gets an exception
ERROR: ‘GPIO busy’
Exception ignored in: <function GPIOBase.del at 0x7f9550ff60>
Traceback (most recent call last):
File “/usr/lib/python3/dist-packages/gpiozero/devices.py”, line 153, in del
self.close()
File “/usr/lib/python3/dist-packages/gpiozero/mixins.py”, line 79, in close
super().close()
File “/usr/lib/python3/dist-packages/gpiozero/devices.py”, line 572, in close
self._pin.close()
File “/usr/lib/python3/dist-packages/gpiozero/pins/lgpio.py”, line 133, in close
lgpio.gpio_claim_input(
File “/usr/lib/python3/dist-packages/lgpio.py”, line 755, in gpio_claim_input
return _u2i(_lgpio._gpio_claim_input(handle&0xffff, lFlags, gpio))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/lib/python3/dist-packages/lgpio.py”, line 458, in _u2i
raise error(error_text(v))
lgpio.error: ‘GPIO busy’

Releasing hardware…
Cleanup done.
ALSA lib pcm.c:8570:(snd_pcm_recover) underrun occurred

We have not yet been able to find a solution to the issue you described.