ctrlshift12138

  • 2024-11-08
  • 回复了主题帖: 【Follow me第二季第2期】(Arduino Uno R4)作品提交汇总

    ctrlshift12138 发表于 2024-11-8 23:54 在旧版种,代码缩进是正常的;新版界面,代码缩进有问题的。       ... 好像是 Tab 缩进无法识别

  • 回复了主题帖: 【Follow me第二季第2期】(Arduino Uno R4)作品提交汇总

    nmg 发表于 2024-11-2 19:36 可以具体说说嘛,看我们这边能否改进 在旧版种,代码缩进是正常的;新版界面,代码缩进有问题的。          

  • 2024-10-11
  • 回复了主题帖: 【Follow me第二季第2期】(Arduino Uno R4)作品提交汇总

    文章中嵌入的代码缩进有些问题,大家可以下载源代码自行查看

  • 回复了主题帖: 【Follow me第二季第2期】(Arduino Uno R4)作品提交汇总

    文章最后2张图是显示BUG,我在编辑页面是没有这2张图的,浏览时请大家忽略

  • 2024-10-08
  • 发表了主题帖: 【Follow me第二季第2期】(Arduino Uno R4)作品提交汇总

    # 【Follow me第二季第2期】任务提交 ## 一、前置准备: 硬件:无 软件:VSCode、科学上网工具 ### 1、设置代理 打开VSCode,进入设置 搜索“代理”,在1和2中填写代理服务器的地址和端口,并取消勾选3 ### 2、安装PlatformIO IDE扩展 选择扩展,搜索“PlatformIO”,安装扩展插件 ### 4、升级WiFi模块固件(非必须步骤,可跳过) 下载下面代码到arduino Uno R4 WiFi开发板,检查的WiFi模块(ESP32-S3)的固件。如果WiFi模块固件不是最新版本,建议升级固件。 ```cpp #include #include void setup() {         Serial.begin(115200);         BaseType_t xReturn;         // 检查WiFi模组         if (WiFi.status() == WL_NO_MODULE)         {                 Serial.println("Communication with WiFi module failed!");                 while (true);         }         String fv = WiFi.firmwareVersion();         Serial.print("Current WiFi firmware version:");         Serial.println(fv);         Serial.print("Laste WiFi firmware version:");         Serial.println(WIFI_FIRMWARE_LATEST_VERSION);         if (fv < WIFI_FIRMWARE_LATEST_VERSION)         {                 Serial.println("Please upgrade the firmware");         } } void loop() { } ``` [官方更新WiFi模块固件教程和资源链接](https://support.arduino.cc/hc/en-us/articles/9670986058780-Update-the-connectivity-module-firmware-on-UNO-R4-WiFi#espflash) 1、下载并解压官方资源 2、使用跳线帽(或金属镊子)短接图中突出显示的引脚: ![The GND and Download ESP32 pins.](/data/attachment/forum/202410/08/020439n8seso30j6f2sosn.png.thumb.jpg?rand=7115.516748703152) 3、使用 USB 线将 UNO R4 WiFi 板连接到电脑 4、运行`update.bat`脚本 5、选择正确的串口,并等待固件更新完成 ## 二、入门任务 **Blink&串口打印Hello EEWorld!** 硬件:Arduino UNO R4 WiFi、USB-C to A线 软件:VSCode ### 1、操作步骤 打开PlatformIO的“home”主页,选择“New Project” 填写“Name”,“Board”选择“Arduino Uno R4 WiFi”,“Framework”选择“Arduino”,“Location”为项目存放位置,自行设置。 点击“FInish”,等待相关资源下载完成(如果卡在下载资源,请设置代理)。 ### 2、代码 ```cpp #include #include void blink(void * para); void printHelloWorld(void * para); // 任务句柄 TaskHandle_t blink_task_handle = NULL; TaskHandle_t print_hello_world_task_handle = NULL; void setup() {         pinMode(LED_BUILTIN, OUTPUT);                // LED管脚设置为输出模式         Serial.begin(115200);                                // 串口设置波特率115200         // 创建Blink任务         xTaskCreate((TaskFunction_t)blink,                                 (const char*)"blink",                                 100,                                 NULL,                                 1,                                 &blink_task_handle);         configASSERT( blink_task_handle );         // 创建串口打印任务         xTaskCreate((TaskFunction_t)printHelloWorld,                                 (const char *)"printHelloWord",                                 100,                                 NULL,                                 2,                                 &print_hello_world_task_handle);         configASSERT(print_hello_world_task_handle);         vTaskStartScheduler();                                // 启动任务调度 } void blink(void * para) {         while (1)         {                 digitalWrite(LED_BUILTIN, HIGH);                // 点亮LED                 vTaskDelay(500 * portTICK_PERIOD_MS);        // 延时500ms                 digitalWrite(LED_BUILTIN, LOW);                        // 关闭LED                 vTaskDelay(500 * portTICK_PERIOD_MS);        // 延时500ms         } } void printHelloWorld(void * para) {         while (1)         {                 Serial.println("Hello EEWorld !");                // 串口打印                 vTaskDelay(1000 * portTICK_PERIOD_MS);        // 延时1000ms         } } void loop() { } ``` ### 3、说明 软件流程图: 使用FreeRTOS创建了“blink”和“printHelloWord”两个任务,分别实现了LED指示灯每隔0.5秒闪烁一次,串口每隔1秒发送一次“Hello EEWorld!”。 ```cpp pinMode(LED_BUILTIN, OUTPUT);                // LED管脚设置为输出模式 ``` `LED_BUILTIN`为板上的黄色LED灯对应的管脚,见下图,`OUTPUT`表示将该管脚设置为输出模式。 ### 4、效果展示 LED灯闪烁 串口打印 ## 三、基础任务 **驱动12x8点阵LED;用DAC生成正弦波;用OPAMP放大DAC信号;用ADC采集并且打印数据到串口等其他接口可上传到上位机显示曲线** 硬件:Arduino UNO R4 WiFi、USB-C to A线、10K插件电阻、公对公杜邦线 软件:VSCode、Arduino IDE ### 1、代码:驱动12x8点阵LED ```cpp #include #include #include #include void blink(void * para); void ledMatrix(void * para); // 任务句柄 TaskHandle_t blink_task_handle = NULL; TaskHandle_t led_matrix_task_handle = NULL; ArduinoLEDMatrix matrix; void setup() {         pinMode(LED_BUILTIN, OUTPUT);         matrix.begin();         // 创建Blink任务         xTaskCreate((TaskFunction_t)blink,                                 (const char*)"blink",                                 100,                                 NULL,                                 1,                                 &blink_task_handle);         configASSERT( blink_task_handle );         // 创建点阵LED任务         xTaskCreate((TaskFunction_t)ledMatrix,                                 (const char *)"ledMatrix",                                 100,                                 NULL,                                 2,                                 &led_matrix_task_handle);         configASSERT(led_matrix_task_handle);         vTaskStartScheduler();                                // 启动任务调度 } void loop() { } void blink(void * para) {         while (1)         {                 digitalWrite(LED_BUILTIN, HIGH);                // 点亮LED                 vTaskDelay(500 * portTICK_PERIOD_MS);        // 延时500ms                 digitalWrite(LED_BUILTIN, LOW);                        // 关闭LED                 vTaskDelay(500 * portTICK_PERIOD_MS);        // 延时500ms         } } void ledMatrix(void *para) {         while (1)         {                 uint16_t length = sizeof(frames)/sizeof(frames[0]);                 for ( uint16_t i = 0; i < length; i++)                 {                         matrix.loadFrame(&frames[0]);                         vTaskDelay(33 * portTICK_PERIOD_MS);                 }         } } ``` ### 2、说明 软件流程图: 使用FreeRTOS创建了“blink”和“led_matrix”两个任务,分别实现了LED指示灯每隔0.5秒闪烁一次;使用LED矩阵播放动画。动画的数据在.h文件中,在代码合集中给出。 因为动画的30fps,每帧约33.3ms,所以使用了`vTaskDelay(33 * portTICK_PERIOD_MS);`来设置固定的延时。 关于如何生成动画的文件: 1、使用ffmpeg,将视频中的每一帧输出为12*8大小的bmp文件; ```ba ffmpeg -i video.m4s -vf scale=12:8 output_frame_%04d.bmp ``` 2、将bmp文件转换为hex格式的文件,以下是python转换脚本 ```python from PIL import Image import os def convert_image_to_led_matrix(input_image):     # 打开图片并将其转换为灰度模式     image = Image.open(input_image).convert('1')  # '1'模式表示黑白模式     # 缩放图片到12x8分辨率     image = image.resize((12, 8))         # 创建一个96位的数组来存储整个LED矩阵     led_matrix_full = [0] * 96         # 遍历每个像素,将其转换为1或0并存储到led_matrix_full中     for y in range(8):         for x in range(12):             pixel = image.getpixel((x, y))             if pixel == 0:  # 黑色像素表示LED点亮                 led_matrix_full[y * 12 + x] = 1         # 将96位数据分割成3个32位的uint32数组     led_matrix_32 = [0, 0, 0]         for i in range(3):         for bit in range(32):             led_matrix_32 |= (led_matrix_full[i * 32 + bit] 1000)         {                 if (digitalRead(LED_BUILTIN) == HIGH)                         led_switch.setState(true);                 else                         led_switch.setState(false);                 last_update_time = millis();         } } /** * @brief MQTT接收到数据后的回调函数 * * @param topic * @param payload * @param length */ void onMqttMessage(const char *topic, const uint8_t *payload, uint16_t length) {         char message[length];         memcpy(message, payload, length);         message[length] = '\0';         // 打印接收的数据         Serial.print("{dbg}New message on topic: ");         Serial.println(topic);         Serial.print("Data: ");         Serial.println((const char *)message);         if (strstr(message, "ON") != NULL) // 在字符串中查找另一个子字符串         {                 // uint8_t dutyCyclt = 0;                 // if (sscanf(message, "on#%d", &dutyCyclt) == 1) // 从一个字符串中读取数据,并按照指定的格式存储到变量中                 // {                 //         /* code */                 // }                 digitalWrite(LED_BUILTIN, HIGH);                 Serial.println("LED ON");         }         else if (strstr(message, "OFF") != NULL)         {                 /* code */                 digitalWrite(LED_BUILTIN, LOW);                 Serial.println("LED OFF");         }         else         {                 Serial.println("Unrecongnized meaasge");         }         memset(message, 0, length); } /** * @brief 连接MQTT服务器后的回调函数 * */ void onMqttConnected() {         Serial.println("Connected to the broker!");         mqtt.subscribe(topic_subscribe);         Serial.println("Subscribe to topic: ");         Serial.print(topic_subscribe);         // mqtt.publish(topic_subscribe, "Hello, MQTT!"); } /** * @brief 断开 MQTT broker后的回调函数 * */ void onMqttDisconneted() {         Serial.println("Disconnected from the broker!"); } /** * @brief MQTT连接状态改变后的回调函数 * * @param state */ void onMqttStateChanged(HAMqtt::ConnectionState state) {         Serial.print("MQTT state changed to: ");         Serial.println(static_cast(state)); } /** * @brief 连接WiFI和MQTT服务器 * */ void wifiAndMqttInit() {         // 检查WiFi模组         if (WiFi.status() == WL_NO_MODULE)         {                 Serial.println("Communication with WiFi module failed!");                 while (true)                         ;         }         String fv = WiFi.firmwareVersion();         if (fv < WIFI_FIRMWARE_LATEST_VERSION)         {                 Serial.println("Please upgrade the firmware");         }         // 连接WiFi         WiFi.begin(ssid, password); // Connect to WPA/WPA2 network:         Serial.print("Attempting to connect to WPA SSID: ");         Serial.println(ssid);         while (WiFi.status() != WL_CONNECTED)         {                 WiFi.begin(ssid, password);                 delay(1000);         }         printWifiStatus();         // 配置MQTT         Serial.println("Starting connect to MQTT server");         mqtt.onMessage(onMqttMessage);                         // 当设备接收到 MQTT 消息时调用         mqtt.onConnected(onMqttConnected);                 // 每次获取与 MQTT 代理的连接时调用         mqtt.onDisconnected(onMqttDisconneted);         // 每次与 MQTT 代理的连接丢失时调用         mqtt.onStateChanged(onMqttStateChanged); // 每次连接状态改变时调用         mqtt.setDataPrefix("homeassistant/sensor"); // 设置数据主题的前缀         // 连接MQTT服务器         if (!mqtt.begin(mqtt_server, mqtt_port, mqtt_user, mqtt_password))         {                 Serial.print("Failed, rc = ");                 Serial.print(mqtt.getState());                 Serial.println(", try again in 5 seconds");                 delay(5000);         } } /** * @brief 打印WiFi信息 * */ 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"); } ``` ### 2、说明 软件流程图: 关于Homeassistant的搭建,9月的技术直播中已经详细说明了,可以观看我的[录播回顾](https://www.bilibili.com/video/BV1884seCEAA)。 我的Homeassistant安装在Linux的docker容器中,EMQX没有使用docker,直接安装在Linux上。 **注意:在MQTT集成中,需要勾选“启用自动发现”,发现前缀配置为“homeassistant”,否则无法自动发现arduno开发板。** 调用`dawidchyrzynski/home-assistant-integration`库,实现HA联动功能。 ```cpp HASwitch led_switch("ledSwitch");                  // 开关实体 ``` 创建了1个HA开关实体,开发板连接到MQTT Broker后,HA自动发现,会在主页面上显示一个LED灯开关,开关可以控制开发板上的LED灯。 ```cpp if (digitalRead(LED_BUILTIN) == HIGH)     led_switch.setState(true);        // 反馈开关状态到MQTT Broker else     led_switch.setState(false);        // 反馈开关状态到MQTT Broker ``` 需要调用`led_switch.setState()`来将开关状态反馈到HA,如果HA获取不到开关状态,会默认开关状态是关。 ### 3、效果展示 关灯状态 开灯状态 ## 五、扩展任务 硬件:Arduino UNO R4 WiFi、USB-C to A线、SHT40温湿度传感器扩展板、Qwiic缆线 软件:VSCode ### 1、代码 ```cpp #include #include #include #include #include #include // macro definitions // make sure that we use the proper definition of NO_ERROR #ifdef NO_ERROR #undef NO_ERROR #endif #define NO_ERROR 0 // WiFi 设置 const char *ssid = "1708";                         // WiFi名称 const char *password = "tsl199725?"; // WiFi密码 // MQTT 设置 const char *mqtt_server = "192.168.31.46";                                          // MQTT服务器IP uint16_t mqtt_port = 1883;                                                                          // MQTT端口 const char *mqtt_user = "arduino_uno_r4";                                          // 用户名 const char *mqtt_password = "arduino_uno_r4";                                  // 密码 const char *mqtt_client_id = "arduino";                                                  // 客户id const char *topic_subscribe = "homeassistant/sensor/arduino"; // 订阅主题 WiFiClient client; HADevice device(mqtt_client_id); // 创建一个HA设备 HAMqtt mqtt(client, device); HASensor sht4x_temp_sensor("sht4x_temp"); // 温度传感器实体 HASensor sht4x_humi_sensor("sht4x_humi"); // 湿度传感器实体 HASwitch led_switch("ledSwitch");                  // 开关实体 SensirionI2cSht4x sensor;                                        // SHT40 static char errorMessage[64]; static int16_t error; uint32_t last_update_time; void wifiAndMqttInit(); void printWifiStatus(); void setup() {         Serial.begin(115200);         pinMode(LED_BUILTIN, OUTPUT);         Wire1.begin();         sensor.begin(Wire1, SHT40_I2C_ADDR_44);         sensor.softReset();         delay(10);         // 读取SHT40序列号         uint32_t serial_number;         error = sensor.serialNumber(serial_number);         if (NO_ERROR != error)         {                 Serial.print("Error trying to execute serialNumber(): ");                 errorToString(error, errorMessage, sizeof(errorMessage));                 Serial.println(errorMessage);                 return;         }         Serial.print("serialNumber: ");     Serial.println(serial_number);         wifiAndMqttInit(); // 初始化         device.setName("Arduino");                        // 设备名称         device.setSoftwareVersion("1.0.0"); // 设备软件版本         led_switch.setIcon("mdi:led-outline");         led_switch.setName("arduino LED");         // led_switch.onCommand(onSwitchCommand);         sht4x_temp_sensor.setIcon("mdi:coolant-temperature");         sht4x_temp_sensor.setName("温度传感器");         sht4x_humi_sensor.setIcon("mdi:water-percent");         sht4x_humi_sensor.setName("湿度传感器"); } void loop() {         mqtt.loop();         if ((millis() - last_update_time) > 1000)         {                 if (digitalRead(LED_BUILTIN) == HIGH)                         led_switch.setState(true);        // 反馈开关状态到MQTT Broker                 else                         led_switch.setState(false);        // 反馈开关状态到MQTT Broker                 // 读取SHT40温湿度数据                 float a_temperature;                 float a_humidity;                 error = sensor.measureHighPrecision(a_temperature, a_humidity);                 if (NO_ERROR != error)                 {                         Serial.print("Error trying to execute measureHighPrecision(): ");                         errorToString(error, errorMessage, sizeof(errorMessage));                         Serial.println(errorMessage);                         return;                 }                 Serial.print("aTemperature: ");                 Serial.println(a_temperature);                 Serial.print("aHumidity: ");                 Serial.println(a_humidity);                 // 发送数据到MQTT Broker                 String str = String(a_temperature, 2);                 sht4x_temp_sensor.setValue(str.c_str());                 sht4x_temp_sensor.setUnitOfMeasurement("℃");                 str = String(a_humidity, 2);                 sht4x_humi_sensor.setValue(str.c_str());                 sht4x_humi_sensor.setUnitOfMeasurement("%");                 last_update_time = millis();         } } /** * @brief MQTT接收到数据后的回调函数 * * @param topic * @param payload * @param length */ void onMqttMessage(const char *topic, const uint8_t *payload, uint16_t length) {         char message[length];         memcpy(message, payload, length);         message[length] = '\0';         // 打印接收的数据         Serial.print("{dbg}New message on topic: ");         Serial.println(topic);         Serial.print("Data: ");         Serial.println((const char *)message);         if (strstr(message, "ON") != NULL) // strstr()在字符串中查找另一个子字符串         {                 // uint8_t dutyCyclt = 0;                 // if (sscanf(message, "on#%d", &dutyCyclt) == 1) // 从一个字符串中读取数据,并按照指定的格式存储到变量中                 // {                 //         /* code */                 // }                 digitalWrite(LED_BUILTIN, HIGH);                 Serial.println("LED ON");         }         else if (strstr(message, "OFF") != NULL)         {                 /* code */                 digitalWrite(LED_BUILTIN, LOW);                 Serial.println("LED OFF");         }         else         {                 Serial.println("Unrecongnized meaasge");         }         memset(message, 0, length); } /** * @brief 连接MQTT服务器后的回调函数 * */ void onMqttConnected() {         Serial.println("Connected to the broker!");         mqtt.subscribe(topic_subscribe);         Serial.println("Subscribe to topic: ");         Serial.print(topic_subscribe);         // mqtt.publish(topic_subscribe, "Hello, MQTT!"); } /** * @brief 断开 MQTT broker后的回调函数 * */ void onMqttDisconneted() {         Serial.println("Disconnected from the broker!"); } /** * @brief MQTT连接状态改变后的回调函数 * * @param state */ void onMqttStateChanged(HAMqtt::ConnectionState state) {         Serial.print("MQTT state changed to: ");         Serial.println(static_cast(state)); } /** * @brief 连接WiFI和MQTT服务器 * */ void wifiAndMqttInit() {         // 检查WiFi模组         if (WiFi.status() == WL_NO_MODULE)         {                 Serial.println("Communication with WiFi module failed!");                 while (true)                         ;         }         String fv = WiFi.firmwareVersion();         if (fv < WIFI_FIRMWARE_LATEST_VERSION)         {                 Serial.println("Please upgrade the firmware");         }         // 连接WiFi         WiFi.begin(ssid, password); // Connect to WPA/WPA2 network:         Serial.print("Attempting to connect to WPA SSID: ");         Serial.println(ssid);         while (WiFi.status() != WL_CONNECTED)         {                 WiFi.begin(ssid, password);                 delay(1000);         }         printWifiStatus();         // 配置MQTT         Serial.println("Starting connect to MQTT server");         mqtt.onMessage(onMqttMessage);                         // 当设备接收到 MQTT 消息时调用         mqtt.onConnected(onMqttConnected);                 // 每次获取与 MQTT 代理的连接时调用         mqtt.onDisconnected(onMqttDisconneted);         // 每次与 MQTT 代理的连接丢失时调用         mqtt.onStateChanged(onMqttStateChanged); // 每次连接状态改变时调用         mqtt.setDataPrefix("homeassistant/sensor"); // 设置数据主题的前缀         // 连接MQTT服务器         if (!mqtt.begin(mqtt_server, mqtt_port, mqtt_user, mqtt_password))         {                 Serial.print("Failed, rc = ");                 Serial.print(mqtt.getState());                 Serial.println(", try again in 5 seconds");                 delay(5000);         } } /** * @brief 打印WiFi信息 * */ 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"); } ``` ### 2、说明 软件流程图: 调用`sensirion/Sensirion I2C SHT4x`的库,来读取STH40的温湿度数据。 **注意:开发板有2个IIC端口,QWIC接口使用的是WIRE1,所以使用`Wire1.begin();`来使能IIC端口。** ```cpp HASensor sht4x_temp_sensor("sht4x_temp"); // 温度传感器实体 HASensor sht4x_humi_sensor("sht4x_humi"); // 湿度传感器实体 ``` 创建了2个HA传感器实体,分别显示温度和湿度。 ```cpp sensor.measureHighPrecision(a_temperature, a_humidity); ``` 使用`measureHighPrecision()`函数,来获取温度和湿度数据。 ```cpp sht4x_temp_sensor.setValue(); sht4x_humi_sensor.setValue(); ``` 通过`setValue()`函数,将温度和湿度数据发送到MQTT Broker。 ### 3、效果展示 HA中显示的温湿度数据: 家里的小米温湿度传感器 ## 六、源代码 ## 七、展示视频 [大学堂视频链接](https://training.eeworld.com.cn/video/41270)

  • 2024-09-12
  • 加入了学习《直播回放: TI 德州仪器基于 Arm 的 AM62 处理器简介》,观看 德州仪器基于 Arm 的 AM62 处理器简介

  • 2023-12-18
  • 发表了主题帖: 【得捷电子Follow me第3期】使用MicroPython完成任务

    ## 第一部分 短视频 https://training.eeworld.com.cn/video/38755 ## 第二部分 总结报告 ### 任务1:使用MicroPython系统 #### 展示 #### 硬件 Seeed Studio XIAO ESP32C3 #### 软件 * [Esptool](https://github.com/espressif/esptool/releases/download/v4.6.2/esptool-v4.6.2-win64.zip)(点击链接下载) * [micorpython固件](https://micropython.org/resources/firmware/ESP32_GENERIC_C3-20231005-v1.21.0.bin)(点击链接下载) * [Thonny](https://github.com/thonny/thonny/releases/download/v4.1.4/thonny-py38-4.1.4-windows-portable.zip)(点击链接下载) #### 操作 1. Esptool配置为环境变量 2. 使用Esptool下载固件    打开下载好的micropython固件目录,在地址栏中输入cmd,打开命令行窗口,输入命令:    ```bash    esptool --chip esp32c3 --port COM13 --baud 921600 --before default_reset --after hard_reset --no-stub write_flash --flash_mode dio --flash_freq 80m 0x0 ESP32_GENERIC_C3-20231005-V1.21.0.bin    ```    其中 `--port`是 ESP32C3 的在设备管理器中的串口号,根据自己的情况修改。    等待下载完成。 3. 与micropython的 REPL交互    打开 Thonny,选择`运行` -> `配置解释器`,解释器选择`MicroPython(ESP32)`,选择正确的端口,点击确定。 ### 任务2:驱动扩展板上的OLED屏幕 #### 展示 #### 硬件 * Seeed Studio XIAO ESP32C3 * Expansion Board Base for XIAO #### 软件 * Thonny * [ampy](https://learn.adafruit.com/micropython-basics-load-files-and-run-code/install-ampy)(Adafruit MicroPython Tool)   (安装需要 Python 环境)   命令行输入:      ```bash   pip install adafruit-ampy   ```   等待安装完成即可。 #### 代码 ```python """ 任务2:驱动扩展板上的OLED屏幕 使用扩展板上的OLED屏幕显示文字和图形 显示图形参考代码 https://docs.micropython.org/en/v1.21.0/esp8266/tutorial/ssd1306.html """ import time from machine import Pin, SoftI2C import ssd1306                          # 第三方库 import math def show_text():     """     显示文本     """     oled.fill(0)     oled.text("DigiKey", 0, 7)     oled.text("X", 60, 7)     oled.text("EEworld", 72, 7)     oled.text("Follow me", 24, 21)     oled.text("Episode 3", 24, 35)     oled.text("XIAO ESP32C3", 12, 49)     oled.show() def show_picture():     """     显示图片     """     oled.fill(0)     oled.fill_rect(0, 0, 32, 32, 1)     oled.fill_rect(2, 2, 28, 28, 0)     oled.vline(9, 8, 22, 1)     oled.vline(16, 2, 22, 1)     oled.vline(23, 8, 22, 1)     oled.fill_rect(26, 24, 2, 4, 1)     oled.text('MicroPython', 40, 0, 1)     oled.text('SSD1306', 40, 12, 1)     oled.text('OLED 128x64', 40, 24, 1)     oled.show() i2c = SoftI2C(scl=Pin(7), sda=Pin(6))   # ESP32C3 引脚分配 oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) button = Pin(3, Pin.IN, Pin.PULL_UP)    # 配置 3 脚为输入(扩展板上的按键),默认上拉 index = 0                               # 页面编号 flash_flag = True                       # 刷新标志位 while True:     if (button.value() == False):       # 当按键被按下,9 脚被拉低         print("button pressed")         index = (index + 1)%2           # 页面编号更新         flash_flag = True               # 刷新标志位置位     if (flash_flag == True):            # 判断是否需要刷新         if (index == 0):             show_text()         else:             show_picture()         flash_flag = False              # 刷新标志位清0     time.sleep_ms(100)                  # 简单按键防抖 ``` ```python import ssd1306                          # 第三方库 ``` [ssd1306](https://github.com/micropython/micropython-lib/blob/master/micropython/drivers/display/ssd1306/ssd1306.py)(点击链接打开) 是驱动 I2C 的库函数。 **** ```python oled.text("DigiKey", 0, 7) ``` 表示在OLED屏幕上的`(0,7)`坐标位置显示`DigiKey`。OLED 屏幕的每个字符是 8 * 8 大小。 #### 操作 1. 上传ssd1306库文件    `ssd1306.py`保存在 `lib`文件夹下    在`lib`所在目录打开命令行,输入    ```bash    ampy -p COM13 lib    ```    表示将`lib`目录及其目录下的文件和文件夹上传到 ESP32C3 中。     2. 编辑 `boot.py` 文件     ### 任务3:控制蜂鸣器播放音乐 #### 展示 (可以看上面视频) #### 硬件 * Seeed Studio XIAO ESP32C3 * Expansion Board Base for XIAO #### 软件 * Esptool * Thonny * ampy #### 代码 ```python """ 任务3:控制蜂鸣器播放音乐 播放音乐参考代码 https://wiki.seeedstudio.com/cn/XIAO_ESP32C3_MicroPython/ 显示图片参考代码 https://blog.martinfitzpatrick.com/displaying-images-oled-displays/ Bad Apple 简谱 http://www.sooopu.com/html/399/399104.html """ import time from machine import SoftI2C, Pin, PWM import ssd1306 import framebuf i2c = SoftI2C(scl=Pin(7), sda=Pin(6)) oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) button = Pin(3, Pin.IN, Pin.PULL_UP)    # 配置 3 脚为输入(扩展板上的按键),默认上拉 # 蜂鸣器初始化 buzzer_Pin = Pin(5, Pin.OUT) buzzer = PWM(buzzer_Pin) buzzer.duty(0) def load_image():     """     读取图片     """     with open('pic/BadApple.pbm', 'rb') as f:         f.readline()    # Magic number         f.readline()    # Creator comment         f.readline()    # Dimensions         data = bytearray(f.read())     return framebuf.FrameBuffer(data, 128, 64, framebuf.MONO_HLSB) # 定义每个音符的频率 C4 = 262 D4 = 294 E4 = 330 F4 = 349 G4 = 392 A4 = 440 B4 = 494 C5 = 523 C5_= 554 D5 = 587 E5 = 659 F5 = 698 G5 = 784 A5 = 880 B5 = 988 C6 = 1047 D6 = 1175 E6 = 1319 F6 = 1397 # 乐谱 notes = [     D5, D5, D5, D5, D5, D5, D5,     D5, D5, D5, D5, D5,     D5, D5, D5, D5, D5, D5, D5,     D5, D5, D5, D5, D5,     D4, 0 , D4, C4, D4, D4, 0 , D4, C4, D4,     D4, 0 , D4, C4, D4, D4, D4, F4, G4, F4, G4,     D4, 0 , D4, C4, D4, D4, 0 , D4, C4, D4,     D4, 0 , D4, C4, D4, G4, F4, G4, F4, D4, F4,     D5, E5, F5, G5, A5, D6, C6,     A5, D5, A5, G5, F5, E5,     D5, E5, F5, G5, A5, G5, F5,     E5, D5, E5, F5, E5, D5, C5_,E5,     D5, E5, F5, G5, A5, D6, C6,     A5, D5, A5, G5, F5, E5,     D5, E5, F5, G5, A5, G5, F5,     E5, F5, G5, A5,     C6, D6, A5, G5, A5, G5, A5,     C6, D6, A5, G5, A5, G5, A5,     G5, F5, E5, C5, D5, C5, D5,     E5, F5, G5, A5, D5, A5, C6,     C6, D6, A5, G5, A5, G5, A5,     C6, D6, A5, G5, A5, G5, A5,     G5, F5, E5, C5, D5, C5, D5,     E5, F5, G5, A5, D5, A5, C6,     C6, D6, A5, G5, A5, G5, A5,     C6, D6, A5, G5, A5, G5, A5,     G5, F5, E5, C5, D5, C5, D5,     E5, F5, G5, A5, D5, A5, C6,     C6, D6, A5, G5, A5, G5, A5,     C6, D6, A5, G5, A5, D6, E6,     F6, E6, D6, C6, A5, G5, A5,     #G5, F5, E5, C5, D5, A5, C6                # 版本1     G5, F5, E5, C5, D5                                # 版本2 ] # 歌曲每个音符的持续时间(以毫秒为单位) # 当 SongSpeed = 1.0 时,四分音符为 200ms durations = [     400, 400, 400, 100, 100, 100, 100,     400, 400, 400, 200, 200,     400, 400, 400, 100, 100, 100, 100,     400, 400, 400, 200, 200,     400, 100, 100, 100, 100, 400, 100, 100, 100, 100,     400, 100, 100, 100, 100, 200, 100, 100, 200, 100, 100,     400, 100, 100, 100, 100, 400, 100, 100, 100, 100,     400, 100, 100, 100, 100, 200, 100, 100, 200, 100, 100,     200, 200, 200, 200, 400, 200, 200,     400, 400, 200, 200, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 200, 200, 200, 200,     200, 200, 200, 200, 400, 200, 200,     400, 400, 200, 200, 200, 200,     200, 200, 200, 200, 400, 200, 200,     400, 400, 400, 400,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     200, 200, 200, 200, 400, 200, 200,     #200, 200, 200, 200, 400, 200, 200        # 版本1     200, 200, 200, 200, 400                            # 版本2 ] def play_song():     """     播放音乐     """     total_notes = len(notes)     for i in range(total_notes):         current_note = notes         wait = durations         if current_note != 0:             buzzer.duty(512)            # Set duty cycle for sound             buzzer.freq(current_note)   # Set frequency for sound         else:             buzzer.duty(0)              # Turn off the sound         time.sleep_ms(wait)         buzzer.duty(0)                  # Turn off the sound         time.sleep_ms(wait/10) def show_image():     """     显示图片     """     oled.invert(1)     oled.blit(load_image(), 0, 0)     oled.show() show_image() while True:     if button.value() == False:         play_song() # Play the song     time.sleep_ms(100) ``` ***** ```python # 蜂鸣器初始化 buzzer_Pin = Pin(5, Pin.OUT) buzzer = PWM(buzzer_Pin) buzzer.duty(0) ``` `buzzer_Pin = Pin(5, Pin.OUT)` 表示将Pin5设置为输出模式,`buzzer = PWM(buzzer_Pin)`表示 buzzer_Pin 作为PWM输出,`buzzer.duty(0)` 表示设置PWM的占空比为 0 。 **** ```python def show_image():     """     显示图片     """     oled.invert(1)     oled.blit(load_image(), 0, 0)     oled.show() ``` `oled.invert(1)`表示颜色反转,`oled.blit(load_image(), 0, 0)`用来显示图片,`load_image()` 是点阵图片数据,`0,0`分别表示绘制图片起始点的x,y坐标。 ***** notes数组是音乐的音符,durations数组是每个音符的持续时间时间。 #### 操作 上传库文件和代码与前面任务相同,不赘述。 ### 任务4:连接WiFi网络 #### 展示 #### 硬件 * Seeed Studio XIAO ESP32C3 * Expansion Board Base for XIAO #### 软件 * Esptool * Thonny * ampy #### 代码 ```python """ 任务4:连接WiFi网络 将Seeed Studio XIAO ESP32C3连接到WiFi网络,并访问互联网信息 参考 https://stackoverflow.com/questions/59296623/micropython-get-correct-current-time """ from machine import Pin, SoftI2C, RTC import ssd1306 from time import sleep import time import network import ntptime # ESP32 Pin assignment i2c = SoftI2C(scl=Pin(7), sda=Pin(6)) oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) station = network.WLAN(network.STA_IF)      # 创建 WLAN 网络接口对象,客户端模式 station.active(True)                        # 激活网络接口 # 网络配置 wifi_ssid = "1708"                          # SSID wifi_password = "tsl199725?"                # 密码 ntp_server = "ntp.aliyun.com"               # NTP 服务器地址 time_zone = 8                               # 时区,东八区 def connect_to_wifi():     """     连接到wifi网络     """     print("Scanning for WiFi networks, please wait...")     authmodes = ['Open', 'WEP', 'WPA-PSK' 'WPA2-PSK4', 'WPA/WPA2-PSK']     # 显示扫描到的网络     for ssid, bssid, channel, RSSI, authmode, hidden in station.scan():         print("* {:s}".format(ssid))         print("   - Channel: {}".format(channel))         print("   - RSSI: {}".format(RSSI))         print("   - BSSID: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(*bssid))         print()     # 连接网络     while not station.isconnected():         print("Connecting...")         station.connect(wifi_ssid, wifi_password)         time.sleep(1)     # 显示连接网络信息     print("Connected!")     print("My IP Address:", station.ifconfig()[0]) def sync_ntp():     """     NTP 同步时间     """     ntptime.host = ntp_server     retry_times = 10     try:         while retry_times > 0:             retry_times = retry_times - 1             if ntptime.settime():                 break     except:         print("Error syncing time") connect_to_wifi()                           # 连接到网络 sync_ntp()                                  # 同步NTP 服务器时间 rtc = RTC() last_second = 61                            # 上一次屏幕显示的秒数 while True:     year, month, day, wday ,hour,minute,second,mocrosecond = rtc.datetime()     if second != last_second:                   # 秒变化时,才刷新屏幕         print(rtc.datetime())                   # 串口打印         last_second = second         oled.fill(0)         oled.text(str(year), 24, 24)            # 年         oled.text(".", 56, 24)         if month < 10:                          # 月             oled.text("0" + str(month), 64, 24)         else:             oled.text(str(month), 64, 24)         oled.text(".", 80, 24)         if day < 10:                            # 日             oled.text("0" + str(day), 88, 24)         else:             oled.text(str(day), 88, 24)         hour = (hour + time_zone)%24                        # 转为东八区时间         if hour < 10:                           # 时             oled.text("0" + str(hour), 32, 32)         else:             oled.text(str(hour), 32, 32)         oled.text(":", 48, 32)         if minute < 10:                         # 分             oled.text("0" + str(minute), 56, 32)         else:             oled.text(str(minute), 56, 32)         oled.text(":", 72, 32)         if second < 10:                         #秒             oled.text("0" + str(second), 80, 32)         else:             oled.text(str(second), 80, 32)         oled.show()     time.sleep_ms(50) ``` ***** `ntptime.host = ntp_server`设置 NTP 服务器地址 `ntptime.settime()`从NTP 服务器获取时间 需要注意,NTP 获取的时间是**UTC +0** 的时间,北京时间是**UCT+8**,所以代码中有`hour = (hour + time_zone)%24` #### 操作 上传库文件和代码与前面任务相同,不赘述。 ### 任务5:使用外部传感器 #### 展示 使用传感器感应环境的温湿度和环境光强度。 小米温湿度传感器 温湿度差别有点大呀 :sweat_smile: #### 硬件 * Seeed Studio XIAO ESP32C3 * Expansion Board Base for XIAO * [Grove - AHT20](https://www.digikey.cn/zh/products/detail/seeed-technology-co-ltd/101990644/11681294) (温湿度传感器) * [Grove - Light Sensor](https://www.digikey.cn/zh/products/detail/seeed-technology-co-ltd/101020132/6558656) (环境光传感器) Grove-AHT20 使用了一颗来自奥松电子(ASAIR)的数字式温度传感器AHT20,湿度测量范围0\~100%RH,分辨率0.024%RH;温度测量范围-40\~125℃,分辨率0.01℃。使用I2C协议传输数据。 Grove-Light Sensor 使用了一颗光敏电阻和来自Ti的运放LM358来构建电路。输出信号为模拟值,光线越亮,数值越大。 #### 软件 * [Esptool](https://github.com/espressif/esptool/releases/download/v4.6.2/esptool-v4.6.2-win64.zip)(点击链接下载) * [Thonny](https://github.com/thonny/thonny/releases/download/v4.1.4/thonny-py38-4.1.4-windows-portable.zip)(点击链接下载) #### 代码 ```python """ 任务5:使用外部传感器 连接环境光传感器或温湿度传感器,获取传感器的数值,并转换成真实的物理量 ssd1306 驱动库: https://github.com/micropython/micropython-lib/blob/master/micropython/drivers/display/ssd1306/ssd1306.py AHT20 驱动库: https://github.com/joepweijers/DFRobot_AHT20_MicroPython """ import sys import time from machine import SoftI2C, Pin, ADC import ssd1306 import DFRobot_AHT20                    # AHT20 # SSD1306 屏幕驱动 i2c = SoftI2C(scl=Pin(7), sda=Pin(6))   # oled屏幕连接I2C引脚 oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) # 环境光传感器 light_pin = Pin(2)                      # 环境光传感器输出脚连接 GPIO2 # AHT20 驱动 light_sensor = DFRobot_AHT20.DFRobot_AHT20(i2c) def read_AHT20_sensor(sensor):     """     读取 AHT20 传感器数据     """     try:         if sensor.begin() != True:             print("Failed to start AHT20 sensor")             sys.exit(1)         sensor.start_measurement_ready()         temperature = sensor.get_temperature_C()         humidity = sensor.get_humidity_RH()         print(f"Temperature: {temperature:3.1f} ℃")         print(f"Humidity: {humidity:3.1f} %RH")         return temperature, humidity     except:         print("Failed to read AHT20 sensor.") def read_light_sensor(pin: Pin) -> int:     """     读取环境光传感器数据     """     adc = ADC(Pin(2)).read_u16()        # 创建 ADC 对象,通过ADC传感器输出的电压值转为数值     print(f"Light: {adc}")     return adc                          # 返回 ADC 值 temperature = 0 humidity = 0 light = 0 oled.text("Temp :", 12, 10) oled.text("Humid:", 12, 28) oled.text("Light:", 12, 48) oled.show() start_time = time.ticks_us() while True:     now_time = time.ticks_us()     if time.ticks_diff(now_time, start_time) > 200:         temperature, humidity =read_AHT20_sensor(light_sensor)         light = read_light_sensor(light_pin)         light = light / 65535 *100      # 转化为百分比值         # 清空上次显示的值         oled.fill_rect(60, 10, 91, 55, 0)         # 显示温度         oled.text(str(temperature)[:4], 60, 10)         oled.text("C", 92, 10)         # 显示湿度         oled.text(str(humidity)[:4], 60, 28)         oled.text("%RH", 92, 28)         # 显示环境光强度,         if (light != 100):              # 当强度等于 100% 时,显示3个字符             oled.text(str(light)[:4], 60, 48)         else:                           # 当强度不等于 100% 时,显示4个字符             oled.text(str(light)[:3], 60, 48)         oled.text("%", 92, 48)         oled.show()         start = now_time     else:         time.sleep_ms(20) ``` ***** ```python # 环境光传感器 light_pin = Pin(2)                      # 环境光传感器输出脚连接 GPIO2 ``` 环境光传感器的输出脚连接到扩展版的J5上,对应ESP32C3的 `GPIO2` ***** ```python # AHT20 驱动 light_sensor = DFRobot_AHT20.DFRobot_AHT20(i2c) ``` AHT20 使用I2C协议传输数据,D4(GPIO6)脚作为SDA,D5(GPIO7)脚作为SCL,与OLED屏幕使用相同的引脚。 ***** ```python light = read_light_sensor(light_pin) light = light / 65535 *100      # 转化为百分比值 ``` ESP32-C3 中的ADC是12位的,最大值2^12^ - 1,即 65535。光强最强时,传感器输出到ADC的转换值为 65535,`light / 65535 *100`把0 \~ 65535的范围转变为0 \~ 100%范围。 ***** ```python now_time = time.ticks_us() if time.ticks_diff(now_time, start_time) > 200: else:     time.sleep_ms(20) ``` `time.ticks_us()` 可以理解为获取当前的系统时间(毫秒单位),`time.ticks_diff(now_time, start_time)`用来计算 now_time 和 start_time 直接是时间差。 这段代码表示每隔200ms读取并显示温湿度和环境光数据。 #### 操作 上传库文件和代码与前面任务相同,不赘述。 ### 任务6:寻找WiFi发射源的位置 #### 展示 #### 硬件 * Seeed Studio XIAO ESP32C3 * Expansion Board Base for XIAO #### 软件 * Esptool * Thonny * ampy #### 代码 ```python """ 任务6:寻找WiFi发射源的位置 实时测量WiFi信号强度,同时移动开发板位置,找到WiFi发射源(例如路由器)的位置 参考 https://wiki.seeedstudio.com/XIAO_ESP32C3_MicroPython/#final-wi-fi-signal-strength-tracker """ import network import time from time import sleep import machine from machine import Pin, SoftI2C import ssd1306 import math # SSD1306 屏幕驱动 i2c = SoftI2C(scl=Pin(7), sda=Pin(6))   # oled屏幕连接I2C引脚 oled_width = 128 oled_height = 64 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) # 网络配置 wifi_ssid = "1708" wifi_password = "tsl199725?" machine.freq(160000000)             # 设置 CPU频率为 160 MHz oled.text("Satrting up...", 0, 0) oled.show() station = network.WLAN(network.STA_IF)      # 创建 WLAN station.active(True)                        # 激活网络接口 station.connect(wifi_ssid, wifi_password)   # 连接到wifi网络 time.sleep(1) while not station.isconnected():     time.sleep(1) oled.fill(0) oled.text("Connecting to", 0, 0) oled.text(wifi_ssid, 0, 20) oled.show() time.sleep(2) oled.fill(0) ip_address = station.ifconfig()[0]  # 获取 IP 地址 oled.text("Connected! ", 0, 0) oled.text("IP Address:", 0, 20) oled.text(ip_address, 0, 40) oled.show() time.sleep(1) x_pos = [12, 38, 64, 90]            # 对应信号强度方格的x坐标位置 statuses = ["poor", "normal", "good", "excellent"] def calculate_block_count(rssi):     """     根据RSSI值确定块数     """     if -80

  • 2023-12-17
  • 加入了学习《 【得捷电子Follow me第3期】使用MicroPython完成任务》,观看 【得捷电子Follow me第3期】使用MicroPython完成任务

  • 加入了学习《【得捷电子Follow me第2期】使用CircuitPython完成任务》,观看 【得捷电子Follow me第2期】使用CircuitPython完成任务

  • 上传了资料: 【得捷Follow me第3期】代码合集

最近访客

现在还没有访客

< 1/0 >

统计信息

已有--人来访过

  • 芯积分:62
  • 好友:--
  • 主题:3
  • 回复:4

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言