superw 发表于 2024-10-8 17:51

【Follow me第二季第2期】+项目总结

本帖最后由 superw 于 2024-11-6 02:00 编辑

<div><br />
<iframe allowfullscreen="true" frameborder="0" height="450" src="https://training.eeworld.com.cn/shareOpenCourseAPI?isauto=true&amp;lessonid=41265" style="background:#eee;margin-bottom:10px;" width="700"></iframe></div>

<div>文章中各任务均由图片中物料实现</div>

<div>
<div style="text-align: center;"></div>

<p>物料清单:</p>

<table align="center" border="1" cellpadding="1" cellspacing="1">
        <tbody>
                <tr>
                        <td>厂商</td>
                        <td>厂商料号</td>
                        <td>名称</td>
                        <td>得捷链接</td>
                </tr>
                <tr>
                        <td>Arduino</td>
                        <td>ABX00087&nbsp;</td>
                        <td>Arduino UNO R4 WiFi</td>
                        <td><a href="https://www.digikey.cn/zh/products/detail/arduino/ABX00087/20371539?s=N4IgTCBcDaIIICEAaAGNAOA7AApAXQF8g" target="_blank">https://www.digikey.cn/zh/products/detail/arduino/ABX00087/20371539?s=N4IgTCBcDaIIICEAaAGNAOA7AApAXQF8g</a></td>
                </tr>
                <tr>
                        <td>Adafruit</td>
                        <td>4991</td>
                        <td>
                        <p>Adafruit I2C STEMMA QT</p>

                        <p>Rotary Encoder Breakout with</p>

                        <p>Neopixel</p>
                        </td>
                        <td><a href="https://www.digikey.cn/zh/products/detail/adafruit-industries-llc/4991/14302511" target="_blank">https://www.digikey.cn/zh/products/detail/adafruit-industries-llc/4991/14302511</a></td>
                </tr>
                <tr>
                        <td>Adafruit</td>
                        <td>5591</td>
                        <td>Adafruit LTR-329 Light Sensor</td>
                        <td><a href="https://www.digikey.cn/zh/products/detail/adafruit-industries-llc/5591/16733167" target="_blank">https://www.digikey.cn/zh/products/detail/adafruit-industries-llc/5591/16733167</a></td>
                </tr>
        </tbody>
</table>

<p>&nbsp;</p>
</div>

<div><strong>一、</strong><strong>入门任务(必做):</strong>搭建环境并开启第一步Blink / 串口打印Hello EEWorld!</div>

<div>&nbsp;</div>

<div>Arduino官方的板子,当然要用Arduino IDE来开发,在Arduino官网根据自己的操作系统下载对应的安装程序,一路next即可。当然电脑硬盘不够的也可以选择使用便携版IDE或者浏览器开发。</div>

<div>安装完成后,搭建环境。按照官方指南<a href="https://docs.arduino.cc/tutorials/uno-r4-wifi/r4-wifi-getting-started/">https://docs.arduino.cc/tutorials/uno-r4-wifi/r4-wifi-getting-started/</a>,安装Board Package后,即可进行编译下载代码。</div>

<div>硬件分析:</div>

<div>
<div style="text-align: center;"></div>

<p>&nbsp;</p>
</div>

<div>板载DL4通过MOS管驱动,当P102输出高电平点亮DL4,当P102输出低电平熄灭DL4。</div>

<div>
<p>软件实现:</p>

<p>通过在loop函数中循环翻转P102电平,并附加相应延时,即可实现板载LED闪烁。Arduino官方开发板默认串口使用Serial.begin进行初始化,其他通信串口使用Serialx.begin初始化(x=1,2,...),串口初始化成功后,可通过print,println函数进行打印。</p>

<div style="text-align: center;"></div>

<p>代码实现:</p>
</div>

<div>
<pre>
<code class="language-cpp">
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
// put your main code here, to run repeatedly:
Serial.println("Hello EEWorld!");
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
</code></pre>

<p>&nbsp;</p>
</div>

<div>上面代码实现任务一,控制板载LED Blink,同时通过串口打印Hello EEWorld!</div>

<div>实现效果:</div>

<div></div>

<div></div>

