蓝牙控制摇摇棒
经过三周的努力,蓝牙控制摇摇棒已经完成,在此过程中收获良多。选择这个题目的原因
是摇摇棒是很不错的一个玩具,再加上蓝牙的交互,可以随心所欲的控制摇晃的内容,趣味性
很强,这也是我选择做摇摇棒的一个原因。
本设计本文介绍了一种以STC89C52RC单片机为主控制器,HC-05蓝牙模块作为数据传
输媒介,利用人眼视觉暂留的原理设计的蓝牙控制的摇摇棒。摇摇棒在摇动过程中形成一个扇
形平面,平面内可清晰显示文字、字母、图案。蓝牙作为一种新型的信息传送工具,具有无限
传输、方便、快捷的优点。将蓝牙的这种特性运用到摇摇棒上,再结合摇摇棒本身可以在手挥
式摆动下动态显示文字及图案的特性,使得摇摇棒具有更好的利用价值。在设计中,通过蓝牙
无线透传,实现摇摇棒实时修改显示内容。
成果展示:
摇摇棒实物图:
摇摇棒画面实图:
蓝牙控制aap界面:
手机端主要采用上中下的列表式与选项卡式布局,可以从上到下清晰的展示已匹配或搜素到的蓝牙设备,分层位置清晰固定。底部为导航菜单栏,共有4个菜单功能选项,分别是终端操作,开关操作,切换显示和自定义显示。
(1)终端操作也是整个手机端的主控界面,在此界面,实现蓝牙的开启与关闭,实现蓝牙设备的搜索与连接,实现基本指令的发送以及数据的接收。
(2)开关操作界面主要由16个红色开关按钮所组成,分别对应摇摇棒中的16个LED发光二极管,点击相应的红色开关按钮,则与之对应的LED法官二极管实现状态的改变。
(3)切换界面主要功能为控制摇摇棒程序中预置摇动的显示内容,预置的内荣为“四川工商电子信息工程学院通信二班”,“LOVE”与心形。通过此界面即可随意变换摇摇棒显示内容。如下图。
(4)自定义显示界面中可以通过手机键盘输入汉字,英文或则图案(由于用的是STC89C52RC芯片,存储空间有限,所以最多可以允许输入4个汉字大小)。并且可以对显示效果进行微调。如图下图所示。
单片机系统程序采用 keil uVision4 软件编写 手机蓝牙控制app基于HBuilderX平台开发
点击 完整程序 可以获得 蓝牙控制摇摇棒相关资源
资源列表:
论文文章目录:
以下为 单片机系统的部分程序
代码语言:javascript复制#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部分程序
代码语言:javascript复制* 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;
}
};
手机界面部分程序
代码语言:javascript复制<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;"> 发现的设备:</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}}
</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(1)"/>终 端 <br> 操 作</a> </li>
<li> <a type="text" @click="getpagas(2)"/>开 关<br> 操 作 </a> </li>
<li> <a type="text" @click="getpagas(3)"/>切 换<br> 显 示</a> </li>
<li> <a type="text" @click="getpagas(4)"/>自定义<br>显 示</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>