蓝牙控制摇摇棒

       经过三周的努力,蓝牙控制摇摇棒已经完成,在此过程中收获良多。选择这个题目的原因

是摇摇棒是很不错的一个玩具,再加上蓝牙的交互,可以随心所欲的控制摇晃的内容,趣味性

很强,这也是我选择做摇摇棒的一个原因。

           本设计本文介绍了一种以STC89C52RC单片机为主控制器,HC-05蓝牙模块作为数据传

 输媒介,利用人眼视觉暂留的原理设计的蓝牙控制的摇摇棒。摇摇棒在摇动过程中形成一个扇

 形平面,平面内可清晰显示文字、字母、图案。蓝牙作为一种新型的信息传送工具,具有无限

 传输、方便、快捷的优点。将蓝牙的这种特性运用到摇摇棒上,再结合摇摇棒本身可以在手挥

 式摆动下动态显示文字及图案的特性,使得摇摇棒具有更好的利用价值。在设计中,通过蓝牙

 无线透传,实现摇摇棒实时修改显示内容。

                 

成果展示:

 摇摇棒实物图:

 

 

 摇摇棒画面实图:

 

 

 

 蓝牙控制aap界面:

手机端主要采用上中下的列表式与选项卡式布局,可以从上到下清晰的展示已匹配或搜素到的蓝牙设备,分层位置清晰固定。底部为导航菜单栏,共有4个菜单功能选项,分别是终端操作,开关操作,切换显示和自定义显示。

          (1)终端操作也是整个手机端的主控界面,在此界面,实现蓝牙的开启与关闭,实现蓝牙设备的搜索与连接,实现基本指令的发送以及数据的接收。

(2)开关操作界面主要由16个红色开关按钮所组成,分别对应摇摇棒中的16个LED发光二极管,点击相应的红色开关按钮,则与之对应的LED法官二极管实现状态的改变。

(3)切换界面主要功能为控制摇摇棒程序中预置摇动的显示内容,预置的内荣为“四川工商电子信息工程学院通信二班”,“LOVE”与心形。通过此界面即可随意变换摇摇棒显示内容。如下图。

 

(4)自定义显示界面中可以通过手机键盘输入汉字,英文或则图案(由于用的是STC89C52RC芯片,存储空间有限,所以最多可以允许输入4个汉字大小)。并且可以对显示效果进行微调。如图下图所示。

 

 

 

       单片机系统程序采用 keil uVision4 软件编写 

        手机蓝牙控制app基于HBuilderX平台开发       

   点击 完整程序 可以获得 蓝牙控制摇摇棒相关资源

           资源列表:

      

        论文文章目录:

 

以下为 单片机系统的部分程序

#include <stc51.h> 
#define uchar unsigned char
#define uint unsigned int
/*****函数声明*****/
void display1_ltor(void);
void display2_ltor(void);
void display3_ltor(void);
void Data_display(void)	;
void display3(void);
void main (void)  
{ 
      init();
		while(1)	
    	{
			 key_pd();
			  switch(pic)      //选择画面
		     {
					case 0: {liushuid();} break;
				    case 1: {f2();} break;
					default:  liushuid();
		     }				
       }
}  
/*****************串口接收中断函数,接收蓝牙模块的数据*********************/
void ser_int (void) interrupt 4   
{  
    if(RI == 1) 
{  //如果收到. 
			  RI = 0;      //清除标志.   
		     UART_buff = SBUF;  //接收. 
		if(UART_buff=='g') {flag2=0; data_tot=0;data_len=0;}  //字符串数据标志长度初始化
	 else if(flag2==0) {
		      if(data_tot>=128||UART_buff=='s'){
				 Data_flag=0;flag2==1;  //开启自定义数据显示 接收停止
				 P2=0x03;DelayUs(50000);P2=0x30; //数据读入成功规则双亮灯
		        } 
                else{
			    if(data_len==0){data_len=(UART_buff-48);}   //字符串数据长度
                  else{		
                         if(data_num){
					Data_data[data_tot++]= Data_zh(data_tem,UART_buff);	//字符串数据
					data_num=0; //每两位数据一存标记
	             }else
	             {	 //中间缓存
				 data_tem=UART_buff;   data_num=1;
													}
					UART_send_byte(UART_buff);	
											     }
				  						      }
				  }else if(UART_buff=='q'){flag4=1;Data_flag=1;}
				   else if(flag4) {pic=UART_buff-48;flag4=0;}
				   else if(UART_buff=='q'){flag4=1;Data_flag=1;}
				   else if(flag5){flag5=0; koz=UART_buff; }          
				   else{	   Data_flag=1;
				  	  if(UART_buff == '0')  LED1 = ~LED1;  
				      if(UART_buff == '1')  LED2 = ~LED2; 
					  if(UART_buff == '2')  LED3 = ~LED3; 
					  if(UART_buff == '3')  LED4 = ~LED4; 
					  if(UART_buff == '4')  LED5 = ~LED5; 
					  if(UART_buff == '5')  LED6 = ~LED6; 
					  if(UART_buff == '6')  LED7 = ~LED7; 
					  if(UART_buff == '7')  LED8 = ~LED8; 
					  if(UART_buff == '8') LED21 = ~LED21; 
					  if(UART_buff == '9') LED22 = ~LED22; 
					  if(UART_buff == 'a') LED23 = ~LED23; 
					  if(UART_buff == 'b') LED24 = ~LED24; 
					  if(UART_buff == 'c') LED25 = ~LED25;
					  if(UART_buff == 'd') LED26 = ~LED26;
					  if(UART_buff == 'e') LED27 = ~LED27;
					  if(UART_buff == 'f') LED28 = ~LED28;       
					   TI = 1; 
				  }
				     
    }  
    else  {        //如果送毕.  
      TI = 0;      //清除标志.  
    }  
}   

  手机app部分程序  

