RFBee stability

I am using an RFBee in a XBee Carrier to measure temperature and humidity (via a Grove DHT11 module) and soil moisture via a homemade resistive probe and send a measurement to a second RFBee connected via a XBee Shield to a Freetronics EtherTen board. I am using the “RFbee firmware for Arduino 1.0(new)” RFBee firmware from the RFBee wiki page on both RFBees, but have modified the code on the RFBee in the XBee Carrier in order to connect with the sensors.

The code I am using is as follows

// Use to send temperature and humidty measurements from a DHT11 sensor
// using a RFBee in a Grove Carrier

// Note DHT11 sensor needs to be connected to D5/D6 grove connector

// XBee Carrier
// Pins
// When using an RFBee, the following pinouts apply for using the arduino IDE
// Pin 5 is the Grove connector for I/O - Yellow wire
// Pin 6 is the Grove connector for I/O - White wire
// Note: you can use the x2 Grove cable with the white and yellow wires swapped on one to access both I/O.
// Pin 16 may need to be driven low to provide enough power to the I/O Grove [via mosfet]
// Pin 17 may need to be driven low to provide enough power to the I2C Grove [via mosfet]

// Compile using
// Arduino Pro or Pro Mini (3.3v, 8MHz) w/ATmega168



#define ENABLE_SERIAL true
#define ENABLE_HEADER false
#define ENABLE_RFBEE true
#define ENABLE_DHT11 true
#define ENABLE_SEND_DHT11_CHK false
#define ENABLE_MOISTURE true
#define ALLOW_RECEIVE false
#define ENABLE_MEMORY_REPORTING true
#define ENABLE_STRING_RESERVE false
#define SEND_EXTENDED_HEADER false

#define ENABLE_TEST_RFBEE false

#if ENABLE_TEST_RFBEE
#undef ENABLE_RFBEE
#define ENABLE_RFBEE true
#undef ENABLE_DHT11
#define ENABLE_DHT11 true
#undef ENABLE_MOISTURE
#define ENABLE_MOISTURE false
#undef ALLOW_RECEIVE
#define ALLOW_RECEIVE false
#endif


#if ENABLE_MEMORY_REPORTING
#include <MemoryFree.h>
#endif


#if ENABLE_RFBEE
#include <EEPROM.h>
#include <RFBeeSendRev.h>
#include <RFBeeCore.h>
//#include <Sleep_n0m1.h>

#define power_adc_enable()      (PRR &= (uint8_t)~(1 << PRADC))
#define power_adc_disable()     (PRR |= (uint8_t)(1 << PRADC))

#define power_spi_enable()      (PRR &= (uint8_t)~(1 << PRSPI))
#define power_spi_disable()     (PRR |= (uint8_t)(1 << PRSPI))

#define power_usart0_enable()   (PRR &= (uint8_t)~(1 << PRUSART0))
#define power_usart0_disable()  (PRR |= (uint8_t)(1 << PRUSART0))

#define power_timer0_enable()   (PRR &= (uint8_t)~(1 << PRTIM0))
#define power_timer0_disable()  (PRR |= (uint8_t)(1 << PRTIM0))

#define power_timer1_enable()   (PRR &= (uint8_t)~(1 << PRTIM1))
#define power_timer1_disable()  (PRR |= (uint8_t)(1 << PRTIM1))

#define power_timer2_enable()   (PRR &= (uint8_t)~(1 << PRTIM2))
#define power_timer2_disable()  (PRR |= (uint8_t)(1 << PRTIM2))

#define power_twi_enable()      (PRR &= (uint8_t)~(1 << PRTWI))
#define power_twi_disable()     (PRR |= (uint8_t)(1 << PRTWI))

#if ALLOW_RECEIVE
unsigned char dtaUart[100];
unsigned char dtaUartLen = 0;
bool stringComplete      = false;        // if get data

unsigned char rxData1[200];               // data len
unsigned char len1;                       // len
unsigned char srcAddress1;
unsigned char destAddress1;
char rssi1;
unsigned char lqi1;
int result1;
#endif

#endif


#if ENABLE_DHT11
#include <dht11.h>
dht11 DHT11;
const int DHT11_PIN = 5;
#endif


#if ENABLE_MOISTURE
// code from  gardenbot

// analogue pin for measurement
const int MOISTURE_SENSOR_PIN = A5;

// digital pins for sensor potential
const int DIVIDER_TOP = 7;
const int DIVIDER_BOTTOM = 8;

// Calibration parameters
// value at pin MOISTURE_PIN when open circuit (no moisture)
const int NO_MOISTURE = 0;
// value at pin MOISTURE_PIN when sensor submerged in water (full moisture)
const int FULL_MOISTURE = 990;

// time for capacitance to settle (milliseconds)
const int CAP_TIME = 1000;

void setSensorPolarity(boolean flip)
{
  if(flip)
  {
    digitalWrite(DIVIDER_TOP, HIGH);
    digitalWrite(DIVIDER_BOTTOM, LOW);
  }
  else
  {
    digitalWrite(DIVIDER_TOP, LOW);
    digitalWrite(DIVIDER_BOTTOM, HIGH);
  }
}