<div>&nbsp;</div>

<div><strong>二、基础任务(必做):</strong>驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线</div>

<div>对于Arduino UNO R4 WiFi板上资源,官方提供了详细的指南。</div>

<div>对于点阵LED,可参考<a href="https://docs.arduino.cc/tutorials/uno-r4-wifi/led-matrix/">https://docs.arduino.cc/tutorials/uno-r4-wifi/led-matrix/</a></div>

<div>对于片上DAC,可参考<a href="https://docs.arduino.cc/tutorials/uno-r4-wifi/dac/">https://docs.arduino.cc/tutorials/uno-r4-wifi/dac/</a></div>

<div>对于片上OPAMP,可参考<a href="https://docs.arduino.cc/tutorials/uno-r4-wifi/opamp/">https://docs.arduino.cc/tutorials/uno-r4-wifi/opamp/</a></div>

<div>对于片上ADC,可参考<a href="https://docs.arduino.cc/tutorials/uno-r4-wifi/adc-resolution/">https://docs.arduino.cc/tutorials/uno-r4-wifi/adc-resolution/</a></div>

<div>综合根据上面指南,可以完成任务二。</div>

<div>硬件分析:本任务涉及到的硬件资源,开发板上均已具备,且对于DAC、OPAMP、ADC均为MCU片上资源,直接通过对应函数操作硬件即可。</div>

<div>对于OPAMP放大DAC信号,需要使用面包板,通过片上OPAMP运放单元搭建一个简易的运算放大器。原理图如下:</div>

<div>
<div style="text-align: center;"></div>

<p>上面的实现是一个电压跟随器,但电压跟随器可以理解为一个特殊的运算放大器,增益为1,输出电压与输入电压同幅值,同频率。电压跟随器在电路中经常起到缓冲和隔离的作用。</p>

<p>将A0(DAC输出)接入A1(OPAMP的正向输入端),A2(OPAMP的反向输入端)和A3短接(OPAMP的输出端),此时便可在A3用示波器观察到与A0的输出波形一致。将A3(OPAMP的输出端)与A4(ADC采集)短接,便可以获取到ADC采集到的信号电压。</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>
</div>

<div>代码实现:</div>

<div>
<pre>
<code class="language-cpp">#include "analogWave.h"
#include "OPAMP.h"
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"

analogWave wave(DAC);
ArduinoLEDMatrix matrix;

int freq = 10;

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
wave.sine(freq);
OPAMP.begin(OPAMP_SPEED_HIGHSPEED);
analogReadResolution(14);

matrix.begin();

}

void loop() {
// put your main code here, to run repeatedly:
int adc_value = analogRead(A4);
Serial.println("current adc value is " + String(adc_value));

    // Make it scroll!
matrix.beginDraw();

matrix.stroke(0xFFFFFFFF);
matrix.textScrollSpeed(50);

// add the text
const char text[] = "   EEWorld &amp; DigiKey   ";
matrix.textFont(Font_4x6);
matrix.beginText(0, 1, 0xFFFFFF);
matrix.println(text);
matrix.endText(SCROLL_LEFT);

matrix.endDraw();
}
</code></pre>

<p>实现效果:</p>
</div>

<div>对于12x8点阵LED,上电后会看到EEWorld &amp; DigiKey的字样。</div>

<div>
<div style="text-align: center;"></div>

<p>手机相机拍的不是很清,人眼视觉效果会相对好点。</p>

<p>用DAC生成正弦波,并经过OPAMP放大DAC信号,现象可通过示波器观察得到。</p>

<div style="text-align: center;"></div>

<p>由于手里没有插件电阻,将片上的OPAMP运放配置为电压跟随器模式,即输入为什么信号,输出就是什么信号。图中黄色为原始DAC正弦波信号,绿色为经过电压跟随器后输出的正弦波信号,二者幅值频率均相等。</p>

<p>用ADC采集生成的正弦波信号,并打印到串口,借助Arduino IDE的串口上位机可将波形大致呈现出来。</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

<p><strong>三、进阶任务(必做):</strong>通过Wi-Fi,利用MQTT协议接入到开源的智能家居平台HA(HomeAssistant)</p>

