Funpack 3-5 Teensy4.1 网络控制 LED
该项目使用了Teensy4.1,实现了网络控制LED的设计,它的主要功能为:通过网口连接到路由器,在局域网建立一个网页服务器,打开浏览器输入板卡IP地址,即可在网页中点击按键点亮、熄灭LED,拖动滑条控制LED的亮度等级。。
标签
Arduino
Funpack活动
PWM
HTTP
teensy4.1
Batman9527
更新2025-01-15
22


1 项目描述

Funpack第三季第五期活动,选用板卡 Teensy4.1 ,实现任务1,点灯,从板子的以太网排针处引出接口,并通过网口通信,控制板子上的LED灯。

1.1 项目介绍

该项目采用 Teensy4.1 板卡,以 Arduino IDE 作为开发环境,通过网线连接到路由器,建立一个局域网网页,手机或者电脑等移动设备在同一个局域网可以访问网页,在网页上控制板卡上的LED亮灭,也可以拖到滑条控制LED的亮度。

1.2 Teensy4.1 板卡介绍

Teensy4.1 开发板是一款成熟的开发板,具有完整的 Arduino 开发环境,易于开发。它采用恩智浦的 i.MX RT1062 芯片,具有 Arm Cortex-M7 内核,具有实时微控制器性能和高集成度,适用于工业和物联网应用。

i.MX RT1060 CM7 工作频率高度600MHz,具有8MB Flash和1MB片上RAM。该系列提供2D图形、摄像头、各种存储器接口和各种连接接口,包括UART、SPI、I2C、USB、2路10/100M 以太网和 3路 CAN。用于实时应用的其他功能包括高速GPIO、CAN FD 和同步并行 NAND/NOR/PSRAM 控制器。



1.3 设计思路

该项任务分解成以下4个子任务:

  • 开发板点亮、熄灭LED
  • 开发板以PWM的方式调节LED的亮度
  • 开发板通过网线接入网络,创建网页服务器
  • 服务器添加功能,网页控制LED亮灭,拖动滑条控制LED亮度

1.3.1 点亮、熄灭LED

第一次接触 Arduino 开发环境,先从点灯开始。安装 Arduino IDE,创建点灯工程并不难,这里不赘述了。以下是一个最简单的点灯代码:

const int led_pin = 13; // 内置的 LED 管脚是 13

void setup(void)
{
pinMode(led_pin, OUTPUT); // 设置管脚为输出模式
}

void loop(void)
{
digitalWrite(led_pin, HIGH); // 管脚输出高电平
delay(500); // 延时 500ms

digitalWrite(led_pin, LOW); // 管脚输出低电平
delay(500); // 延时 500ms
}

1.3.2 以PWM的方式调节LED亮度

Arduino 平台支持脉宽调制(PWM, Pulse Width Modulation),这是一种用于控制模拟电路或调节数字信号平均功率的技术。PWM 通过快速地开启和关闭数字信号来实现这一点,其占空比(即信号处于高电平的时间与周期的比率)决定了输出的平均电压值。

  • 占空比 (Duty Cycle):是指一个周期内信号为高电平的时间所占的比例。例如,50% 的占空比意味着信号一半时间是高电平,另一半时间是低电平。
  • 频率 (Frequency):PWM 信号的频率决定了每秒钟发生多少个完整的周期。不同的引脚可能支持不同的 PWM 频率。
  • 分辨率 (Resolution):指 PWM 占空比可以设置的精度,通常以位数表示。8 位分辨率意味着有 256 (2^8) 个可能的占空比设置。

并非所有的 Arduino 数字引脚都支持 PWM。例如 Teensy4.1 标有 PWM 的管脚才支持,如下图所示。



analogWrite() 函数

在 Arduino 中,使用 analogWrite() 函数来生成 PWM 信号。该函数接受两个参数:要设置的引脚编号和占空比值(范围通常是0到255,对应0%到100%的占空比)。

通过 PWM 调节 LED 亮度的示例代码如下:

int ledPin = 9; // 选择连接 LED 的引脚

void setup() {
pinMode(ledPin, OUTPUT); // 设置为输出模式
}

void loop() {
for (int i = 0; i <= 255; i++) { // 从 0 到 255 循环
analogWrite(ledPin, i); // 改变 PWM 占空比
delay(15); // 等待 15 毫秒
}
for (int i = 255; i >= 0; i--) { // 从 255 到 0 循环
analogWrite(ledPin, i); // 改变 PWM 占空比
delay(15); // 等待 15 毫秒
}
}

1.3.3 接入网线,创建服务器

连接 Ethernet Kit 到 Teensy4.1 开发板,另一头连接到路由器。然后代码中引入 NativeEthernet 库,先设置MAC和IP地址,然后创建HTTP服务器,等待客户端连接并处里客户端连接请求。

