pi_servo_hat initialization fine, but then 'NoneType' object has no attribute "move_servo_position"

Hello!

I am at a loss for why python doesn’t see the object servo_pHAT as a PiServoHat able to call move_servo_position()

Here is the error I’m seeing:

jetbot@jetson:~/jeri_ws$ python3 jetson_driver.py
pygame 2.5.0 (SDL 2.28.0, Python 3.6.9)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "jetson_driver.py", line 30, in <module>
    from sparkfun_servo_tilt_pan import *
  File "/home/jetbot/jeri_ws/sparkfun_servo_tilt_pan.py", line 17, in <module>
    servo_pHAT.move_servo_position(PAN_SERVO, old_pan_angle, MAX_PAN_ANGLE_DEGREES)
AttributeError: 'NoneType' object has no attribute 'move_servo_position'

At the bottom is the code I’ve written–not too different from the sample code at https://learn.sparkfun.com/tutorials/ba … servo-phat

Troubleshooting steps I’ve already tried:

  1. Verify no typos: all instances of servo_pHAT are spelled the same

  2. Verify the package is installed: I ran pip install sparkfun-qwiic both as a user and as sudo. I did the same with pip3 install sparkfun-qwiic. Lots of “Requirement already satisfied” output.

  3. Run using python instead of python3: When I run using python, I get an ImportError: No module named pygame. I have a different file in the project that uses pygame, and I went through most of the same steps as in #2. Ultimately, running with python3 worked. If you could help me with that issue, then we can avoid resolving this one.

import pi_servo_hat as sparkfun_servo
#Ensure Sparkfun libraries are installed pip install sparkfun-qwiic
#https://learn.sparkfun.com/tutorials/pi-servo-phat-v2-hookup-guide/python-package-overview
#https://github.com/sparkfun/PiServoHat_Py/blob/main/pi_servo_hat.py

#These refer to specific servos on headers 0-15 on the Pi Servo pHAT
PAN_SERVO = 0
TILT_SERVO = 1

MAX_TILT_ANGLE_DEGREES = MAX_PAN_ANGLE_DEGREES = SERVO_180_DEG = 180 #Third arg of move_servo_position; default is 90 degrees

servo_pHAT = sparkfun_servo.PiServoHat()
servo_pHAT = servo_pHAT.restart()

old_pan_angle = old_tilt_angle = 90 #default centered

servo_pHAT.move_servo_position(PAN_SERVO, old_pan_angle, MAX_PAN_ANGLE_DEGREES)
servo_pHAT.move_servo_position(TILT_SERVO, old_tilt_angle, MAX_TILT_ANGLE_DEGREES)

ABSOLUTE = True #Use Absolute positioning for debug. Set False as soon as practicable to make nice to use.
MAX_SPEED = 10

def sparkfun_servo_move_head(joy_x, joy_y):
#joy_x and joy_y are from -1 to +1
#arg2 wants 0 to 180
    if ABSOLUTE:
        pan_angle = joy_x * 90 + SERVO_180_DEG
        tilt_angle = joy_y * 90 + SERVO_180_DEG
    else:
        old_pan_angle = servo_pHAT.get_servo_position(PAN_SERVO, MAX_PAN_ANGLE_DEGREES)
        old_tilt_angle = servo_pHAT.get_servo_position(TILT_SERVO, MAX_TILT_ANGLE_DEGREES)

        pan_angle = old_pan_angle + (MAX_SPEED * joy_x)
        tilt_angle = old_tilt_angle + (MAX_SPEED * joy_y)
    # Error Checking/Correction
    if pan_angle < 0:
        pan_angle = 0
    elif pan_angle > MAX_PAN_ANGLE_DEGREES:
        pan_angle = MAX_PAN_ANGLE_DEGREES

    if tilt_angle < 0:
        tilt_angle = 0
    elif tilt_angle > MAX_TILT_ANGLE_DEGREES:
        tilt_angle = MAX_TILT_ANGLE_DEGREES
    #Command the moves

    servo_pHAT.move_servo_position(PAN_SERVO, pan_angle, MAX_PAN_ANGLE_DEGREES)
    servo_pHAT.move_servo_position(TILT_SERVO, tilt_angle, MAX_TILT_ANGLE_DEGREES)

    old_pan_angle = pan_angle
    old_tilt_angle = tilt_angle

Right.

I get that, but I don’t understand why it wouldn’t fail before that line; say, servo_pHAT.restart()

It should throw the error there: that None has no attribute restart

instead it fails later. That’s what I’m struggling to wrap my head around.

To the people of the future who come across this thread with the same problem, I bring closure and disappointment:

I never solved this problem.

Actually:

I abandoned the problem: Instead of using the qwiic library implementation, I used jetbot. (from the juptyer notebook instead of the terminal) IE: Open 192.168.50.45:8888

from jetbot import robot
myRobot = Robot()
myRobot.setMotors(0.3, 0.3)

**while writing this, I found out this code does not use Sparkfun’s scmd code, but instead uses ```
from Adafruit_MotorHAT import Adafruit_MotorHAT


And I moved from my current 18.04-based jetbot image from 2020 (past EOL at the time of writing) to the latest jetbot image from NVIDIA [https://jetbot.org/master/software_setup/sd_card.html](https://jetbot.org/master/software_setup/sd_card.html) (which is behind the current JetPack 5.1.1 image) with Sparkfun's mods, because the latest jetbot image from Sparkfun v01-21 [https://sfecdn.s3.amazonaws.com/jetbot/ ... _linux.zip](https://sfecdn.s3.amazonaws.com/jetbot/sparkfun_4GB_jetbot_v01-21_linux.zip) provides no info on what it's based on.

I'm hoping this resolves the other problems I was having:

1. SSH disconnects after some long amount of time, and then clients can't find the jetbot anymore. Neither through SSH nor the Web Interface on Port 8888.

2. The problems in this thread: python not finding pygame and python3 not correctly assigning