1+ /*
2+ * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
3+ *
4+ * SPDX-License-Identifier: MIT
5+ */
6+
7+ #include " M5Chain.h"
8+
9+ // Serial Pin Definitions / 串口引脚定义
10+ #define TXD_PIN (GPIO_NUM_32 ) /* *< Transmit Pin / 发送引脚 */
11+ #define RXD_PIN (GPIO_NUM_33 ) /* *< Receive Pin / 接收引脚 */
12+
13+ // Configuration Constants / 配置常量
14+ #define LOOP_DELAY_MS (500 ) /* *< Loop delay in milliseconds / 循环延迟(毫秒) */
15+
16+ // Global Objects and Variables / 全局对象和变量
17+ Chain M5Chain; /* *< M5Chain instance / M5Chain实例 */
18+ device_list_t *devices_list = NULL ; /* *< Device list pointer / 设备列表指针 */
19+ uint16_t device_nums = 0 ; /* *< Device count / 设备数量 */
20+ uint8_t operation_status = 0 ; /* *< Operation status / 操作状态 */
21+ chain_status_t chain_status = CHAIN_OK ; /* *< Chain status / 链路状态 */
22+
23+ // Function Declarations / 函数声明
24+ void printDeviceList (device_list_t *devices);
25+ void updateDeviceList ();
26+ bool initializeAdcModes ();
27+ bool readAndDisplayAdcValues ();
28+
29+ void setup ()
30+ {
31+ Serial.begin (115200 );
32+ Serial.println (" M5Chain Unit 8Servos2 Chain ADC Test" );
33+
34+ // Initialize M5Chain communication / 初始化M5Chain通信
35+ M5Chain.begin (&Serial2, 115200 , RXD_PIN , TXD_PIN );
36+
37+ // Update device list / 更新设备列表
38+ updateDeviceList ();
39+
40+ // Initialize all ADC modes / 初始化所有ADC模式
41+ if (!initializeAdcModes ()) {
42+ Serial.println (" ADC mode initialization failed / ADC模式初始化失败" );
43+ }
44+ }
45+
46+ void loop ()
47+ {
48+ // Validate device list validity / 验证设备列表有效性
49+ if (!devices_list) {
50+ Serial.println (" Device list is NULL / 设备列表为空" );
51+ delay (LOOP_DELAY_MS );
52+ return ;
53+ }
54+
55+ // Read and display ADC values / 读取并显示ADC值
56+ if (!readAndDisplayAdcValues ()) {
57+ Serial.println (" ADC reading or validation failed / ADC读取或验证失败" );
58+ }
59+
60+ delay (LOOP_DELAY_MS );
61+ }
62+
63+ /* *
64+ * @brief Initialize ADC modes for all 8Servos2 devices / 初始化所有8Servos2设备的ADC模式
65+ *
66+ * Set all channels to ADC mode and verify the operation / 将所有通道设置为ADC模式并验证操作
67+ *
68+ * @return true if successful / 成功返回true
69+ * @return false if failed / 失败返回false
70+ */
71+ bool initializeAdcModes ()
72+ {
73+ if (!devices_list) {
74+ Serial.println (" Device list is NULL, cannot initialize / 设备列表为空,无法初始化" );
75+ return false ;
76+ }
77+
78+ // Prepare ADC mode configuration / 准备ADC模式配置
79+ user_gpio_mode_t mode[SERVOS2_GPIO_NUM_MAX ];
80+ for (uint8_t i = 0 ; i < SERVOS2_GPIO_NUM_MAX ; i++) {
81+ mode[i] = USER_GPIO_ADC_MODE ;
82+ }
83+
84+ bool all_success = true ;
85+
86+ // Iterate through all devices / 遍历所有设备
87+ for (uint8_t i = 0 ; i < devices_list->count ; i++) {
88+ // Check device type / 检查设备类型
89+ if (devices_list->devices [i].device_type != UNIT_8SERVOS2_CHAIN_TYPE_CODE ) {
90+ continue ;
91+ }
92+
93+ uint8_t device_id = devices_list->devices [i].id ;
94+
95+ // Write operation: Set ADC mode for all channels / 写入操作:设置所有通道ADC模式
96+ chain_status = M5Chain.setServosModeAll (device_id, mode, SERVOS2_GPIO_NUM_MAX , &operation_status);
97+
98+ // Validate write operation / 验证写入操作
99+ if (chain_status != CHAIN_OK ) {
100+ Serial.printf (
101+ " Device ID[%d] set all channel ADC mode failed (communication error) / "
102+ " 设备ID[%d]设置所有通道ADC模式失败(通信错误)\r\n " ,
103+ device_id, device_id);
104+ all_success = false ;
105+ continue ;
106+ }
107+
108+ if (operation_status != 1 ) {
109+ Serial.printf (
110+ " Device ID[%d] set all channel ADC mode failed (operation status error) / "
111+ " 设备ID[%d]设置所有通道ADC模式失败(操作状态异常)\r\n " ,
112+ device_id, device_id);
113+ all_success = false ;
114+ continue ;
115+ }
116+
117+ // Read verification: Confirm mode was set correctly / 读取验证:确认模式设置正确
118+ user_gpio_mode_t read_mode[SERVOS2_GPIO_NUM_MAX ];
119+ if (M5Chain.getServosModeAll (device_id, read_mode, SERVOS2_GPIO_NUM_MAX ) != CHAIN_OK ) {
120+ Serial.printf (" Device ID[%d] read all channel ADC mode failed / 设备ID[%d]读取所有通道ADC模式失败\r\n " ,
121+ device_id, device_id);
122+ all_success = false ;
123+ continue ;
124+ }
125+
126+ // Verify data consistency for all channels / 验证所有通道的数据一致性
127+ uint8_t err_count = 0 ;
128+ for (uint8_t j = 0 ; j < SERVOS2_GPIO_NUM_MAX ; j++) {
129+ if (read_mode[j] != USER_GPIO_ADC_MODE ) {
130+ err_count++;
131+ Serial.printf (
132+ " Device ID[%d] channel %d mode verification failed: expected ADC_MODE, got %d / "
133+ " 设备ID[%d]通道%d模式验证失败:期望ADC_MODE,实际%d\r\n " ,
134+ device_id, j, read_mode[j], device_id, j, read_mode[j]);
135+ }
136+ }
137+
138+ if (err_count == 0 ) {
139+ Serial.printf (
140+ " Device ID[%d] all channel ADC mode set and verified successfully / "
141+ " 设备ID[%d]所有通道ADC模式设置并验证成功\r\n " ,
142+ device_id, device_id);
143+ } else {
144+ Serial.printf (" Device ID[%d] has %d channels with incorrect mode / 设备ID[%d]有%d个通道模式不正确\r\n " ,
145+ device_id, err_count, device_id, err_count);
146+ all_success = false ;
147+ }
148+ }
149+
150+ return all_success;
151+ }
152+
153+ /* *
154+ * @brief Read and display ADC values from all channels / 读取并显示所有通道的ADC值
155+ *
156+ * Process: Verify mode -> Read ADC values -> Display values /
157+ * 流程:验证模式 -> 读取ADC值 -> 显示数值
158+ *
159+ * @return true if successful / 成功返回true
160+ * @return false if failed / 失败返回false
161+ */
162+ bool readAndDisplayAdcValues ()
163+ {
164+ bool all_success = true ;
165+
166+ // Iterate through all devices / 遍历所有设备
167+ for (uint8_t i = 0 ; i < devices_list->count ; i++) {
168+ // Check device type / 检查设备类型
169+ if (devices_list->devices [i].device_type != UNIT_8SERVOS2_CHAIN_TYPE_CODE ) {
170+ continue ;
171+ }
172+
173+ uint8_t device_id = devices_list->devices [i].id ;
174+ user_gpio_mode_t mode[SERVOS2_GPIO_NUM_MAX ];
175+ uint16_t adc_val[SERVOS2_GPIO_NUM_MAX ];
176+
177+ // Step 1: Read and verify current mode / 步骤1:读取并验证当前模式
178+ if (M5Chain.getServosModeAll (device_id, mode, SERVOS2_GPIO_NUM_MAX ) != CHAIN_OK ) {
179+ Serial.printf (
180+ " Device ID[%d] get all channel ADC mode failed (communication error) / "
181+ " 设备ID[%d]获取所有通道ADC模式失败(通信错误)\r\n " ,
182+ device_id, device_id);
183+ all_success = false ;
184+ continue ;
185+ }
186+
187+ // Verify all channels are in ADC mode / 验证所有通道都处于ADC模式
188+ uint8_t err_count = 0 ;
189+ for (uint8_t j = 0 ; j < SERVOS2_GPIO_NUM_MAX ; j++) {
190+ if (mode[j] != USER_GPIO_ADC_MODE ) {
191+ err_count++;
192+ }
193+ }
194+
195+ if (err_count != 0 ) {
196+ Serial.printf (" Device ID[%d] has %d channels not in ADC mode / 设备ID[%d]有%d个通道不在ADC模式\r\n " ,
197+ device_id, err_count, device_id, err_count);
198+ all_success = false ;
199+ continue ;
200+ }
201+
202+ // Step 2: Read ADC values from all channels / 步骤2:读取所有通道的ADC值
203+ if (M5Chain.getServosAdcValueAll (device_id, adc_val, SERVOS2_GPIO_NUM_MAX ) != CHAIN_OK ) {
204+ Serial.printf (
205+ " Device ID[%d] get all channel ADC value failed (communication error) / "
206+ " 设备ID[%d]获取所有通道ADC值失败(通信错误)\r\n " ,
207+ device_id, device_id);
208+ all_success = false ;
209+ continue ;
210+ }
211+
212+ // Step 3: Display ADC values for all channels / 步骤3:显示所有通道的ADC值
213+ Serial.printf (" === Device ID[%d] ADC Values / 设备ID[%d] ADC值 ===\r\n " , device_id, device_id);
214+ for (uint8_t j = 0 ; j < SERVOS2_GPIO_NUM_MAX ; j++) {
215+ Serial.printf (" Channel %d: %d (0x%04X) / 通道 %d: %d (0x%04X)\r\n " , j, adc_val[j], adc_val[j], j,
216+ adc_val[j], adc_val[j]);
217+ }
218+ Serial.println (" ==========================================" );
219+ }
220+
221+ return all_success;
222+ }
223+
224+ /* *
225+ * @brief Print device list information / 打印设备列表信息
226+ *
227+ * @param devices Device list pointer / 设备列表指针
228+ */
229+ void printDeviceList (device_list_t *devices)
230+ {
231+ if (devices == NULL ) {
232+ Serial.println (" Device list is NULL / 设备列表为空" );
233+ return ;
234+ }
235+
236+ Serial.print (" Device count / 设备数量: " );
237+ Serial.println (devices->count );
238+
239+ for (uint8_t i = 0 ; i < devices->count ; i++) {
240+ Serial.printf (" Device #%d - ID: %d, Type: 0x%02X / 设备 #%d - ID: %d, 类型: 0x%02X\r\n " , i,
241+ devices->devices [i].id , devices->devices [i].device_type , i, devices->devices [i].id ,
242+ devices->devices [i].device_type );
243+ }
244+ }
245+
246+ /* *
247+ * @brief Update device list / 更新设备列表
248+ *
249+ * Detect connected devices and retrieve device information / 检测连接的设备并获取设备信息
250+ */
251+ void updateDeviceList ()
252+ {
253+ // Check device connection status / 检查设备连接状态
254+ if (!M5Chain.isDeviceConnected ()) {
255+ Serial.println (" Devices not connected / 设备未连接" );
256+ return ;
257+ }
258+
259+ Serial.println (" Devices connected / 设备已连接" );
260+
261+ // Get device count / 获取设备数量
262+ chain_status = M5Chain.getDeviceNum (&device_nums);
263+ if (chain_status != CHAIN_OK ) {
264+ Serial.printf (" Get device count failed, error code: %d / 获取设备数量失败,错误码: %d\r\n " , chain_status,
265+ chain_status);
266+ return ;
267+ }
268+
269+ // Allocate device list memory / 分配设备列表内存
270+ devices_list = (device_list_t *)malloc (sizeof (device_list_t ));
271+ if (!devices_list) {
272+ Serial.println (" Memory allocation failed / 内存分配失败" );
273+ return ;
274+ }
275+
276+ devices_list->count = device_nums;
277+ devices_list->devices = (device_info_t *)malloc (sizeof (device_info_t ) * device_nums);
278+
279+ if (!devices_list->devices ) {
280+ Serial.println (" Device info memory allocation failed / 设备信息内存分配失败" );
281+ free (devices_list);
282+ devices_list = NULL ;
283+ return ;
284+ }
285+
286+ // Get device list / 获取设备列表
287+ if (M5Chain.getDeviceList (devices_list)) {
288+ Serial.println (" Get device list success / 获取设备列表成功" );
289+ printDeviceList (devices_list);
290+ } else {
291+ Serial.println (" Get device list failed / 获取设备列表失败" );
292+ // Clean up allocated memory / 清理已分配的内存
293+ free (devices_list->devices );
294+ free (devices_list);
295+ devices_list = NULL ;
296+ }
297+ }
0 commit comments