Skip to content

Arduino - 三角函数

三角函数是您项目中实现运动、姿态和振荡的关键。无论您是构建机械臂、自平衡机器人,还是创建流畅的视觉效果,sin()、cos() 和 tan() 等函数都是不可或缺的。Arduino 平台通过 <cmath> 库提供了这些标准 C++ 数学函数,该库会自动包含在您的草图中。

这些函数处理的角是弧度,而不是角度。Arduino 环境提供了便捷的辅助函数来在两者之间进行转换。

// 标准三角函数
float sin(float rad); // 返回弧度角正弦值
float cos(float rad); // 返回弧度角余弦值
float tan(float rad); // 返回弧度角正切值
// 反三角函数(返回弧度角)
float asin(float value); // 返回 -1.0 到 1.0 之间值的反正弦
float acos(float value); // 返回 -1.0 到 1.0 之间值的反余弦
float atan(float value); // 返回反正切
float atan2(float y, float x); // 一个更健壮的反正切函数,常用于将坐标转换为角度
// Arduino 特有的角度转换辅助函数
float radians(float deg); // 将角度转换为弧度
double degrees(double rad); // 将弧度转换为角度

在许多经典的 Arduino 开发板(例如基于 AVR 微控制器的 UNO、Nano、Mega)上,double 数据类型是 32 位浮点数,与 float 完全相同。使用 double 不会提供额外的精度,并且可能引起误解。对于这些开发板,最佳实践是坚持使用 float。而在更强大的 32 位开发板(例如 Arduino Due、ESP32 或 MKR 系列)上,double 提供真正的 64 位精度。

让我们使用 sin() 函数在 LED 上创建一个平滑、自然的脉冲效果。正弦波自然地在 -1.0 和 1.0 之间振荡。我们可以将这个值进行缩放,以控制连接到 PWM 引脚的 LED 亮度。

constexpr int LED_PIN = 9; // 需要一个支持 PWM 的引脚(例如 Uno 上的 3, 5, 6, 9, 10, 11)
float angle = 0.0; // 当前正弦函数的角度,单位为弧度
float increment = 0.02; // 角度变化的速度;控制呼吸灯的速度
void setup() {
// 虽然 analogWrite 不需要初始化引脚,但这是一种良好的实践。
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600); // 用于可选调试
}
void loop() {
// 1. 计算正弦值。它将在 -1.0 和 1.0 之间振荡。
float sinValue = sin(angle);
// 2. 将正弦值映射到 LED 亮度范围(0-255)。
// Arduino 中的 map() 函数适用于整数,所以我们将手动处理浮点数。
// 首先,将范围从 [-1.0, 1.0] 转换为 [0.0, 2.0]
float shiftedValue = sinValue + 1.0;
// 接下来,将其缩放到 PWM 的 [0, 255] 范围
int brightness = (int)(shiftedValue * 127.5);
// 3. 设置 LED 亮度
analogWrite(LED_PIN, brightness);
// 4. 增加角度以便在下一次循环迭代中创建动画效果
angle += increment;
// 可选:将数值打印到串口绘图器以可视化波形!
// Serial.println(brightness);
delay(10); // 一个小延迟,用于控制动画速度
}
  • 机器人技术:根据机械臂关节的角度计算其夹持器的 (X, Y) 位置(称为正向运动学)。pos_x = L1 * cos(angle1) + L2 * cos(angle1 + angle2);
  • 导航:使用 atan2(y_diff, x_diff) 计算机器人需要移动的航向(角度)以到达目标坐标。
  • 数据可视化:在 LED 矩阵或图形显示器上创建圆形或波浪形图案。
  • 音频合成:通过将正弦值输出到 DAC(数模转换器)来生成简单的声波。

为了更好地理解这些概念,请尝试将它们可视化!使用 Arduino IDE 的串口绘图器(工具 > 串口绘图器),并结合上面的示例代码(取消 Serial.println 行的注释)。它将随时间绘制亮度值,揭示平滑的正弦波。