- 2024-10-08
-
加入了学习《【Follow me第二季第2期】任务讲解视频》,观看 Follow me第二期任务讲解
- 2024-10-07
-
发表了主题帖:
【Follow me第二季第2期】汇总提交贴: 全部任务
之前有幸参加过几期digikey的活动,这次很荣幸能使用arduino uno R4这块开发板
项目视频演示
https://training.eeworld.com.cn/video/41253
物料展示
物料实物照片
入门任务:搭建环境并开启第一步Blink / 串口打印Hello EEWorld!
使用bing搜索引擎搜索arduino即可进去官网下载软件安装包
根据自己的操作系统下载对应的软件安装包
我这里使用的是windows操作系统,下载后安装软件即可
软件打开后如图所示,安装arduino uno R4支持包
安装好之后就可以愉快玩耍了
关于闪灯可以参考官方提供的blink例程
串口输出借鉴了官方的指导手册
https://www.arduino.cc/reference/en/language/functions/communication/serial/print/
最后将两部分代码融合后
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(921600); // open the serial port at 9600 bps:
Serial.println("User: bigjiong");
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
Serial.println("Hello EEWorld!");
}
串口输出效果:
亮灯图片
灭灯图片
阶段总结:入门任务难度相对适中,只要细心查阅资料,基本都可以完成,我这里调高了串口波特率,这样会方便基础任务ADC采集数据串口打印时的数据吞吐量。
基础任务(必做):驱动12x8点阵LED;
led点阵的代码参考链接如下
https://docs.arduino.cc/tutorials/uno-r4-wifi/led-matrix/
上面链接讲解的很详细,arduino底层使用的是c++类形式的编程方式,驱动函数以public函数的形式对外提供,具体的实现细节属于private部分,我们实际操作中无需太多关注。
下面上代码
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
void setup() {
Serial.begin(115200);
matrix.begin();
}
uint8_t frame[8][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
void leftEye(){
//Left eye
frame[1][3] = 1;
frame[1][4] = 1;
frame[2][3] = 1;
frame[2][4] = 1;
}
void wink(){
//Wink with the left eye
frame[1][3] = 0;
frame[1][4] = 0;
frame[2][3] = 1;
frame[2][4] = 1;
}
void rightEye(){
//Right eye
frame[1][8] = 1;
frame[1][9] = 1;
frame[2][8] = 1;
frame[2][9] = 1;
}
void mouth(){
//Mouth
frame[5][3] = 1;
frame[5][9] = 1;
frame[6][3] = 1;
frame[6][4] = 1;
frame[6][5] = 1;
frame[6][6] = 1;
frame[6][7] = 1;
frame[6][8] = 1;
frame[6][9] = 1;
}
void loop(){
leftEye();
rightEye();
mouth();
matrix.renderBitmap(frame, 8, 12);
delay(1000);
wink();
matrix.renderBitmap(frame, 8, 12);
delay(1000);
}
这里实现了一个眨眼的动画效果
大眼睛图片
小眼睛图片
基础任务(必做):用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线
因为我手里目前没有示波器,所以这三个任务我就合并一起做了使用dac生成正弦波,并通过opamp进行信号放大,然后再通过adc采集电压信号
参考链接
https://docs.arduino.cc/tutorials/uno-r4-minima/dac/
https://docs.arduino.cc/tutorials/uno-r4-minima/opamp/
https://docs.arduino.cc/tutorials/uno-r4-wifi/adc-resolution/
具体代码如下
DAC输出相关代码
#include "analogWave.h" // Include the library for analog waveform generation
analogWave wave(DAC); // Create an instance of the analogWave class, using the DAC pin
int freq = 10; // in hertz, change accordingly
void setup() {
Serial.begin(115200); // Initialize serial communication at a baud rate of 115200
wave.sine(freq); // Generate a sine wave with the initial frequency
}
void loop() {
// put your main code here, to run repeatedly:
}
opamp相关代码
#include <OPAMP.h>
void setup () {
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
}
void loop() {}
ADC采集相关代码
void setup(){
analogReadResolution(14); //change to 14-bit resolution
}
void loop(){
int reading = analogRead(A3); // returns a value between 0-16383
}
具体实现方案,使用dac在A0脚输出正弦波,打开运放功能,利用电阻分压原理,运放输入端A1采集1/2 A0信号,放大器放大2倍后通过A3输出
A4为信号采集引脚,通过手动插拔杜邦线的方式,分别测量放大前信号波形和放大后信号波形。
电路示意图
融合后代码
#include "analogWave.h" // Include the library for analog waveform generation
#include <OPAMP.h>
analogWave wave(DAC); // Create an instance of the analogWave class, using the DAC pin
int freq = 10; // in hertz, change accordingly
void setup() {
Serial.begin(921600); // Initialize serial communication at a baud rate of 115200
wave.sine(freq); // Generate a sine wave with the initial frequency
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
analogReadResolution(14); //change to 14-bit resolution
}
void loop() {
// put your main code here, to run repeatedly:
int adcValue = analogRead(A4); // returns a value between 0-16383
Serial.println(adcValue);
delay(10);
}
实际效果
A4直接采集A0端口DAC输出信号
A4采集运放输入信号
A4采集运放输出信号
阶段总结:需要提高串口波特率,增大数据传输量,以保证采集信号波形不失真,同时也要避免过采样导致不能展示整体波形的问题,在代码循环结构中加入适当延时。
进阶任务(必做):通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)
此任务需要运行home assistant server,我这里使用的是wondiws环境下通过virtual box直接运行官方镜像的方式完成的
具体参考连接
https://www.home-assistant.io/installation/windows
下载完毕后按照教程安装运行即可
运行后效果
输入网址http://homeassistant.local:8123/登录后台界面
创建用户登录后台,登陆后界面如图
安装emqx插件
配置mqtt
添加topic
mqttx客户端通信正常
接下来搞arduino部分代码
Arduino Home Assistant integration使用此代码库的binary-sensor历程作为基础代码
链接地址https://www.arduino.cc/reference/en/libraries/home-assistant-integration/
github地址https://github.com/dawidchyrzynski/arduino-home-assistant
此例程未使用wifi连接,需配合wifis3的wifi web client历程的wifi通信相关代码
两部分代码整合后如下所示
#include "WiFiS3.h"
#include <ArduinoHA.h>
#include "arduino_secrets.h"
#define INPUT_PIN 9
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key index number (needed only for WEP)
int status = WL_IDLE_STATUS;
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;
byte mac[] = {0x00, 0x10, 0xFA, 0x6E, 0x38, 0x4A};
unsigned long lastReadAt = millis();
bool lastInputState = false;
HADevice device(mac, sizeof(mac));
HAMqtt mqtt(client, device);
// "myInput" is unique ID of the sensor. You should define you own ID.
HABinarySensor sensor("myInput");
/* -------------------------------------------------------------------------- */
void setup() {
/* -------------------------------------------------------------------------- */
pinMode(INPUT_PIN, INPUT_PULLUP);
lastInputState = digitalRead(INPUT_PIN);
pinMode(LED_BUILTIN, OUTPUT);
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
printWifiStatus();
Serial.println("\nStarting connection to broker...");
// optional device's details
device.setName("Arduino");
device.setSoftwareVersion("1.0.0");
// optional properties
sensor.setCurrentState(lastInputState);
sensor.setName("Door sensor");
sensor.setDeviceClass("door");
sensor.setIcon("mdi:fire");
mqtt.begin(BROKER_ADDR);
}
/* -------------------------------------------------------------------------- */
void loop() {
/* -------------------------------------------------------------------------- */
mqtt.loop();
// reading the digital input of the Arduino device
if ((millis() - lastReadAt) > 30) { // read in 30ms interval
// library produces MQTT message if a new state is different than the previous one
PinStatus switchState = digitalRead(INPUT_PIN);
sensor.setState(switchState);
digitalWrite(LED_BUILTIN, switchState);
lastInputState = sensor.getCurrentState();
lastReadAt = millis();
}
}
/* -------------------------------------------------------------------------- */
void printWifiStatus() {
/* -------------------------------------------------------------------------- */
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
代码中使用了板载LED同步指示按键状态,使显示效果更加直观
开关按下显示效果
开关未按下显示效果
阶段总结:尽量使用现有的函数库,避免重复造轮子,要活学活用。适当对代码进行裁剪,目前本方案使用的是自动发现逻辑,无需配置home asistant的configure.yaml文件,比较方便。
扩展任务一:通过外部LTR-329 环境光传感器,上传光照度到HA,通过HA面板显示数据
以下是ltr-329的一些介绍信息
安装驱动程序库
先单独测试ltr329数据读取
/***************************************************
This is an example for the LTR329 light sensor that reads both channels
and demonstrates how to set gain and check data validity
Designed specifically to work with the LTR-329 light sensor from Adafruit
----> https://www.adafruit.com/product/5591
These sensors use I2C to communicate, 2 pins are required to
interface
****************************************************/
#include "Adafruit_LTR329_LTR303.h"
Adafruit_LTR329 ltr = Adafruit_LTR329();
void setup() {
Serial.begin(115200);
Serial.println("Adafruit LTR-329 advanced test");
if ( ! ltr.begin(&Wire1) ) {
Serial.println("Couldn't find LTR sensor!");
while (1) delay(10);
}
Serial.println("Found LTR sensor!");
ltr.setGain(LTR3XX_GAIN_2);
Serial.print("Gain : ");
switch (ltr.getGain()) {
case LTR3XX_GAIN_1: Serial.println(1); break;
case LTR3XX_GAIN_2: Serial.println(2); break;
case LTR3XX_GAIN_4: Serial.println(4); break;
case LTR3XX_GAIN_8: Serial.println(8); break;
case LTR3XX_GAIN_48: Serial.println(48); break;
case LTR3XX_GAIN_96: Serial.println(96); break;
}
ltr.setIntegrationTime(LTR3XX_INTEGTIME_100);
Serial.print("Integration Time (ms): ");
switch (ltr.getIntegrationTime()) {
case LTR3XX_INTEGTIME_50: Serial.println(50); break;
case LTR3XX_INTEGTIME_100: Serial.println(100); break;
case LTR3XX_INTEGTIME_150: Serial.println(150); break;
case LTR3XX_INTEGTIME_200: Serial.println(200); break;
case LTR3XX_INTEGTIME_250: Serial.println(250); break;
case LTR3XX_INTEGTIME_300: Serial.println(300); break;
case LTR3XX_INTEGTIME_350: Serial.println(350); break;
case LTR3XX_INTEGTIME_400: Serial.println(400); break;
}
ltr.setMeasurementRate(LTR3XX_MEASRATE_200);
Serial.print("Measurement Rate (ms): ");
switch (ltr.getMeasurementRate()) {
case LTR3XX_MEASRATE_50: Serial.println(50); break;
case LTR3XX_MEASRATE_100: Serial.println(100); break;
case LTR3XX_MEASRATE_200: Serial.println(200); break;
case LTR3XX_MEASRATE_500: Serial.println(500); break;
case LTR3XX_MEASRATE_1000: Serial.println(1000); break;
case LTR3XX_MEASRATE_2000: Serial.println(2000); break;
}
}
void loop() {
bool valid;
uint16_t visible_plus_ir, infrared;
if (ltr.newDataAvailable()) {
valid = ltr.readBothChannels(visible_plus_ir, infrared);
if (valid) {
Serial.print("CH0 Visible + IR: ");
Serial.print(visible_plus_ir);
Serial.print("\t\tCH1 Infrared: ");
Serial.println(infrared);
}
}
delay(100);
}
通过串口助手可以查看传感器数据
下一步将此代码与home-assistant-integration库代码的sensor-integer历程融合后
#include "WiFiS3.h"
#include <ArduinoHA.h>
#include "arduino_secrets.h"
#include "Adafruit_LTR329_LTR303.h"
Adafruit_LTR329 ltr = Adafruit_LTR329();
#define INPUT_PIN 9
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key index number (needed only for WEP)
int status = WL_IDLE_STATUS;
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;
byte mac[] = {0x00, 0x10, 0xFA, 0x6E, 0x38, 0x4A};
unsigned long lastReadAt = millis();
bool lastInputState = false;
HADevice device(mac, sizeof(mac));
HAMqtt mqtt(client, device);
// "myInput" is unique ID of the sensor. You should define you own ID.
HASensorNumber ltrSensor("myLtr");
/* -------------------------------------------------------------------------- */
void setup() {
/* -------------------------------------------------------------------------- */
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
if ( ! ltr.begin(&Wire1) ) {
Serial.println("Couldn't find LTR sensor!");
while (1) delay(10);
}
Serial.println("Found LTR sensor!");
ltr.setGain(LTR3XX_GAIN_2);
ltr.setIntegrationTime(LTR3XX_INTEGTIME_100);
ltr.setMeasurementRate(LTR3XX_MEASRATE_200);
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
printWifiStatus();
Serial.println("\nStarting connection to broker...");
// optional device's details
device.setName("Arduino");
device.setSoftwareVersion("1.0.0");
// optional properties
ltrSensor.setIcon("mdi:home");
ltrSensor.setName("LTR-329");
ltrSensor.setUnitOfMeasurement("lux");
mqtt.begin(BROKER_ADDR);
}
/* -------------------------------------------------------------------------- */
void loop() {
/* -------------------------------------------------------------------------- */
bool valid;
uint16_t visible_plus_ir, infrared;
mqtt.loop();
if (ltr.newDataAvailable()) {
valid = ltr.readBothChannels(visible_plus_ir, infrared);
if (valid) {
Serial.print("CH0 Visible + IR: ");
Serial.println(visible_plus_ir);
}
}
// reading the digital input of the Arduino device
if ((millis() - lastReadAt) > 30) { // read in 30ms interval
// library produces MQTT message if a new state is different than the previous one
ltrSensor.setValue(visible_plus_ir);
lastReadAt = millis();
}
delay(50);
}
/* -------------------------------------------------------------------------- */
void printWifiStatus() {
/* -------------------------------------------------------------------------- */
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
展示效果如图所示
普通光照
开灯效果
阶段总结:不要畏惧苦难,勇往直前。这些代码基本都是10月7日一天时间完成的,中间包含了代码测试和文章编写两部分工作。大概晚上8点40分代码部分工作已完成。坚持不懈,定会成功。还有一点,我承认确实有点拖延了,希望小伙伴们不要学我哦。
项目总结
通过此次活动,使我有幸把玩arduino uno r4这块开发板,首先对主办方表示感谢。本人在2015年左右就有接触过arduino不过当时用的是arduino nano,同时对C++了解可能比较肤浅,只停留在了点灯阶段,随着近几年日常工作中经常用到C++的类编程思想,觉得arduino的开发方式确实比较友好,对外隐藏了技术实现细节,使用户只关注应用逻辑部分的代码即可,并且代码移植性较强。相同的代码可以运行在不同平台的板子上。本次活动的任务也是由浅入深,循序渐进,难度适中,可发挥空间比较大。希望后期多举办几期类似的活动。
项目源码
https://download.eeworld.com.cn/detail/bigjiong/634551
-
上传了资料:
【Follow me第二季第2期】程序源码 user bigjiong
-
加入了学习《Follow me 第二季第2期任务提交》,观看 【得捷电子Follow me】提交视频
- 2024-09-26
-
加入了学习《【Follow me第二季第2期】+开发板硬件介绍和实现任务一 LED灯闪烁和串口打印》,观看 【Follow me第二季第2期】实现任务二 驱动12x8点阵LED;用DAC生成正弦波并放大采集
- 2024-09-11
-
加入了学习《C2837x入门指南》,观看 (3) - 开发环境
-
加入了学习《C2837x入门指南》,观看 (2) - 芯片架构
-
加入了学习《C2837x入门指南》,观看 (1) - 概述
-
加入了学习《直播回放: TI MSPM0 应用详解, 家用电器和电机控制》,观看 TI MSPM0 应用详解, 家用电器和电机控制
-
加入了学习《直播回复: TI CapTIvate - MSP430?电容触摸开发入门》,观看 CapTIvate.p5.套件快速体验
-
加入了学习《直播回复: TI CapTIvate - MSP430?电容触摸开发入门》,观看 CapTIvate.p4.软件开发工具
-
加入了学习《直播回复: TI CapTIvate - MSP430?电容触摸开发入门》,观看 CapTIvate.p2.MCU选型与功能评估
-
加入了学习《直播回复: TI CapTIvate - MSP430?电容触摸开发入门》,观看 CapTIvate.p1.技术介绍
-
加入了学习《直播回放: TI MSPM0 MCU 在汽车系统中的应用》,观看 TI MSPM0 MCU 在汽车系统中的应用
- 2024-09-10
-
加入了学习《串口打印Hello EEWorld!》,观看 控制LED8*12矩阵
- 2024-08-30
-
回复了主题帖:
>>征集 | 使用 MCU,哪些问题最令你头大?
芯片选型方面,能有图形化的界面方便工程师根据芯片板载外设资源进行初筛效果比较好.
针对不同软件平台,目前大方向在朝着图形化配置底层参数的方向前进,这种战略布局使得软件工程师不必去详细阅读多达上百页的芯片datasheet,可以将更多的精力集中在应用层代码的开发工作,同时也方便代码在不同厂家芯片之间的迁移工作.降低耦合性.
芯片底层驱动,建议建立硬件抽象层,寄存器基本上大同小异.
加密的话,要在防解密上下功夫,在芯片band的时候多关注离电源引脚较近的GPIO,防止EMI导致IO电平翻转.
-
回复了主题帖:
【Follow me第二季第2期】+ 基础任务(DAC,OPAMP,ADC)
想在串口看到波形的话,波特率得调大一些,要不波形会失真.