CodexPadFrameDecoder Arduino Lib 1.0.3

Loading...
Searching...
No Matches
basic_polling.ino
Go to the documentation of this file.
1/**
2 * @~Chinese
3 * @file ble_uno_or_nl_16_module/basic_polling/basic_polling.ino
4 * @example ble_uno_or_nl_16_module/basic_polling/basic_polling.ino
5 * @brief 演示通过基本轮询方式定期打印 CodexPad 所有按钮状态与摇杆值。
6 * @details 本示例先通过 AT 指令连接到指定的 CodexPad 设备（根据蓝牙设备地址），然后进入轮询循环。
7 * 每隔 30 毫秒，它会打印所有按钮的当前状态（按下/弹起）以及两个摇杆的原始模拟值（0‑255）。
8 * 它展示了 `button_state()` 用于离散按钮查询和 `axis_value()` 用于连续摇杆读取的基本用法。
9 * @note 本示例使用简单的定时机制（`millis()`）以固定间隔打印，适用于状态监控或日志记录。
10 * 对于实时控制应用，请确保尽可能频繁地调用 `Update()` 且无阻塞延时。
11 * @see CodexPadFrameDecoder::button_state
12 * @see CodexPadFrameDecoder::axis_value
13 * @see CodexPadFrameDecoder::Update
14 */
15/**
16 * @~English
17 * @file ble_uno_or_nl_16_module/basic_polling/basic_polling.ino
18 * @example ble_uno_or_nl_16_module/basic_polling/basic_polling.ino
19 * @brief The demonstration regularly prints the status of all buttons and joystick values in CodexPad using a basic polling method.
20 * @details This example first sends AT commands to connect to a designated CodexPad (by Bluetooth Device Address), then enters a simple polling loop.
21 * Every 30 milliseconds, it prints the current state of all buttons (pressed/released) and the raw analog values (0‑255) of both joysticks.
22 * It showcases the fundamental usage of `button_state()` for discrete button queries and `axis_value()` for continuous joystick readings.
23 * @note This example uses a simple timing mechanism (`millis()`) to print at a fixed interval, which is suitable for monitoring or logging.
24 * For real‑time control, ensure `Update()` is called as frequently as possible without blocking delays.
25 * @see CodexPadFrameDecoder::button_state
26 * @see CodexPadFrameDecoder::axis_value
27 * @see CodexPadFrameDecoder::Update
28 */
29
30#include <SoftwareSerial.h>
31
32#include "codex_pad_frame_decoder.h"
33
34 namespace {
35// 调试串口引脚定义。
36// 将外部串口工具连接到这些引脚以查看调试输出。
37// Debug serial port pin definitions.
38// Connect external serial port tools to these pins to view debug output.
39 constexpr uint8_t kDebugSerialRxPin = 6; // 调试输出接收引脚 | RX pin for debug output
40 constexpr uint8_t kDebugSerialTxPin = 5; // 调试输出发送引脚 | TX pin for debug output
41
42// 替换为你的 CodexPad 的 Bluetooth device address。
43// Replace with your CodexPad device's Bluetooth device address.
44 const String kBluetoothDeviceAddress = "0C:3D:5E:9D:80:99";
45
46// 与蓝牙模块通信的串口波特率（请查阅模块数据手册，替换为模块对应的波特率）。
47// The serial port baud rate for communication with the Bluetooth module (please refer to the module data manual, replace with the corresponding baud
48// rate for the module).
49 constexpr uint32_t kBluetoothModuleSerialBaudRate = 115200;
50
51// 此处解码器传入的串口实例，与 Connect() 中传入的为同一个串口实例。
52// The serial instance passed in by the decoder here is the same as the one passed in Connect().
53 CodexPadFrameDecoder g_codex_pad_frame_decoder(Serial);
54
55// 用于调试输出的软串口。
56// A soft serial port used for debugging output.
57SoftwareSerial g_debug_serial(kDebugSerialRxPin, kDebugSerialTxPin);
58
59/**
60 * @~Chinese
61 * @brief 向蓝牙模块发送 AT 指令以建立 BLE 连接。
62 * @details 依次执行 AT 指令序列，将蓝牙模块配置为主机模式并连接到指定 MAC 地址的目标设备。
63 * 指令顺序：AT+DISCON → AT+RESET → AT+ECHO=0 → AT+ROLE=0 → AT+AUTOCON=0 → AT+CON=<mac>。
64 * @param[in] bluetooth_stream 连接蓝牙模块的 Stream 对象。
65 * 注意：此对象必须与传入 CodexPadFrameDecoder 的 Stream 是同一个实例（如 Serial），
66 * 因为解码器正是从这同一个串口读取手柄发来的数据。
67 * @param[in] bluetooth_device_address 目标设备的 MAC 地址，格式为 "XX:XX:XX:XX:XX:XX"。
68 */
69/**
70 * @~English
71 * @brief Send AT commands to the Bluetooth module to establish a BLE connection.
72 * @details Executes a sequence of AT commands to configure the Bluetooth module as master and connect to the target device
73 * at the specified MAC address.
74 * Command order: AT+DISCON → AT+RESET → AT+ECHO=0 → AT+ROLE=0 → AT+AUTOCON=0 → AT+CON=<mac>.
75 * @param[in] bluetooth_stream Stream connected to the Bluetooth module.
76 * Note: This must be the same Stream instance that is passed to the CodexPadFrameDecoder
77 * (e.g., Serial), as the decoder reads incoming data from this same serial port.
78 * @param[in] bluetooth_device_address MAC address of the target device in format "XX:XX:XX:XX:XX:XX".
79 */
80 void Connect(Stream &bluetooth_stream, const String &bluetooth_device_address) {
81 if (bluetooth_device_address.length() != 17 || bluetooth_device_address[2] != ':' || bluetooth_device_address[5] != ':' ||
82 bluetooth_device_address[8] != ':' || bluetooth_device_address[11] != ':' || bluetooth_device_address[14] != ':') {
83 g_debug_serial.println("Error: Invalid MAC address format. Expected: XX:XX:XX:XX:XX:XX");
84 while (true);
85 }
86
87 g_debug_serial.print("Start to connect ");
88 g_debug_serial.println(kBluetoothDeviceAddress);
89
90 // 模块可能处于连接状态，先发送断开指令，确保模块是未连接状态。
91 // The module may be in a connected state. Send the disconnection command first to ensure the module is in an unconnected state.
92 bluetooth_stream.println("AT+DISCON");
93 delay(100);
94
95 // 软件复位蓝牙芯片，清除所有配对和配置数据。
96 // Software reset BLE chip, clear all pairing and configuration data.
97 bluetooth_stream.println("AT+RESET");
98 delay(100);
99
100 // 关闭AT信息回显。
101 // Close AT information echo.
102 bluetooth_stream.println("AT+ECHO=0");
103 delay(100);
104
105 // 设置模块为主机模式，使其能够主动连接从机蓝牙。
106 // Set the module to host mode so that it can actively connect to the BLE of the slave device.
107 bluetooth_stream.println("AT+ROLE=0");
108 delay(100);
109
110 // 关闭模块的蓝牙自动连接模式。
111 // Disable the module's automatic Bluetooth connection mode.
112 bluetooth_stream.println("AT+AUTOCON=0");
113 delay(100);
114
115 // 使用指定的MAC地址发起与从机蓝牙连接。
116 // Initiate BLE connection with the slave using the specified MAC address.
117 bluetooth_stream.print("AT+CON=");
118 bluetooth_stream.println(bluetooth_device_address);
119 delay(100);
120
121 g_debug_serial.println("Connected");
122}
123} // namespace
124
125 void setup() {
126 g_debug_serial.begin(115200);
127
128 Serial.begin(kBluetoothModuleSerialBaudRate);
129
130 Connect(Serial, kBluetoothDeviceAddress);
131}
132
133 void loop() {
134 // 重要：Update()方法必须在循环中尽可能频繁地调用，不能添加延时。
135 // 该方法负责处理所有接收到的蓝牙数据包，延时会导致数据丢失和响应延迟。
136 // 对于实时控制应用，必须保持高频率调用以确保及时响应手柄输入。
137 // Important: Update() method must be called as frequently as possible in the loop, no delays should be added.
138 // This method processes all received Bluetooth packets, delays will cause data loss and response lag.
139 // For real-time control applications, high-frequency calls are essential to ensure prompt response to gamepad input.
140 g_codex_pad_frame_decoder.Update();
141
142 static uint32_t s_print_time = 0;
143 if (s_print_time == 0 || s_print_time + 30 < millis()) {
144 s_print_time = millis();
145
146 // 获取各个按钮的状态，button_state()返回bool类型，true表示按下，false表示弹起
147 // Get button states, button_state() returns bool type, true means pressed, false means released
148 g_debug_serial.print("Up:");
149 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kUp));
150 g_debug_serial.print(", ");
151 g_debug_serial.print("Down:");
152 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kDown));
153 g_debug_serial.print(",");
154 g_debug_serial.print("Left:");
155 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kLeft));
156 g_debug_serial.print(", ");
157 g_debug_serial.print("Right:");
158 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kRight));
159 g_debug_serial.print(", ");
160 g_debug_serial.print("Square(X):");
161 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kSquareX));
162 g_debug_serial.print(", ");
163 g_debug_serial.print("Triangle(Y):");
164 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kTriangleY));
165 g_debug_serial.print(", ");
166 g_debug_serial.print("Cross(A):");
167 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kCrossA));
168 g_debug_serial.print(", ");
169 g_debug_serial.print("Circle(B):");
170 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kCircleB));
171 g_debug_serial.print(", ");
172 g_debug_serial.print("L1:");
173 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kL1));
174 g_debug_serial.print(", ");
175 g_debug_serial.print("L2:");
176 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kL2));
177 g_debug_serial.print(", ");
178 g_debug_serial.print("L3:");
179 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kL3));
180 g_debug_serial.print(", ");
181 g_debug_serial.print("R1:");
182 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kR1));
183 g_debug_serial.print(", ");
184 g_debug_serial.print("R2:");
185 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kR2));
186 g_debug_serial.print(", ");
187 g_debug_serial.print("R3:");
188 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kR3));
189 g_debug_serial.print(", ");
190 g_debug_serial.print("Select:");
191 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kSelect));
192 g_debug_serial.print(", ");
193 g_debug_serial.print("Start:");
194 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kStart));
195 g_debug_serial.print(", ");
196 g_debug_serial.print("Home:");
197 g_debug_serial.print(g_codex_pad_frame_decoder.button_state(CodexPadFrameDecoder::Button::kHome));
198 g_debug_serial.print(", ");
199
200 // 获取摇杆轴数据，axis_value()返回0~255的数值。
201 // 中间位置约为128，数值范围表示摇杆的偏移程度。
202 // Get joystick axis data, axis_value() returns value from 0 to 255.
203 // Center position is around 128, values represent stick deflection.
204 g_debug_serial.print("L(X:");
205 g_debug_serial.print(g_codex_pad_frame_decoder.axis_value(CodexPadFrameDecoder::Axis::kLeftStickX));
206 g_debug_serial.print(", Y:");
207 g_debug_serial.print(g_codex_pad_frame_decoder.axis_value(CodexPadFrameDecoder::Axis::kLeftStickY));
208 g_debug_serial.print("), R(X:");
209 g_debug_serial.print(g_codex_pad_frame_decoder.axis_value(CodexPadFrameDecoder::Axis::kRightStickX));
210 g_debug_serial.print(", Y:");
211 g_debug_serial.print(g_codex_pad_frame_decoder.axis_value(CodexPadFrameDecoder::Axis::kRightStickY));
212 g_debug_serial.println(")");
213 }
214}
CodexPadFrameDecoder
CodexPad controller data frame decoding main class.
Definition codex_pad_frame_decoder.h:29
CodexPadFrameDecoder::Button::kSelect
@ kSelect
Select.
Definition codex_pad_frame_decoder.h:220
CodexPadFrameDecoder::Button::kStart
@ kStart
Start.
Definition codex_pad_frame_decoder.h:230
CodexPadFrameDecoder::Button::kL2
@ kL2
L2.
Definition codex_pad_frame_decoder.h:170
CodexPadFrameDecoder::Button::kL1
@ kL1
L1.
Definition codex_pad_frame_decoder.h:160
CodexPadFrameDecoder::Button::kCrossA
@ kCrossA
Cross or A.
Definition codex_pad_frame_decoder.h:140
CodexPadFrameDecoder::Button::kLeft
@ kLeft
Left.
Definition codex_pad_frame_decoder.h:100
CodexPadFrameDecoder::Button::kRight
@ kRight
Right.
Definition codex_pad_frame_decoder.h:110
CodexPadFrameDecoder::Button::kHome
@ kHome
Home.
Definition codex_pad_frame_decoder.h:240
CodexPadFrameDecoder::Button::kL3
@ kL3
L3.
Definition codex_pad_frame_decoder.h:180
CodexPadFrameDecoder::Button::kDown
@ kDown
Down.
Definition codex_pad_frame_decoder.h:90
CodexPadFrameDecoder::Button::kSquareX
@ kSquareX
Square or X.
Definition codex_pad_frame_decoder.h:120
CodexPadFrameDecoder::Button::kR3
@ kR3
R3.
Definition codex_pad_frame_decoder.h:210
CodexPadFrameDecoder::Button::kR2
@ kR2
R2.
Definition codex_pad_frame_decoder.h:200
CodexPadFrameDecoder::Button::kUp
@ kUp
Up.
Definition codex_pad_frame_decoder.h:80
CodexPadFrameDecoder::Button::kCircleB
@ kCircleB
Circle or B.
Definition codex_pad_frame_decoder.h:150
CodexPadFrameDecoder::Button::kR1
@ kR1
R1.
Definition codex_pad_frame_decoder.h:190
CodexPadFrameDecoder::Button::kTriangleY
@ kTriangleY
Triangle or Y.
Definition codex_pad_frame_decoder.h:130
CodexPadFrameDecoder::Axis::kLeftStickX
@ kLeftStickX
Left stick X axis.
Definition codex_pad_frame_decoder.h:262
CodexPadFrameDecoder::Axis::kRightStickY
@ kRightStickY
Right stick Y axis.
Definition codex_pad_frame_decoder.h:292
CodexPadFrameDecoder::Axis::kLeftStickY
@ kLeftStickY
Left stick Y axis.
Definition codex_pad_frame_decoder.h:272
CodexPadFrameDecoder::Axis::kRightStickX
@ kRightStickX
Right stick X axis.
Definition codex_pad_frame_decoder.h:282
codex_pad_frame_decoder.h