Skip to content

Commit af20237

Browse files
Merge pull request #14 from nulllaborg/v1.1.1
去除AI VOX Board开发板示例,另外AI-VOX3开发板的WS2812b灯环示例和舵机示例优化,改用其他库
2 parents 8b26bd4 + 31fbd6a commit af20237

File tree

212 files changed

+694
-587242
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

212 files changed

+694
-587242
lines changed
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: AI VOX Board Build
1+
name: AI VOX3 Build
22

33
on:
44
push:
@@ -17,8 +17,7 @@ jobs:
1717
AI_VOX_VERSION: "v1.3.0"
1818
strategy:
1919
matrix:
20-
example: ["ai_vox_board/ai_vox_engine_led_mcp", "ai_vox_board/ai_vox_engine_motordriver_mcp","ai_vox_board/ai_vox_engine_servo_mcp","ai_vox_board/ai_vox_engine_ws2812b_mcp",
21-
"ai_vox3/ai_vox_engine_dht11_servo_led_mcp","ai_vox3/ai_vox_engine_led_mcp","ai_vox3/ai_vox_engine_motor_fan_mcp","ai_vox3/ai_vox_engine_motordriver_mcp",
20+
example: ["ai_vox3/ai_vox_engine_dht11_servo_led_mcp","ai_vox3/ai_vox_engine_led_mcp","ai_vox3/ai_vox_engine_motor_fan_mcp","ai_vox3/ai_vox_engine_motordriver_mcp",
2221
"ai_vox3/ai_vox_engine_servo_mcp","ai_vox3/ai_vox_engine_us04_dht11_photosensitive_mcp","ai_vox3/ai_vox_engine_ws2812b_mcp"]
2322
core_version: ["3.2.0"]
2423
fqbn: ["esp32:esp32:esp32s3"]
@@ -50,11 +49,11 @@ jobs:
5049
run: |
5150
${ARDUINO_CLI_DIR}/arduino-cli --config-dir ${ARDUINO_CLI_CONFIG_DIR} lib install "lvgl@9.2.2"
5251
53-
- name: install lib FastLED
52+
- name: install lib Adafruit NeoPixel
5453
run: |
55-
${ARDUINO_CLI_DIR}/arduino-cli --config-dir ${ARDUINO_CLI_CONFIG_DIR} lib install "FastLED@3.10.3"
54+
${ARDUINO_CLI_DIR}/arduino-cli --config-dir ${ARDUINO_CLI_CONFIG_DIR} lib install "Adafruit NeoPixel@1.15.2"
5655
57-
- name: install lib DHT_sensor_library
56+
- name: install lib DHT sensor library
5857
run: |
5958
${ARDUINO_CLI_DIR}/arduino-cli --config-dir ${ARDUINO_CLI_CONFIG_DIR} lib install "DHT sensor library@1.4.6"
6059

.github/workflows/arduino_esp32_build.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@ jobs:
4646
run: |
4747
${ARDUINO_CLI_DIR}/arduino-cli --config-dir ${ARDUINO_CLI_CONFIG_DIR} lib install "lvgl@9.2.2"
4848
49-
- name: install lib FastLED
50-
run: |
51-
${ARDUINO_CLI_DIR}/arduino-cli --config-dir ${ARDUINO_CLI_CONFIG_DIR} lib install "FastLED@3.10.3"
52-
5349
- name: install lib DHT_sensor_library
5450
run: |
5551
${ARDUINO_CLI_DIR}/arduino-cli --config-dir ${ARDUINO_CLI_CONFIG_DIR} lib install "DHT sensor library@1.4.6"

.github/workflows/platform_io_build.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ jobs:
1414
target: [
1515
"esp32_display_lcd",
1616
"esp32_display_oled",
17-
"ai_vox_board_led",
18-
"ai_vox_board_motordriver",
19-
"ai_vox_board_servo",
20-
"ai_vox_board_ws2812b",
2117
"ai_vox3_dht11_servo_led",
2218
"ai_vox3_led",
2319
"ai_vox3_motor_fan",

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/managed_components
2+
dependencies.lock
3+
/sdkconfig
4+
/sdkconfig.old
5+
/build
6+
/.vscode
7+
/.pio

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# AI VOX engine extend examples
2+
3+
[![Arduino ESP32 Build](https://github.com/nulllaborg/ai_vox_engine_extend_examples/actions/workflows/arduino_esp32_build.yml/badge.svg)](https://github.com/nulllaborg/ai_vox_engine_extend_examples/actions/workflows/arduino_esp32_build.yml)
4+
[![AI VOX3 Build](https://github.com/nulllaborg/ai_vox_engine_extend_examples/actions/workflows/ai_vox3_build.yml/badge.svg)](https://github.com/nulllaborg/ai_vox_engine_extend_examples/actions/workflows/ai_vox3_build.yml)
5+
[![PlatformIO Build](https://github.com/nulllaborg/ai_vox_engine_extend_examples/actions/workflows/platform_io_build.yml/badge.svg)](https://github.com/nulllaborg/ai_vox_engine_extend_examples/actions/workflows/platform_io_build.yml)
6+
[![PlatformIO Full Build](https://github.com/nulllaborg/ai_vox_engine_extend_examples/actions/workflows/platform_io_full_build.yml/badge.svg)](https://github.com/nulllaborg/ai_vox_engine_extend_examples/actions/workflows/platform_io_full_build.yml)
7+
18
## 概述
29

310
Arduino IDE版小智AI 扩展示例

ai_vox3/ai_vox_engine_dht11_servo_led_mcp/main.cpp

Lines changed: 17 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "network_config_mode_mp3.h"
2121
#include "network_connected_mp3.h"
2222
#include "notification_0_mp3.h"
23+
#include "servo.h"
2324

2425
#ifndef ARDUINO_ESP32S3_DEV
2526
#error "This example only supports ESP32S3-Dev board."
@@ -90,21 +91,18 @@ std::unique_ptr<Display> g_display;
9091
auto g_observer = std::make_shared<ai_vox::Observer>();
9192
button_handle_t g_button_boot_handle = nullptr;
9293

93-
constexpr uint8_t kServoFrequency = 50;
94-
constexpr uint8_t kServoResolution = 12;
9594
constexpr uint32_t kMinPulse = 500;
9695
constexpr uint32_t kMaxPulse = 2500;
9796
constexpr uint16_t kMaxServoAngle = 180;
9897

99-
constexpr uint32_t kMaxPwmDuty = pow(2, kServoResolution) - 1;
100-
constexpr uint32_t kPwmFactor = 1000 * 1000 / kServoFrequency;
101-
10298
constexpr uint8_t kLcdBacklightChannel = 7;
10399
constexpr uint32_t kDisplayBacklightFrequency = 1000;
104100
constexpr uint8_t kDisplayBacklightResolution = 8;
105101

106102
std::vector<uint16_t> g_servo_angles(kServoPins.size(), 90);
107103

104+
std::vector<std::unique_ptr<em::Servo>> g_servos;
105+
108106
uint8_t g_display_brightness = 255;
109107

110108
DHT g_dht11(kDht11Pin, DHT11);
@@ -534,47 +532,22 @@ void InitMcpTools() {
534532
);
535533
}
536534

537-
uint32_t CalculateDuty(const uint16_t angle) {
538-
// Map the angle to the pulse width(500-2500μs)
539-
const uint32_t pulse_width = map(angle, 0, kMaxServoAngle, kMinPulse, kMaxPulse);
540-
return static_cast<uint32_t>((pulse_width * kMaxPwmDuty) / kPwmFactor);
541-
}
542-
543535
void InitServos() {
544536
printf("init servos\n");
545537

538+
g_servos.clear();
546539
for (uint8_t i = 0; i < kServoPins.size(); i++) {
547-
if (!ledcAttach(kServoPins[i], kServoFrequency, kServoResolution)) {
548-
printf("Error: Failed to attach servo %" PRIu8 " on pin%" PRIu8 " .\n", i, kServoPins[i]);
549-
continue;
550-
}
540+
auto servo = std::make_unique<em::Servo>(kServoPins[i], 0, kMaxServoAngle, kMinPulse, kMaxPulse);
551541

552-
if (!ledcWrite(kServoPins[i], CalculateDuty(g_servo_angles[i]))) {
553-
printf("Error: Failed to set initial duty for servo %" PRIu8 " .\n", i);
542+
if (!servo->Init()) {
543+
printf("Error: Failed to init servo %" PRIu8 " on pin %" PRIu16 "\n", i, kServoPins[i]);
554544
continue;
555545
}
556-
}
557-
}
558546

559-
bool SetServoAngle(const uint8_t servo_index, const uint16_t angle) {
560-
if (servo_index < 1 || servo_index > kServoPins.size()) {
561-
printf("Error: Invalid servo index: %" PRIu8 ", valid range: 1-%" PRIu8 " .\n", servo_index, kServoPins.size());
562-
return false;
563-
}
564-
565-
if (angle > kMaxServoAngle) {
566-
printf("Error: Invalid servo angle: %" PRIu16 " for index: %" PRIu8 " .\n", angle, servo_index);
567-
return false;
568-
}
547+
servo->Write(g_servo_angles[i]);
569548

570-
if (!ledcWrite(kServoPins[servo_index - 1], CalculateDuty(angle))) {
571-
printf("Error: Failed to write duty for servo %" PRIu8 " .\n", servo_index);
572-
return false;
549+
g_servos.push_back(std::move(servo));
573550
}
574-
575-
g_servo_angles[servo_index - 1] = angle;
576-
577-
return true;
578551
}
579552

580553
} // namespace
@@ -771,11 +744,10 @@ void loop() {
771744
}
772745

773746
printf("on mcp tool call: self.servo.set_one_servo, index: %" PRId64 ", angle: %" PRId64 "\n", *index_ptr, *angle_ptr);
774-
if (SetServoAngle(static_cast<uint8_t>(*index_ptr), static_cast<uint16_t>(*angle_ptr))) {
775-
engine.SendMcpCallResponse(mcp_tool_call_event->id, true);
776-
} else {
777-
engine.SendMcpCallError(mcp_tool_call_event->id, "Failed to set servo angle for index: " + std::to_string(*index_ptr));
778-
}
747+
g_servos[*index_ptr - 1]->Write(static_cast<uint16_t>(*angle_ptr));
748+
g_servo_angles[*index_ptr - 1] = *angle_ptr;
749+
750+
engine.SendMcpCallResponse(mcp_tool_call_event->id, true);
779751

780752
} else if ("self.servo.set_range_servos" == mcp_tool_call_event->name) {
781753
const auto start_index_ptr = mcp_tool_call_event->param<int64_t>("start_index");
@@ -820,16 +792,11 @@ void loop() {
820792
*end_index_ptr,
821793
*angle_ptr);
822794

823-
uint8_t index = 0;
824-
for (index = *start_index_ptr; index <= *end_index_ptr; index++) {
825-
if (!SetServoAngle(index, static_cast<uint16_t>(*angle_ptr))) {
826-
engine.SendMcpCallError(mcp_tool_call_event->id, "Failed to set servo angle for index: " + std::to_string(index));
827-
break;
828-
}
829-
}
830-
if (index > *end_index_ptr) {
831-
engine.SendMcpCallResponse(mcp_tool_call_event->id, true);
795+
for (uint8_t index = *start_index_ptr - 1; index < *end_index_ptr; index++) {
796+
g_servos[index]->Write(static_cast<uint16_t>(*angle_ptr));
797+
g_servo_angles[index - 1] = *angle_ptr;
832798
}
799+
engine.SendMcpCallResponse(mcp_tool_call_event->id, true);
833800

834801
} else if ("self.servo.get_index_servo_angle" == mcp_tool_call_event->name) {
835802
const auto index_ptr = mcp_tool_call_event->param<int64_t>("index");
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* @file servo.cpp
3+
*/
4+
5+
#include "servo.h"
6+
7+
#include <Arduino.h>
8+
#include <stdio.h>
9+
10+
#include <cmath>
11+
12+
namespace em {
13+
namespace {
14+
constexpr uint8_t kPwmResolution = 12;
15+
constexpr uint8_t kPwmFrequency = 50;
16+
constexpr uint16_t kMaxAngle = 360;
17+
constexpr int16_t kMaxPwmDuty = pow(2, kPwmResolution) - 1;
18+
constexpr double kPwmFactor = 1 / static_cast<double>(kPwmFrequency) * 1000 * 1000;
19+
20+
double Map(const double x, const double min_in, const double max_in, const double min_out, const double max_out) {
21+
if (x <= min_in) {
22+
return min_out;
23+
} else if (x >= max_in) {
24+
return max_out;
25+
}
26+
27+
return (x - min_in) / (max_in - min_in) * (max_out - min_out) + min_out;
28+
}
29+
30+
} // namespace
31+
Servo::Servo(
32+
const uint8_t pin, const uint16_t min_angle, const uint16_t max_angle, const uint32_t min_pulse_width_us, const uint32_t max_pulse_width_us)
33+
: pin_(pin),
34+
min_angle_(min_angle),
35+
max_angle_(std::min(max_angle, kMaxAngle)),
36+
min_pulse_width_us_(min_pulse_width_us),
37+
max_pulse_width_us_(max_pulse_width_us) {
38+
}
39+
40+
bool Servo::Init() {
41+
return ledcAttach(pin_, kPwmFrequency, kPwmResolution);
42+
}
43+
44+
void Servo::Write(const uint16_t angle) {
45+
WriteMicroseconds(Map(angle, min_angle_, max_angle_, min_pulse_width_us_, max_pulse_width_us_));
46+
}
47+
48+
void Servo::WriteMicroseconds(const double us) {
49+
ledcWrite(pin_, us * kMaxPwmDuty / kPwmFactor);
50+
}
51+
} // namespace em
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#pragma once
2+
3+
#ifndef _EM_SERVO_H_
4+
#define _EM_SERVO_H_
5+
6+
/**
7+
* @file servo.h
8+
*/
9+
10+
#include <stdint.h>
11+
12+
namespace em {
13+
14+
/**
15+
* @~Chinese
16+
* @class Servo
17+
* @brief EspServo类用于控制舵机相关操作。该类仅支持ESP32平台。
18+
*/
19+
/**
20+
* @~English
21+
* @class Servo This class is used to control a servo motor and is supported only on the ESP32 platform.
22+
* @brief The Servo class is used for servo control related operations.
23+
*/
24+
class Servo {
25+
public:
26+
/**
27+
* @~Chinese
28+
* @brief 构造函数,初始化伺服电机的引脚和角度范围。
29+
* @param pin 伺服电机连接的GPIO引脚。
30+
* @param min_angle 最小角度,默认为0度。
31+
* @param max_angle 最大角度,默认为180度。
32+
* @param min_pulse_width_us 最小脉冲宽度(微秒),默认为500微秒。
33+
* @param max_pulse_width_us 最大脉冲宽度(微秒),默认为2500微秒。
34+
*/
35+
/**
36+
* @~English
37+
* @brief Constructor, initializes the servo motor's pin and angle range.
38+
* @param pin The GPIO pin connected to the servo motor.
39+
* @param min_angle The minimum angle, default is 0 degrees.
40+
* @param max_angle The maximum angle, default is 180 degrees.
41+
* @param min_pulse_width_us The minimum pulse width (microseconds), default is 500 microseconds.
42+
* @param max_pulse_width_us The maximum pulse width (microseconds), default is 2500 microseconds.
43+
*/
44+
explicit Servo(const uint8_t pin,
45+
const uint16_t min_angle = 0,
46+
const uint16_t max_angle = 180,
47+
const uint32_t min_pulse_width_us = 500,
48+
const uint32_t max_pulse_width_us = 2500);
49+
50+
/**
51+
* @~Chinese
52+
* @brief 初始化。
53+
* @return 如果初始化成功返回true,否则返回false。
54+
*/
55+
/**
56+
* @~English
57+
* @brief Initializes
58+
* @return Returns true if initialization is successful, otherwise returns false.
59+
*/
60+
bool Init();
61+
62+
/**
63+
* @~Chinese
64+
* @brief 将舵机旋转到指定的角度。
65+
* @param angle 要旋转到的角度。
66+
*/
67+
/**
68+
* @~English
69+
* @brief Rotates the servo motor to the specified angle.
70+
* @param angle The angle to rotate to.
71+
*/
72+
void Write(const uint16_t angle);
73+
74+
/**
75+
* @~Chinese
76+
* @brief 以微秒为单位设置舵机的脉冲宽度。
77+
* @param us 脉冲宽度(微秒)。
78+
*/
79+
/**
80+
* @~English
81+
* @brief Sets the pulse width of the servo in microseconds.
82+
* @param us Pulse width (microseconds).
83+
*/
84+
void WriteMicroseconds(const double us);
85+
86+
private:
87+
Servo(const Servo&) = delete;
88+
Servo& operator=(const Servo&) = delete;
89+
90+
const uint8_t pin_;
91+
const uint16_t min_angle_;
92+
const uint16_t max_angle_;
93+
const uint32_t min_pulse_width_us_;
94+
const uint32_t max_pulse_width_us_;
95+
};
96+
} // namespace em
97+
98+
#endif

0 commit comments

Comments
 (0)