<p><strong>四、</strong><b>扩展任务一:</b>通过外部LTR-329 环境光传感器,上传光照度到HA,通过HA面板显示数据</p>
</div>

<div>首先,非常感谢这期老师给大家带来的直播任务讲解,里面清楚的介绍了如何在windows平台上搭建HomeAssistant环境。当然,我自己也尝试了在泰山派上通过docker安装HomeAssistant,但貌似是由于Docker Hub不稳定的问题,总是访问超时,在ubuntu上也不会魔法上网,只能放弃。后来又尝试安装CasaOS(系统本身已具有docker),但最终还是需要通过docker访问HomeAssistant的Docker Hub,也未能完整实现。最终选择了直播中老师讲解的方法,在windows上安装Docker Desktop,之后拉取HomeAssistant镜像,并创建容器。</div>

<div>具体搭建过程可参考直播讲解<a href="https://training.eeworld.com.cn/video/40793">https://training.eeworld.com.cn/video/40793</a></div>

<div></div>

<div>HomeAssistant界面</div>

<div></div>

<div>EMQX(MQTT)服务器界面</div>

<div>硬件分析:</div>

<div>
<div style="text-align: center;"></div>

<p>上图为任务推荐的LTR329光照传感器模块,板载Qwiic接口。对应Adafruit采购型号为5591。</p>
</div>

<div>
<div style="text-align: center;"></div>

<p>上图为任务之外选购的编码器模块,板载Qwiic接口。对应Adafruit采购型号为4991。板载一个内置固件的MCU,采集板载的编码器信息,并且支持外部IIC总线访问来获取。</p>
</div>

<div>
<div style="text-align: center;"></div>

<p>上图为Arduino开发板的J2接口,硬件形式为Qwiic,可通过SH1.0排线将上述两个模块串联到一块,共同挂载在IIC总线上,通过IIC主机寻址不同的设备地址,访问设备。</p>

<p>注意:LTR329的IIC地址为0x29,编码器模块的IIC地址为0x36。</p>
</div>

<div>软件实现:</div>

<div>打开Library Manager,搜索框输入LTR329,安装对应的Library。详细介绍及驱动代码可见<a href="https://learn.adafruit.com/adafruit-ltr-329-ltr-303/overview" target="_blank">https://learn.adafruit.com/adafruit-ltr-329-ltr-303/overview</a></div>

<div></div>

<div>本次活动选择的另一个器件是I2C QT ROTARY ENCODER,片上集成了一个编码器和一个WS2812,单片机下载seesaw固件,通过I2C接口获取命令,进一步通过单片机读取编码器的值,控制WS2812。搜索框输入seesaw,安装对应的Library。详细介绍及驱动代码可见<a href="https://learn.adafruit.com/adafruit-i2c-qt-rotary-encoder" target="_blank">https://learn.adafruit.com/adafruit-i2c-qt-rotary-encoder</a></div>

<div>
<div style="text-align: center;"></div>

<p>当然,要通过WiFi接入HA平台,最重要的还需要一个home-assistant-integration库,通过这个库,可以创建各种设备类型,包括灯、按键、传感器、锁等等。具体库介绍可参考<a href="https://dawidchyrzynski.github.io/arduino-home-assistant/index.html" target="_blank">https://dawidchyrzynski.github.io/arduino-home-assistant/index.html</a></p>

<div style="text-align: center;"></div>

<p>环境搭建和各种library安装好之后,就可以进行代码编写。</p>

<div style="text-align: center;"></div>

<p>代码实现:</p>

<pre>
<code class="language-cpp">#include "WiFiS3.h"
#include "arduino_secrets.h"
#include "Adafruit_LTR329_LTR303.h"
#include &lt;ArduinoHA.h&gt;
#include &lt;seesaw_neopixel.h&gt;

#define MQTT_OBJECT_ID"followme"
#define BROKER_ADDR   IPAddress(192,168,10,246)
#define MQTT_PORT       1883
#define MQTT_USERNAME   "admin"
#define MQTT_PASSWORD   "123"
#define SS_NEOPIX      6
#define SEESAW_ADDR          0x36

