发表了主题帖:
【Follow me第二季第2期】任务汇总贴
本帖最后由 美猴游山 于 2024-9-29 13:35 编辑
任务/项目介绍
这期活动的主角是Arduino UNO R4 WiFi开发板,为了完成所有任务,我还额外搭配了一块树莓派zero和一个BMP280模块。
入门任务(必做):搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
由于是Arduino官方出品的开发板,因此环境搭建十分简单,直接在开发板管理器中添加就可以。
搭建完后就可以把示例程序blink略作修改并上传。代码功能为让LED闪烁并打印内容到串口。
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
Serial.println("Hello EEWorld!");
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
基础任务(必做):驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
这个任务中需要使用到一个第三方库,这个库是TimerOne。使用这个库的目的是用一个定时器来触发正弦波的生成,因此生成正弦波并不需要loop参与。这样我们就可以在loop中读取运算放大器的值,以此来观察放大器是否正常工作。
特别需要注意的是,这里的TimerOne并不能使用库管理器中自带的版本,因为那个版本并不支持Arduino UNO R4 WiFi。修改过的TimerOne我会放在附件中一并上传,需要使用那个库才可以正常工作。
至于LED矩阵的使用,我们并不需要去逐个操作LED,Arduino已经有了现成的方法,我们可以很容易的使用这个方法来画一个笑脸出来。
#include <OPAMP.h>
#include <TimerOne.h>
#include <Arduino_LED_Matrix.h>
ArduinoLEDMatrix matrix;
const int N = 256;
const int amp = 2047;
// minimum value for T: 12
// with digitalWrite: 13 --> 300 Hz
// reducing analogWriteResolution does not help
const int T = 20; // 1E6 / (N * T) = 195 Hz
int sineTab[N];
volatile byte index = 0; // automatic wrap around after 255
const uint32_t happy[] = {
0x19819,
0x80000001,
0x81f8000
};
void setup() {
Serial.begin(115200);
Timer1.initialize(T);
Timer1.attachInterrupt(doIt);
analogWriteResolution(12); // set the analog output resolution to 12 bit (4096 levels)
for (int i = 0; i < N; i++)
sineTab[i] = amp * (sin(TWO_PI * i / N) + 1);
pinMode(8, OUTPUT);
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
matrix.begin();
matrix.loadFrame(happy);
}
void loop() {
Serial.println(analogRead(A3));
}
void doIt() {
int v = sineTab[index++];
analogWrite(DAC, v);
digitalWrite(8, v > amp);
}
OPAMP我使用的是电压跟随器的接线方式,用面包板把运放的反相输入(A2)和输出(A3)连接在一起,再把DAC输出(A0)连接到运放正向输入端(A1).
进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
扩展任务:通过外部BMP280传感器,上传温度和气压到HA,通过HA面板显示数据
这两个任务由于都是连接到Homeassistant中,因此我放到一起来进行说明。
首先需要在树莓派上安装Homeassistant。安装方法非常简单,先去https://www.raspberrypi.com/software/下载树莓派官方的刷机程序:
下载完后进行安装,然后再写入操作系统页面选择HomeAssistant,烧写到TF卡,然后插入树莓派,并上电,就可以完成安装。
安装完成后通过SSH进入树莓派,使用下面命令就可以安装MQTT:
sudo apt-get install mosquitto
安装好后,进入HA的管理页面,添加mqtt集成,就可以完成配置。
接下来编写Arduino UNO R4 WiFi的代码。在代码中我们使用了自动配置的方式,因此只要完成代码上传,便会自动在Homeassistant中添加好设备,无需再手动配置HomeAssistant。
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "DFRobot_BMP280.h"
#include "Wire.h"
const char* ssid = "";
const char* password = "";
const char* mqtt_username = "";
const char* mqtt_password = "";
const char* mqtt_id = "Arduino_UNO_R4";
IPAddress server(192, 168, 0, 0);
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
typedef DFRobot_BMP280_IIC BMP; // ******** use abbreviations instead of full names ********
BMP bmp(&Wire, BMP::eSdoLow);
#define SEA_LEVEL_PRESSURE 1015.0f // sea level pressure
// show last sensor operate status
void printLastOperateStatus(BMP::eStatus_t eStatus) {
switch (eStatus) {
case BMP::eStatusOK: Serial.println("everything ok"); break;
case BMP::eStatusErr: Serial.println("unknow error"); break;
case BMP::eStatusErrDeviceNotDetected: Serial.println("device not detected"); break;
case BMP::eStatusErrParameter: Serial.println("parameter error"); break;
default: Serial.println("unknow status"); break;
}
}
void setup() {
Serial.begin(115200);
Serial.println("Starting...");
connectWifi();
mqttClient.setServer(server, 1883);
connectMQTTServer();
delay(1000);
config_Sensor_1();
config_Sensor_2();
bmp.reset();
while (bmp.begin() != BMP::eStatusOK) {
Serial.println("bmp begin faild");
printLastOperateStatus(bmp.lastOperateStatus);
delay(2000);
}
Serial.println("bmp begin success");
}
void loop() {
if (!mqttClient.connected()) {
connectMQTTServer();
}
mqttClient.loop();
float temp = bmp.getTemperature();
uint32_t press = bmp.getPressure();
mqttClient.publish("homeassistant/sensor/bmp280_temperature/state", String(temp).c_str());
mqttClient.publish("homeassistant/sensor/bmp280_pressure/state", String(press).c_str());
delay(2000);
}
void connectMQTTServer() {
if (mqttClient.connect(mqtt_id, mqtt_username, mqtt_password)) {
Serial.println("Connected to MQTT Server.");
} else {
Serial.print("Failed to connect. State: ");
Serial.println(mqttClient.state());
delay(3000);
}
}
void connectWifi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nWiFi Connected!");
Serial.println(WiFi.localIP());
}
void config_Sensor_1() {
const char* topic = "homeassistant/sensor/bmp280_temperature/config";
JsonDocument doc;
doc["name"] = "bmp280_temperature";
doc["state_topic"] = "homeassistant/sensor/bmp280_temperature/state";
char output[256];
serializeJson(doc, output);
if (mqttClient.publish(topic, output)) {
Serial.println("Success");
} else {
Serial.println("Failed");
}
}
void config_Sensor_2() {
const char* topic = "homeassistant/sensor/bmp280_pressure/config";
JsonDocument doc;
doc["name"] = "bmp280_pressure";
doc["state_topic"] = "homeassistant/sensor/bmp280_pressure/state";
char output[256];
serializeJson(doc, output);
if (mqttClient.publish(topic, output)) {
Serial.println("Success");
} else {
Serial.println("Failed");
}
}
回到HomeAssistnt页面,便会直接看到首页多出来了两个设备。
BMP280模块接线使用的是I2C接口,只需要把5V,GND, SCL, SDA四根线一一对应接上就可以。
对本活动的心得体会
FM活动选择的开发板都是简单容易上手的,非常适合初学者,大力支持这样的活动!
项目代码:https://download.eeworld.com.cn/detail/%E7%BE%8E%E7%8C%B4%E6%B8%B8%E5%B1%B1/634526