首页 文章

为什么XBee传输有时会失败?

提问于
浏览
0

我正在做一个带有Arduino Uno R3和XBee S2传输的项目 . 我使用了几个传感器,如无线(RF)温度传感器,两个SHT75传感器,一个3轴加速度计和一个照度传感器 . 收集数据后,我们使用XBee(S2,API模式)将数据发送到网关 . 每轮大约一秒钟 .

  • 第一个问题是数据大约是16个字节,但数据包每轮都没有成功发送 . 有时它工作,有时它没有,但XBee的有效载荷在数据表中可以是60或70字节......但是如果我把有效载荷放在一些简单的整数(如1,2,3),而不是来自传感器的数据,传输将是稳定的 .

  • 在遇到上述问题后,我将数据分成两个数据包(每个数据包有8个字节的有效负载),第一个数据包非常稳定,但第二个数据包非常不稳定 . 如上所述,如果我将一些数字放入第二个数据包而不是传感数据,那么第二个数据包将变得稳定并且每一轮都成功发送 .

所以我认为这是代码问题,但idk在哪里是问题 . 我尝试改变波特率或增加两个数据包之间的延迟时间 . 问题出在哪儿?以下是我的代码:

#include <XBee.h>
#include <i2cmaster.h>
#include <string.h>
#include <ctype.h>
#include <Sensirion.h>
#include "Wire.h"
#include "MMA845XQ.h"

**///////////////////////////// XBee setup //////////////////////////////////**
XBee xbee = XBee();
XBeeAddress64 remoteAddress = XBeeAddress64(0x00000000, 0x00000000);
ZBRxResponse zbRx = ZBRxResponse();
ZBTxStatusResponse zbTxStus = ZBTxStatusResponse();

uint8_t payload[] = {0,0,0,0,0,0,0,0,0};
uint8_t payload1[] = {0,0,0,0,0,0,0,0,0};

**///////////////////////////// Accelerometer //////////////////////////////////**
MMA845XQ accel;

**////////////////////////// SHT1 serial data and clock ////////////////////**
const byte dataPin = 2;
const byte sclkPin = 3;
Sensirion sht = Sensirion(dataPin, sclkPin);
unsigned int rawData;
float temperature;
float humidity;
byte stat;

**////////////////////////// SHT2 serial data and clock ////////////////////**
const byte dataPin1 = 4;
const byte sclkPin1 = 5;
Sensirion sht1 = Sensirion(dataPin1, sclkPin1);
unsigned int rawData1;
float temperature1;
float humidity1;
byte stat1;

**//////////////////////////// Illumination sensor ////////////////////////**
int sensorPin = A0;    // Select the input pin for the potentiometer
int sensorValue = 0;   // Variable to store the value coming from the sensor
long int pardata, pardata_low, pardata_hi, real_pardata;
uint16_t illumindata = 0;

void setup () {
    i2c_init(); //Initialise the I²C bus
    PORTC = (1 << PORTC4) | (1 << PORTC5); //Enable pullups
    Wire.begin();
    accel.begin(false, 2);
    Serial.begin(115200);
    xbee.begin(Serial);
}

