CodexPad Arduino Lib 2.1.6
Loading...
Searching...
No Matches
inputs_detection.ino
Go to the documentation of this file.
1/**
2 * @~English
3 * @file inputs_detection.ino
4 * @example inputs_detection.ino
5 * @brief Demonstrates how to detect real-time button states and joystick movements of a connected CodexPad.
6 * @details This example establishes a connection to a specific CodexPad device (by Bluetooth Device Address) and continuously monitors all user
7 * inputs. It showcases the detection of three distinct button states: **pressed** (momentary press), **released** (momentary release), and
8 * **holding** (sustained press). It also monitors the analog joystick axes and prints their values when a significant change beyond a set threshold
9 * is detected, filtering out minor jitter.
10 * @note The `Update()` method must be called as frequently as possible within the main loop without delays to ensure real-time
11 * responsiveness and prevent data packet loss.
12 * @see CodexPad::Update
13 * @see CodexPad::pressed
14 * @see CodexPad::released
15 * @see CodexPad::holding
16 * @see CodexPad::HasAxisValueChanged
17 * @see CodexPad::axis_value
18 */
19/**
20 * @~Chinese
21 * @file inputs_detection.ino
22 * @example inputs_detection.ino
23 * @brief 演示如何检测已连接的 CodexPad 设备的实时按钮状态与摇杆移动。
24 * @details 本示例通过Bluetooth Device Address连接到指定的 CodexPad 设备,并持续监控所有用户输入。
25 * 它展示了三种不同的按钮状态检测: **按下** (瞬间按下)、 **释放** (瞬间释放)和 **持续按住** 。
26 * 同时,它监控模拟摇杆轴,当检测到超过设定阈值的显著变化时打印其值,从而过滤微小抖动。
27 * @note 必须在主循环中尽可能频繁地调用 `Update()` 方法,且不得添加延时,以确保实时响应性并防止数据包丢失。
28 * @see CodexPad::Update
29 * @see CodexPad::pressed
30 * @see CodexPad::released
31 * @see CodexPad::holding
32 * @see CodexPad::HasAxisValueChanged
33 * @see CodexPad::axis_value
34 */
35
36#include "codex_pad.h"
37
38namespace {
39// Replace with your CodexPad device's Bluetooth device address
40// 替换为你的 CodexPad 的 Bluetooth device address
41const std::string kBluetoothDeviceAddress = "E4:66:E5:A2:24:5D";
42
43CodexPad g_codex_pad;
44
45/**
46 * Convert button constant to readable string name
47 * 将按钮枚举转换为可读的字符串名称
48 */
49std::string ButtonToString(CodexPad::Button button) {
50 switch (button) {
52 return "Up"; // 上按钮 | UP button
53 }
55 return "Down"; // 下按钮 | DOWN button
56 }
58 return "Left"; // 左按钮 | LEFT button
59 }
61 return "Right"; // 右按钮 | RIGHT button
62 }
64 return "Square(X)"; // 方形 或者 X 按钮 | SQUARE or X button
65 }
67 return "Triangle(Y)"; // 三角 或者 Y 按钮 | TRIANGLE or Y button
68 }
70 return "Cross(A)"; // 叉型 或者 A 按钮 | CROSS or A button
71 }
73 return "Circle(B)"; // 圆形 或者 B 按钮 | CIRCLE or B button
74 }
76 return "L1"; // L1按钮 | L1 button
77 }
79 return "L2"; // L2按钮 | L2 button
80 }
82 return "L3"; // L3按钮 | L3 button
83 }
85 return "R1"; // R1按钮 | R1 button
86 }
88 return "R2"; // R2按钮 | R2 button
89 }
91 return "R3"; // R3按钮 | R3 button
92 }
94 return "Select"; // 选择按钮 | SELECT button
95 }
97 return "Start"; // 开始按钮 | START button
98 }
100 return "Home"; // 首页按钮 | HOME button
101 }
102 default: {
103 return {}; // 未知按钮返回空字符串 | Unknown button returns empty string
104 }
105 }
106}
107
108void Connect() {
109 printf("Start to connect %s\n", kBluetoothDeviceAddress.c_str());
110 // Connect to the CodexPad with specified Bluetooth device address
111 // 连接到指定蓝牙设备地址的手柄
112 while (!g_codex_pad.Connect(kBluetoothDeviceAddress, 5000)) {
113 printf("Retry to connect %s\n", kBluetoothDeviceAddress.c_str());
114 }
115
116 printf("Remote device name: %s\n", g_codex_pad.remote_device_name().c_str());
117 printf("Remote model number: %s\n", g_codex_pad.remote_model_number().c_str());
118 printf("Remote firmware revision: %u.%u.%u\n",
119 g_codex_pad.remote_firmware_version()[0],
120 g_codex_pad.remote_firmware_version()[1],
121 g_codex_pad.remote_firmware_version()[2]);
122
123 if (const auto ble_client = g_codex_pad.ble_client(); ble_client != nullptr) {
124 printf("Remote Bluetooth Device Address: %s\n", ble_client->getPeerAddress().toString().c_str());
125 } else {
126 printf("Remote Bluetooth Device Address: unknown\n");
127 }
128
129 // Set transmission power to 0dBm
130 // Transmission power affects communication range and power consumption:
131 // Higher power provides longer range but consumes more battery
132 // Choose appropriate power level based on your application to balance range and battery life
133 // 设置发射功率为0dBm
134 // 发射功率影响通信距离和功耗:功率越高,通信距离越远,但功耗也越大
135 // 建议根据实际应用场景选择合适的功率等级以平衡距离和电池寿命
137 printf("Set remote tx power to 0dBm successfully\n");
138 }
139
140 printf("Connected\n");
141}
142} // namespace
143
144void setup() {
145 Serial.begin(115200);
146
147 printf("Init\n");
148 g_codex_pad.Init();
149
150 Connect();
151}
152
153void loop() {
154 // Important: Update() method must be called as frequently as possible in the loop, no delays should be added
155 // This method processes all received Bluetooth packets, delays will cause data loss and response lag
156 // For real-time control applications, high-frequency calls are essential to ensure prompt response to gamepad input
157 // 重要:Update()方法必须在循环中尽可能频繁地调用,不能添加延时
158 // 该方法负责处理所有接收到的蓝牙数据包,延时会导致数据丢失和响应延迟
159 // 对于实时控制应用,必须保持高频率调用以确保及时响应手柄输入
160 g_codex_pad.Update();
161
162 if (!g_codex_pad.is_connected()) {
163 printf("Disconnected, start to reconnect\n");
164 Connect();
165 return;
166 }
167
168 // Detect state changes for all buttons
169 // Use pressed(), released(), holding() methods to detect different button states
170 // 检测所有按钮的状态变化
171 // 使用pressed(), released(), holding()方法检测按钮的不同状态
172 for (auto button : {CodexPad::Button::kUp,
189 // Check if button was just pressed (transition from released to pressed)
190 // 检测按钮是否刚刚按下(从弹起变为按下)
191 if (g_codex_pad.pressed(button)) {
192 printf("Button %s: pressed\n", ButtonToString(button).c_str());
193 }
194
195 // Check if button was just released (transition from pressed to released)
196 // 检测按钮是否刚刚释放(从按下变为弹起)
197 else if (g_codex_pad.released(button)) {
198 printf("Button %s: released\n", ButtonToString(button).c_str());
199 }
200
201 // Check if button is holding
202 // 检测按钮是否持续按下状态
203 else if (g_codex_pad.holding(button)) {
204 printf("Button %s: holding\n", ButtonToString(button).c_str());
205 }
206 }
207
208 // Check if joystick axis values have changed significantly (using threshold to avoid minor jitter)
209 // Threshold is set to 2, only consider changes equal to or greater than 2 units as significant
210 // 检测摇杆轴值是否发生了有效变化(使用阈值避免微小抖动)
211 // 阈值设置为2,只有当摇杆值变化达到或超过2个单位时才认为是有效变化
212 constexpr uint8_t kAxisValueChangeThreshold = 2;
213
214 // Check if left stick X or Y axis has significant change
215 // 检测左摇杆X轴或Y轴是否有显著变化
216 if (g_codex_pad.HasAxisValueChanged(CodexPad::Axis::kLeftStickX, kAxisValueChangeThreshold) ||
217 g_codex_pad.HasAxisValueChanged(CodexPad::Axis::kLeftStickY, kAxisValueChangeThreshold) ||
218 g_codex_pad.HasAxisValueChanged(CodexPad::Axis::kRightStickX, kAxisValueChangeThreshold) ||
219 g_codex_pad.HasAxisValueChanged(CodexPad::Axis::kRightStickY, kAxisValueChangeThreshold)) {
220 // Print current joystick axis values (0-255)
221 // 打印摇杆轴的当前值(0-255)
222 printf("L(X: %3" PRIu8 ", Y:%3" PRIu8 "), R(X: %3" PRIu8 ", Y: %3" PRIu8 ")\n",
223 g_codex_pad.axis_value(CodexPad::Axis::kLeftStickX), // 左摇杆X轴当前值 | Left stick X axis current value
224 g_codex_pad.axis_value(CodexPad::Axis::kLeftStickY), // 左摇杆Y轴当前值 | Left stick Y axis current value
225 g_codex_pad.axis_value(CodexPad::Axis::kRightStickX), // 右摇杆X轴当前值 | Right stick X axis current value
226 g_codex_pad.axis_value(CodexPad::Axis::kRightStickY) // 右摇杆Y轴当前值 | Right stick Y axis current value
227 );
228 }
229}
CodexPad main class.
Definition codex_pad.h:46
const std::array< uint8_t, 3 > remote_firmware_version() const
Get firmware version of the CodexPad.
Definition codex_pad.h:734
const std::string & remote_model_number() const
Get model number of the CodexPad.
Definition codex_pad.h:722
@ kLeftStickX
Left stick X axis.
Definition codex_pad.h:411
@ kRightStickY
Right stick Y axis.
Definition codex_pad.h:441
@ kLeftStickY
Left stick Y axis.
Definition codex_pad.h:421
@ kRightStickX
Right stick X axis.
Definition codex_pad.h:431
bool pressed(const Button button) const
check if a button is pressed
bool Connect(const std::string &bluetooth_device_address, const uint32_t timeout_ms=5000)
Connect.
Definition codex_pad.cpp:38
@ kSelect
Select.
Definition codex_pad.h:369
@ kCrossA
Cross or A.
Definition codex_pad.h:289
@ kSquareX
Square or X.
Definition codex_pad.h:269
@ kCircleB
Circle or B.
Definition codex_pad.h:299
@ kTriangleY
Triangle or Y.
Definition codex_pad.h:279
const std::string & remote_device_name() const
Get model number of the CodexPad.
Definition codex_pad.h:710
NimBLEClient * ble_client() const
Get the BLE client object.
Definition codex_pad.h:903
uint8_t axis_value(const Axis axis) const
Get axis value.
bool HasAxisValueChanged(const Axis axis, const uint8_t threshold) const
check if an axis value has changed
bool set_remote_tx_power(const TxPower power)
Set transmission power, only effective when connected, immediately effective for current connection,...
bool is_connected() const
Is connected.
bool released(const Button button) const
check if a button is released
void Init()
Initialize.
Definition codex_pad.cpp:32
void Update()
Update, need to be called in Loop.
bool holding(const Button button) const
check if a button is held