- 2024-08-28
-
加入了学习《Follow me第二季第一期 任务演示》,观看 Follow me第二季第一期 任务演示
-
回复了主题帖:
Follow me第二季第一期 任务提交 arduino
欸 这markdown的流程图为啥不能正常显示啊,我在编辑预览里看是正常的
-
发表了主题帖:
Follow me第二季第一期 任务提交 arduino
本帖最后由 西电小学僧 于 2024-8-28 22:12 编辑
# 物料介绍
## 主板
本期活动使用的是Adafruit Circuit Playground Express。其基于ATSAMD21微控制器,采用32位ARM® Cortex®-M0+内核。ATSAMD21采用先进的电源管理技术,电流消耗极低。它可以由USB、“AAA”电池组或Lipoly电池供电。传感器封装圆形Circuit Playground Express板的边缘具有鳄鱼夹焊盘,便于连接到项目而无需焊接。可通过内置USB快速连接进行编程,无需专用电缆或适配器。其规格参数为:
• 10颗Mini NeoPixel LED,每个LED均可显示任何彩虹颜色
• 1个运动传感器(LIS3DH 3轴XYZ加速度计),带有轻击和自由落体检测功能
• 1个温度传感器 (MMBT2222)
• 1个光传感器 (ALSPT1931),也可以用作颜色或脉冲传感器
• 1个声音传感器(MEMS麦克风)
• 红外发射器和接收器 (DSOP38338),可发射和接收远程控制代码,在Circuit Playground Expresses之间发送消息,或用作接近传感器
• 1个带D类放大器的迷你扬声器(7.5mm磁性扬声器/蜂鸣器)
• 2个按钮,标记为A和B
• 1个滑动开关
• 8个易于使用的鳄鱼夹输入/输出引脚(含I2C、UART、8个可进行模拟输入的引脚/多PWM 输出)
• 7个焊盘可用作电容式触摸输入, 剩余 焊盘是一个真模拟输出
• 绿色“ON”LED
• 红色“#13”LED,用于基本闪烁
• 复位按钮
## 舵机
舵机是随单购买的FS90R舵机。
FS90R是一型360°连续旋转伺服电机, 在6V时,它的最大转速约为130 RPM (空载),可产生高达1.5千克cm的扭矩。 伺服系统可以通过直接连接到单个微控制器I/O线来控制,而无需任何其他电子设备。
## 超声波传感器
任务中使用了HC-SR04型超声波传感器实现测距功能。
## 图片
# 任务实现
## 入门任务:开发环境搭建,板载LED点亮
使用Adafruit NeoPixel库来驱动板载的NeoPixel点亮。实例化pixels对象来操作NeoPixel、setPixelColor函数用于设置pixel的颜色。
### 代码
main.cpp
```C
#include
#include
#define PIN 8
#define NUMPIXELS 10
void setup() {
// write your initialization code here
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
pixels.begin();
for (uint16_t i = 0; i < NUMPIXELS; i++)
pixels.setPixelColor(i, Adafruit_NeoPixel::Color(10, 10, 10));
pixels.show();
}
void loop() {
// write your code here
}
```
### 流程图
```flow
init=>start: 资源初始化
led=>operation: 点亮板载LED
loop=>end: 循环等待
st=>start: 用户登陆
op=>operation: 登陆操作
cond=>condition: 登陆成功 Yes or No?
e=>end: 进入后台
init->led->loop
```
### 实物图
动态视频请查看文章后的链接
## 基础任务一:控制板载炫彩LED,跑马灯点亮和颜色变换
### 代码
main.cpp
```C
#include
#include
#define PIN 8
#define NUMPIXELS 10
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
// write your initialization code here
pixels.begin();
}
void loop() {
// write your code here
static uint8_t led_num = 0;
static uint32_t colors[7] = {0x0A0000, 0x000A00, 0x00000A, 0x050500, 0x050005, 0x000505, 0x040304};
static uint8_t color_num = 0;
static Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
pixels.clear();
pixels.setPixelColor(led_num, colors[color_num]);
pixels.show();
led_num++;
if (led_num == NUMPIXELS) {
led_num = 0;
color_num++;
if (color_num == 7)
color_num = 0;
}
delay(100);
}
```
### 流程图
```flow
init=>start: 资源初始化
led=>operation: 点亮第一个LED后等待1s
nextled=>operation: 熄灭所有LED然后点亮下一个LED后等待1s
round=>condition: 检查是否为最后一个LED
color=>operation: 切换颜色并从第一个LED开始点亮
st=>start: 用户登陆
op=>operation: 登陆操作
cond=>condition: 登陆成功 Yes or No?
e=>end: 进入后台
init->led->nextled->round
round(yes)->color
round(no)->nextled
color->nextled
```
### 实物图
动态视频请查看文章后的链接
## 基础任务二:监测环境温度和光线,通过板载LED展示舒适程度
根据Adafruit官方在Github上发布的原理图和CircuitPython库的代码可以得出引脚电压与温度、光照之间的关系。
### 代码
main.cpp
```C
#include
#include
#include "Sensor.h"
#define PIN 8
#define NUMPIXELS 10
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
// write your initialization code here
Serial.begin(115200);
pixels.begin();
}
void loop() {
// write your code here
const double temperature = get_temperature(A9);
const double photocell = get_photocell(A8);
pixels.clear();
if (temperature < 14) {
pixels.setPixelColor(5, 0, 0, 10);
} else if (temperature < 18 && temperature >= 14) {
pixels.setPixelColor(6, 0, 5, 5);
} else if (temperature >= 18 && temperature 26 && temperature 30) {
pixels.setPixelColor(9, 10, 0, 0);
}
if (photocell > 1000) {
pixels.setPixelColor(0, 10, 0, 0);
} else if (photocell > 500 && photocell = 200 && photocell = 50 && photocell < 200) {
pixels.setPixelColor(3, 0, 5, 5);
} else if (photocell < 50) {
pixels.setPixelColor(4, 0, 0, 10);
}
pixels.show();
Serial.print("temperature:" + String(temperature) + "℃\n" + "photocell:" + String(photocell) + "lux\n");
delay(1000);
}
```
Sensor.h
```C
//
// Created by SLCTX on 24-7-30.
//
#ifndef SENSOR_H
#define SENSOR_H
#include
#define R_T2 10000
#define B 3380000
#define T2 25
double get_temperature(uint32_t pin);
double get_photocell(uint32_t pin);
#endif //SENSOR_H
```
Sensor.cpp
```C
//
// Created by SLCTX on 24-7-30.
//
#include "Sensor.h"
double get_temperature(const uint32_t pin) {
return 1.0/(log(1023.0/analogRead(pin)-1)/3950.0+1.0/(273.15+25))-273.15;
}
double get_photocell(const uint32_t pin) {
return analogRead(pin)*3.3/1023.0/2.9*3446;
}
```
### 流程图
```flow
init=>start: 资源初始化
read=>operation: 读取光照亮度和温度
led=>operation: 根据亮度和温度点亮相应的LED
wait=>operation: 等待1秒
st=>start: 用户登陆
op=>operation: 登陆操作
cond=>condition: 登陆成功 Yes or No?
e=>end: 进入后台
init->read->led->wait->read
```
### 实物图
动态视频请查看文章后的链接
## 基础任务三:接近检测——设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警
根据Adafruit发布的原理图可以看出在红外接受器到处理器之间有一解码器,由于时间原因没能编写出可用的编码逻辑与解码逻辑,故采用外部的超声波传感器进行接近检测。
### 代码
main.cpp
```C
#include
#include
#include "Ultrasonic.h"
#define PIN 8
#define NUMPIXELS 10
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
// write your initialization code here
Serial.begin(115200);
pixels.begin();
pinMode(A0,OUTPUT);
}
void loop() {
// write your code here
static int time = 0;
static bool sound = false;
if (time == 1000) {
double distance = getDistance(A2, A1);
pixels.clear();
for (uint8_t tmp = 0, distance_level = distance > 100 ? 9 : distance / 10; tmp operation: 读取距离
led=>operation: 点亮对应的LED
distance=>condition: 判断距离是否在警报线以下
sound=>operation: 驱动扬声器报警
wait=>operation: 等待1秒
st=>start: 用户登陆
op=>operation: 登陆操作
cond=>condition: 登陆成功 Yes or No?
e=>end: 进入后台
init->read->led->distance
distance(yes)->sound->wait
distance(no)->wait
wait->read
```
### 实物图
动态视频请查看文章后的链接
## 进阶任务:制作不倒翁——展示不倒翁运动过程中的不同灯光效果
板载的加速度传感器型号为LIS3DH。该传感器使用I2C与处理器进行连接,使用I2C通信以获取加速度数据。
### 代码
main.cpp
```C
#include
#include
#include "Acceleration.h"
#define PIN 8
#define NUMPIXELS 10
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
// write your initialization code here
Serial.begin(115200);
pixels.begin();
if (!init_acceleration()) {
Serial.println("ERROR");
}
}
void loop() {
// write your code here
std::array data = get_acceleration();
double length = sqrt(pow(data[0], 2) + pow(data[1], 2));
int degree = atan(-1 * data[0] / data[1]) / M_PI * 180;
degree += data[0] * data[1] >= 0 ? 180 : 0;
pixels.clear();
if (degree >= 15 && degree operation: 点亮对应的LED
wait=>operation: 等待1秒
st=>start: 用户登陆
op=>operation: 登陆操作
cond=>condition: 登陆成功 Yes or No?
e=>end: 进入后台
init->read->led->wait->read
wait->read
```
### 实物图
动态视频请查看文章后的链接
## 创意任务二:章鱼哥——章鱼哥的触角根据环境声音的大小,章鱼哥的触角可舒展或者收缩
由于板载麦克风使用了MEMS麦克风,需要大量的计算才能获得声音大小,于是使用了Adafruit Zero PDM Library库来计算声音大小。使用Servo库来控制舵机。
### 代码
main.cpp
```C
#include
#include
#include
#include "Volume.h"
#define PIN 8
#define NUMPIXELS 10
Adafruit_ZeroPDM pdm = Adafruit_ZeroPDM(34, 35);
uint16_t sincfilter[DECIMATION] = {
0, 2, 9, 21, 39, 63, 94, 132, 179, 236, 302, 379, 467, 565, 674, 792, 920, 1055, 1196, 1341, 1487, 1633, 1776, 1913,
2042, 2159, 2263, 2352, 2422, 2474, 2506, 2516, 2506, 2474, 2422, 2352, 2263, 2159, 2042, 1913, 1776, 1633, 1487,
1341, 1196, 1055, 920, 792, 674, 565, 467, 379, 302, 236, 179, 132, 94, 63, 39, 21, 9, 2, 0, 0
};
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Servo servo;
int time = 0;
int max_volume = 0;
void setup() {
// write your initialization code here
Serial1.begin(115200);
Serial1.println("init");
pixels.begin();
servo.attach(A1);
if (!init_volume(pdm)) {
Serial1.println("volume init failed.");
while (1);
}
}
void loop() {
// write your code here
uint8_t num;
int volume = get_volume(pdm, sincfilter);
if (volume > max_volume) {
max_volume = volume;
}
if (time >= 0) {
time++;
if (time < max_volume / 165) {
if (max_volume / 3300 > 3) {
servo.writeMicroseconds(1000);
}
} else {
time = -1;
}
} else {
time--;
if (time > -max_volume / 165) {
if (max_volume / 3300 > 3) {
servo.writeMicroseconds(2000);
}
} else {
time = 0;
servo.writeMicroseconds(1500);
max_volume = 0;
}
}
num = abs((volume)/3300);
pixels.clear();
for (int tmp = 0; tmp >= 1;
}
)
}
return runningsum - 32768;
}
```
### 流程图
```flow
init=>start: 资源初始化
read=>operation: 读取声音大小
led=>operation: 点亮对应的LED
servo=>operation: 驱动舵机
wait=>operation: 等待0.1秒
st=>start: 用户登陆
op=>operation: 登陆操作
cond=>condition: 登陆成功 Yes or No?
e=>end: 进入后台
init->read->led->servo->wait->read
```
### 实物图
动态视频请查看文章后的链接
# 感想
Adafruit Circuit Playground Express是个非常有趣且外设丰富的开发板,同时支持arduino、circuitpython、makecode等多种开发语言适合各种群体。在这个活动中学习到了很多开发知识。祝愿EEWROLD的活动能越办越好。
# 资源
## 代码
[任务代码](https://download.eeworld.com.cn/detail/%E8%A5%BF%E7%94%B5%E5%B0%8F%E5%AD%A6%E5%83%A7/634228 "任务代码")
## 视频
[演示视频](https://training.eeworld.com.cn/video/40794 "演示视频")
- 2024-08-27
-
加入了学习《【Follow me第二季第1期】全部任务演示短视频》,观看 【Follow me第二季第1期】任务演示视频
-
上传了资料:
Follow me 第二季第1期 任务代码提交
- 2024-08-17
-
加入了学习《FollowMe 第二季: 1 Adafruit Circuit Playground Express及任务讲解》,观看 Adafruit Circuit Playground Express 及任务讲解