void loop () {
    payload[0] = 10;
    payload1[0] = 11;

    **/////////////////////RF temperature sensor/////////////////////////////**
    int dev = 0x5A<<1;
    int data_low = 0;
    int data_high = 0;
    int pec = 0;
    i2c_start_wait(dev + I2C_WRITE);
    i2c_write(0x07);
    i2c_rep_start(dev + I2C_READ);
    data_low = i2c_readAck(); //Read 1 byte and then send ack
    data_high = i2c_readAck(); //Read 1 byte and then send ack
    pec = i2c_readNak();
    i2c_stop();

    double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
    double tempData = 0x0000; // Zero out the data
    int frac; // Data past the decimal point

    // This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
    tempData = (double)(((data_high & 0x007F) << 8) + data_low);
    tempData = (tempData * tempFactor)-0.01;
    float celcius = tempData - 273.15;
    float fahrenheit = (celcius*1.8) + 32;

    celcius *= 100;
    int a = int(celcius) + 1;
    payload[1] = a >> 8 & 0xff;
    payload[2] = a & 0xff;

    **//////////////////////////// Illumination sensor ////////////////////////////////**
    sensorValue = analogRead(sensorPin);
    TSR(sensorValue);

    payload[3] = pardata_low >> 8 & 0xff;
    payload[4] = pardata_low & 0xff;

    **//////////////////////////// 3-axis accelemeter sensor ////////////////////////////////**
    accel.update();
    payload[5] = accel.getX()*10;
    payload[6] = accel.getY()*10;
    payload[7] = accel.getZ()*10;

    delay(100);

    **////////////////////////////// XBee send first packet///////////////////////////////////////////////**
    xbee = XBee();
    xbee.begin(Serial);
    ZBTxRequest zbTx = ZBTxRequest(remoteAddress, payload, sizeof(payload));
    zbTx.setAddress16(0xfffe);
    xbee.send(zbTx);

    delay(500);

    **//////////////// SHT 1x temperature and humidity sensor /////////////////////////**
    sht.readSR(&stat);                     // Read sensor status register
    sht.writeSR(LOW_RES);                  // Set sensor to low resolution
    sht.readSR(&stat);                     // Read sensor status register again
    sht.measTemp(&rawData);                // sht.meas(TEMP, &rawData, BLOCK)
    sht.meas(TEMP, &rawData, NONBLOCK);
    temperature = sht.calcTemp(rawData);
    sht.measHumi(&rawData);                // sht.meas(HUMI, &rawData, BLOCK)
    humidity = sht.calcHumi(rawData, temperature);
    sht.meas(HUMI, &rawData, NONBLOCK);
    humidity = sht.calcHumi(rawData, temperature);
    temperature *= 100;
    a = int(temperature) + 1;

    payload1[1] = a >> 8 & 0xff;
    payload1[2] = a & 0xff;

    humidity *= 100;
    a = int(humidity) + 1;
    payload1[3] = a >> 8 & 0xff;
    payload1[4] = a & 0xff;

    delay(10);

    sht1.readSR(&stat1);
    sht1.writeSR(LOW_RES);                  // Set sensor to low resolution
    sht1.readSR(&stat1);
    sht1.measTemp(&rawData1);                // sht.meas(TEMP, &rawData, BLOCK)
    temperature1 = sht1.calcTemp(rawData1);
    sht1.measHumi(&rawData1);                // sht.meas(HUMI, &rawData, BLOCK)
    humidity1 = sht1.calcHumi(rawData1, temperature1);

    delay(10);

    temperature1 *= 100;
    a = int(temperature1) + 1;
    payload1[5] = a >> 8 & 0xff;
    payload1[6] = a & 0xff;

    humidity1 *= 100;
    a = int(humidity1) + 1;
    payload1[7] = a >> 8 & 0xff;
    payload1[8] = a & 0xff;

    **////////////////////////////// XBee send second packet ///////////////////////////////////////////////**
    xbee = XBee();
    xbee.begin(Serial);
    zbTx = ZBTxRequest(remoteAddress,payload1, sizeof(payload1));
    zbTx.setAddress16(0xfffe);
    xbee.send(zbTx);
    delay(500);
}

void TSR(int sensorValue)
{
    illumindata = (sensorValue * 4 * 5) / 1.5;
    pardata = 6250/6144*illumindata*10;

    if(pardata > 0)
    {
        if(pardata < 11500)
        {
            real_pardata = 0.0000000020561*pardata*pardata*pardata -
                           0.00002255*pardata*pardata +
                           0.25788*pardata -
                           6.481;
            if (real_pardata < 0)
            {
              real_pardata = 0;
            }

            pardata_hi = real_pardata/65535;
            pardata_low = real_pardata%65535;
        }
        else
        {
            real_pardata = 0.0000049204*pardata*pardata*pardata -
                           0.17114*pardata*pardata +
                           1978.7*pardata -
                           7596900;
            if (real_pardata < 0)
            {
                real_pardata = 0;
            }
            pardata_hi = real_pardata/65535;
            pardata_low = real_pardata%65535;
        }
    }
    else
    {
        pardata_hi = 0;
        pardata_low = 0;
    }
}

1 回答

  • 1

    正如我写的那样,我已经解决了你遇到的同样的问题,尽管有类似的硬件设置 . 我使用了裸avr atxmega128a3u(所以没有arduino板)和Xbee S1以波特率115200进行通信 . 经过几天试图解决这个问题后,我得出结论,如果你的avr没有以精确时钟运行(外部xtal)并且您使用略微“更快”的波特率(> = 115200)Xbee的串行硬件可能无法恢复时钟信号,从而导致传输错误 . (也许Xbee的比特采样率很慢) .

    无论如何,通过确保您的微处理器以稳定的时钟运行(您应该在这里安全,因为arduino有一个外部xtal)并且使用较慢的波特率(尝试57600,19200或9600)应该可以解决您的问题 . 希望如此 . :) ...不要忘记在XCTU中重新配置Xbee的波特率 .

    如果你只启动xbee一次也可能会有所帮助 . 将这些行移到setup()函数中:

    setup(){
        // This is changed
        Serial.begin(9600);
        // This is new
        xbee = XBee();
        xbee.begin(Serial);
        // ...
      }
    

    编辑:您也可能对这个网站感兴趣,你可以看到给定时钟频率和波特率的错误百分比(以及如果你使用裸avr设置的直接寄存器值)http://www.wormfood.net/avrbaudcalc.php?postbitrate=9600&postclock=16&hidetables=1

相关问题