int getSoilMoistureLevel()
{
  int reading;        // a value between 0 and 1023

#if ENABLE_RFBEE
  // enable analogue to digital reading
  power_adc_enable();
#endif

  setSensorPolarity(true);
  delay(CAP_TIME);
  int val1 = analogRead(MOISTURE_SENSOR_PIN);
#if ENABLE_SERIAL
  Serial.print("val1: ");
  Serial.println(val1);
#endif
  delay(CAP_TIME);  
  setSensorPolarity(false);
  delay(CAP_TIME);
  // invert the reading
  int val2 = 1023 - analogRead(MOISTURE_SENSOR_PIN);
#if ENABLE_SERIAL
  Serial.print("val2: ");
  Serial.println(val2);
#endif

  // stop the current
  digitalWrite(DIVIDER_TOP,LOW);
  digitalWrite(DIVIDER_BOTTOM,LOW);

#if ENABLE_RFBEE
  // disable analogue to digital reading
  power_adc_disable();
#endif

  reading = (val1 + val2) / 2;

#if ENABLE_SERIAL
  Serial.print("Soil moisture raw reading is ");
  Serial.println(reading);
#endif

  return reading;
}

#endif


const char DATA_PREFIX = '$';
const char DATA_SEPARATOR = ',';
const char SYSTEM_REF = 'M';
#if ENABLE_STRING_RESERVE
const int MAX_DATA_SIZE = 32;
const int MAX_HEADER_SIZE = 16;
#endif
//const int MAX_TX_SIZE = 32;


const unsigned long iamaliveInterval = 10000;
static unsigned long iamalivePrev = 0;

const unsigned long measurementInterval = 30000UL;    // take a measurement every 30 seconds
static unsigned long measurementPrev = 0;

static unsigned long measurementCount = 0;

/*--------------------------------------------------------------------------------------
 setup()
 Called by the Arduino framework once, before the main loop begins
 --------------------------------------------------------------------------------------*/
void setup()
{
#if  ENABLE_SERIAL
  Serial.begin(38400);
#endif

#if ENABLE_SERIAL && ENABLE_MEMORY_REPORTING
  Serial.println("Begin setup()");
  Serial.print("freeMemory()= ");
  Serial.println(freeMemory());
#endif

#if ENABLE_RFBEE
  RFBEE.init();

//  power_adc_disable();
//  power_timer1_disable();
//  power_timer2_disable();
//  power_twi_disable();
#endif

#if ENABLE_SERIAL
  Serial.println("RFBee Grove Carrier Remote Module");
#if ENABLE_DHT11
  Serial.print("DHT11 library version ");
  Serial.println(DHT11LIB_VERSION);
#endif
#endif

#if ENABLE_MOISTURE
  pinMode(MOISTURE_SENSOR_PIN, INPUT);
  pinMode(DIVIDER_TOP, OUTPUT);
  pinMode(DIVIDER_BOTTOM, OUTPUT);
#endif

#if ENABLE_SERIAL && ENABLE_MEMORY_REPORTING
  Serial.println("End setup()");
  Serial.print("freeMemory()= ");
  Serial.println(freeMemory());
#endif
}

/*--------------------------------------------------------------------------------------
 loop()
 Arduino main loop
 --------------------------------------------------------------------------------------*/