* html+ 串口蓝牙操作
 */
function BluetoothTool() {
	var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
	var Intent = plus.android.importClass("android.content.Intent");
	var IntentFilter = plus.android.importClass("android.content.IntentFilter");
	var BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");
	var UUID = plus.android.importClass("java.util.UUID");
	var Toast = plus.android.importClass("android.widget.Toast");
	//连接串口设备的 UUID
	//var MY_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
 var MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	var invoke = plus.android.invoke;
	var btAdapter = BluetoothAdapter.getDefaultAdapter();
	var activity = plus.android.runtimeMainActivity();
  
	var btSocket = null;
	var btInStream = null;
	var btOutStream = null;
	var setIntervalId = 0;

	var btFindReceiver = null; //蓝牙搜索广播接收器
	var btStatusReceiver = null; //蓝牙状态监听广播

	var state = {
		bluetoothEnable: false, //蓝牙是否开启
		bluetoothState: "", //当前蓝牙状态
		discoveryDeviceState: false, //是否正在搜索蓝牙设备
	}

	/**
	 * 关闭蓝牙
	 */
	function turnOffBluetooth() {
		if(btAdapter != null && btAdapter.isEnabled()) {
			btAdapter.disable();
		}
		if(btFindReceiver != null) {
			try {
				activity.unregisterReceiver(btFindReceiver);
			} catch(e) {

			}
			btFindReceiver = null;
		}

		state.bluetoothEnable = false;
		cancelDiscovery();
		closeBtSocket();

		if(btAdapter != null && btAdapter.isEnabled()) {
			btAdapter.disable();
			shortToast("蓝牙关闭成功");
		} else {
			shortToast("蓝牙已经关闭");
		}
	}

	/**
	 * 发现设备
	 */
	function discoveryNewDevice() {
		if(btFindReceiver != null) {
			try { 
				activity.unregisterReceiver(btFindReceiver);
			} catch(e) 
{
				console.error(e);
			}
			btFindReceiver = null;
			cancelDiscovery();
		}
		var Build = plus.android.importClass("android.os.Build");
		
		 //6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限
        if(Build.VERSION.SDK_INT >= 6.0){
            
        } 
		btFindReceiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
			"onReceive": function(context, intent) {
				plus.android.importClass(context);
				plus.android.importClass(intent);
				var action = intent.getAction();
				if(BluetoothDevice.ACTION_FOUND == action) { // 找到设备
	/**
	 * 读取数据
	 * @param {Object} activity
	 * @param {Function} callback
	 * @return {Boolean}
	 */
		var setTimeCount = 0;
		read();
		state.readThreadState = true;
		return true;
	/**
	 * 发送数据
	 * @param {String} dataStr
	 * @return {Boolean}
	 */
	function sendData(dataStr) {
		if(!btOutStream) {
			shortToast("创建输出流失败!");
			return;
		}  
		var bytes = invoke(dataStr, 'getBytes', 'gbk');
		try {	
			btOutStream.write(bytes);
		} catch(e) {
			return false;
		} 
		return true;
	}
};

手机界面部分程序

<div id="app">
                       <div class="mui-card-header">
						  <img style="width: 30px;height: 30px;opacity: 0.5;"src="img/lanya.png"><span class=" btn-boxfs">蓝牙控LED.v8 </span>
						  
						 
						  <div class="switch" style="right:-60px;">
			 				<input type="checkbox" name="toggle" @click="fshow(show)">
							<label for="toggle"><i></i>  </label><span></span>
						  </div>
					      
					  </div>
					 。。。。。。
							 
 
                      <button style="float: right;margin: 0px 5px 0px 0px;" @click="discoveryNewDevice">搜索</button><p style="font-size: large;">&nbsp;&nbsp;&nbsp;发现的设备:</p><br>
						<ul class="mui-card-content bdan">
					 		<li v-for="device in newDevices">
								<input style="float: right;" type="button" value="连接" @click="connDevice(device.address)" />名称:{{device.name}}<br> 地址:{{device.address}} <br>
								
							</li>
						</ul>
						</div>
						<div v-if="bluetoothState.readThreadState" class="bdan">
								发送数据:
								<textarea cols="20" rows="4" v-model="sendData"></textarea>
								<input type="button" value="发送" @click="onSendData" />
							<br>
							{{this.sendData}}
							<div style="margin-bottom: 100px;">接收的数据:
								<input type="button" value="清空" @click="receiveDataArr = [];" />
								<div style="width: 100%;min-height: 50px;">byte数组:
									<span v-for="data in receiveDataArr">
										{{data}}&nbsp;
									</span>
								</div>
								<div style="width: 100%;min-height: 50px;word-wrap:break-word;">
									对应的string字符串:<br> {{receiveDataStr}}
								</div>
							</div>
						</div>
					</div>	
					
				
				  
			
			
			<div style="height: 60px;"></div>

			<footer class="navbar-container">
			 <ul>
			   <li> <a type="text"  @click="getpagas"/>终&nbsp;端 <br> 操&nbsp;作</a>  </li>
			   <li> <a type="text"  @click="getpagas"/>开&nbsp;关<br>  操&nbsp;作 </a> </li>
			   <li> <a type="text"   @click="getpagas"/>切&nbsp;换<br> 显&nbsp;示</a> </li>
			   <li> <a type="text"   @click="getpagas"/>自定义<br>显&nbsp; &nbsp;示</a> </li>
			 <ul>
           </footer>
			</div>
			
		<script src="js/mui.min.js"></script>
		<script src="js/immersed.js"></script>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		<script type="text/javascript" src="js/BluetoothTool.js"></script>
		<script type="text/javascript" charset="utf-8">
			mui.init({
				statusBarBackground: '#009be0'
			});



									var canvas = document.createElement('canvas');
									var ctx = canvas.getContext('2d');
									var cols = 16;
									var	rows = 16;
	                                var cx=145;
									var arr=[];
			 
							function lattice(txt,textvlaue){
								  
	                                    cx= textvlaue*2+50;
										cols = txt.length * 16
										canvas.width = cols;
				 						canvas.height = rows;
						 				ctx.clearRect(0,0,cols,rows);
										ctx.font ="16px SimSun";
									    ctx.fillStyle = "#000"; 
										ctx.fillText(txt, 0, 14);
									
								for(var t=1;t<=cols;t++){
										arr[t]=[];
										arr[t][0]=10;
										
										} 
										var data1 = ctx.getImageData(0, 0, cols, rows)
										var len = data1.data.length;
										var res = '';
										for(var i = 1; i <= rows; i++){
											for(var j = 1; j <= cols; j++){
												var pos = ((( i-1 )*cols+( j ))*4-1);
												
												if(data1.data[pos] >cx){
												res += `<span class="black" style="left: ${j*10}px;top: ${i*10}px"></span>`	
											        
													arr[i][j]=1;
												}else{
													arr[i][j]=0;}
											}
										} 
										
											var tem=new Array();
											tem[0]='g';
											tem[1]=(cols/16).toString(16);
											var tct=2;
										for(var j = 1; j <= cols; j++){
										var ttt=0;
										for(var i = rows; i>=1; i--){
											if(i==8){var te=parseInt(ttt/16);var te2=ttt-te*16; tem[tct]=te.toString(16);tct++;tem[tct]=te2.toString(16);tct++;ttt=0} 
												ttt=ttt*2+arr[i][j];
										}
											var te=parseInt(ttt/16);var te2=ttt-te*16; tem[tct]=te.toString(16);tct++;tem[tct]=te2.toString(16); tct++;
										}
										
										wrap.innerHTML = res;	
										//wrap1.innerHTML=tem.join(",");
									//console.log("%s",tem.join(""));
										return tem.join("");
									}
									
									function draw(textvlaue){
										var txt = text.value; 
										if(txt){
										var data2=lattice(txt,textvlaue); 
										return data2;
										}
										
									}	
									//draw();
							
	function sleep(n) {
				var start1 = new Date().getTime();
				while (true) {
					if (new Date().getTime() - start1 > n) {
						break;
					}
				}
            }
							
							document.addEventListener("plusready", function() {
								var bluetoothTool = null;
								var vm = new Vue({
									"el": "#app",
									data: function() {
										return {
											bluetoothState: {},
											pairedDevices: [],
											newDevices: [],
											receiveDataArr: [],
											sendData: "",
											sendData2: "",
											msg: "",
											show: false,
                                            muindex: 1,
											getPaired: false,
											 rangeBoundary0:50,
											 selected: 0,
												 value1: 0,
											
										}
										
									},
									computed: {
										receiveDataStr: function() {
											return String.fromCharCode.apply(String, this.receiveDataArr);
										},
										bluetoothStatusDesc: function() {
											return this.bluetoothStatus ? "已开启" : "已关闭";
										},
										
										
										rangeMax:function () {
									          
                                            return Number(this.rangeBoundary0) 
                                            }
											
                                     
									}, 
									created: function() {
										let that = this;
										bluetoothTool = BluetoothTool();
										this.bluetoothState = bluetoothTool.state;
										bluetoothTool.init({
											listenBTStatusCallback: function(state) {
												that.msg = "蓝牙状态: " + state;
											},
											discoveryDeviceCallback: function(newDevice) {
												that.newDevices.push(newDevice);
											},
											discoveryFinishedCallback: function() {
												that.msg = "搜索完成";
											},
											readDataCallback: function(dataByteArr) {
												if(that.receiveDataArr.length > 17*3) {
													that.receiveDataArr = [];
												}
												that.receiveDataArr.push.apply(that.receiveDataArr, dataByteArr);
											},
											connExceptionCallback: function(e) {
												console.log(e);
												that.msg = "设备连接失败";
											}
		
										});
		 							},
									methods: {
										fshow:function(messge){
											if(!messge){
												vm.show=true;
												bluetoothTool.turnOnBluetooth();
											}else{ vm.show= false;
												bluetoothTool.turnOffBluetooth();
											}
											
										}, 
										getPairedDevices: function() {
											vm.getPaired=!vm.getPaired;
											this.pairedDevices = bluetoothTool.getPairedDevices();
										},
										discoveryNewDevice: function() {
											this.newDevices = [];
											bluetoothTool.discoveryNewDevice();
										},
										cancelDiscovery: function() {
											bluetoothTool.cancelDiscovery();
										},
										connDevice: function(address) {
											bluetoothTool.connDevice(address);
										}, 
										disConnDevice: function() {
											bluetoothTool.disConnDevice();
										},
										onSendData: function() {
											bluetoothTool.sendData(this.sendData);
											//alert("1"+this.sendData);
										},
										onSendData2: function(){
										this.sendData2=draw(vm.rangeMax);
										    //var tot=0;
											for(var tot=0;tot<this.sendData2.length;tot++)
											{
											bluetoothTool.sendData(this.sendData2[tot]);
											 sleep(12);
											}
											bluetoothTool.sendData('s');
										},
										onSendData3: function(message){
										this.sendData3=message;
											bluetoothTool.sendData(this.sendData3);
											//alert("3"+this.sendData3);
										},
										onSendData4: function(message){
										this.sendData4=message;
											bluetoothTool.sendData(this.sendData4);
											//alert("4"+this.sendData4);
										},
										getpagas:function(message){
											vm.muindex=message;
										},
										f:function(){
											draw(vm.rangeMax);
										},
										
									}
								});
							}, false);
			
		</script>
	</body>

</html> 

   点击 完整程序 可以获得 蓝牙控制摇摇棒相关资源