- 2024-10-30
-
回复了主题帖:
【2024 DigiKey 创意大赛】ESP32-S3-LCD-EV-BOARD点亮lcd、联网、SNTP校时
Jacktang 发表于 2024-10-25 07:24
时间戳范围的单位是ms,gmtime处理时间的单位是秒,所以需要把时间戳先除以1000再传入函数,这是技巧
是呀,一开始没仔细看,获取到的都成了最大值了,都是固定的时间,还以为出问题没获取到时间
- 2024-10-23
-
发表了主题帖:
【2024 DigiKey 创意大赛】ESP32-S3-LCD-EV-BOARD点亮lcd、联网、SNTP校时
大家好,我是郑工,尘世间一个迷途小工程师。
这次大赛想挑战一下自己,也想写一个手把手esp idf开发入门的帖子,所以这次大赛决定用esp idf开发应用(真是给自己整了个大活呀T_T)
经过了好多天的调试,终于是把WiFi联网功能与SNTP功能给摸透了,下面就给大家分享一下一些经验,希望对大家有帮助。
一、点亮lcd屏幕
由于我们是拿的乐鑫官方的开发板,所以其实点亮屏幕是很简单的,直接用官方的例程就可以了,GitHub地址如下:
esp-dev-kits/esp32-s3-lcd-ev-board at master · espressif/esp-dev-kits · GitHub
出厂的程序用的是86box_smart_panel,我看过代码了,逻辑和界面写了好多,不方面我们从零开始学习,所以我决定还是用lvgl_demo这个例程。
直接帮我们把lvgl移植好了,省去我们好多的开发工作,而esp32s3一直lvgl的文档视频网上都挺多的了,总的来说不难,就是下载lvgl官方库,然后对接液晶接口和触摸接口。这里就不详细介绍了。
然后我们就可以开始做界面开发了,这里我学习了一些代码写界面的方法,感觉跟用tkinter开发界面一样,每个控件每个控件的创建,调整大小样式布局,没有仿真,esp32s3的下载速度又说不上快,调整多几次,一个小时就过去了。所以最后我选择使用squareline studio开发界面。
这样只要拖拽,调整属性什么的,图片也会自动转码,实在是可以节省很多功夫。
二、联网
用乐鑫的芯片又怎么可以不使用联网功能呢,下面是一段简单的联网测试代码
static EventGroupHandle_t wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
static void event_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
static uint32_t wifi_retry_cnt = 0;
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
}else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
if( wifi_retry_cnt < 10){
ESP_LOGI(TAG, "WiFi disconnected, retrying...");
esp_wifi_connect();
wifi_retry_cnt++;
}else {
ESP_LOGE(TAG, "WiFi disconnected, retrying failed");
xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
}
}else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "Got IP address: %s", ip4addr_ntoa(&event->ip_info.ip));
wifi_retry_cnt = 0;
xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
}
}
void wifi_init_sta(void){
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
wifi_event_group = xEventGroupCreate();
// tcpip_adapter_init();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
wifi_config_t wifi_config = {
.sta = {
.ssid = "QC",
.password = "Qaz123456",
.scan_method = WIFI_FAST_SCAN,
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_start() );
ESP_LOGI(TAG, "wifi_init finished.");
EventBits_t bits = xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "connected to ap");
}else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "fail to connected to ap");
}else {
ESP_LOGE(TAG, "WIFI_EVENT_STA_DISCONNECTED");
}
ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
vEventGroupDelete(wifi_event_group);
}
简单来说,esp32s3联网有以下的步骤:
初始化网络堆栈: 初始化网络接口和协议栈。
ESP_ERROR_CHECK(esp_netif_init());
创建默认的 Wi-Fi 接口: 创建一个默认的 Wi-Fi Station(STA)接口。
esp_netif_create_default_wifi_sta();
配置 Wi-Fi 接口: 设置 Wi-Fi 的模式和配置参数。
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
设置 Wi-Fi 模式: 设置 ESP32-S3 为 Wi-Fi Station 模式。
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
配置 Wi-Fi 凭证: 设置 Wi-Fi SSID 和密码。
wifi_config_t wifi_config;
memset(&wifi_config, 0, sizeof(wifi_config_t));
strncpy((char *)wifi_config.sta.ssid, "your_ssid", sizeof(wifi_config.sta.ssid));
strncpy((char *)wifi_config.sta.password, "your_password", sizeof(wifi_config.sta.password));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
启动 Wi-Fi: 启动 Wi-Fi 接口。
ESP_ERROR_CHECK(esp_wifi_start());
连接到 Wi-Fi 网络: 使用 esp_wifi_connect() 函数连接到 Wi-Fi 网络。
ESP_ERROR_CHECK(esp_wifi_connect());
等待连接完成: 通常需要等待 Wi-Fi 连接完成,可以通过轮询或注册事件回调函数来实现。
while (!esp_netif_is_connected()) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
获取 IP 地址: 连接成功后,获取分配给 ESP32-S3 的 IP 地址。
ip_info_t ip;
esp_netif_get_ip_info(esp_netif_get_handle(ESP_IF_WIFI_STA), &ip);
使用网络: 此时 ESP32-S3 已经连接到 Wi-Fi 网络,可以进行网络通信。
然后函数需要添加以下判断网络状态,自动重连的业务代码即可。
三、SNTP校时
这个主题我做了两个程序,一个是根据之前做follow me任务使用的网络时间服务api获取时间,二个是使用ESP-IDF提供的SNTP(simple network time potocol)。下面我就帖以下代码讲解以下。
网络api
#include "cJSON.h"
#include "esp_http_client.h"
struct tm timeinfo;
void parse_json_time(const char *json_str) {
// 解析 JSON 字符串
cJSON *json = cJSON_Parse(json_str);
if (json == NULL) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
ESP_LOGE(TAG, "Error before: %s", error_ptr);
}
return;
}
// 提取 server_time 字段
cJSON *server_time_item = cJSON_GetObjectItemCaseSensitive(json, "server_time");
if (cJSON_IsNumber(server_time_item)) {
// 获取时间戳
long server_time = server_time_item->valuedouble /1000;
// 将时间戳转换为本地时间
time_t l_time = (time_t)server_time;
struct tm *utc_time = gmtime(&l_time);
utc_time->tm_hour += 8; //东八区
if(utc_time->tm_hour > 23) //防止过界
utc_time->tm_hour -= 24;
timeinfo = *utc_time;
// 格式化时间并打印
char time_str[32];
printf("TIME: %02d:%02d:%02d\n",utc_time->tm_hour, utc_time->tm_min, utc_time->tm_sec);
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", utc_time);
ESP_LOGI(TAG, "Server time: %s", time_str);
} else {
ESP_LOGE(TAG, "server_time is not a number");
}
// 清理 cJSON 对象
cJSON_Delete(json);
}
void http_test_task(void *pvParameters)
{
char output_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0}; //用于接收通过http协议返回的数据
int content_length = 0; //http协议头的长度
struct tm* l_time = get_time();
//02-2 配置http结构体
//定义http配置结构体,并且进行清零
esp_http_client_config_t config ;
memset(&config,0,sizeof(config));
//向配置结构体内部写入url
static const char *URL = "http://api.pinduoduo.com/api/server/_stm";
config.url = URL;
//初始化结构体
esp_http_client_handle_t client = esp_http_client_init(&config); //初始化http连接
//设置发送请求
esp_http_client_set_method(client, HTTP_METHOD_GET);
//02-3 循环通讯
while(1)
{
// 与目标主机创建连接,并且声明写入内容长度为0
esp_err_t err = esp_http_client_open(client, 0);
//如果连接失败
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
}
//如果连接成功
else {
//读取目标主机的返回内容的协议头
content_length = esp_http_client_fetch_headers(client);
//如果协议头长度小于0,说明没有成功读取到
if (content_length < 0) {
ESP_LOGE(TAG, "HTTP client fetch headers failed");
}
//如果成功读取到了协议头
else {
//读取目标主机通过http的响应内容
int data_read = esp_http_client_read_response(client, output_buffer, MAX_HTTP_OUTPUT_BUFFER);
if (data_read >= 0) {
//打印响应内容,包括响应状态,响应体长度及其内容
ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
esp_http_client_get_status_code(client), //获取响应状态信息
esp_http_client_get_content_length(client)); //获取响应信息长度
// printf("data:%s\n", output_buffer);
parse_json_time(output_buffer);
}
//如果不成功
else {
ESP_LOGE(TAG, "Failed to read response");
}
}
}
//关闭连接
esp_http_client_close(client);
//延时
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
测试代码可以通过xTaskCreate(&http_test_task, "http_test_task", 8192, NULL, 5, NULL);添加任务。
代码主要就是通过网络请求访问http://api.pinduoduo.com/api/server/_stm拼多多时间api,获取时间戳,返回数据的样式是如:
{"server_time":1729698004538}
的时间戳,然后解析json获取"server_time"对应的值,再把时间戳通过gmtin函数转换为标准时间,需要注意的是
1、时间戳范围的单位是ms,gmtime处理时间的单位是秒,所以需要把时间戳先除以1000再传入函数。
2、获取的时间戳是本初子午线上的时间,北京时间需要把时间+8处理。
这种办法很难实现精确到秒的时间显示,或许可以请求一次,后续内部自己创建一个时间维护,然后定期去校准时间,不然如我例子那样,每一秒请求一次,会浪费好多网络资源,而且请求返回也需要时间,经常会发生跳秒的情况,实现效果并不理想
SNTP时间服务器
第二个办法就是使用ESP-IDF提供的SNTP时间服务器,使用方法简单,不怎么占用系统资源,不需要维护系统时间,代码如下:
static void initialize_sntp(void);
static void obtain_time(void);
static void time_sync_notification_cb(struct timeval *tv)
{
ESP_LOGI(TAG, "Notification of a time synchronization event, sec=%lu", tv->tv_sec);
settimeofday(tv, NULL);
}
void app_sntp_init(void)
{
setenv("TZ", "CST-8", 1);
tzset();
obtain_time();
}
static void obtain_time(void)
{
initialize_sntp();
int retry = 0;
const int retry_count = 10;
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
if (retry == retry_count) {
ESP_LOGI(TAG, "Could not obtain time after %d attempts", retry);
}else {
ESP_LOGI(TAG, "Time synchronized");
}
}
static void initialize_sntp(void)
{
ESP_LOGI(TAG, "Initializing SNTP");
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
//设置3个时间服务器
esp_sntp_setservername(0, "ntp.aliyun.com");
esp_sntp_setservername(1, "time.asia.apple.com");
esp_sntp_setservername(2, "pool.ntp.org");
esp_sntp_set_time_sync_notification_cb(time_sync_notification_cb);
esp_sntp_init();
}
大家可以看到,代码非常的简单,基本上执行一次,就可以通过time函数获取本地时间了,获取时间的方法也很简单,只需要调用两个函数就可以
// 获取当前时间
time_t unix_time = time(NULL);
// 将时间转换为本地时间,这是非线程安全的方法,只有一个参数,所以不能在多线程中使用
struct tm *time_info = localtime(&unix_time);
时间更新的间隔可以使用idf.py menuconfig打开系统设置,在Component config -> LWIP -> SNTP下设置Request interval to update time(ms)中设置,我设置了12小时校准一次,一般也够用了。
需要注意的是,最好不要在任何的callback函数或者中断处理中调用obtain_time函数,不然都有可能被卡死,结合上面的联网内容,可以在断网重连之后重新校准一次时间。
后面还会增加天气功能进去,到时候就是使用网络api的方法,注册心知天气的个人业务即可。
查看你的 API 密钥 | 心知天气文档 (seniverse.com)
-
回复了主题帖:
【2024 DigiKey 创意大赛】ESP-IDF安装使用
hellokitty_bean 发表于 2024-10-19 21:47
是在Ubuntu下安装esp-idf,还是就在Windows下安装esp-idf?
ubuntu下载的,通过mobaXterm访问ubuntu,不过现在看好多人都用Windows下载idf了,等开发完再试试看
- 2024-10-18
-
回复了主题帖:
【2024 DigiKey 创意大赛】ESP-IDF安装使用
秦天qintian0303 发表于 2024-10-15 13:03
跑Linux系统好弄吗?
还可以,开发还是用vscode,然后编译下载传输文件都可以用MobaXterm。感觉都还好,没啥影响
- 2024-10-15
-
发表了主题帖:
【2024 DigiKey 创意大赛】ESP-IDF安装使用
大家好,我是郑工,尘世间一个迷途小工程师
好久没回归EE主线了,我们赶紧来搞得捷创意大赛吧
今天来开始安装ESP-IDF。ESP-IDF是ESP系列芯片的主流开发环境,但是也是公认安装最麻烦的。我也琢磨搞了一天,所以还是给大家分享一下,也当做一个记录吧
安装ESP-IDF
下载Linux系统,Ubuntu服务器版本20.04
下载地址Ubuntu 20.04.6 LTS (Focal Fossa)
使用VMware安装,安装时记得安装SSH服务
用命令sudo apt-get net-tools安装网络服务
使用命令ifconig查看IP地址
使用MobaXtern的SSH连接连接到Ubuntu上
根据教程ubuntu20.04更换清华源-CSDN博客更换城国内源
使用命令sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0安装必要软件
创建新文件夹mkdir esp32
cd esp32进入新文件夹
使用git clone https://gitee.com/EspressifSystems/esp-gitee-tools.git 拉取esp gitee tools
cd esp-gitee-tools/进入文件夹
使用命令./jihu-mirror.sh set安装,然后cd ..退出文件夹
使用命令git clone --recursive https://github.com/espressif/esp-idf.git 拉取esp idf
cd esp-idf
git checkout v5.2 切换版本
更新子模块git submodule update --init --recursive
使用命令../esp-gitee-tools/install.sh 安装工具
使用python3.8是问题最少,最稳定的版本
这也是为什么Linux用服务器版20.04的原因
vscode使用说明
点击扩展,安装插件
安装完会多一个远程资源管理器,打开配置文件
设置ESP-IDF的环境变量
进入esp-idf目录
执行脚本source export.sh
这是设置的临时环境变量
需要永久设置,可以cd ~
Ls -al查看所有文件有个.profile文件,终端登录后会默认执行文件里面的文件
vim .profile 编辑文件
最后一行点i,插入,输入source esp32/esp-idf/export.sh,点esc退出插入模式,然后输入:wq写入退出
-
发表了主题帖:
【得捷Follow me第二季第1期】任务汇总+舵机与AGS02MA气体传感器使用
本帖最后由 eew_Ya3s2d 于 2024-10-18 15:46 编辑
Hello,大家好,我是郑工,尘世间一个迷途小工程师。
这个帖子我们来汇总一下所有的任务与讲解一下
0、物料清单:
CPX主板
舵机
AGS02MA气体传感器
首先是我自己感觉有些尴尬的视频讲解
[localvideo]eedfda84f28c67abea9939b1ddca653e[/localvideo]
这个视频拍着拍着就拍到差不多15分钟了,视频2个G,最后是压缩了之后才能上传,下次拍视频之前还是得选不要太高清才行
入门任务(必做):开发环境搭建,板载LED点亮
【Follow me第二季第1期】任务0:开发环境搭建,板载LED点亮 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
程序就是通过time.sleep函数产生一个pwm去点亮led,不断更改pwm的占空比,这样led看起来就led就会有亮暗变化,像呼吸灯
最主要的函数是下面这个,产生一个简单的pwm,控制led灯。
def onLed(onTime, duty):
if onTime > 0:
led.value = True
time.sleep(onTime)
if duty - onTime > 0:
led.value = False
time.sleep(duty - onTime)
[localvideo]8c23d536df42401548b2dd2f7df07893[/localvideo]
基础任务一(必做):控制板载炫彩LED,跑马灯点亮和颜色变换
【Follow me第二季第1期】任务1:控制板载炫彩LED,跑马灯点亮和颜色变换 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
这个其实就是控制WS2812B灯珠做流水灯,总体来说就是用neopixel库来实现彩色灯的效果,封装得太好,显得没有难度,其实中间一些时序问题,当年我也是想破头
颜色变换写了两种不同函数去遍历。
def Wheel2(i, r_in, g_in):
if i < 0 or i > 10:
r = g = b = 0
elif i % 3 == 0:
r = r_in
g = g_in
b = 255 - r - g
elif i % 3 == 1:
r = g_in
b = r_in
g = 255 - r - b
else:
g = r_in
b = g_in
r = 255 - b - g
return (r, g, b)
def rainbow_cycle2():
dir = True
for r in range(255):
start = 0
stop = 255 - r
step = 1
if not dir:
start = 255 - r
stop = 0
step = -1
for g in range(start, stop, step):
for i in range(10):
pixels[i] = Wheel2(i, r, g)
pixels.show()
time.sleep(colorFulWaitTime / 50)
dir = not dir
def wheel(pos):
if pos < 0 or pos > 768:
r = g = b = 0
elif pos < 256:
r = int(pos)
g = int(255 - pos)
b = 0
elif pos < 512:
pos -= 256
r = int(255 - pos)
g = 0
b = int(pos)
else:
pos -= 512
r = 0
g = int(pos)
b = int(255 - pos)
return (r, g, b)
def rainbow_cycle():
for j in range(767):
for i in range(num_pixels):
pixel_index = (i * 767 // num_pixels) + j
pixels[i] = wheel(pixel_index % 767)
pixels.show()
time.sleep(colorFulWaitTime)
[localvideo]22f9bc383bf6e55af3472be4f947f179[/localvideo]
基础任务二(必做):监测环境温度和光线,通过板载LED展示舒适程度
【Follow me第二季第1期】任务2:监测环境温度和光线,通过板载LED展示舒适程度 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
这个任务就是读取AD任务,通过读取光敏AD上的值,获取照度,通过adafruit_thermistor库,可以直接获取温度值,也是站在别人的肩膀上,顿时感觉轻松好多
库的使用也非常简单,我写了一些注释,只要初始化设置好,后面直接得到温度,简单快捷
import adafruit_thermistor
# 模拟输入的管脚
pin = board.TEMPERATURE
# 热敏电阻的常温阻值
resistor = 10000
# 普通电阻的阻值
resistance = 10000
# 热敏电阻的阻值温度
nominal_temp = 25
# 热敏电阻的B系数
b_coefficient = 3950
# 还有最后一个参数,参数名为high_side,表示热敏电阻是否连接在上端,默认为True,可以不填
thermistor = adafruit_thermistor.Thermistor(
pin, resistor, resistance, nominal_temp, b_coefficient)
程序通过灯珠数量反应照度值,通过灯珠颜色反应温度。不过灯珠就在光敏三极管旁边,还是有一些影响。
基础任务三(必做):接近检测——设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警
【Follow me第二季第1期】任务3:接近检测 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
这是我耗时最久的一个任务,用红外收发实在是完成不了,最后是用了超声波距离模块实现程序功能,超声波模块只需要测量反馈的脉冲长度就可以知道物体的距离的,测试距离使用time.monotonic_ns()函数计算时间戳的差值(单位ns)即可,如下面代码
# 发送出发信号,时间是500us,只要比需求长就可以了
ir_tx.value = True
time.sleep(0.0005)
ir_tx.value = False
rx_count = 0
# 等待回复的高电平
while ir_rx.value is False:
time.sleep(0.0001)
rx_count = rx_count + 1
if rx_count > 10000: # 发送高电平之后等待时间太长,认为是发送失败
break
start_time = time.monotonic_ns() #获取高电平开始的时间戳,单位是ns
while ir_rx.value is True:
pass
end_time = time.monotonic_ns() #获取高电平结束的时间戳,单位是ns
duration = round((end_time - start_time)/1000000, 2)
if duration < 0.05: # 时间太短
continue
print(f'duration time:{duration} ms')
distance = round(duration*17.0, 1) # 时间*340m/s(34cm/ms)/2
print(f'distance:{distance} cm')
[localvideo]98bcbcd1ec2107ae87dc9cffc0d17e29[/localvideo]
进阶任务(必做):制作不倒翁——展示不倒翁运动过程中的不同灯光效果
【Follow me第二季第1期】任务4:制作不倒翁——展示不倒翁运动过程中的不同灯光效果 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
这是一个整活的任务,其实我很多精力都用在搞那个不倒翁底座那里去了T_T
加速度传感器使用也非常简单,只需要调用库即可,如下
import board
import busio
import adafruit_lis3dh
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c, address=0x19)
# Set range of accelerometer (can be RANGE_2_G, RANGE_4_G, RANGE_8_G or RANGE_16_G).
lis3dh.range = adafruit_lis3dh.RANGE_2_G
ax, ay, az = [
value / adafruit_lis3dh.STANDARD_GRAVITY for value in lis3dh.acceleration
]
[localvideo]047a18051831057b8517ff7198dcf743[/localvideo]
最后补充一下我另外买的两个零件,一个是舵机,一个是AGS02MA气体传感器
舵机
舵机主要就是通过pwm占空比来控制舵机的动作,从规格书我们可以看到具体的控制方式
从上面可以看到,停止脉冲是1500us,顺时针方向是700-1500us,逆时针方向是1500-2300us
所以只要用pwmio库产生一个pwm就可以控制舵机
# create a PWMOut object on Pin A1.
pwm = pwmio.PWMOut(board.A1, frequency=50, duty_cycle=7536)
# 2294 0.7ms min
# 4915 1.5ms stop
# 7536 2.3ms max
我这里产生的是一个50hz的pwm波
AGS02MA气体传感器
这个要调试其实也有些麻烦,不过其实用法也简单,就那么两三个指令需要调试,不过直到我找到下面这个网站,所有困难都烟消云散了,还是得再次感叹一下python社区的人多力量大,我们都是站在巨人的肩膀上
adafruit-circuitpython-ags02ma - 用于 AGS02MA 气体传感器的 CircuitPython / Python 库_PyPI中文网
直接安装就可以了。然后找到文件
放到板子里面就可以使用了,文件里也说了使用方法
代码如下:
import board
import busio
import time
from adafruit_ags02ma import AGS02MA
# Initialize I2C bus.
i2c = busio.I2C(board.SCL, board.SDA, frequency = 20000)
ags = AGS02MA(i2c, address=0x1A)
while True:
res = ags.gas_resistance
tvoc = ags.TVOC
print(f'tvoc:{tvoc},res:{res}')
time.sleep(2)
可惜的是,CPX线路板的硬件I2C并不支持20k的通讯速率,而AGS02MA的最大通讯速率是30k。最后我是使用ESP-S3 feather这个板子来完成,同样是follow me活动的板子,同样是使用circuit python代码完成的
感想
最后的最后,还是得感谢举办方,感谢得捷电子,感谢EE。在不断摸索的过程中,感受到前人智慧的浩渺,我只是后来者,模仿者,轻松拿来使用的人。并没有什么值得骄傲的。科学进步才是社会发展的动力,我仍然需要虚心学习更多的知识,创造更美好的生活。
下面是课程链接:
【得捷Follow me第二季第1期】任务汇总+舵机与AGS02MA气体传感器使用-EEWORLD大学堂
源码:
Follow me第二季第一期 所有代码 + 库-嵌入式开发相关资料下载-EEWORLD下载中心
- 2024-10-14
-
回复了主题帖:
【Follow me第二季第1期】任务3:接近检测
wangerxian 发表于 2024-10-12 15:34
用python写超声波代码这么简单的吗?
AS100S是个专用芯片,使用起来就是简单,现在好像都是用模块比较多
-
上传了资料:
Follow me第二季第一期 所有代码 + 库
- 2024-10-13
-
发表了主题帖:
【Follow me第二季第1期】任务4:制作不倒翁——展示不倒翁运动过程中的不同灯光效果
大家好,我是郑工,尘世间一个迷途小工程师。
我们赶紧把任务4完成了,制作一个不倒翁,之前我在路边捡到一个木头,如下:
我们来搞个不倒翁吧,电子上没办法整活,我们来整个木工活
经过我一堆磨切敲打,终于把木头弄成下面这个形状了
(请忽略木头上那条裂纹,搞了一天,木头裂了,人都要炸了,最后用了些电工胶粘在一起了,我们是电子论坛,这是可以接收的,以后有机会得搞个车床才行)
再打上木蜡油上去,经过晾晒,这个底座就可以用了
好了,木工活搞完了,我们继续来搞我们些原理分析吧。
CPX的板子上,自带了一个lis3dh,这个芯片是ST生产的三轴线性加速度传感器,具有超低功耗,1到5.3k输出速率,提供±2g/±4g/±8g/±16g的动态用户可选全量程,好用的芯片
首先是初始化,因为两个管脚就是芯片的I2C管脚,在board库里面有定义board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA,所以初始化比较简单,代码如下:
import board
import busio
import adafruit_lis3dh
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c, address=0x19)
# Set range of accelerometer (can be RANGE_2_G, RANGE_4_G, RANGE_8_G or RANGE_16_G).
lis3dh.range = adafruit_lis3dh.RANGE_2_G
然后读取三轴加速度的值,只需要通过函数:
ax, ay, az = [
value / adafruit_lis3dh.STANDARD_GRAVITY for value in lis3dh.acceleration
]
因为读取出来是重力加速度,所以需要除以重力加速度
然后计算俯仰角跟横滚角:
# 计算俯仰角
pitch = math.atan2(ay, math.sqrt(ax*ax + az*az)) * 180 / math.pi;
# 计算横滚角
roll = math.atan2(ax, math.sqrt(ay*ay + az*az)) * 180 / math.pi;
俯仰角就是物体前后倾斜的角度,横滚角就是物体横向翻滚的角度。
这里我做了个逻辑判断,如果两个角度都小于5度,则表示没有倾斜,如果倾斜之后,则用 (俯仰角/横滚角) 计算比例,再用arctan函数计算对应的角度,再转换成数值,对应到10个灯珠上。函数表现如下,基本能实现线路板倾斜,对应的灯珠能亮起来红灯。
if abs(pitch) < 5 and abs(roll) < 5: # 倾斜角度小于5度,认为水平,显示绿灯
pixels.fill((0, 15, 0))
pixels.show()
else:
if roll == 0: # 防止roll等于0的错误
roll = 1
arc = math.atan(pitch/roll)* 180 / math.pi
num = ((arc + 90) / 180) * 4.7
if roll > 0:
fill_led(int(num))
else:
fill_led(int(num + 5))
- 2024-10-12
-
发表了主题帖:
【Follow me第二季第1期】任务3:接近检测
本帖最后由 eew_Ya3s2d 于 2024-10-12 10:02 编辑
大家好,我是郑工,尘世间一个迷途小工程师。
最近家里比较忙,人到中年,忙忙碌碌的,正如张爱玲在《半生缘》里写的“中年以后的男人,时常会觉得孤独,因为他一睁开眼睛,周围都是要依靠他的人,却没有他可以依靠的人”。咦,等等,我们是工程师,回到正题,说说这次FM活动第一期的任务3,这个任务我也研究了一些时间,做了一些实验,我们先说说原理。
电路图如下:
红外发送的电路很简单就是用一个npn三极管去驱动红外发射管。
红外接收电路就用了一个专用芯片VSOP383。在网上找到了原理图,框图如下
可以看到红外接收管如果的地方,有个bias偏置电路,所以在无发送的时候,也会有个偏置电压,用万用表测试了一下,这个电压是0.925v。用白光测试了一下,发现红外接收管对于白光是不敏感的。然后规格书上也说了,器件是对38kHz的红外光敏感,可以看到下图的频率响应。
而在CPX的规格书里面说明了,可以用A10作为接近感应器的输入管脚。
最后,进入REPL查询我们可以知道管脚定义并不是A10,而是IR_PROXIMITY
(附:进入REPL的办法,可以用mu,打开串口,使用ctr + c暂停程序,然后按回车进入REPL。REPL代表“读取-评估-打印-循环”(Read-Evaluate-Print Loop),它是一个交互式编程环境,允许用户输入代码并立即执行,然后显示结果。这非常有用,尤其是当你需要对代码进行故障排除或测试新想法时。)
所以我们的程序思路其实就很明确了,就是使用IR_TX管脚,输入一个38khz的脉冲或者多个脉冲,然后立刻去读取IR_PROXIMITY的AD值。当有物体接近的时候,反射光会叠加到芯片的偏置上,接近得越近,AD的数值就越大。
之前我些了一个简单的代码,程序也可以运行,跟我猜想的也一样,代码如下:
import analogio
import digitalio
import board
import time
ir_tx = digitalio.DigitalInOut(board.IR_TX)
ir_tx.direction = digitalio.Direction.OUTPUT
proximity = analogio.AnalogIn(board.IR_PROXIMITY)
delay_time = 0.00001
while True:
for i in range(2):
time.sleep(delay_time)
ir_tx.value = True
time.sleep(delay_time)
ir_tx.value = False
proximity_value = proximity.value
print("proximity Level: %d" % proximity_value)
time.sleep(0.1)
延时的数值确定为10微秒是因为38khz方波的周期为26微秒,高电平,低电平的时间都为13微秒,粗略估计进入退出time.sleep函数的时间3微秒,函数是用于大致测试使用的,没有卡太准,我用示波器测试看到波形确实也是有的,波形如下:
讲真这波形跟我想象中还是有些出入,可能这发射跟接收之间并没有严格隔离,所以其实可以看到发射期间IR_PROXIMITY的电压都有上升的,只是我接近的时候,在准备低电平那时候有个尖峰,没接近的时候,就没这个尖峰。在我正想研究这个到底有什么内在逻辑的时候,这个波形消失了。然而我单独测试发射或者接收,也是没问题的,搞了好久,都没理解到底哪里出问题了,搞得我一度很气馁,也研究过好多坛友的帖子,感觉也是大差不差,甚至我担心38k输入不准确,使用pwmio.PWMOut(board.IR_TX, frequency=38000, duty_cycle=35768)产生一个准确的38k方波,都是一点反应没有。不知道是不是被我用示波器捅的时候捅出什么问题了。
加上生活工作上一些琐事,让我一直拖延到了现在,我想事情还是得解决的,既然这条路走不通,我们要创造条件完成任务,所以我买了一个超声波距离传感器
由图可见使用的是CS100A超声波芯片。这个芯片的使用方式也很简单,在 TRIG 管脚输入一个 10US 以上的高电平(一般建议 50US 左右),芯片(TP,TN管脚)便可发出 8 个 40KHZ 的超声波脉冲,然后(RP,RN)检测回波信号。当检测到回波信号后,通过 ECHO 管脚输出。
根据 ECHO 管脚输出高电平的持续时间可以计算距离值。即距离值为:(高电平时间*340m/s)/2。当测量距离超过测量范围时,CS100A 仍会通过 ECHO 管脚输出高电平的信号,高电
平的宽度约为 33ms 。
测量周期:当芯片通过 ECHO 管脚输出的高电平脉冲后,便可进行下一次测量,所以测量周期取决于测量距离,当测距很近时,ECHO 返回的脉冲宽度较窄,测量周期就很短;当测距较远时,ECHO 返回的脉冲宽度较宽,测量周期也就相应的变长。
最坏情况下,被测物体超出测量范围,此时返回的脉冲宽度最长,约为 33ms,所以最坏情况下的测量周期大于 33ms 即可(比如测量周期可取 50ms)。
这是正常时候的波形
这是超出范围的波形
计算其实就比较简单,音波在空气中的传播速度是340m/s = 34000cm/1000ms = 34cm/ms。距离 = 时间 x 速度,考虑上一来一回,所以 距离 = 时间 x 速度 / 2。最后距离 = 时间 x 17,单位是厘米。由此可知,33ms也有500+m,显然是超出我们想侦测的范围。
由此我写了以下的代码侦测距离
# 发送出发信号,时间是500us,只要比需求长就可以了
ir_tx.value = True
time.sleep(0.0005)
ir_tx.value = False
rx_count = 0
# 等待回复的高电平
while ir_rx.value is False:
time.sleep(0.0001)
rx_count = rx_count + 1
if rx_count > 10000: # 发送高电平之后等待时间太长,认为是发送失败
break
start_time = time.monotonic_ns() #获取高电平开始的时间戳,单位是ns
while ir_rx.value is True:
pass
end_time = time.monotonic_ns() #获取高电平结束的时间戳,单位是ns
duration = round((end_time - start_time)/1000000, 2)
if duration < 0.05: # 时间太短
continue
print(f'duration time:{duration} ms')
distance = round(duration*17.0, 1) # 时间*340m/s(34cm/ms)/2
print(f'distance:{distance} cm')
代码并不复杂,就是发送一个出发信号,然后等待回复,用time.monotonic_ns()函数获取时间戳,计算开始与结束的时间差。
后面需要简单说一下的就是播放音频的代码。其实就是一些代码的参(复)考(制)
CircuitPython Audio Out | Adafruit Circuit Playground Express | Adafruit Learning System
简单说就是使用audioio库里面的AudioOut作为播放器,用audiocore或者audioio里的WaveFile加载音频文件,这样就可以播放音频文件了。
try:
from audiocore import WaveFile
except ImportError:
from audioio import WaveFile
try:
from audioio import AudioOut
except ImportError:
try:
from audiopwmio import PWMAudioOut as AudioOut
except ImportError:
pass # not always supported by every board!
def play_file(filename):
print("Playing file: " + filename)
wave_file = open(filename, "rb")
with WaveFile(wave_file) as wave:
with AudioOut(board.SPEAKER) as audio:
audio.play(wave)
while audio.playing:
pass
print("Finished")
灯光警报就没什么好说的,之前就提过的内容,因为距离测试耗费的时间太长了,就没有整什么花活,可以参考我之前的帖子
【Follow me第二季第1期】任务1:控制板载炫彩LED,跑马灯点亮和颜色变换 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
或者等我把任务代码提交了,直接拷贝一下。
专业的超声波测距模块还是挺准的,我测试精确度都有厘米级别了。
- 2024-08-09
-
发表了主题帖:
【2024 DigiKey 创意大赛】开箱贴(ESP32-S3-LCD-EV-BOARD、SEN-21231人在传感器)
大家好,我是郑工,尘世间一个迷途小工程师。
这次特别荣幸能参加得捷创意大赛,这次我做的题目是一个智能植物管理系统,这次得好好搞,选的都是ESP32,带一块3.95" 480x480的屏幕。话不多说,我们直接来看实物吧!!
这是这次比赛的主角ESP32-S3-LCD-EV-BOARD,乐鑫官方的板子,整个质感还是做得挺好的,demo程序看起来也挺协调的,看背后丝印,这是1.5版本的板子,详细资料可以看下面链接
ESP32-S3-LCD-EV-Board v1.5 - - — esp-dev-kits latest 文档 (espressif.com)
然后是SEN-21231人在传感器
背面,可以看到是ESP32-S3的方案,相机有些渣,不过比我肉眼好了,现在年纪大了,这些小字都看不清了T_T
资料如下
person_sensor_docs/README.md at main · usefulsensors/person_sensor_docs · GitHub
兄弟萌,得捷现在又把压力给到我了,要努力加油干!!
- 2024-08-01
-
发表了主题帖:
【Follow me第二季第1期】任务2:监测环境温度和光线,通过板载LED展示舒适程度
大家好,我是郑工,尘世间一个迷途小工程师。
这两天家里有些事情,耽误了些时间,我们继续下一个任务,监控温度和照度。
首先是温度,我们先看看原理图
可以看到原理还是比较简单的,就是一个热敏电阻,下拉一个10k电阻做分压,用ADC接口去读取这个口的电压就可以。
不过查资料之后,CircuitPython有个库adafruit_thermistor可以直接适配这种情况的温度读取。代码如下:
import adafruit_thermistor
# 模拟输入的管脚
pin = board.TEMPERATURE
# 热敏电阻的常温阻值
resistor = 10000
# 普通电阻的阻值
resistance = 10000
# 热敏电阻的阻值温度
nominal_temp = 25
# 热敏电阻的B系数
b_coefficient = 3950
# 还有最后一个参数,参数名为high_side,表示热敏电阻是否连接在上端,默认为True,可以不填
thermistor = adafruit_thermistor.Thermistor(
pin, resistor, resistance, nominal_temp, b_coefficient)
后续只需要读取thermistor.temperature就可以获取的摄氏温度的值。
然后到照度值,我们先看看原理图
原理也就是一个光电三极管下接一个10k电阻,当光照到光电三极管,会产生光电流,等效电阻减小,电压升高。初始化代码如下:
import analogio
# Adc的值为0-65535(16bit)
light = analogio.AnalogIn(board.LIGHT)
后续只需要查询light.value就可以获取adc的值,范围0-65535
后续代码根据获取的数值显示舒适程度,使用neopixel灯珠显示,初始化代码如下:
import neopixel
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.05, auto_write=False)
pixels.fill((0, 0, 0))
pixels.show()
后面的功能逻辑就是温度高为红色,温度低为蓝色,中间温度在这两个颜色之间切换
照度呢就是照度越低,灯珠数量越多,代表越舒服,越适合睡觉。
也是一个有些乱的逻辑,没有仔细深究。大家有什么想法可以跟我说说,我去改一下。以下是具体代码
index = 0
while True:
# light value remapped to pixel position
peak = simpleio.map_range(light.value, 500, 10000, 0, 10)
# def map_range(
# x: float,
# in_min: float,
# in_max: float,
# out_min: float,
# out_max: float) -> float:
light_num = 10 - peak
print('\n\n')
print(f'time: {index}')
index = index + 1
print(f'light val:{light.value}')
print(f'light num:{int(light_num)}')
color = simpleio.map_range(thermistor.temperature, 10, 35, 0, 255)
temp_color = (int(color) , 0, 255 - int(color))
print(f'temperature:{int(thermistor.temperature)}')
print(f'temp num:{color}')
for i in range(10):
if i <= light_num:
pixels[i] = temp_color
else:
pixels[i] = (0, 0, 0)
pixels.show()
time.sleep(1)
使用了simpleio的map_range函数,这个函数会根据输入的数据,做出等级划分。
-
回复了主题帖:
【Follow me第二季第1期】任务1:控制板载炫彩LED,跑马灯点亮和颜色变换
Jacktang 发表于 2024-7-31 07:30
里胡哨的跑马灯环节,,
整个图片或小视频就完美了
[localvideo]ac5de446be1f2801a853515553fd1fba[/localvideo]
简单拍了段,其实也就是简单做一下遍历算法,时间比较长
- 2024-07-30
-
发表了主题帖:
【Follow me第二季第1期】任务1:控制板载炫彩LED,跑马灯点亮和颜色变换
大家好,我是郑工,尘世间一个迷途小工程师。
昨天有些事情,没给大家分享第一个任务,今天继续。
任务一是控制WS2812B灯珠,其实就是学习使用neopixel库,需要参考这个网址-->Adafruit CircuitPython NeoPixel — Adafruit CircuitPython NeoPixel Library 1.0 documentation
说白了就是需要知道用的是哪个管教,一共有多少个灯珠,亮度是多少之类的信息,最重要最重要就是初始化做好,其他啥问题没有,下面是我的初始化函数:
pixel_pin = board.NEOPIXEL
num_pixels = 10
ORDER = neopixel.GRB
pixels = neopixel.NeoPixel(
pixel_pin, num_pixels, brightness=0.2, auto_write=False, pixel_order=ORDER
)
然后需要做的就是给pixels赋值颜色了,有两种方式,一种是调用pixels.fill()函数,所有灯珠都同一个颜色,另一个是给pixels[i]赋值。
最后就是调用pixels.shows()函数执行操作就新行了。
剩下的就是花里胡哨的跑马灯环节。我自己做了两种循环模式,一种是在RGB三种颜色上渐变,另一种是指定RGB之和为255的情况下渐变。也算是争奇斗艳,花里胡哨了。下面是两个函数,有兴趣的同学可以琢磨一下,有啥问题跟我沟通沟通哈!
def Wheel2(i, r_in, g_in):
if i < 0 or i > 10:
r = g = b = 0
elif i % 3 == 0:
r = r_in
g = g_in
b = 255 - r - g
elif i % 3 == 1:
r = g_in
b = r_in
g = 255 - r - b
else:
g = r_in
b = g_in
r = 255 - b - g
return (r, g, b)
def rainbow_cycle2():
dir = True
for r in range(255):
start = 0
stop = 255 - r
step = 1
if not dir:
start = 255 - r
stop = 0
step = -1
for g in range(start, stop, step):
for i in range(10):
pixels[i] = Wheel2(i, r, g)
pixels.show()
time.sleep(colorFulWaitTime / 50)
dir = not dir
def wheel(pos):
if pos < 0 or pos > 768:
r = g = b = 0
elif pos < 256:
r = int(pos)
g = int(255 - pos)
b = 0
elif pos < 512:
pos -= 256
r = int(255 - pos)
g = 0
b = int(pos)
else:
pos -= 512
r = 0
g = int(pos)
b = int(255 - pos)
return (r, g, b)
def rainbow_cycle():
for j in range(767):
for i in range(num_pixels):
pixel_index = (i * 767 // num_pixels) + j
pixels[i] = wheel(pixel_index % 767)
pixels.show()
time.sleep(colorFulWaitTime)
- 2024-07-27
-
回复了主题帖:
【Follow me第二季第1期】开箱帖(现在得捷速度就是这么块)
秦天qintian0303 发表于 2024-7-26 13:32
祝贺楼主喜提开发板,其实我还没有想到舵机干嘛用,还不如搞个屏呢
FM任务里面要用到这个东西,屏幕我自己也有,后面看看怎么驱动一下哈,到时候再告诉你哈
- 2024-07-26
-
发表了主题帖:
【Follow me第二季第1期】任务0:开发环境搭建,板载LED点亮
大家好,我是郑工,尘世间一个迷途小工程师。
昨天给大家分享了开箱帖,今天迫不及待就完成了Follow me的基础任务,搭载开发环境,点亮第一个LED灯。
这次使用的核心板Circuit Playground Express,简称CPX有非常丰富的板载功能。可以使用微软MakeCode,CircuitPython,Arduino还有Code.org CSD四个方式开发。
我们这个帖子,我用的是CircuitPython的方式开发。
首先是搭建开发环境。主要还是参考下面官方网址:
CircuitPython | Adafruit Circuit Playground Express | Adafruit Learning System
一、升级CPX固件
1、下载最新版的cp Circuit Playground Express Download (circuitpython.org)
2、选择US,下载.UF2
3、内置的模块有 adafruit_bus_device, adafruit_pixelbuf, analogio, array, audiobusio, audiocore, audioio, bitbangio, board, builtins, busio, busio.SPI, busio.UART, codeop, collections, countio, digitalio, errno, locale, math, microcontroller, neopixel_write, nvm, onewireio, os, pulseio, pwmio, rainbowio, random, rotaryio, rtc, storage, struct, supervisor, sys, time, touchio, usb_cdc, usb_hid, usb_midi, warnings。后面要用可以查一下看看
4、我这里的文件名叫adafruit-circuitpython-circuitplayground_express-en_US-9.1.1.uf2,大家可以参考一下
5、把板子连接电脑,快速点击RESET按键两次,板子上所有指示灯会变成绿色,如果变成红色,请检查一下usb线(如果确认不是线的问题,就单击一下,第一次上电的情况)
电脑会多出一个叫CPLAYBOOT的盘,把固件拖到盘里
成功后,盘的名字会变成CIRCUITPY,我们就是在这个
二、安装开发环境Mu
下面就安装Mu软件了Download Mu (codewith.mu)
下载软件安装包
安装后第一次打开选择模式为CircuitPython
编译器右下角会显示CircuitPython,同时这个芯片表示已经连接好CPX的板子,无连接的话,芯片上会有个红色的叉
至此开发环境已经搭建完成了,大家可以在MU上编程,编程后点击检查校验代码对错,然后保存到CIRCUITPY盘里的code.py文件。
三、点亮LED灯
点亮LED会用到的模块有board,digitalio,time
import board
import digitalio
import time
然后初始化管脚
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
简单的闪烁我觉得有些简单了,整了点花活,做了个简单的呼吸灯程序,代码如下
timeOn = 0
step = 0.0001 #duty is 0.01s -> 100Hz
isIncrease = True
def onLed(onTime, duty):
if onTime > 0:
led.value = True
time.sleep(onTime)
if duty - onTime > 0:
led.value = False
time.sleep(duty - onTime)
while True:
if isIncrease:
timeOn = 0 - step
for i in range(100):
if isIncrease:
timeOn = timeOn + step
else:
timeOn = timeOn - step
onLed(timeOn, step * 100)
for i in range(100):
onLed(timeOn, step * 100)
isIncrease = not isIncrease
程序逻辑就是不断更改led的占空比。
大家有什么问题,欢迎留言哈。
-
回复了主题帖:
【Follow me第二季第1期】开箱帖(现在得捷速度就是这么块)
吾妻思萌 发表于 2024-7-26 08:23
现货,现在就发的货
期货,遥遥无期的货
现货是真的香,期货不能碰,不止板子,还有房子
- 2024-07-25
-
加入了学习《DigiKey 应用说:蓝牙5.4 新特性解读及实例演示》,观看 蓝牙5.4 新特性解读及实例演示
-
发表了主题帖:
【Follow me第二季第1期】开箱帖(现在得捷速度就是这么块)
大家好,我是郑工,尘世间一个迷途小工程师。
有幸被选上得捷follow me第二季第一期的活动。首先还是得感谢得捷,感谢ee,感谢各位领导给我这个机会。
看到许多未被选上小伙伴嗷嗷待哺的眼光,我顿感肩上的担子重了一些些。
这里收到这次活动所购(白)买(piao)【玩笑】到的板子!
给各位小伙伴看看,后面有什么经验,问题也会在论坛上跟各位坛友分享一下,希望各位坛友多多帮忙。
这是采用32位ARM M0核心的ATSAMD21微控制器的核心板,上面有运动、温度、光、声音传感器,还带红外收发。可以说是为了感应万物而生的。
这是活动推荐的舵机,讲真我还没用过,不过活动推荐的,想来难度不大
这是我为了探(作)索(si)新功能买的气体传感器,一切未知,也不知道能不能驱动得了。
万一有啥问题,希望各位坛友大力帮忙
- 2024-07-10
-
回复了主题帖:
【得捷Follow me第3期】XIAO主板读取磁力开关
wangerxian 发表于 2024-1-29 14:32
这传感器的检测距离大概是多少?
也就一两厘米,可能跟磁铁的磁性也有关系