【毕业设计】基于单片机的蓝牙相机设计与实现 - 物联网 单片机 嵌入式

201 篇文章 121 订阅
151 篇文章 42 订阅


0 前言

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

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

🚩 基于单片机的蓝牙相机设计与实现

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

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

🧿 选题指导, 项目分享:

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 简介

基于Arduino单片机的蓝牙相机,想通过蓝牙在100到501次的Android手机和Arduino UNO之间交换数据。但我想传输的不仅仅是一组字符和数字,还包括图片。

通过Arduino和Android手机之间的蓝牙连接,从Arduino UNO上的OV7670相机获取图片并将其传输到Android手机。然后,相反,将图片(来自相机的图像)从Android手机传输到Arduino UNO,并将其显示在独特的TFT屏蔽屏幕上。

2 主要器件

  • Arduino UNO和Genuino UNO× 1
  • HC-05蓝牙模块× 1
  • 相机OV7670× 1
  • Arduino TFT屏蔽× 1

在这里插入图片描述

3 实现效果

在这里插入图片描述

4 硬件设计

蓝牙模块

需要将蓝牙模块中的汇率设置为115200(命令“AT+ UART = 115200,0,0”)。这是Arduino UNO设法接收和处理数据的最佳速度。(从理论上讲,您可以提高速度,优化数据接收和处理,但这需要更多的RAM)。有关如何设置汇率的更详细说明可以在互联网上找到。

注意的是,蓝牙模块连接到Arduino UNO的调试端口。因此,当使用蓝牙时,调试端口不可用。在编程之前,Arduino UNO(包括蓝牙模块)必须断开蓝牙模块的连接。编程后,将其设置回去。

在这里插入图片描述

设备的组装非常简单:

  • 连接Arduino UNO和TFT-shield;
  • 将OV7670相机连接到防护罩的TFT屏蔽上的20针连接器(有时我使用间距为2.54 mm的倾斜18-20针连接器作为适配器);
  • 将蓝牙模块HC-06(HC-05)连接到TFT防护板上带有“蓝牙”字样的4针连接器;
  • 将 6-12V 电源适配器连接到 Arduino UNO 板上的电源输入。

打开电源后,TFT扩展板的屏幕应变为红色。这意味着愿意从Android手机接收命令。

5 软件说明

所有演示草图都是在Arduino IDE环境中编写的,因此在开始时需要安装Arduino IDE -环境。然后,您需要为TFT shield安装一个库 - github.com/YATFT/YATFT(下载该库并将其解压缩到Arduino IDE目录中的“库”文件夹中)。

安装Arduino IDE后,您必须对Arduino UNO板进行编程。为简单起见,我建议单独闪烁,不带TFT屏蔽。为此:

  • 将USB电缆连接到Arduino UNO板;
  • 在计算机上运行Arduino IDE;
  • 选择Arduino UNO连接到的相应端口;
  • 下载ArduinoBluetoothCamera.ino演示草图(以及用于相机初始化的文件ov7670_regs.h);
  • 点击上传按钮。
    如果Arduino UNO板已成功编程,则可以继续下一步。

安卓部分

在这里插入图片描述

在安卓手机上执行以下操作:

  • 在 安卓手机上启动ArduinoTFT应用程序;
  • 将手机水平转动;
  • 启用蓝牙连接,选择检测到的蓝牙模块(HC-06);

屏幕上应显示两个窗口和四个按钮:

  • 右上角的窗口是手机的相机取景器窗口;
  • 大的左窗口 - 接收或发送的图像。

按钮功能:

  • 将单个图像从Android手机传输到Arduino;
  • 将图像从Android手机连续传输到Arduino;
  • 将单个图像从Arduino传输到Android手机;
  • 将图像从Arduino连续传输到Android手机。

6 部分核心代码

ArduinoBluetoothCamera.ino sketch:

