大家好,我是一名电气工程及其自动化的普通本科生,相信大家都和我一样,在大三的那段时间,开始思考着自己未来的就业,翻遍了许多的招聘网站,看着各种各样的岗位,心里愈发迷茫,偶然间,我发现了嵌入式开发这个职位,便开始对这个行业进行了深入的了解,经过一段时间的了解,我渐渐地喜欢上了嵌入式,这种感觉似乎是找到了真爱,于是,我便大胆地开始了嵌入式的学习之旅。
因为我的专业并不是嵌入式的对口专业,因此在起步阶段,我对很多嵌入式技术,术语完全是一个懵懵的状态,在上网课时,有一些知识点也不能理解,甚至连软件怎么下载配置都不知道,于是,我开始对嵌入式的知识充满了一种莫名的好奇心,只要遇到我不懂的技术,我就去技术网站上查阅,不停地扩展自己的知识面,单片机基础不过关,我就多做项目......功夫不负有心人,就这样摸打滚爬了半年,我进步了许多,从一开始什么都不知道到现在的"有问必答",也有了一些自己的项目。
好了,我也不说那么多了,毕竟技术是用我的头发换来的,半年的学习让我的头发少了不少。
言归正传,给大伙们看看我都学了什么技术吧。
这么一看,感觉自己在学习嵌入式的道路上也是花了不少的钱,我是几乎把常见的单片机都买了个遍,有树莓派4B,Arduino,esp系列板,k210,stm32。还有的就是一些外设模块,比如红外线模块,超声波模块,离线语音模块,触摸屏,多路继电器,RGB灯带,4自由度舵机机械手,蓝牙模块,RFID等等,粗略计算,也有个几千块。
跟大部分人的学习路线一样,从点灯开始练习,然后就学习ADC,IIC,SPI,uart,PWM,中断,DMA的原理,接着开始动手操作,虽然在学习理论知识的时候非常枯燥,但是动手操作后,并得到了想要的结果,瞬间整个人充满了成就感,能开心个半天,也许这就是我喜欢嵌入式的原因吧。
嗯~ 学完了技术后,我便开始做项目,第一个项目就是智能家居了,(现在看来,其实这个项目也不算太难,因为还没有加上freertos,稍微有点难度的就是要编写opencv程序进行手势识别和如何使用APP控制家电,图形界面设计不怎么难,就是有点费时间),第一个版本使用的是8位的单片机,后面就换成了stm32作为主控,并且用freertos实现了部分功能(为什么只是实现了部分功能呢?因为......我懒) (手机APP用的是点灯科技,要去它的官网下载sdk)
部分代码:
点灯科技APP
#define BLINKER_PRINT Serial
#define BLINKER_BLE
#include
#include
#define LED_PIN 7
#define NUM_LEDS 21
CRGB leds[NUM_LEDS];
// 新建组件对象
BlinkerButton Button1("btn-abc");
BlinkerButton Button2("open");
BlinkerButton Button3("close");
BlinkerNumber Number1("num-abc");
BlinkerRGB RGB1("color");
BlinkerSlider Slider1("change");
int counter = 0;
// 按下按键即会执行该函数
void button1_callback(const String & state) {
BLINKER_LOG("get button state: ", state);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
void button2_callback(const String & state)
{
fill_solid(leds,20,CRGB::Blue);
FastLED.show();
}
void button3_callback(const String & state)
{
fill_solid(leds,20,CRGB::Black);
FastLED.show();
}
void slider1_callback(int32_t value)
{
int num = value;
Slider1.color("#1E90FF");
Slider1.print();
for(int i=0;i0;i--){
FastLED.setBrightness(i);
FastLED.show();
delay(num);
}
}
}
// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
counter++;
Number1.print(counter);
}
void rgb1_callback(uint8_t r_value, uint8_t g_value,
uint8_t b_value, uint8_t bright_value)
{
int r1 = r_value ;
int g1 = g_value ;
int b1 = b_value ;
int L1 = bright_value;
fill_solid(leds , 20, CRGB( r1, g1, b1 ));
FastLED.setBrightness(L1);
FastLED.show();
}
void setup() {
// 初始化串口
Serial.begin(115200);
#if defined(BLINKER_PRINT)
BLINKER_DEBUG.stream(BLINKER_PRINT);
#endif
// 初始化有LED的IO
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
FastLED.addLeds(leds,NUM_LEDS);
FastLED.setBrightness(50);
// 初始化blinker
Blinker.begin();
Blinker.attachData(dataRead);
Button1.attach(button1_callback);
Button2.attach(button2_callback);
Button3.attach(button3_callback);
Slider1.attach(slider1_callback);
RGB1.attach(rgb1_callback);
}
void loop() {
Blinker.run();
}
手势识别代码:
import time
import cv2
import mediapipe as mp
import math
import serial
serialPort = "COM3" # 串口
baudRate = 9600 # 波特率
ser = serial.Serial(serialPort, baudRate, timeout=0.5)
def vector_2d_angle(v1,v2):
'''
求解二维向量的角度
'''
v1_x=v1[0]
v1_y=v1[1]
v2_x=v2[0]
v2_y=v2[1]
try:
angle_= math.degrees(math.acos((v1_x*v2_x+v1_y*v2_y)/(((v1_x**2+v1_y**2)**0.5)*((v2_x**2+v2_y**2)**0.5))))
except:
angle_ =65535.
if angle_ > 180.:
angle_ = 65535.
return angle_
def hand_angle(hand_):
'''
获取对应手相关向量的二维角度,根据角度确定手势
'''
angle_list = []
#---------------------------- thumb 大拇指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])- int(hand_[2][0])),(int(hand_[0][1])-int(hand_[2][1]))),
((int(hand_[3][0])- int(hand_[4][0])),(int(hand_[3][1])- int(hand_[4][1])))
)
angle_list.append(angle_)
#---------------------------- index 食指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])-int(hand_[6][0])),(int(hand_[0][1])- int(hand_[6][1]))),
((int(hand_[7][0])- int(hand_[8][0])),(int(hand_[7][1])- int(hand_[8][1])))
)
angle_list.append(angle_)
#---------------------------- middle 中指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])- int(hand_[10][0])),(int(hand_[0][1])- int(hand_[10][1]))),
((int(hand_[11][0])- int(hand_[12][0])),(int(hand_[11][1])- int(hand_[12][1])))
)
angle_list.append(angle_)
#---------------------------- ring 无名指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])- int(hand_[14][0])),(int(hand_[0][1])- int(hand_[14][1]))),
((int(hand_[15][0])- int(hand_[16][0])),(int(hand_[15][1])- int(hand_[16][1])))
)
angle_list.append(angle_)
#---------------------------- pink 小拇指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])- int(hand_[18][0])),(int(hand_[0][1])- int(hand_[18][1]))),
((int(hand_[19][0])- int(hand_[20][0])),(int(hand_[19][1])- int(hand_[20][1])))
)
angle_list.append(angle_)
return angle_list
def h_gesture(angle_list):
'''
# 二维约束的方法定义手势
# fist five gun love one six three thumbup yeah
'''
thr_angle = 65.
thr_angle_thumb = 53.
thr_angle_s = 49.
gesture_str = None
if 65535. not in angle_list:
if (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):
gesture_str = "fist"
elif (angle_list[0]thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):
gesture_str = "gun"
ser.write(b"b")
time.sleep(1.8)
elif (angle_list[0]thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]5) and (angle_list[1]thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):
gesture_str = "one"
elif (angle_list[0]thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]thr_angle_thumb) and (angle_list[1]thr_angle):
gesture_str = "three"
ser.write(b"c")
time.sleep(1.8)
elif (angle_list[0]thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):
gesture_str = "thumbUp"
elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]thr_angle) and (angle_list[4]>thr_angle):
gesture_str = "two"
ser.write(b"d")
time.sleep(1.8)
return gesture_str
def detect():
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.75,
min_tracking_confidence=0.75)
cap = cv2.VideoCapture(0)
while True:
ret,frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame= cv2.flip(frame,1)
results = hands.process(frame)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
hand_local = []
for i in range(21):
x = hand_landmarks.landmark[i].x*frame.shape[1]
y = hand_landmarks.landmark[i].y*frame.shape[0]
hand_local.append((x,y))
if hand_local:
angle_list = hand_angle(hand_local)
gesture_str = h_gesture(angle_list)
cv2.putText(frame,gesture_str,(0,100),0,1.3,(0,0,255),3)
cv2.imshow('MediaPipe Hands', frame)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
if __name__ == '__main__':
detect()
第二个项目就是智能小车:
除了能够通过蓝牙,红外线对小车进行基础遥控外,小车还有循迹,避障,跟随功能,车上装载摄像头,可以实现移动监控,还有一个高大上的功能,就是可以识别方向标志,然后按照标志所指方向进行移动。
esp32-cam监控(还没有弄内网穿透,所以只能实现短距离监控)
最后看看成品视频吧
智能家居和智能小车
离线语言音箱