Pantilthat, python.py won't work anymore, but python commandline does? [SOLVED]

Until recently my pantilthat work flawlessly in combination with motioneye. Yesterday I noticed that the buttons one can use in motioneye to control the pantilthat, didn’t anymore, or at least not very responsive.

Somehow the scripts an python programs controlling the pantilthat won’t work propperly any more.

I stripped down the program for tilting the hat up to it’s bare minimum:

pi@PanTiltHAT:~ $ cat up.py 
import pantilthat
#file = open("/home/pi/tiltangle.txt","r")

#a = int(file.readline())
#file.close()

#if a > -90 :
#   a = a - 10

#print(a)
#file = open("/home/pi/tiltangle.txt","w")
#file.write(str(a))
#pantilthat.tilt(a)

pantilthat.tilt(0)

When I run this program I sometimes get exceptions:

pi@PanTiltHAT:~ $ python up.py 
Exception in thread Thread-1 (most likely raised during interpreter shutdown):
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
  File "/usr/lib/python2.7/threading.py", line 1080, in run
  File "/usr/lib/python2.7/threading.py", line 621, in wait
  File "/usr/lib/python2.7/threading.py", line 364, in wait
<type 'exceptions.ValueError'>: list.remove(x): x not in list
pi@PanTiltHAT:~ $ python up.py 
pi@PanTiltHAT:~ $ python up.py 
pi@PanTiltHAT:~ $ python up.py 
Exception in thread Thread-1 (most likely raised during interpreter shutdown):

And sometimes not…
When I run python from the commandline and talk to the hat it works:

pi@PanTiltHAT:~ $ python
Python 2.7.9 (default, Sep 17 2016, 20:26:04) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pantilthat
>>> pantilthat.tilt(0)

Again, before these separate python programs worked okay. I did an apt-get update an upgrade recently, but that shouldn’t be an issue write?

I just tried this out on my own Pi to little success.
When I run “up.py” in the terminal via “sudo python up.py”, the program doesn’t do anything with the hat, yet still prints. However, running “up.py” in the python2 IDLE it runs perfectly.
I’m no expert in how the terminal runs, so I’m afraid someone else will have to help you there, but I hope this helped anyway!

Same issues here with the pan-tilt hat and a Pi 3 runnng a recent version of Raspbian. Scripts to move the servos work perfectly in IDLE (2 or 3).

When run from terminal with python 2.7 it throws the exception as mentioned above (and sometimes not). Sometimes the servos respond. But most of the time they don’t.

With python 3 from terminal no exceptions are thrown but the servos don’t respond most of the time.

I have the pan-tilt hat for about a month and I have experienced the exceptions and irregular behaviour when run from terminal from the beginning that I started using the hat.

2 Likes

I’ve a suspicion I may know what’s amiss. Try:

import time
import pantilthat

pantilthat.tilt(90)
time.sleep(2)
1 Like

That worked, thx!

But the original code also worked, so any idea why the extra timeout is needed now?

Thanks! Running my scripts from Terminal and controlling the camera from MotionEye is now working as expected.

Aha. I think that more or less proves my theory correct.

PanTilt HAT has a feature where, by default, the servos will timeout and turn off after a while of inactivity. This is to keep the servos from being actively driven constantly, which is unnecessary. Additionally, before the library exits it will turn off the servos to prevent them being left on.

Where previous the threads handing the timeout would stop an example from existing until the timeout elapsed, I changed this in the library so examples could exit immediately. This means that the example will exit and turn off the servos before they’ve even had a chance to move.

I’ll have to figure out a graceful way to address this :D (probably a small pre-exit delay if a servo has been changed in the last N seconds)

1 Like

Changing library behaviour just for the sake of some examples is not ideal design.

You should expose this time out behaviour in the API in some sort of event form (C++ programmer here with just passing knowledge of Python)

This way one can rewrite the example to wait for proper servos finish.

I’d tend to agree. But our libraries and examples are designed with the beginner in mind, so design is mostly led by attempts to avoid giving them ways to shoot themselves in the foot.

Since it’s reasonable to expect,and even encourage, a beginner to write just:

import pantilthat
pantilthat.pan(45)

I figured it’d be better just subscribing to the principle of least surprise :D