树莓派Pico油门踏板:零点两侧绝对值转0-100%线性值方案
树莓派Pico油门踏板模拟器传感器数据转换问题优化
问题描述
- 模拟传感器返回值为65535→0→65535的绝对值形式,而非预期的-65535→0→65535,常规范围映射函数因首尾取值相同无法生效
- 尝试通过死区(值≤20)标记及踏板运动方向跟踪,将数据转换为0-100%线性值,再映射至-127至127范围用于模拟游戏手柄扳机,但在方向与死区标记的逻辑处理上存在困惑
当前代码
def getScaledAcceleratorPosition(): # Establish a few basic values we need to evaluate acceleratorValue = analog_activePins[0].value posDifference = (last_AcceleratorVal - acceleratorValue) if (digital_activePins[9].value == False) and (digital_activePins[10].value == False): #If neither butterfly switch is enabled, then return 127 for the position of the accelerator global last_AcceleratorVal = 65535 global sawAccelDeadBand = False # Reset memory on seeing the deadband in the middle of accelerator pedal travel global pedalMovingDown = False global pedalMovingUp = True return -127 # Send fully retracted position for analog Right Trigger elif (digital_activePins[9].value == True or digital_activePins[10].value == True): # Take care of a condition where the accelerator pedal rests at Maximum value if acceleratorValue > 65520 and acceleratorValue <= 65535: global last_AcceleratorVal = 65535 global sawAccelDeadBand = False # Reset memory on seeing the deadband in the middle of accelerator pedal travel global pedalMovingDown = False global pedalMovingUp = True return -127 # Create small dead zones at the ends of travel if acceleratorValue >= 65520: acceleratorValue = 65530 if acceleratorValue <= 500: acceleratorValue = 0 if acceleratorValue > 0 and acceleratorValue <= 20: sawAccelDeadBand = True # Set a flag when we pass the accelerator deadband in the middle of travel. # Compensate for the analog feedback device value map that looks like 65535->0->65535, rather than -65535->0->65535 if (posDifference > 0 and sawAccelDeadBand == False) or (posDifference < 0 and sawAccelDeadBand == True): global pedalMovingDown = True global pedalMovingUp = False print("Accel Pedal Moving Down. Value: %s"%acceleratorValue) elif (posDifference > 0 and sawAccelDeadBand == True) or (posDifference < 0 and sawAccelDeadBand == False): global pedalMovingDown = False global pedalMovingUp = True print("Accel Pedal Moving Up. Value: %s"%acceleratorValue) # Values if Pedal is moving Down: if pedalMovingDown == True and sawAccelDeadBand == True: retVal = range_map(acceleratorValue, 0, 65535, 0, 127) # sawDeadBandAndPedalMovingDown = True # Need some memory for when I pass by the dead band and the pedal is moving down? elif pedalMovingDown == True and sawAccelDeadBand == False: retVal = range_map(acceleratorValue, 65535, 0, -127, 0) # Values if Pedal is moving Up: if pedalMovingUp == True and sawAccelDeadBand == True: retVal = range_map(acceleratorValue, 65535, 0, 0, 127) # sawDeadBandAndPedalMovingUp = True # Need some memory for when I pass by the dead band and the pedal is moving up? elif pedalMovingUp == True and sawAccelDeadBand == False: retVal = range_map(acceleratorValue, 0, 65535, -127, 0) global last_AcceleratorVal = acceleratorValue return round(retVal) else: print("Something wrong in getScaledAcceleratorPosition Routine") return 0
优化建议
1. 全局变量管理优化
- 把全局变量移到函数外部初始化,避免在分支内重复赋值,同时用类或闭包封装状态,减少
global关键字的滥用,提升代码可维护性:# 全局状态初始化 last_AcceleratorVal = 65535 sawAccelDeadBand = False pedalMovingDown = False pedalMovingUp = True
2. 死区与方向判断逻辑简化
- 补充死区离开的判断逻辑,避免仅触发进入死区的标记;同时简化方向判断条件,直接通过差值正负结合死区状态推导运动方向:
# 死区状态更新 if 0 < acceleratorValue <= 20: sawAccelDeadBand = True elif acceleratorValue > 20 and sawAccelDeadBand: # 仅当离开死区时保留状态,避免误重置 pass # 简化方向判断 if posDifference != 0: moving_trend_down = posDifference > 0 if sawAccelDeadBand: pedalMovingDown = moving_trend_down pedalMovingUp = not moving_trend_down else: pedalMovingDown = not moving_trend_down pedalMovingUp = moving_trend_down
3. 范围映射逻辑合并
- 取消多分支的
range_map调用,根据死区和方向状态直接计算目标值,减少冗余:# 直接计算映射值,替代range_map if sawAccelDeadBand: # 过死区后:0→65535对应0→127(踩下),65535→0对应127→0(抬起) if pedalMovingDown: retVal = (acceleratorValue / 65535) * 127 else: retVal = (1 - acceleratorValue / 65535) * 127 else: # 未过死区:65535→0对应-127→0(踩下),0→65535对应0→-127(抬起) if pedalMovingDown: retVal = -127 + (acceleratorValue / 65535) * 127 else: retVal = (acceleratorValue / 65535) * (-127)
4. 边界值处理优化
- 统一边界修正逻辑,避免原代码中
>=65520设为65530的不一致问题:# 两端死区修正 if acceleratorValue >= 65520: acceleratorValue = 65535 elif acceleratorValue <= 500: acceleratorValue = 0
5. 代码结构优化
- 将开关判断、边界处理、方向判断、映射计算拆分为独立代码块,提升可读性;增加默认返回值,避免分支遗漏导致的未定义变量问题。
内容的提问来源于stack exchange,提问作者Brennan Thomason
相关产品推荐
相关产品推荐

