【毕业设计】基于单片机的手势检测识别系统 - arduino 物联网嵌入式

187 篇文章 114 订阅
151 篇文章 37 订阅


0 前言

🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

🚩 基于单片机的手势检测识别系统

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:4分
  • 工作量:4分
  • 创新点:3分

🧿 选题指导, 项目分享:

https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md


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);
}


5 最后

  • 7
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值