以下代码是一个最简单的示例:

#include <NativeEthernet.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // 设置板卡MAC地址
IPAddress ip(192, 168, 3, 16); // 设置板卡IP 地址
EthernetServer server(80); // 创建以太网服务器,端口 80 (HTTP协议的默认端口)

void handleRequest(String request) {
// TODO: 处理网页请求
}

void sendResponse(EthernetClient client) {
// 生成网页响应,再发送给客户端
}

void setup(void) {
Serial.begin(115200); // 初始化串口
Ethernet.begin(mac, ip); // 初始化以太网
server.begin(); // 初始化HTTP服务器

Serial.println("Server is at " + String(Ethernet.localIP() )); // 打印本地以太网IP地址
}

void loop(void) {

// 监听客户端请求
EthernetClient client = server.available();

if (client) {
boolean currentLineIsBlank = true;
String currentRequest = "";

while (client.connected()) {
if (client.available()) {
char c = client.read();
currentRequest += c;

if (c == '\n' && currentlineIsBlank) { // 请求结束符(空行)
handleRequest(currentRequest); // 处理网页请求


sendResponse(client); // 生成 HTTP 响应,发送网页到客户端
break;
}

if (c == '\n') {
currentLineIsBlank = true;
} else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1);
client.stop();
}
}

1.3.4 网页控制LED亮灭、滑条控制亮度

实现上面的 handleRequest() 函数,处理客户端请求,解析LED控制命令,然后实现 sendRequest() 函数,把执行结果封装成网页响应文本信息,再发送给客户端。

这两个函数的详细实现参见下文软件流程图

1.4 硬件介绍

此次活动采购了两个物件,一个是主控 Teensy4.1,一个是 SparkFun Electronics ETHERNET Kit For Teensy4.1。

在将 Teensy4.1 焊上排针,把 Ethernet Kit 排线、网口焊接到PCB上,最终插入到 Teensy4.1 板卡上,效果如下图3.



插曲:Ethernet Kit 一头通过网线接入到路由器,只有一个灯是亮的。我以为是哪里出问题了,以为另外一个灯坏了。最终检查 Ethernet Kit 原理图,才发现只有一个灯接到了 LED 管脚,另外一个灯两个管脚都浮空。


2 软件流程图

此项目基于 HTTP 服务,在局域网建立一个网页服务器,等待客户端请求,然后处理请求,最后把处理后的结果包装到网页文本中再次发送给客户端。

2.1 主流程

整个程序的主流程如下图所示:

  1. 在全局变量和 setup() 函数中初始化硬件、初始化网络,最后初始化 HTTP 服务;
  2. HTTP 服务等待客户端连接,接收客户端请求;
  3. 处理客户端请求,并发送响应给客户端;
  4. 关闭当前客户端请求,并等待下一个客户端请求;




相关代码如下

#include <Arduino.h>
#include <NativeEthernet.h>

// 设置连接以太网的MAC地址和IP地址
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 3, 16); // 设置开发板的IP地址

// 创建以太网服务器,端口80(HTTP协议的默认端口)
EthernetServer server(80);

// LED控制引脚
int pwmPin = 13; // 使用 PWM 的引脚(pin 13)
int brightness = 128; // 初始化亮度为最大值的一半(128)
int previousBrightness = 128; // 保存熄灭前的亮度

bool isLedOn = true; // 保存LED的开关状态

/*----------------------------------------- 函数声明 ---------------------------------------------*/

void handleRequest(String request);
void sendResponse(EthernetClient client);
int percentToBrightness(int percent);

/*----------------------------------------- 函数实现 ---------------------------------------------*/

// 将百分比转换为对应的 0-255 亮度值
int percentToBrightness(int percent)
{
return map(percent, 0, 100, 0, 255);
}

void setup()
{
Serial.begin(9600); // 初始化串口,用于调试输出
// 初始化以太网
Ethernet.begin(mac, ip);
server.begin();

// 设置LED引脚为输出模式
pinMode(pwmPin, OUTPUT);

// 初始化LED状态和亮度,设置初始亮度为最大值的一半
analogWrite(pwmPin, brightness);

Serial.print("Server is at ");
Serial.println(Ethernet.localIP());
}