seesaw_NeoPixel sspixel = seesaw_NeoPixel(1, SS_NEOPIX, NEO_GRB + NEO_KHZ800, &amp;Wire1);
Adafruit_LTR329 ltr = Adafruit_LTR329();
WiFiClient client;
HADevice device(MQTT_OBJECT_ID);
HAMqtt mqtt(client, device);

HAButton buttonR("myButtonR");
HAButton buttonG("myButtonG");
HAButton buttonB("myButtonB");

HASensorNumber lightSensor("mylight");

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 status = WL_IDLE_STATUS;
unsigned long lastUpdateAt = 0;

void onButtonCommand(HAButton* sender)
{
    if (sender == &amp;buttonR) {
      // button A was clicked, do your logic here
      sspixel.setPixelColor(0, sspixel.Color(255, 0, 0));
    } else if (sender == &amp;buttonG) {
      // button B was clicked, do your logic here
      sspixel.setPixelColor(0, sspixel.Color(0, 255, 0));
    } else if (sender == &amp;buttonB) {
      sspixel.setPixelColor(0, sspixel.Color(0, 0, 255));
    }
    sspixel.show();
}



void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
}

wifi_init();
ltr329_init();
pixel_init();

device.setName("Arduino");
device.setSoftwareVersion("1.0.0");

buttonR.setIcon("mdi:fire");
buttonR.setName("RED");
buttonG.setIcon("mdi:home");
buttonG.setName("GREEN");
buttonB.setIcon("mdi:water");
buttonB.setName("BLUE");

buttonR.onCommand(onButtonCommand);
buttonG.onCommand(onButtonCommand);
buttonB.onCommand(onButtonCommand);

lightSensor.setIcon("mdi:home");
lightSensor.setName("light value");

mqtt.begin(BROKER_ADDR, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD);
}

void loop() {
// put your main code here, to run repeatedly:
bool valid;
uint16_t visible_plus_ir, infrared;

mqtt.loop();

if ((millis() - lastUpdateAt) &gt; 1000)
{ // 1000ms debounce time
    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);
      lightSensor.setValue(visible_plus_ir);
      }

    }
   
    lastUpdateAt = millis();
      
}
}

void wifi_init()
{
// 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 &lt; 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();
}

void ltr329_init()
{
Serial.println("Adafruit LTR-329 advanced test");
if ( ! ltr.begin(&amp;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);
}

void pixel_init()
{
Serial.println("Looking for seesaw!");

if (!sspixel.begin(SEESAW_ADDR)) {
    Serial.println("ERROR! seesaw not found");
    while(1) delay(1);
}
Serial.println("seesaw started");

      // set not so bright!
sspixel.setBrightness(20);
sspixel.show();
}

/* -------------------------------------------------------------------------- */
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");
}
</code></pre>

<p>上面代码实现了两个功能,一个是将LTR-329获取到的光照强度上传到HA平台,另一个是通过HA平台创建三个按键,分别用来控制WS2812的红、绿、蓝三种颜色。</p>

<p>硬件连接如图</p>
</div>

<div>
<div style="text-align: center;"></div>

<p>实现效果</p>
</div>

<div>
<div style="text-align: center;"></div>

<p>在HA平台上可看见上传的光照强度值,具体现象可见视频。</p>
</div>

<div><strong>五、心得体会</strong></div>

<div>非常感谢官方提供的Arduino板卡,这块板子22年发布的,在技术创新和功能上都非常有特色,最感兴趣的还是上面12x8点阵LED了,可以生成表情、动物、字符等信息。另外,这期活动还跟着教程学会了home assistant的搭建和使用,后面也要继续尝试在泰山派上成功搭建起来。最后希望follow me活动越办越好,给大家带来更多更优秀的大厂开发板。</div>

<div><strong>六、可编译下载的代码</strong></div>

<div><br />
<br />
&nbsp;</div>

<div>&nbsp;</div>

<div>&nbsp;</div>

<p><!--importdoc--></p>

Jacktang 发表于 2024-10-9 07:26

<p>看来选择了直播中老师讲解的方法,在windows上安装Docker Desktop,这个方法可行,收藏备用</p>
页: [1]
查看完整版本: 【Follow me第二季第2期】+项目总结