#include <YATFT.h>
#include <util/yacam.h>
#include <util/yacodec.h>
#include <util/yasrl.h>
#include "ov7670_regs.h"
JPEG_DECODE  jpeg_decode;
YATFT  tft(0);
INTRFC ifc;
CAM    cam;
CODEC  codec;
SRL    srl;
#define IMG_SizeX    320
#define IMG_SizeY    240
uint8_t   mode = 0;
uint8_t   last_mode = 0;
uint8_t   start_capt = 0;
uint16_t  err;
void setup()
{
   // initialize the serial port
   Serial.begin(115200);
   // initialize the display
   tft.begin();
   tft.SetColor(BRIGHTRED);
   tft.ClearDevice();
}
void loop()
{
   // put your main code here, to run repeatedly:
   if (Serial.available())
   {
       uint8_t temp = Serial.read();
       switch (temp)
       {
           case 0x10: // Send single Photo
                mode = 1;
                start_capt = 1;
                if (last_mode != mode && last_mode != 2) {
                    tft.begin();
                    tft.SetRGB();               // Switch to RGB mode
                    cam.CamInit(&OV7670_QVGA[0][0]);
                    cam.CamVideoPreview(0, 0, 1, true);
                    codec.JPEGInit();
                    codec.JPEGSetRegs(IMG_SizeX, IMG_SizeY);
                    delay(1000);
                }
                break;
           case 0x20: // Continuous send Photo
                mode = 2;
                start_capt = 2;
                if (last_mode != mode && last_mode != 1) {
                    tft.begin();
                    tft.SetRGB();               // Switch to RGB mode
                    cam.CamInit(&OV7670_QVGA[0][0]);
                    cam.CamVideoPreview(0, 0, 1, true);
                    codec.JPEGInit();
                    codec.JPEGSetRegs(IMG_SizeX, IMG_SizeY);
                }
                break;
           case 0x30: // Receive single Photo
                mode = 3;
                start_capt = 3;
                if (last_mode != mode && last_mode != 4) {
                    tft.begin();
                    tft.SetYUV();               // Switch to YUV mode
                }
                break;
           case 0x40: // Continuous receive Photo
                mode = 4;
                start_capt = 4;
                if (last_mode != mode && last_mode != 3) {
                    tft.begin();
                    tft.SetYUV();               // Switch to YUV mode
                }
                break;
           default:
                break;
       }
   }
   if (mode == 1) // Send single Photo
   {
       if (start_capt == 1)
       {
           start_capt = 0;
           last_mode = mode;
           mode = 0;
           CamCapture();
       }
   }
   else if (mode == 2) // Continuous send Photo
   {
       while (1)
       {
           uint8_t temp = Serial.read();
           if (start_capt == 2)
           {
               start_capt = 0;
           }        
           if (temp == 0x21) // Stop ?
           {
               start_capt = 0;
               last_mode = mode;
               mode = 0;
               break;
           }
           if (CamCapture()) continue;
       }
   }
   else if (mode == 3) // Receive single Photo
   {
       if (start_capt == 3)
       {
           //Start capture
           start_capt = 0;
           last_mode = mode;
           mode = 0;
           Serial.print("!");
           srl.JPEGReadFromSerial(&jpeg_decode,  // jpeg decode structure
                                             0,  // x0 (left)
                                             0,  // y0 (top)
                                   GetMaxX()+1,  // x1 (right)
                                   GetMaxY()+1,  // y1 (bottom)
                                       32000); // max image size
           }
   }
   else if (mode == 4) // Continuous receive Photo
   {
       uint8_t temp = Serial.read();
       while (1)
       {
           if (start_capt == 4)
           {
               //Start capture
               start_capt = 0;
           }
           if (temp == 0x41) // Stop ?
           {
               start_capt = 0;
               last_mode = mode;
               mode = 0;
               break;
           }
           Serial.print("!");
           srl.JPEGReadFromSerial(&jpeg_decode,  // jpeg decode structure
                                             0,  // x0 (left)
                                             0,  // y0 (top)
                                   GetMaxX()+1,  // x1 (right)
                                   GetMaxY()+1,  // y1 (bottom)
                                        32000); // max image size
       }
   }
}
uint8_t  CamCapture(void)
{
   uint8_t temp = 0xff, temp_last = 0;
   bool is_header = false;
   uint32_t length = 0;
   length = codec.JPEGStart();
   uint32_t en_jpeg_address = ifc.rdReg32(0x414)<<2;
   int k = 0;
   if ((length >= 0x5FFFF) | (length == 0))
   {
       start_capt = 2;
       return 1;
   }
   temp = ifc.GetMem(en_jpeg_address+k);
   k++;
   length --;
   while ( length-- )
   {
       temp_last = temp;
       temp = ifc.GetMem(en_jpeg_address+k);
       k++;
       if (is_header == true)
       {
           Serial.write(temp);
       }
       else if ((temp == 0xD8) & (temp_last == 0xFF))
       {
           is_header = true;
           Serial.write(temp_last);
           Serial.write(temp);
       }
       if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while,
           break;
   }
   is_header = false;
   return 0;
}

