228|0

3

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【Follow me第二季第2期】汇总提交贴: 全部任务 [复制链接]

  本帖最后由 bigjiong 于 2024-11-16 21:54 编辑

之前有幸参加过几期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地址

链接已隐藏,如需查看请登录或者注册

此例程未使用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

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表