[Adruino]XBEE 无线数据传输实际操作
双轮小车制作实例代码
引用:http://hi.baidu.com/dlfla84/item/52b89017a6209c5cf1090e9b
双轮小车制作
2009-6-12 初步完成了串口数据缓存、跨帧读取、协议、LED控制、读取传感器并发送至串口的部分。
但经过试验,12日的程序有问题,遇到了大量的数据丢失等问题。经过两天的调试,终于写出了如下的代码,小车已经可以将发送的命令串接收并返回了。虽然还是有信号丢失的问题,但并不严重,而且经过校验位计算后,会抛弃错误的命令串。当抛弃后,小车可以向上位机发送信号接收失败的信息,让上位机发送新的命令,直到接收成功为止。
整体设计思想:类似一个小游戏,程序的最小循环单位称为帧。在每帧中,完成LED控制、moto控制、传感器读取和指令读取。
其中指令读取是跨帧的,且带有协议。moto指令和LED指令,各有专门的寄存器。 一旦指令读取完毕,就将readState置为CMD_MOTO或CMD_LED的状态,在这种状态下才能激活各自的控制函数。
#define RETRY 20//控制桢速率,这个数值规定的毫秒数为1桢,目前是每秒50桢
#define REREAD 100//每次read命令的时候,跳过-1的次数,目前是每个字符可以重试100次
#define INPUT_SIZE 7
#define LED_SIZE 8
#define MOTO_SIZE 4
#define SENSOR_SIZE 5 #define CMD_MOTO 1
#define CMD_LED 2 #define HEAD 85
#define HEAD_MOTO 170
#define HEAD_LED 187
//LED常用命令,每个数字控制2个灯
//55 bb ff ff ff ff 0c //全部点亮
//55 bb 00 00 00 00 10 //全部熄灭 //moto常用命令
//55 aa 02 02 80 80 03 停止
//55 aa 02 02 ff ff 01 全速前进
//55 aa 02 02 00 00 03 全速后退 int input0,input1,sum,i;//读取串口的字符串,校验和,循环下标
int readState = ,retryCount = ,readCount = ;
int input[INPUT_SIZE];
//led
int ledPort[] = { , , , , , , , };//led地址,电路决定。左大-前-下-后,右大-前-下-后
int ledCmd[LED_SIZE];
int ledState[LED_SIZE];//led状态,每个成员可以是0-255,控制LED亮度。
int ledCount;
//sensor
int sensorPort[] = { , , , , };//传感器地址,电路决定.accxpin,accypin,acczpin,gyroxpin,gyroypin
int sensorState[SENSOR_SIZE];//传感器的返回值 应该用double吗?
//moto
int E1 = ;
int E2 = ;
int M1 = ;
int M2 = ;
int motoCmd[MOTO_SIZE];
int motoState[MOTO_SIZE];
/***************** read cmd ***************************************************/
void do_read() {
while(retryCount < RETRY) {
if(Serial.available() > ){
input1 = Serial.read();
//完整读取命令并校验,如果读取次数readCount超过REREAD,则放弃
if(input0 ==HEAD && (input1 == HEAD_MOTO || input1 == HEAD_LED))
{
input[] = input0;
input[] = input1;
for(i = ;i<INPUT_SIZE;i++){//2:减去了信息头
input[i] = Serial.read();
if(input[i] == - && readCount < REREAD){//跳过-1的
i--;
readCount++;//不能无限的跳过
}else
readCount = ;
}
sum=;//效验和
for(i=; i<INPUT_SIZE - ;i++){
sum += input[i];
}
sum%=;
if(sum == input[INPUT_SIZE-]){//校验和
parseCmd();
}else
outputMsg();//输出"error"
}
input0 = input1;
}else{
delay();
retryCount++;
}
}
retryCount = ;
}
void parseCmd(){//解析输入命令,转换成moto和led用的命令
if(input[] == HEAD_MOTO){
readState = CMD_MOTO;
//解析输入数据为moto专用命令
for(i=;i<MOTO_SIZE;i++){
motoCmd[i] = input[i+];
}
//outputMsg(2);//输出moto指令
}else if(input[] == HEAD_LED){
readState = CMD_LED;
//解析输入数据为led专用命令
for(i=;i<LED_SIZE;i+=){
ledCmd[i] = input[i/+]/;
ledCmd[i]*=;
ledCmd[i+] = input[i/+]%;
ledCmd[i+]*=;
}
//outputMsg(3);//输出LED指令
}
//outputMsg(1);//输出输入指令
}
void outputMsg(int s){
switch(s){
case :
Serial.println("error");
break;
case :
//输出接收到的命令(DEBUG)
for(i=;i<INPUT_SIZE;i++){
Serial.print(input[i]);
Serial.print(";");
}
Serial.println();
break;
case ://输出moto指令
for(i=;i<MOTO_SIZE;i++){
Serial.print(motoCmd[i]);
Serial.print(";");
}
Serial.println();
break;
case ://输出LED指令
for(i=;i<LED_SIZE;i++){
Serial.print(ledCmd[i]);
Serial.print(";");
}
Serial.println();
break;
}
}
/***************** moto *******************************************************/
void do_moto() {
if(readState != CMD_MOTO)
return;
else
readState = ; if(motoCmd[]==&&motoCmd[]==){
stop();
}else if(motoCmd[]>&&motoCmd[]>){
//Serial.print((motoCmd[2]-128)*2);Serial.print(";");Serial.println((motoCmd[3]-128)*2);
back_off((motoCmd[]-)*,(motoCmd[]-)*);
}else if(motoCmd[]<&&motoCmd[]>){
//Serial.print((128-motoCmd[2])*2);Serial.print(";");Serial.println((motoCmd[3]-128)*2);
turn_L((-motoCmd[])*,(motoCmd[]-)*);
}else if(motoCmd[]<&&motoCmd[]<){
//Serial.print((128-motoCmd[2])*2);Serial.print(";");Serial.println((128-motoCmd[3])*2);
advance((-motoCmd[])*,(-motoCmd[])*);
}else if(motoCmd[]>&&motoCmd[]<){
//Serial.print((motoCmd[2]-128)*2);Serial.print(";");Serial.println((128-motoCmd[3])*2);
turn_R((motoCmd[]-)*,(-motoCmd[])*);
}
} void stop(void) //停止
{
digitalWrite(E1, LOW);
digitalWrite(E2, LOW);
set_led(,,,,,,,);
}
void advance(char a, char b) //前进
{
analogWrite(E1, a); //PWM调速
digitalWrite(M1, LOW);
analogWrite(E2, b);
digitalWrite(M2, LOW);
set_led(,,,,,,,);
}
void back_off(char a, char b) //后退
{
analogWrite(E1, a);
digitalWrite(M1, HIGH);
analogWrite(E2, b);
digitalWrite(M2, HIGH);
set_led(,,,,,,,);
}
void turn_L(char a, char b) //左转
{
analogWrite(E1, a);
digitalWrite(M1, LOW);
analogWrite(E2, b);
digitalWrite(M2, HIGH);
set_led(,,,,,,,);
}
void turn_R(char a, char b) //右转
{
analogWrite(E1, a);
digitalWrite(M1, HIGH);
analogWrite(E2, b);
digitalWrite(M2, LOW);
set_led(,,,,,,,);
}
/***************** LED *******************************************************/
void do_led() {
if(readState != CMD_LED)
return;
else
readState = ; for (i = ; i < LED_SIZE; i++) {
//在8个LED中循环,对比LED的历史状态和命令,
if(ledCmd[i] == ledState[i] || ledCmd[i] == -)//如果命令不变,就下一个
continue;
if(ledState[i] == ) {//如果历史命令是关闭,则加电,并写入亮度
digitalWrite(ledPort[i], HIGH);
analogWrite(ledPort[i], ledCmd[i]);
}
else if(ledCmd[i] == ) {//如果新命令是关闭,则关闭
digitalWrite(ledPort[i], LOW);
}
else {//到这里只可能是改变亮度的命令
analogWrite(ledPort[i], ledCmd[i]);
}
ledState[i] = ledCmd[i];//将命令写入LED状态
//Serial.print(ledState[i]);
//Serial.print(";");
}
}
void set_led(int v0,int v1,int v2,int v3,int v4,int v5,int v6,int v7){
readState = CMD_LED;
ledCmd[] = v0;ledCmd[] = v1;ledCmd[] = v2;ledCmd[] = v3;
ledCmd[] = v4;ledCmd[] = v5;ledCmd[] = v6;ledCmd[] = v7;
}
/*************** sensor *********************************************/
void do_sensor() {
//读取原始数据, 1代表3.2mv 1023=3300mV
//计算出电压偏置值, 300mv=1g 加速度 0g读数为1.5v,换算成466, 参考ADXL330 Mannual
//计算出电压偏置值 , 20mv= 10度/s 的角速度 静止读数为1.5v,换算成466, 参考IDG330 Mannual
//加速度和角速度的公式是一样的,所以就整合成一条
for (i = ; i < SENSOR_SIZE; i++) {
//sensorState[i] = analogRead(sensorPort[i]) - 466;
sensorState[i] = analogRead(sensorPort[i]);//在上位机实现归零
}
for (i = ; i < SENSOR_SIZE; i++) {
Serial.print(sensorState[i]);
Serial.print(";");
}
Serial.println();
}
/***************** setup-loop *************************************************/
void setup() {
//init LEDs
for (i = ; i < LED_SIZE; i++) {
pinMode(ledPort[i], OUTPUT);
digitalWrite(ledPort[i], LOW);
}
//init motos
for (i = ; i <= ; i++) {
pinMode(i, OUTPUT);
}
Serial.begin();
analogReference(EXTERNAL); //设置模拟输入为外部参考3.3V
//Serial.println("Ready");
} void loop() {
do_moto();//控制电机
do_led();//通过m_state变量,控制LED灯
do_sensor();//读取五轴传感器的值
do_read();//读取命令,顺便延时至结束.
}
[Adruino]XBEE 无线数据传输实际操作的更多相关文章
- 《例说XBee无线模块开发》
<例说XBee无线模块开发> 基本信息 原书名:The Hands-on XBee Lab Manual:Experiments that Teach you XBee Wireless ...
- xbee无线通讯终端
无线数传电台支持DIGI全系列无线数传模块,包括有xbee/xbee PRO S1.xbee/xbee PRO S2C.xbee WIFI.xbee PRO S3B.xbee/xbee PRO SX( ...
- Android手机便携式wifi的使用及无线数据传输(主要针对XP系统)
适用条件: 1.可以上网的安卓系统2.2以上的智能手机,或有便携式wifi功能的安卓智能手机 2.有无线网卡的笔记本电脑或台式机(特别是XP系统) 测试手机:中兴U930 电脑:华硕K50系列笔记本 ...
- Aruba无线控制器常用操作
初始配置 1.console到初始化的无线控制器上 Enter System name [Aruba7005]: Enter VLAN 1 interface IP address [172.16.0 ...
- zigbee学习之路(十四):基于协议栈的无线数据传输
一.前言 上次实验,我们介绍了zigbee原理的应用与使用,进行了基于zigbee的串口发送协议,但是上个实验并没有实现数据的收发.在这个实验中,我们要进行zigbee的接受和发送实验. 二.实验功能 ...
- [Arduino] 基于Xbee Pro和网络技术的智能公交系统设计
转自:http://www.21ic.com/app/rf/201112/99474.htm 引言 公共交通具有个体交通无法比拟的强大优势,优先发展城市公共交通系统是解决大.中城市交通问题的最佳途径. ...
- Android基于WIFI实现电脑和手机间数据传输的技术方案研究
Android手机和电脑间基于wifi进行数据传输,从技术上讲,主要有两种方案: 一种是通过ftp协议实现,Android手机作为数据传输过程中的ftp服务器: 一种是通过http协议实现.Andro ...
- Windows 8 关闭无线后无法打开WIFI的解决办法
转:http://blog.sina.com.cn/s/blog_49d02ed101016b4n.html 在使用 Windows 8 的过程中,遇到过几次使用键盘上的功能键(笔者笔记本上的快捷键是 ...
- 【Zigbee技术入门教程-01】Zigbee无线组网技术入门的学习路线
[Zigbee技术入门教程-01]Zigbee无线组网技术入门的学习路线 广东职业技术学院 欧浩源 一.引言 在物联网技术应用的知识体系中,Zigbee无线组网技术是非常重要的一环,也是大家感 ...
随机推荐
- unigui MessageDlg方法调用例子
procedure TfrmEmployee.btnDeleteClick(Sender: TObject);var aBool: Boolean;begin inherited; MessageDl ...
- mysql慢查询Slow Query Log和未使用索引(Not Using Indexes)查询配置和使用
mysql的“慢查询”指的是超过了允许的最大查询时间(long_query_time)的sql语句,而“未使用索引”查询顾名思义就是查询语句没有使用到索引的sql语句. 慢查询配置和使用 在msyql ...
- HIT 2275 Number sequence
点击打开HIT 2275 思路: 树状数组 分析: 1 题目要求的是总共的搭配方式,满足Ai < Aj > Ak.并且i j k不同 2 我们开两个树状数组,第一个在输入的时候就去更新.然 ...
- HDU 4497 GCD and LCM (数学,质数分解)
题意:给定G,L,分别是三个数最大公因数和最小公倍数,问你能找出多少对. 析:数学题,当时就想错了,就没找出规律,思路是这样的. 首先G和L有公因数,就是G,所以就可以用L除以G,然后只要找从1-(n ...
- MFC中消息响应机制
由于视类窗口始终覆盖在框架类窗口之上,因此所有操作,包括鼠标单击.鼠标移动等操作都只能由视类窗口捕获.一个MFC消息响应函数在程序中有三处相关信息:函数原型.函数实现和以及用来关联消息和消息响应函数的 ...
- iOS版本检测与版本升级
14年苹果官方要求所有的APP不能出现 “当前版本”字样,是因为从iOS8系统开始,你可以在设置里面设置在WiFi情况下,自动更新安装的APP.此功能大大方便了用户,但是一些用户没有开 启此项功能,因 ...
- socket编写简单回显server
socket在公司代码中应用比较广,比如接口调用的IPCRPC机制,经常看到这样的代码,但是一直也没有动手写过. 在某个比较大的进程中创建一个子进程,由于父子进程复制会浪费内存,可以将创建进程的命令通 ...
- miniui datagrid 保存到服务端,使用.NET 自带 JSON 转换时发现日期格式不兼容。
使用 miniui datagrid 修改表格后,保存到服务端,然后使用 .NET 自带 JSON 转换,会抛出DateTime 内容“2015-12-27T11:02:28”未按 JSON 的要求以 ...
- easyui中tree型控件不正常显示的处理方法
我在使用easyui中的tree控件时,出现不正常显示的现象,比如li中不能使用自定义的图标.父级展开或关闭时,其子级仍然显现并出现重叠等.找了很多资料,都没解决这个问题,后来逐个对照官方的源码,才找 ...
- c#实现word,winWordControl 文档不允许复制、粘贴、隐藏工具栏、快捷保存
1.隐藏工具栏 //隐藏工具栏 ; i <= winWordControl1.document.CommandBars.Count; i++) { winWordControl1.documen ...