这是一个常见的双轴 XY 摇杆模块,核心部件是两个电位器。芯片通过 ADC 模数转换器读取各电位器的电压值,再把读数转换为摇杆在 XY 坐标轴上的位置。
接线参考
| 双轴摇杆 | BPI-PicoW-S3 |
|---|---|
GND |
GND |
+5V |
3V3 |
VRx |
GP27_A1 |
VRy |
GP26_A0 |
CircuitPython 提供的 ADC 精度为 16 位,最大值的十六进制表示为 FFFF,十进制表示为 65535,对应的电压范围为 0 mV~3300 mV。 BPI-PicoW-S3 所用 ESP32-S3 芯片的实际 ADC 电压范围为 0 mV~3100 mV,因此在实际应用中最高只能测量 3100 mV。
基础 ADC 读数,读取两个电位器的值,并将其转换为电压值。
请注意,代码中的 X、Y 轴方向经过对调,使用时需要把双轴摇杆模块逆时针旋转 90°。这样,当摇杆沿 Y 轴向上移动时 ADC 读数会增大,向下移动时则减小,符合常用直角坐标系的方向。
import board,analogio,time
x_axis_pin = analogio.AnalogIn(board.A0)
y_axis_pin = analogio.AnalogIn(board.A1)
while True:
x_axis = x_axis_pin.value
y_axis = y_axis_pin.value
# print((x_axis,y_axis))
x_value = x_axis / 65535 * 3300
y_value = y_axis / 65535 * 3300
print("{0}mv,{1}mv".format(x_value,y_value))
time.sleep(0.1)
在 Mu 编辑器中单击 Plotter 图标打开绘图器,它会把 REPL 输出值实时绘制成随时间变化的折线图。
以下程序用于校准坐标零点。程序运行后的前五秒内请勿触碰摇杆,等待程序取得零点值。
import board,analogio,time
x_axis_pin = analogio.AnalogIn(board.A0)
y_axis_pin = analogio.AnalogIn(board.A1)
def get_zero(times =500, sleep = 0.01):
x_total = 0
y_total = 0
for i in range (times):
x_axis = x_axis_pin.value
y_axis = y_axis_pin.value
x_total += x_axis
y_total += y_axis
time.sleep(sleep)
x_zero = x_total // times
y_zero = y_total // times
return (x_zero,y_zero)
zero = get_zero(times =500, sleep = 0.01)
print(zero)
while True:
x_axis = x_axis_pin.value - zero[0]
y_axis = y_axis_pin.value - zero[1]
print((x_axis,y_axis))
time.sleep(0.1)
下面的程序获取摇杆方向,这是双轴摇杆最常见的应用。
import board,analogio,time
x_axis_pin = analogio.AnalogIn(board.A0)
y_axis_pin = analogio.AnalogIn(board.A1)
direction_list = ["East","Southeast","South","Southwest","West","Northwest","North","Northeast","Centre"]
def get_zero(times =500, sleep = 0.01):
x_total = 0
y_total = 0
for i in range (times):
x_axis = x_axis_pin.value
y_axis = y_axis_pin.value
x_total += x_axis
y_total += y_axis
time.sleep(sleep)
x_zero = x_total // times
y_zero = y_total // times
return (x_zero,y_zero)
def get_direction(zero = (32767,32767)):
x_axis = x_axis_pin.value - zero[0]
y_axis = y_axis_pin.value - zero[1]
if x_axis >= 10000 and -10000 < y_axis < 10000:
return direction_list[0]
elif x_axis >= 10000 and y_axis <= -10000:
return direction_list[1]
elif -10000 < x_axis < 10000 and y_axis <= -10000:
return direction_list[2]
elif x_axis <= -10000 and y_axis <= -10000:
return direction_list[3]
elif x_axis <= -10000 and -10000 < y_axis < 10000:
return direction_list[4]
elif x_axis <= -10000 and y_axis >= 10000:
return direction_list[5]
elif -10000 < x_axis < 10000 and y_axis >= 10000:
return direction_list[6]
elif x_axis >=10000 and y_axis >= 10000:
return direction_list[7]
else :
return direction_list[8]
zero = get_zero(times =50, sleep = 0.01)
print(zero)
while True:
x_axis = x_axis_pin.value - zero[0]
y_axis = y_axis_pin.value - zero[1]
print((x_axis,y_axis))
print(get_direction(zero = zero))
time.sleep(0.1)
下面的程序可以设置坐标精度等级,计算每个等级的跨度,根据需要消除抖动,增强数据的实用性。
import board,analogio,time
x_axis_pin = analogio.AnalogIn(board.A0)
y_axis_pin = analogio.AnalogIn(board.A1)
def get_zero(times =500, sleep = 0.01):
x_total = 0
y_total = 0
for i in range (times):
x_axis = x_axis_pin.value
y_axis = y_axis_pin.value
x_total += x_axis
y_total += y_axis
time.sleep(sleep)
x_zero = x_total // times
y_zero = y_total // times
return (x_zero,y_zero)
def get_extremum(times =500, sleep = 0.01):
x_list = []
y_list = []
for i in range (times):
x_axis = x_axis_pin.value
y_axis = y_axis_pin.value
x_list.append(x_axis)
y_list.append(y_axis)
time.sleep(sleep)
x_extremum = (min(x_list),max(x_list))
y_extremum = (min(y_list),max(y_list))
return (x_extremum,y_extremum)
def get_spacing(level = 16 , zero =(32767,32767) ,x_extremum = (0,65535),y_extremum = (0,65535)):
x_temp_1 = (zero[0] - x_extremum[0]) // level
x_temp_2 = (x_extremum[1] - zero[0] ) // level
y_temp_1 = (zero[1] - y_extremum[0]) // level
y_temp_2 = (y_extremum[1] - zero[1] ) // level
x_spacing = (x_temp_1,x_temp_2)
y_spacing = (y_temp_1,y_temp_2)
return (x_spacing,y_spacing)
def get_coordinates(zero = (32767,32767), x_spacing = (2048,2048),y_spacing = (2048,2048)):
x_value = x_axis_pin.value - zero[0]
y_value = y_axis_pin.value - zero[1]
if x_value >= 0:
x_axis = x_value // x_spacing[1]
else:
x_axis = - ((-x_value) // x_spacing[0])
if y_value >= 0:
y_axis = y_value // y_spacing[1]
else:
y_axis = - ((-y_value) // y_spacing[0])
return (x_axis,y_axis)
zero = get_zero(times =500, sleep = 0.01)
print(zero)
(x_extremum,y_extremum) = get_extremum(times = 500, sleep = 0.01)
print((x_extremum, y_extremum))
(x_spacing,y_spacing) = get_spacing(level = 128 , zero = zero, x_extremum = x_extremum,y_extremum = y_extremum)
print((x_spacing, y_spacing))
while True:
coordinates = get_coordinates(zero = zero, x_spacing = x_spacing, y_spacing = y_spacing)
print(coordinates)
time.sleep(0.1)