void loop()
{
  // at beginning of loop get time program has been running
  unsigned long runTime = millis();

  // Check to see if it is time to get another temperature reading
  if ( runTime - measurementPrev > measurementInterval )
  {
    measurementPrev = runTime;
    measurementCount++;

#if ENABLE_SERIAL
    Serial.print("\n\n");
    Serial.print("Measurement ");
    Serial.print(measurementCount);
    Serial.print(" at ");
    Serial.print((long)runTime/1000);
    Serial.print(" seconds");
    Serial.println();
#endif

#if ENABLE_SERIAL && ENABLE_MEMORY_REPORTING
    Serial.print("freeMemory()= ");
    Serial.println(freeMemory());
#endif

#if ENABLE_DHT11
    // read DHT11 data
    int chk = DHT11.read(DHT11_PIN);

#if ENABLE_SERIAL
    Serial.print("DHT reading from pin ");
    Serial.println(DHT11_PIN);
    Serial.print("DHT status: ");
    switch (chk)
    {
    case  0:  
      Serial.println("OK");            
      break;
    case -1: 
      Serial.println("Checksum error"); 
      break;
    case -2: 
      Serial.println("Time out error"); 
      break;
    default: 
      Serial.println("Unknown error");  
      break;
    }
#endif

#if ENABLE_SERIAL
    Serial.print("Humidity (%): ");
    Serial.println((int)DHT11.humidity);

    Serial.print("Temperature (oC): ");
    Serial.println((int)DHT11.temperature);
#endif
#endif

    // create data string
    String dataString = "";
#if ENABLE_STRING_RESERVE
    dataString.reserve(MAX_DATA_SIZE);  // reserve MAX_DATA_SIZE bytes for the dataString
#endif

    int dataFieldCount = 0;

#if !ENABLE_HEADER
    dataString += DATA_PREFIX;
    dataString += DATA_SEPARATOR;
    dataString += SYSTEM_REF;
    dataString += DATA_SEPARATOR;
#endif

#if ENABLE_DHT11
#if ENABLE_SEND_DHT11_CHK
    dataString += chk;
    dataString += DATA_SEPARATOR;
#endif
    dataFieldCount++;
    dataString += DHT11.temperature;
    dataString += DATA_SEPARATOR;
    dataFieldCount++;
    dataString += DHT11.humidity;
    dataString += DATA_SEPARATOR;
    dataFieldCount++;
#endif
#if ENABLE_MOISTURE
    dataString += getSoilMoistureLevel();
    dataFieldCount++;
#endif
//    dataString += '\n';

#if ENABLE_HEADER
    // create header string (after dataString to include data length)
    String headerString = "";
#if ENABLE_STRING_RESERVE
    headerString.reserve(MAX_HEADER_SIZE);  // reserve MAX_HEADER_SIZE bytes for the dataString
#endif

    headerString += DATA_PREFIX;
    headerString += DATA_SEPARATOR;
    headerString += SYSTEM_REF;
    headerString += DATA_SEPARATOR;
#if SEND_EXTENDED_HEADER
    headerString += (int)(measurementInterval/1000);
    headerString += DATA_SEPARATOR;
    headerString += dataFieldCount;
    headerString += DATA_SEPARATOR;
    headerString += dataString.length();
    headerString += DATA_SEPARATOR;
#endif

    String txString = headerString + dataString;
    int txStringLength = txString.length();
    
    char txChar[txStringLength+1];
    txString.toCharArray(txChar, sizeof(txChar));
#else
    int txStringLength = dataString.length();
    
    char txChar[txStringLength+1];
    dataString.toCharArray(txChar, sizeof(txChar));
#endif

#if ENABLE_SERIAL
    Serial.println("Measurement string:");
    Serial.println(txChar);
#endif

#if ENABLE_SERIAL && ENABLE_MEMORY_REPORTING
    Serial.print("freeMemory()= ");
    Serial.println(freeMemory());
#endif

#if ENABLE_RFBEE
    RFBEE.sendDta(txStringLength, (unsigned char *)txChar);
#endif

#if ENABLE_SERIAL
    Serial.println("Data sent by RFBee");
#endif

#if ENABLE_SERIAL && ENABLE_MEMORY_REPORTING
    Serial.print("freeMemory()= ");
    Serial.println(freeMemory());
#endif

  }  // end if ( runTime - measurementPrev > measurementInterval )


#if ENABLE_RFBEE && ALLOW_RECEIVE
  if(RFBEE.isDta())
  {
    result1=receiveData(rxData1, &len1, &srcAddress1, &destAddress1, (unsigned char *)&rssi1 , &lqi1);
    Serial.println("Data received ...");
    Serial.print("Length = ");
    Serial.println(len1);
    for(int i = 0; i< len1; i++)
    {
      Serial.write(rxData1[i]);
    }
  }
#endif

}

The issue I am having is that the RFBee in the XBee Carrier will work for a low number (< 30) of measurement loops and will then stop working. I have done a some debugging and found that the program appears to get stuck in an infinite loop within the while(1) statement, within the transmitData function as located in the RFBeeCore.cpp file.

I therefore wondered whether other people have had a similar issue or whether anyone could provide any suggestions to resolve the issue.

Many thanks in advance

Hi! Did you solved the problem?
I’m waiting for an answer for a long time!
I think is about the 256 character limit of string. Isn’t it?

Hi,

There is a race condition in the transmit routine. I have fixed this in my “clone” of the firmware.

github.com/robots/RFBee/commit/ … 5498a8f49b

I have switched to different approach then the previous routine. I am using GDO2 signal, as sync with packet transmission. My version of firmware also fixes few issues in the receiving part - ie. register reading errata from TI.

Have fun.
Mike

Hi again! Thank you very much your code solved my problem!!!
I have a little question, In your code you send the measures in packages, isn’t it? how you convert the packages in variables? Could you post a code to do this?

I call something like this after each reception of package (at the end of writeSerialData function)

exec(&packet);

And in the exec function i handle relays according to the content of the packet.

void exec(struct ccxPacket_t *packet)
{
	if (packet->len < 3) 
		return;

	if (!(packet->frame[0] != 0 || packet->frame[0] != config_get(CONFIG_MY_ADDR)))
		return;

	LEDPORT = LEDPORT ^ LED;

	if (packet->frame[2] == '1') {
		if (packet->frame[3] & 1) {
			RELPORT |= REL1;
		}
		if (packet->frame[3] & 2) {
			RELPORT |= REL2;
		}
	} else if (packet->frame[2] == '0') {
		if (packet->frame[3] & 1) {
			RELPORT &= ~REL1;
		}
		if (packet->frame[3] & 2) {
			RELPORT &= ~REL2;
		}
	}
}

packet->frame[0] is the destination address, and your data starts from index 2