OV7670_regs.h:

#ifndef OV7670_REGS_H
#define OV7670_REGS_H
const uint8_t OV7670_VGA[][2] PROGMEM =
{
   {   1, 0x42}, // Size of byte, Address (ID) 
   { 640/16,  480/16}, // Size X, Size Y
   {0b01000010, 0b00000100}, // Reset_Enable_N, 7|6|5|4|3|Vsync Invert|Hsync Invert|0
   {0x3a, 0x0C},   {0x40, 0xC0},   {0x12, 0x00},   {0x0c, 0x00},           
   {0x3e, 0x00},   {0x70, 0x3A},   {0x71, 0x35},   {0x72, 0x11},
   {0x73, 0xF0},   {0xa2, 0x02},   {0x11, 0x80},   {0x7a, 0x18},
   {0x7b, 0x02},   {0x7c, 0x07},   {0x7d, 0x1F},   {0x7e, 0x49},
   {0x7f, 0x5A},   {0x80, 0x6A},   {0x81, 0x79},   {0x82, 0x87},
   {0x83, 0x94},   {0x84, 0x9F},   {0x85, 0xAF},   {0x86, 0xBB},
   {0x87, 0xCF},   {0x88, 0xEE},   {0x89, 0xEE},   {0x13, 0xE0},
   {0x00, 0x00},   {0x10, 0x00},   {0x0d, 0x00},   {0x24, 0x98},
   {0x25, 0x63},   {0x26, 0xD3},   {0x2a, 0x00},   {0x2b, 0x00},
   {0x2d, 0x00},   {0x13, 0xe5},   {0x13, 0xe7},   {0x1e, 0x30},
   {0x74, 0x60},   {0x01, 0x80},   {0x02, 0x80},   {0x15, 0x10},
   {0x4f, 0x40},   {0x50, 0x34},   {0x51, 0x0C},   {0x52, 0x17},
   {0x53, 0x29},   {0x54, 0x40},   {0x57, 0x80},   {0x58, 0x1e},
   {0x41, 0x10},   {0x75, 0x60},   {0x76, 0x50},   {0x77, 0x48},
   {0x3d, 0x92},   {0x3b, 0x00},   {0x04, 0x00},   {0xff, 0xff},
};        
const uint8_t OV7670_QVGA[][2] PROGMEM =
{
   {   1, 0x42}, // Size of byte, Address (ID) 
   { 320/16,  240/16}, // Size X, Size Y
   {0b01000010, 0b00000100}, // Reset_Enable_N, 7|6|5|4|3|Vsync Invert|Hsync Invert|0
   {0x3a, 0x0C},   {0x40, 0xC0},   {0x12, 0x10},   {0x0c, 0x00},
   {0x3e, 0x00},   {0x70, 0x3A},   {0x71, 0x35},   {0x72, 0x11},
   {0x73, 0xF0},   {0xa2, 0x02},   {0x11, 0x80},   {0x7a, 0x18},
   {0x7b, 0x02},   {0x7c, 0x07},   {0x7d, 0x1F},   {0x7e, 0x49},
   {0x7f, 0x5A},   {0x80, 0x6A},   {0x81, 0x79},   {0x82, 0x87},
   {0x83, 0x94},   {0x84, 0x9F},   {0x85, 0xAF},   {0x86, 0xBB},
   {0x87, 0xCF},   {0x88, 0xEE},   {0x89, 0xEE},   {0x13, 0xE0},
   {0x00, 0x00},   {0x10, 0x00},   {0x0d, 0x00},   {0x24, 0x98},
   {0x25, 0x63},   {0x26, 0xD3},   {0x2a, 0x00},   {0x2b, 0x00},
   {0x2d, 0x00},   {0x13, 0xe5},   {0x13, 0xe7},   {0x1e, 0x30},
   {0x74, 0x60},   {0x01, 0x80},   {0x02, 0x80},   {0x15, 0x10},
   {0x4f, 0x40},   {0x50, 0x34},   {0x51, 0x0C},   {0x52, 0x17},
   {0x53, 0x29},   {0x54, 0x40},   {0x57, 0x80},   {0x58, 0x1e},
   {0x41, 0x10},   {0x75, 0x60},   {0x76, 0x50},   {0x77, 0x48},
   {0x3d, 0x92},   {0x3b, 0x00},   {0x04, 0x00},   {0xff, 0xff},
};        
#endif

7 最后

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值