Compare commits

...

1 Commits

Author SHA1 Message Date
Tanner
3fe0a5757c Begin motor sync control loop 2025-04-02 12:30:43 -07:00

62
main.py
View File

@ -27,6 +27,7 @@ dmm2 = None
MOTOR_EN1 = 1 MOTOR_EN1 = 1
MOTOR_EN2 = 2 MOTOR_EN2 = 2
DISABLED = None DISABLED = None
RPM_TARGET = 0
def enable_motors(): def enable_motors():
global DISABLED global DISABLED
@ -76,6 +77,8 @@ def set_motors(rpm):
async def process_mqtt(message): async def process_mqtt(message):
global RPM_TARGET
try: try:
text = message.payload.decode() text = message.payload.decode()
except UnicodeDecodeError: except UnicodeDecodeError:
@ -86,7 +89,7 @@ async def process_mqtt(message):
if topic == 'motion/set_rpm': if topic == 'motion/set_rpm':
rpm = int(float(text)) rpm = int(float(text))
set_motors(rpm) RPM_TARGET = rpm
async def monitor_mqtt(): async def monitor_mqtt():
@ -143,7 +146,7 @@ async def check_sync(rev1, rev2):
difference = rev1 - rev2 difference = rev1 - rev2
if abs(difference) > 1.0: if abs(difference) > 2.0:
# out of sync, kill both motors # out of sync, kill both motors
set_motors(0) set_motors(0)
disable_motors() disable_motors()
@ -154,9 +157,13 @@ async def check_sync(rev1, rev2):
logging.error('MOTOR READINGS OUT OF SYNC! Motor1: %s, Motor2: %s, difference: %s', rev1, rev2, difference) logging.error('MOTOR READINGS OUT OF SYNC! Motor1: %s, Motor2: %s, difference: %s', rev1, rev2, difference)
await send_mqtt('server/motor_status', 'Motor desync') await send_mqtt('server/motor_status', 'Motor desync')
return False
return True
async def monitor_dyn4(): async def monitor_dyn4():
global dmm1, dmm2 global dmm1, dmm2, RPM_TARGET
while True: while True:
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
@ -173,20 +180,63 @@ async def monitor_dyn4():
if pos1 is False: if pos1 is False:
dmm1 = False dmm1 = False
continue continue
rev1 = pos1 / ENCODER_PPR rev1 = round(pos1 / ENCODER_PPR, 4)
if ONE_MOTOR: if ONE_MOTOR:
revolutions = rev1 revolutions = rev1
motor1_rpm = RPM_TARGET
else: else:
pos2 = await read_motor(dmm2, 'Motor2') pos2 = await read_motor(dmm2, 'Motor2')
if pos2 is False: if pos2 is False:
dmm2 = False dmm2 = False
continue continue
rev2 = pos2 / ENCODER_PPR rev2 = round(pos2 / ENCODER_PPR, 4)
revolutions = (rev1 + rev2) / 2.0 revolutions = (rev1 + rev2) / 2.0
await check_sync(rev1, rev2) if not await check_sync(rev1, rev2):
continue
motor1_scaler = 1.0
motor2_scaler = 1.0
kp = 0.01
difference = rev1 - rev2
if abs(difference) > 0.25:
if RPM_TARGET > 0:
if rev1 > rev2:
motor1_scaler = 1.0 - kp * abs(difference)
motor1_scaler = min(motor1_scaler, 1.0) # clamp to range 0.5 - 1.0
motor1_scaler = max(motor1_scaler, 0.5)
elif rev2 > rev1:
motor2_scaler = 1.0 - kp * abs(difference)
motor2_scaler = min(motor2_scaler, 1.0) # clamp to range 0.5 - 1.0
motor2_scaler = max(motor2_scaler, 0.5)
elif RPM_TARGET < 0:
if rev1 < rev2:
motor1_scaler = 1.0 - kp * abs(difference)
motor1_scaler = min(motor1_scaler, 1.0) # clamp to range 0.5 - 1.0
motor1_scaler = max(motor1_scaler, 0.5)
elif rev2 < rev1:
motor2_scaler = 1.0 - kp * abs(difference)
motor2_scaler = min(motor2_scaler, 1.0) # clamp to range 0.5 - 1.0
motor2_scaler = max(motor2_scaler, 0.5)
motor1_rpm = int(RPM_TARGET * motor1_scaler)
motor2_rpm = int(RPM_TARGET * motor2_scaler)
if abs(difference) > 0.25:
logging.info('Pos difference: %s, rev1: %s, rev2: %s, scaler1: %s, scaler2: %s, target: %s, rpm1: %s, rpm2: %s',
difference, rev1, rev2, motor1_scaler, motor2_scaler, RPM_TARGET, motor1_rpm, motor2_rpm)
if ONE_MOTOR:
logging.debug('Setting motor1: %s', motor1_rpm)
dmm1.set_speed(motor1_rpm)
else:
logging.debug('Setting motor1: %s, motor2: %s', motor1_rpm, motor2_rpm)
dmm1.set_speed(motor1_rpm)
dmm2.set_speed(motor2_rpm)
topic = 'server/position' topic = 'server/position'
message = str(round(revolutions, 5)) message = str(round(revolutions, 5))