文章目录
- 0 前言
- 1 简介
- 2 主要器件
- 3 实现效果
- 4 设计原理
- 5 部分核心代码
- 6 最后
0 前言
🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。
为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是
🚩 基于单片机的手势检测识别系统
🥇学长这里给一个题目综合评分(每项满分5分)
- 难度系数:4分
- 工作量:4分
- 创新点:3分
1 简介
2 主要器件
- Arduino Nano R3
- PIR传感器
- OLED显示模块(128X64)
- 热阵列传感器
3 实现效果
成品展示
4 设计原理
PIR传感器:
PIR传感器:一种电子传感器,测量从其视野内的物体辐射的红外(IR)光。最常用于基于PIR的运动检测器。所有温度高于绝对零度的物体都会以辐射的形式放出热能,通常这种辐射对人眼来说是不可见的,因为它是以红外波长辐射,但它可以被为此目的设计的电子设备检测到。
在这种情况下,术语“无源”指的是这样一个事实,即PIR设备不产生或辐射用于检测目的的能量。它们完全通过探测物体发射或反射的红外辐射来工作,它们不能探测或测量热量。
TPA81:
热电堆阵列,检测2微米~22微米内的红外线(辐射热的波长)
同时测量8个相邻点的温度
控制伺服系统来平移模块并建立热成像
检测2米(6英尺)范围内的蜡烛火焰,不受环境光影响
Arduino IDE
电路图:
如果想使用8个PIR传感器,应将8个单个PIR传感器连接到Arduino板上,并逐个读取它们
软件部分
运行Arduino板步骤:
- 在www.arduino.cc/en/Main/Software下载操作系统软件,并按照说明安装集成开发环境软件
- 运行Arduino IDE,清除文本编辑器,在文本编辑器中复制下面的代码
- 导航至草图并包含库(从以下链接下载库),点击添加压缩库并添加库
- 在工具和电路板中选择电路板,选择Arduino Nano
- 将Arduino连接到电脑,并在工具和端口中设置通讯端口
- 按上传(箭头符号)按钮
运行此代码后,在 Arduino IDE 中打开串行终端并查看 TPA81 感应到的 8 阵列温度。每行的第一个数字属于总温度。
要手动定义手势,需知道手部温度,并将其设置为偏移量。
将偏移量设置为 29 度,上传以下一代码查看在 TPA81 前的手部动作。
5 部分核心代码
#include <Wire.h>
#include <TPA81.h>
// Create new TPA81 instance
TPA81 tpa;
void setup() {
Serial.begin(9600);
// You need to begin the Wire library to use TPA81 library
Wire.begin();
}
void loop() {
// Print temperature light
Serial.print(tpa.getAmbient());
Serial.print(" ");
// Print all temperature point
for (int i = 1; i <= 8; i++)
{
Serial.print(tpa.getPoint(i));
Serial.print(" ");
}
Serial.println("\n");
delay(500);
}
const uint8_t Signal816[16] PROGMEM = //mobie signal
{
0xFE,0x02,0x92,0x0A,0x54,0x2A,0x38,0xAA,0x12,0xAA,0x12,0xAA,0x12,0xAA,0x12,0xAA
};
const uint8_t Msg816[16] PROGMEM = //message
{
0x1F,0xF8,0x10,0x08,0x18,0x18,0x14,0x28,0x13,0xC8,0x10,0x08,0x10,0x08,0x1F,0xF8
};
const uint8_t Bat816[16] PROGMEM = //batery
{
0x0F,0xFE,0x30,0x02,0x26,0xDA,0x26,0xDA,0x26,0xDA,0x26,0xDA,0x30,0x02,0x0F,0xFE
};
const uint8_t Bluetooth88[8] PROGMEM = // bluetooth
{
0x18,0x54,0x32,0x1C,0x1C,0x32,0x54,0x18
};
const uint8_t GPRS88[8] PROGMEM = //GPRS
{
0xC3,0x99,0x24,0x20,0x2C,0x24,0x99,0xC3
};
const uint8_t Alarm88[8] PROGMEM = //alram
{
0xC3,0xBD,0x42,0x52,0x4E,0x42,0x3C,0xC3
};
void command(uint8_t cmd){
digitalWrite(OLED_DC, LOW);
SPIWrite(&cmd, 1);
}
void SPIWrite(uint8_t *buffer, int bufferLength) {
int i;
for (i = 0; i < bufferLength; i++) {
SPI.transfer(buffer[i]);
}
}
void SSD1306_begin()
{
pinMode(OLED_RST, OUTPUT);
pinMode(OLED_DC, OUTPUT);
pinMode(OLED_CS, OUTPUT);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV128);
digitalWrite(OLED_CS, LOW);
digitalWrite(OLED_RST, HIGH);
delay(10);
digitalWrite(OLED_RST, LOW);
delay(10);
digitalWrite(OLED_RST, HIGH);
command(SSD1306_DISPLAYOFF);
command(SSD1306_SETDISPLAYCLOCKDIV);
command(0x80); // the suggested ratio 0x80
command(SSD1306_SETMULTIPLEX);
command(0x3F);
command(SSD1306_SETDISPLAYOFFSET);
command(0x0); // no offset
command(SSD1306_SETSTARTLINE | 0x0); // line #0
command(SSD1306_CHARGEPUMP);
command((VCCSTATE == SSD1306_EXTERNALVCC) ? 0x10 : 0x14);
command(SSD1306_MEMORYMODE);
command(0x00); // 0x0 act like ks0108
command(SSD1306_SEGREMAP | 0x1);
command(SSD1306_COMSCANDEC);
command(SSD1306_SETCOMPINS);
command(0x12); // TODO - calculate based on _rawHieght ?
command(SSD1306_SETCONTRAST);
command((VCCSTATE == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF);
command(SSD1306_SETPRECHARGE);
command((VCCSTATE == SSD1306_EXTERNALVCC) ? 0x22 : 0xF1);
command(SSD1306_SETVCOMDETECT);
command(0x40);
command(SSD1306_DISPLAYALLON_RESUME);
command(SSD1306_NORMALDISPLAY);
command(SSD1306_DISPLAYON);
}
void SSD1306_clear(uint8_t* buffer)
{
int i;
for(i = 0;i < WIDTH * HEIGHT / 8;i++)
{
buffer[i] = 0;
}
}
void SSD1306_pixel(int x, int y, char color, uint8_t* buffer)
{
if(x > WIDTH || y > HEIGHT)return ;
if(color)
buffer[x+(y/8)*WIDTH] |= 1<<(y%8);
else
buffer[x+(y/8)*WIDTH] &= ~(1<<(y%8));
}
void SSD1306_char1616(uint8_t x, uint8_t y, uint8_t chChar, uint8_t* buffer)
{
uint8_t i, j;
uint8_t chTemp = 0, y0 = y, chMode = 0;
for (i = 0; i < 32; i++) {
chTemp = pgm_read_byte(&Font1612[chChar - 0x30][i]);
for (j = 0; j < 8; j++) {
chMode = chTemp & 0x80? 1 : 0;
SSD1306_pixel(x, y, chMode, buffer);
chTemp <<= 1;
y++;
if ((y - y0) == 16) {
y = y0;
x++;
break;
}
}
}
}
void SSD1306_char(unsigned char x, unsigned char y, char acsii, char size, char mode, uint8_t* buffer)
{
unsigned char i, j, y0=y;
char temp;
unsigned char ch = acsii - ' ';
for(i = 0;i<size;i++) {
if(size == 12)
{
if(mode)temp = pgm_read_byte(&Font1206[ch][i]);
else temp = ~pgm_read_byte(&Font1206[ch][i]);
}
else
{
if(mode)temp = pgm_read_byte(&Font1608[ch][i]);
else temp = ~pgm_read_byte(&Font1608[ch][i]);
}
for(j =0;j<8;j++)
{
if(temp & 0x80) SSD1306_pixel(x, y, 1, buffer);
else SSD1306_pixel(x, y, 0, buffer);
temp <<= 1;
y++;
if((y-y0) == size)
{
y = y0;
x++;
break;
}
}
}
}
void SSD1306_string(uint8_t x, uint8_t y, const char *pString, uint8_t Size, uint8_t Mode, uint8_t* buffer)
{
while (*pString != '\0') {
if (x > (WIDTH - Size / 2)) {
x = 0;
y += Size;
if (y > (HEIGHT - Size)) {
y = x = 0;
}
}
SSD1306_char(x, y, *pString, Size, Mode, buffer);
x += Size / 2;
pString++;
}
}
void SSD1306_char3216(uint8_t x, uint8_t y, uint8_t chChar, uint8_t* buffer)
{
uint8_t i, j;
uint8_t chTemp = 0, y0 = y, chMode = 0;
for (i = 0; i < 64; i++) {
chTemp = pgm_read_byte(&Font3216[chChar - 0x30][i]);
for (j = 0; j < 8; j++) {
chMode = chTemp & 0x80? 1 : 0;
SSD1306_pixel(x, y, chMode, buffer);
chTemp <<= 1;
y++;
if ((y - y0) == 32) {
y = y0;
x++;
break;
}
}
}
}
void SSD1306_bitmap(uint8_t x,uint8_t y,const uint8_t *pBmp, uint8_t chWidth, uint8_t chHeight, uint8_t* buffer)
{
uint8_t i, j, byteWidth = (chWidth + 7)/8;
for(j = 0;j < chHeight;j++){
for(i = 0;i <chWidth;i++){
if(pgm_read_byte(pBmp + j * byteWidth + i / 8) & (128 >> (i & 7))){
SSD1306_pixel(x + i,y + j, 1, buffer);
}
}
}
}
void SSD1306_display(uint8_t* buffer)
{
command(SSD1306_COLUMNADDR);
command(0); //cloumn start address
command(WIDTH -1); //cloumn end address
command(SSD1306_PAGEADDR);
command(0); //page atart address
command(PAGES -1); //page end address
digitalWrite(OLED_DC, HIGH);
SPIWrite(buffer, WIDTH * HEIGHT / 8);
}