Compare commits

...

9 Commits

4 changed files with 38 additions and 11 deletions

View File

@ -141,6 +141,7 @@ class PWMSteering:
self.pulse = dk.utils.map_range(angle, self.pulse = dk.utils.map_range(angle,
self.LEFT_ANGLE, self.RIGHT_ANGLE, self.LEFT_ANGLE, self.RIGHT_ANGLE,
self.left_pulse, self.right_pulse) self.left_pulse, self.right_pulse)
logger.debug(f"new steering value {angle} -> {self.pulse}")
def run(self, angle): def run(self, angle):
self.run_threaded(angle) self.run_threaded(angle)
@ -197,6 +198,7 @@ class PWMThrottle:
else: else:
self.pulse = dk.utils.map_range(throttle, self.MIN_THROTTLE, 0, self.pulse = dk.utils.map_range(throttle, self.MIN_THROTTLE, 0,
self.min_pulse, self.zero_pulse) self.min_pulse, self.zero_pulse)
logger.debug(f"new steering value {throttle} -> {self.pulse}")
def run(self, throttle): def run(self, throttle):
self.run_threaded(throttle) self.run_threaded(throttle)

View File

@ -5,7 +5,7 @@ Usage:
rc-pca9685 [steering|throttle] [-u USERNAME | --mqtt-username=USERNAME] [--mqtt-password=PASSWORD] \ rc-pca9685 [steering|throttle] [-u USERNAME | --mqtt-username=USERNAME] [--mqtt-password=PASSWORD] \
[--mqtt-broker=HOSTNAME] [--mqtt-topic=TOPIC] [--mqtt-client-id=CLIENT_ID] [--i2c-bus=BUS] \ [--mqtt-broker=HOSTNAME] [--mqtt-topic=TOPIC] [--mqtt-client-id=CLIENT_ID] [--i2c-bus=BUS] \
[--i2c-address=ADDRESS] [--pca9685-channel=CHANNEL] [--left-pulse=LEFT_PULSE] [--right-pulse=RIGHT_PULSE] \ [--i2c-address=ADDRESS] [--pca9685-channel=CHANNEL] [--left-pulse=LEFT_PULSE] [--right-pulse=RIGHT_PULSE] \
[--max-pulse=MAX_PULSE] [--min-pulse=MIN_PULSE] [--zero-pulse=ZEO_PULSE] [--max-pulse=MAX_PULSE] [--min-pulse=MIN_PULSE] [--zero-pulse=ZEO_PULSE] [--debug]
Options: Options:
-h --help Show this screen. -h --help Show this screen.
@ -22,9 +22,11 @@ Options:
-M MAX_PULSE --max-pulse=MAX_PULSE Max Pulse for throttle -M MAX_PULSE --max-pulse=MAX_PULSE Max Pulse for throttle
-m MIN_PULSE --min-pulse=MIN_PULSE Min Pulse for throttle -m MIN_PULSE --min-pulse=MIN_PULSE Min Pulse for throttle
-z ZERO_PULE --zero-pulse=ZEO_PULSE Zero Pulse for throttle -z ZERO_PULE --zero-pulse=ZEO_PULSE Zero Pulse for throttle
-d --debug Debug logging
""" """
import logging import logging
import os import os
import signal, sys
from docopt import docopt from docopt import docopt
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
@ -41,12 +43,22 @@ logging.basicConfig(level=logging.INFO)
default_client_id = "robocar-pca9685-python" default_client_id = "robocar-pca9685-python"
class SignalHandler:
def __init__(self, client: mqtt.Client):
self._client = client
def sigterm_handler(self, _signo, _stack_frame):
logger.info("exit on SIG_TERM")
self._client.disconnect()
sys.exit(0)
def init_mqtt_steering_client(steering_controller: actuator.PWMSteering, broker_host: str, user: str, password: str, client_id: str, def init_mqtt_steering_client(steering_controller: actuator.PWMSteering, broker_host: str, user: str, password: str, client_id: str,
steering_topic: str) -> mqtt.Client: steering_topic: str) -> mqtt.Client:
logger.info("Start steering part") logger.info("Start steering part")
client = mqtt.Client(client_id=client_id, clean_session=True, userdata=None, protocol=mqtt.MQTTv311) client = mqtt.Client(client_id=client_id, clean_session=True, userdata=None, protocol=mqtt.MQTTv311)
def on_connect(client, userdata, flags, rc): def on_connect(client: mqtt.Client, userdata, flags, rc):
logger.info("Register callback on topic %s", steering_topic) logger.info("Register callback on topic %s", steering_topic)
# Subscribing in on_connect() means that if we lose the connection and # Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed. # reconnect then subscriptions will be renewed.
@ -56,9 +68,9 @@ def init_mqtt_steering_client(steering_controller: actuator.PWMSteering, broker_
try: try:
steering_msg = SteeringMessage() steering_msg = SteeringMessage()
steering_msg.ParseFromString(msg.payload) steering_msg.ParseFromString(msg.payload)
steering_controller.run_threaded(steering_msg.Steering) steering_controller.run_threaded(steering_msg.steering)
except: except:
logger.debug("unexpected error: unable to process steering, skip message") logger.exception("unexpected error: unable to process steering, skip message")
client.username_pw_set(user, password) client.username_pw_set(user, password)
client.on_connect = on_connect client.on_connect = on_connect
@ -84,9 +96,9 @@ def init_mqtt_throttle_client(throttle_controller: actuator.PWMThrottle, broker_
try: try:
throttle_msg = ThrottleMessage() throttle_msg = ThrottleMessage()
throttle_msg.ParseFromString(msg.payload) throttle_msg.ParseFromString(msg.payload)
throttle_controller.run_threaded(throttle_msg.Throttle) throttle_controller.run_threaded(throttle_msg.throttle)
except: except:
logger.debug("unexpected error: unable to process throttle, skip message") logger.exception("unexpected error: unable to process throttle, skip message")
client.username_pw_set(user, password) client.username_pw_set(user, password)
client.on_connect = on_connect client.on_connect = on_connect
@ -111,22 +123,31 @@ def execute_from_command_line():
i2c_address = get_default_value(args["--i2c-address"], "I2C_ADDRESS", 40) i2c_address = get_default_value(args["--i2c-address"], "I2C_ADDRESS", 40)
pca9685_channel = get_default_value(args["--pca9685-channel"], "PCA9685_CHANNEL", 0) pca9685_channel = get_default_value(args["--pca9685-channel"], "PCA9685_CHANNEL", 0)
debug = bool(args["--debug"])
if debug:
logging.basicConfig(level=logging.DEBUG)
pin_id = "PCA9685.{bus}:{address}.{channel}".format(bus=i2c_bus, address=i2c_address,channel=pca9685_channel) pin_id = "PCA9685.{bus}:{address}.{channel}".format(bus=i2c_bus, address=i2c_address,channel=pca9685_channel)
if args["steering"]: if args["steering"]:
steering_pin = donkeycar.parts.pins.pwm_pin_by_id(pin_id) steering_pin = donkeycar.parts.pins.pwm_pin_by_id(pin_id)
steering = actuator.PWMSteering(steering_pin, left_pulse=args["--left-pulse"], right_pulse=args["--right-pulse"]) controller = actuator.PulseController(steering_pin)
steering = actuator.PWMSteering(controller=controller, left_pulse=int(args["--left-pulse"]), right_pulse=int(args["--right-pulse"]))
client = init_mqtt_steering_client(steering_controller=steering, broker_host=broker_host, user=user, client = init_mqtt_steering_client(steering_controller=steering, broker_host=broker_host, user=user,
password=password, client_id=client_id, steering_topic=topic) password=password, client_id=client_id, steering_topic=topic)
elif args["throttle"]: elif args["throttle"]:
throttle_pin = donkeycar.parts.pins.pwm_pin_by_id("PCA9685.0:40.7") throttle_pin = donkeycar.parts.pins.pwm_pin_by_id(pin_id)
throttle = actuator.PWMThrottle(throttle_pin, max_pulse=args["--max-pulse"], min_pulse=args["--min-pulse"], controller = actuator.PulseController(throttle_pin)
zero_pulse=args["--zero-pulse"]) throttle = actuator.PWMThrottle(controller=controller, max_pulse=int(args["--max-pulse"]), min_pulse=int(args["--min-pulse"]),
zero_pulse=int(args["--zero-pulse"]))
client = init_mqtt_throttle_client(throttle_controller=throttle, broker_host=broker_host, user=user, client = init_mqtt_throttle_client(throttle_controller=throttle, broker_host=broker_host, user=user,
password=password, client_id=client_id, throttle_topic=topic) password=password, client_id=client_id, throttle_topic=topic)
else: else:
raise Exception('invalid mode selected, must be steering or throttle') raise Exception('invalid mode selected, must be steering or throttle')
sh = SignalHandler(client)
signal.signal(signal.SIGTERM, sh.sigterm_handler)
client.loop_forever() client.loop_forever()

View File

@ -4,3 +4,5 @@ google~=3.0.0
google-api-core~=2.4.0 google-api-core~=2.4.0
setuptools==60.5.0 setuptools==60.5.0
adafruit-pca9685 adafruit-pca9685
pigpio
RPi.GPIO

View File

@ -32,6 +32,8 @@ setup(name='robocar-pca9685-python',
'protobuf3', 'protobuf3',
'google', 'google',
'adafruit-pca9685', 'adafruit-pca9685',
'pigpio',
'RPi.GPIO',
], ],
tests_require=tests_require, tests_require=tests_require,
extras_require={ extras_require={