在物联网或者一些项目开发过程中,我们需要相应的开发板,如树莓派、Arduino、Esp8266、ESP32等。不同的案例,选择的板子有所不同。本期为大家带来基于Arduino R4 WIFI 这款板子的测评和使用。
Arduino R4 WiFi和Arduino uno有何不同呢?通过对比,我做了一个表格。
特性 | Arduino Uno | Arduino R4 WIFI |
---|---|---|
核心处理器 | ATmega328P(8位AVR架构,16MHz) | Renesas RA4M1(32位ARM Cortex - M4,48MHz) + ESP32 - S3(WiFi/蓝牙模块) |
内存 | 2KB SRAM,32KB闪存(含0.5KB引导程序) | 32KB SRAM,256KB闪存(含引导程序) + ESP32 - S3独立内存(128KB SRAM,8MB PSRAM) |
引脚资源 | 14个数字引脚(6个PWM),6个模拟输入引脚 | 20个数字引脚(6个PWM),6个模拟输入引脚 + 12位DAC(A0)、CAN总线(D4/D5)、OP AMP |
通信接口 | USB - B(UART转串口),SPI,I2C | USB - C(支持USB 2.0),SPI,I2C,CAN总线,UART |
无线功能 | 需外接扩展板(如ESP8266) | 内置ESP32 - S3模块,支持WiFi 4(802.11 b/g/n)和蓝牙5.0 |
电源管理 | 输入电压6 - 20V(推荐7 - 12V),5V/3.3V输出 | 输入电压6 - 24V(推荐7 - 12V),5V/3.3V输出 + 24V耐压能力(直接驱动电机/LED灯带) |
扩展能力 | 兼容Uno标准扩展板(如Ethernet Shield) | 兼容Uno扩展板,新增Qwiic I2C连接器,支持即插即用传感器 |
板载外设 | 1个用户LED(D13) | 12×8 LED矩阵(支持图形/动画显示)、VRTC(实时时钟)、OFF引脚(低功耗控制) |
价格 | 约15 - 25美元 | 约25 - 35美元 |
可以看到,最大的不同时内存容量的增加以及支持WiFi何蓝牙连接。当然,价格也很可观!
正面
侧面
前
LED矩阵
与其最大的特色,在于可以连接WiFi了。但你会说ESP8266不是更便宜吗?是的,但是Arduino支持更多的模拟脚针,如果是多个数据,esp8266就显得力不从心了。
接下来,我们通过一个小案例来测试其性能。
风速传感器采用小型直流有刷电机与三杯式旋转风杯组装而成,其工作原理为,当环境有水平流动风时,旋转风杯能够产生旋转,并带动小型电机产生电压,其电压与旋转速度基本成正比。利用此信号电压,可以对环境风速进行测量。
线路连接
(棕色)
-- A0(蓝色)
-- GND
实验代码
#include <WiFiS3.h>
#include <ArduinoMqttClient.h>
#include <ArduinoJson.h>
// WiFi 配置
constchar* ssid = "PDCN";
constchar* password = "1234567890";
// MQTT 配置
constchar* mqttServer = "MQTT服务器地址";
constint mqttPort = 1883;
constchar* mqttUser = "admin";
constchar* mqttPassword = "admin";
constchar* mqttClientId = "ArduinoR4_Wind_"; // 将在setup中添加随机数
constchar* mqttTopic = "fengsu"; //订阅主题
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
constint windPin = A0;
char finalClientId[50]; // 存储完整的客户端ID
// 添加校准相关变量
constfloat VOLTAGE_OFFSET = 22.22; // 无风时的电压偏移值(mv)
constint CALIBRATION_SAMPLES = 10; // 校准时的采样次数
float voltageOffset = 0; // 实际测得的电压偏移值
// 生成随机的客户端ID
void generateClientId() {
unsignedlong randNumber = random(1000000, 9999999);
sprintf(finalClientId, "%s%lu", mqttClientId, randNumber);
Serial.print("使用客户端ID: ");
Serial.println(finalClientId);
}
// 校准函数
void calibrateSensor() {
Serial.println("开始校准风速传感器...");
float sum = 0;
for(int i = 0; i < CALIBRATION_SAMPLES; i++) {
int sensorValue = analogRead(windPin);
float voltage = sensorValue * (3.3 / 1023.0) * 1000; // 转换为mv
sum += voltage;
delay(100);
}
voltageOffset = sum / CALIBRATION_SAMPLES;
Serial.print("电压偏移值: ");
Serial.println(voltageOffset);
}
void connectWiFi() {
Serial.println("\n正在连接WiFi...");
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("通信失败!找不到WiFi模块");
while (true);
}
String fv = WiFi.firmwareVersion();
Serial.print("固件版本: ");
Serial.println(fv);
WiFi.disconnect();
delay(1000);
Serial.print("正在连接到 ");
Serial.println(ssid);
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi已连接");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
Serial.print("信号强度: ");
Serial.println(WiFi.RSSI());
} else {
Serial.println("\nWiFi连接失败!");
}
}
void connectMQTT() {
if (!mqttClient.connected()) {
Serial.println("正在连接MQTT服务器...");
// 设置MQTT连接参数
mqttClient.setId(finalClientId);
mqttClient.setUsernamePassword(mqttUser, mqttPassword);
mqttClient.setKeepAliveInterval(60 * 1000);
mqttClient.setCleanSession(true); // 设置Clean Start为true
Serial.print("正在连接到MQTT服务器 ");
Serial.print(mqttServer);
Serial.print(":");
Serial.println(mqttPort);
int attempts = 0;
bool connected = false;
while (!connected && attempts < 5) {
Serial.print("尝试 MQTT 连接...");
if (mqttClient.connect(mqttServer, mqttPort)) {
Serial.println("已连接到MQTT服务器");
connected = true;
} else {
Serial.print("连接失败, 错误 = ");
Serial.println(mqttClient.connectError());
Serial.println("4秒后重试");
delay(4000);
}
attempts++;
}
}
}
void setup() {
Serial.begin(115200);
while (!Serial) {
; // 等待串口连接
}
// 初始化随机数生成器
randomSeed(analogRead(0));
generateClientId();
pinMode(windPin, INPUT);
delay(1000);
// 在连接WiFi前进行校准
calibrateSensor();
connectWiFi();
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi连接断开,尝试重连...");
connectWiFi();
delay(5000);
return;
}
if (!mqttClient.connected()) {
connectMQTT();
}
// 保持MQTT连接
mqttClient.poll();
if (mqttClient.connected()) {
// 读取风速传感器数据
int sensorValue = analogRead(windPin);
float voltage = sensorValue * (3.3 / 1023.0) * 1000; // 转换为mv
// 计算校准后的电压值
float calibratedVoltage = voltage - voltageOffset;
if (calibratedVoltage < 0) calibratedVoltage = 0;
// 使用校准后的电压计算风速
float speed = round(0.027 * calibratedVoltage * 10) / 10.0; // 保留一位小数
StaticJsonDocument<200> doc;
doc["FS"] = speed;
doc["FDJ"] = getWindLevel(speed);
char json[200];
serializeJson(doc, json);
// 发布消息
if (mqttClient.beginMessage(mqttTopic)) {
mqttClient.print(json);
mqttClient.endMessage();
Serial.print("发送成功: ");
Serial.println(json);
} else {
Serial.println("发送失败");
}
}
delay(5000);
}
// 获取风速等级函数
const char* getWindLevel(float speed) {
// 添加一个小的误差范围
constfloat EPSILON = 0.0001; // 误差范围
if (speed >= 0.0 - EPSILON && speed <= 0.2 + EPSILON) return"无风";
elseif (speed > 0.2 && speed <= 1.5) return"软风";
elseif (speed > 1.5 && speed <= 3.3) return"轻风";
elseif (speed > 3.3 && speed <= 5.4) return"微风";
elseif (speed > 5.4 && speed <= 7.9) return"和风";
elseif (speed > 7.9 && speed <= 10.7) return"轻劲风";
elseif (speed > 10.7 && speed <= 13.8) return"强风";
elseif (speed > 13.8 && speed <= 17.1) return"疾风";
elseif (speed > 17.1 && speed <= 20.7) return"大风";
elseif (speed > 20.7 && speed <= 24.4) return"烈风";
elseif (speed > 24.4 && speed <= 28.4) return"狂风";
elseif (speed > 28.4 && speed <= 32.6) return"暴风";
elseif (speed > 32.6) return"飓风";
return"未知等级";
}
效果:
会向fengsu
主题发送json数据,格式如下:
{"FS":1.1,"FDJ":"软风"}