void loop()
{
// 监听客户端请求
EthernetClient client = server.available();
if (client) {
boolean currentLineIsBlank = true;
String currentRequest = "";

while (client.connected()) {
if (client.available()) {
char c = client.read();
currentRequest += c;

// 请求结束符(空行)
if (c == '\n' && currentLineIsBlank) {
// 处理网页请求
handleRequest(currentRequest);

// 生成HTTP响应,发送网页到客户端
sendResponse(client);

break;
}
if (c == '\n') {
currentLineIsBlank = true;
} else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1);
client.stop();
}
}

2.2 处理客户端请求

服务器接收到客户端的请求,分为两类:

  1. 一类是 GET /TOGGLE 即网页上的按钮,按下表示LED由点亮变为熄灭,由熄灭变为点亮;
  2. 一类是 BRIGHTNESS= 即网页上的滑条,滑条拖动一次则发送这个请求给服务器。服务器根据滑条数值来改变LED的亮度;

我修复了一个问题,如果滑条拖动到0则熄灭LED,但是如果下次从网页按钮点亮LED,那么由于之前的滑条数值为0,那么点亮LED时的亮度值为0,因此点亮动作执行了但是LED实际没有点亮。我增加了一个变量 previousBrightness 来保存之前的亮度值,如果之前的亮度值为0,再次点亮LED时,默认把亮度值调整为 50% ,可以避免没有点亮的问题。




这个功能对应的函数是 handlRequest(),代码如下:


// 处理客户端请求,解析LED的控制指令
void handleRequest(String request)
{
// 控制LED亮灭
if (request.indexOf("GET /TOGGLE") != -1) {
if (isLedOn) {
previousBrightness = brightness; // 保存当前亮度
analogWrite(pwmPin, 0); // 熄灭LED
isLedOn = false;
} else {
// 重新打开LED,如果亮度为0,恢复最大值的一半
if (previousBrightness == 0) {
brightness = 128;
} else {
brightness = previousBrightness;
}
analogWrite(pwmPin, brightness);
isLedOn = true;
}
} else if (request.indexOf("BRIGHTNESS=") != -1) { // 解析亮度调节请求,百分比值映射到0-255
int index = request.indexOf("BRIGHTNESS=");
String percentValue = request.substring(index + 11); // 百分比值
int percent = percentValue.toInt();

// 将百分比转换为0-255的亮度范围
brightness = percentToBrightness(percent);
brightness = constrain(brightness, 0, 255); // 限制范围为0-255

// 如果亮度不为0,点亮LED
if (brightness > 0) {
analogWrite(pwmPin, brightness); // 使用PWM控制亮度
isLedOn = true; // 无论LED之前是否关闭,都应该点亮
previousBrightness = brightness; // 更新保存的亮度值
} else {
// 如果亮度为0,保持LED关闭
analogWrite(pwmPin, 0);
isLedOn = false;
}
}
}

2.3 发送响应请求

在处理完客户端的请求后,在这个函数 sendResponse() 中构造响应文本,然后发送到对应的客户端。流程如下:

  • 网页界面布局,添加标签、按键、滑条等元素
  • 根据变量 isLedOn 设置 LED 状态的按键样式
  • 根据变量 brightness 亮度值更新滑条的百分比数值
  • 给滑条绑定函数,每当滑条拖动则提交表格,更新 BRIGHTNESS=xxx 请求
  • script 函数,实现滑条拖动时监听状态的函数
  • script 函数,window.load() 窗口加载时更具 isLedOn 更新滑条的背景色
  • script 函数,设置一个定时器,每隔1000ms请求主页
  • 发送网页文本和样式到客户端


3 功能展示及说明

3.1 网页效果

先确保电脑或者手机和开发板在同一个局域网,然后在浏览器中输入开发板IP地址,如下图:

  1. 网页页面中间上方一个标签显示 LED Control
  2. 中间一行左边一个标签 LED Status: 右边是一个按键表示 LED 亮灭的状态,单击可以切换LED 点亮、熄灭;
  3. 下方一行左边一个标签 Set LED Brightness: 右边是一个滑条,拖动可以改变LED亮度。
  4. 如果滑条拖动到最左边,滑条数值为0,则表示关闭LED,同时上方的按键变为灰色;如果拖动滑条数值不为0,上方的按键变为黄色;


演示视频,见 B站视频-Funpack3-5 Teensy4.1 网络控制LED


4 心得体会

此次活动收获颇丰:

  1. 第一次接触 Arduino 开发环境,从零学会了环境搭建、代码编写、调试。随着学习的深入,尝试着用 PlatformIO IDE 也能搭建环境、写代码,更方便的完成任务;
  2. 之前接触过NXP的其他芯片,尝试用 NXP 官方 IDE 开发 i.MX RT1062 点灯程序,编译输出 hex 文件,成功用 Teensy Loader 烧录并运行;
  3. Arduino 环境支持的第三方库非常丰富,引用非常方便,开发项目原型非常便捷;
  4. 引用第三方库创建网页应用非常方便,只需处理用户请求、再发送结果给客户端,流程简洁,可类比UART命令行程序,读取输入、解析命令、执行命令、发送结果;
  5. Arduino IDE 也有缺点,编译每次都从零开始,速度很慢,属实让人着急;用 PlatformIO IDE 就非常方便,支持增量编译。


附件下载
Teensy4.1_Funpack3_5_WebController.ino
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号