If Things Don't Work Right
A Quick Note About API Modes
Setting Up API Modes
XBee Thermometer
XBee Thermometer Part 2
XBee Thermometer Part 3
Using XBee Broadcast
More About XBee Broadcast (BEWARE)
Using the Arduino XBee Library Part 1
Using the Arduino XBee Library Part 2
Using the Arduino XBee Library Part 3
Integers, Floats, and Such Over XBee
XBee Pool Controller
XBee Acid Pump Timer
Monitoring My XBee Network
Raspberry Pi and XBee Part 1
Raspberry Pi and XBee Part 2
A Quick Note About API Modes
Setting Up API Modes
XBee Thermometer
XBee Thermometer Part 2
XBee Thermometer Part 3
Using XBee Broadcast
More About XBee Broadcast (BEWARE)
Using the Arduino XBee Library Part 1
Using the Arduino XBee Library Part 2
Using the Arduino XBee Library Part 3
Integers, Floats, and Such Over XBee
XBee Pool Controller
XBee Acid Pump Timer
Monitoring My XBee Network
Raspberry Pi and XBee Part 1
Raspberry Pi and XBee Part 2
If Things Don't Work Right
There's about a million tutorials on XBee devices on the web and I'm not going to rehash other people's work in this area. The problem is that they seem to repeat themselves too much, and many times the examples only work once. You reprogram the radio and the system stops working. I had this happen several times and finally almost threw them in a box on the shelf in pursuit of something that actually worked. Blind stubbornness helped me overcome all the problems I ran into and I can now make them work. Not that I have a huge sophisticated network, but I can make them talk to each other.
First, some things that you need to know that aren't mentioned:
- The router and end devices have to be commissioned into the network. This has to be done every time the coordinator is reprogrammed. This takes 4 pulses on pin 20. This is because the data that is used to communicate is lost during the reprogramming process.
- When the commission finishes, the NI parameter (name) is blank on the router, the router must be reset to restore this. Of course you can reprogram the name back into the router as well
- The best software that I have worked with so far is ZigBee using a XB24-ZB modem. This is one of the choices offered by X-CTU
- A network reset (ATNR 1) will blow off all the devices on the network and you have to recommission each of them.
- The coordinator has to be running for the router and end device to commission into the network. So, start the coordinator first then commission the various routers.
OP Read the operating 64-bit PAN ID.
OI Read the operating 16-bit PAN ID.
CH Read the operating channel.
ZS Read the stack profile.
Now, most of us don't mess with the ZS command and zero seems to work fine so I leave it alone. The OI is set by the coordinator and we don't get to choose it when we first start up. The CH (channel) is also chosen by the coordinator. The only one we are usually told to mess with is the OP when we set the ID. So, what you have to do is record these when you get a working network and then keep them around to fix the network when you reprogram a coordinator or accidentally issue a network reset.
So let me illustrate how you can reprogram a coordinator node and then get the network back up and working. The assumptions are that you have:
- Two or more XBees already working in AT mode - this is the 'transparent' mode where you issue commands to the modem using some terminal program or X-CTU itself.
- These little guys are running Zigbee software with the modem set to XB24-ZB. The particular set is dependent on what the XBee's role is: Coordinator, Router or End Device. For simplicity I'm just going to consider coordinator and routers.
- Since you have already gotten a network set up, you've already come up with a way to talk to them using some terminal program or X-CTU. Remember, if you have two or more unused USB ports you can plug them into your computer and use multiple instances of X-CTU to control and monitor the devices.
ATOP (returns up to 16 hex digits for example 1234)
ATOI (returns up to 4 hex digits for example ABCD)
ATCH (returns the actual channel being used, 1 hex digit for example C)
ATZS ( returns one hex digit, usually zero)
Each of these will return a value that is necessary to a working network. So after reprogramming the coordinator to something (usually going from API mode to AT mode) you have to put these values back in. However, you don't just use the same command, since most of these are read only values. The commands below are used to put the values back into the reprogrammed coordinator:
ATID 1234 - this sets the PAN to the value you read from the OP parameter above.
ATII ABCD - this sets the initial operating 16 bit id to the value read from the OI above
ATZS 0 - this sets the stack profile as above (this is not a read only value)
ATSC 2 - this is a bitfield that specifies the channels that may be scanned. 0x02 allows
only the channel 0x0C to be used. This prevents the coordinator from moving
off the channel.
If you want to be sure the values get recorded to eeprom, issue the ATWR command, but the commands above should save the commands. I always do the write command because I want to be darn sure it worked.
As you issue these commands, the coordinator will exit the network and rejoin allowing the various other devices to join as well. After completing the commands the coordinator is running on a known set of network parameters and can be troubleshot without nearly as much difficulty. If you happen to notice, the ATII command is not documented in the command references that you find. It is documented in the Digi documentation under replacing the coordinator. This was hard to find and solved most of my problems when I came across it. Look in:
http://ftp1.digi.com/support/documentation/90000976_G.pdf
Regarding the routers, the easiest way to program them is to ground pin 20 on the XBee 4 times like you are pushing a switch. This will tell the device to leave the current network and rejoin. This process is called commissioning. The device will flash a couple of lights if you have them and join the network you just set up on the coordinator. This is how you add a new device and make sure it can talk. You can also program the router in the same fashion as above to make it join. There's also the command ATCB 4 that will cause the same action as grounding the commission pin.
Power cycles, unplugging, hardware resets (like grounding the reset pin) don't change the settings and the devices will work fine under these conditions. The problem now is that going from AT mode to API mode will always cause the coordinator to lose these items and they cannot be set with at commands because you just switched modes and typing AT commands doesn't work. This is the situation where I was ready to stomp a couple of the devices into fine dust on the floor.
I put together a simple script to work with Xbees in API mode and observe the various actions. You're welcome to grab it and modify it to your needs. This script was thrown together in a hurry and has the bare minimum necessary to command and observe the devices, don't expect massive sophistication or features. One thing that is not made clear in a lot of tutorials is that every device doesn't have to be in API mode. If your coordinator is running in API and the routers all in AT, the network will work just fine. So you can move into higher levels of sophistication at your leisure. A couple of things to note: I did not use the Arduino XBee library, that thing is just too darn hard to understand for me. Also, I used NewSoftSerial version 10C (in case you have trouble compiling). This allows me to have the XBee and the serial port active at the same time. Let's face it, switching the programming serial port around every time you test something slows testing down too much. http://arduiniana.org/libraries/newsoftserial/
SKETCH
#include <NewSoftwareSerial.h>
SoftwareSerial xbeeSerial = SoftwareSerial(3, 2);
/*
at commands begin with a frame delimiter
then the length in two bites
the hex number 8 (meaning AT command
the number 1 meaning I want a response back
the command to be executed
any parameters to the command
a checksum
*/
// The command and parameters are here
char ATND[]={
0x08, 0x01, 'N', 'D'}; //node discover
char ATID[]={
0x08, 0x01, 'I', 'D', 0x12, 0x34}; // Pan id to use
char ATOP[]={
0x08, 0x01, 'O', 'P'}; //read operating pan id
char ATII[]={
0x08, 0x01, 'I', 'I', 0x17, 0xE8}; // Initial 16 bit PAN ID
char ATSC[]={
0x08, 0x01, 'S', 'C', 0x02}; //only allow chanel 0x0C
char ATZS[]={
0x08, 0x01, 'Z', 'S', 0x00}; //zigbee addressing type 0
char TX[]={0x10, 0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, // 64 bit hardware address
0x88,0x0c, // network address
0x00,0x00, // broadcast radius and options
'A',}; // finally, the actual data
char cmdbuf [100];
unsigned int cmdlen;
byte checksum;
void sendATcommand(char* command, int length){
// first calculate the length and fill it in
checksum = 0;
cmdbuf[0] = 0x7E; //command start signal
cmdlen = length; //the command characters & overhead
cmdbuf[1] = cmdlen >> 8;
cmdbuf[2] = cmdlen & 0xFF;
//copy command string into buffer
int i = 0;
for ( ; i < length; i++){
cmdbuf[i + 3] = command[i];
checksum += command[i];
}
cmdbuf[i+3] = 0xFF - checksum;
Serial.print("Packet sent ");
for (i=0; i < cmdlen + 4; i++){
printByteData(cmdbuf[i]);
Serial.print(" ");
}
Serial.println();
for(i=0; i < cmdlen+4; i++){
xbeeSerial.print(cmdbuf[i]);
}
}
void setup() {
Serial.begin(9600);
// set the data rate for the SoftwareSerial port
xbeeSerial.begin(9600);
Serial.println("Serial ports initialized");
}
uint8_t received;
#define WaitForFrameStart 1
#define LengthHighByte 2
#define LengthLowByte 3
#define PayloadCapture 4
#define CheckChecksum 5
int framestatus = WaitForFrameStart;
int datalength = 0;
int savedDataLength;
char buf[100];
char *payloadbuffer;
char inputbuf[50], constructed[50];
char* bufptr = inputbuf;
int count = 0;
void loop() // run over and over again
{
if(Serial.available()){
switch (Serial.read()){
case '1':
sendATcommand(ATSC, sizeof(ATSC));
break;
case '2':
sendATcommand(ATID, sizeof(ATID));
break;
case '3':
sendATcommand(ATOP, sizeof(ATOP));
break;
case '4':
sendATcommand(ATII, sizeof(ATII));
break;
case '5':
sendATcommand(ATZS, sizeof(ATZS));
break;
case '6':
sendATcommand(ATND, sizeof(ATND));
break;
case '7':
sendATcommand(TX, sizeof(TX));
break;
default:
break;
}
Serial.flush();
}
if(millis() % 10000 == 0)
sendATcommand(TX, sizeof(TX));
checkXbee();
}
void checkXbee(){
if (xbeeSerial.available()) {
received = (uint8_t)xbeeSerial.read();
switch( framestatus ){
case WaitForFrameStart:
if(received != 0x7E)
break;
else {
framestatus = LengthHighByte;
// Serial.print("Frame start, ");
checksum = 0;
payloadbuffer = buf;
}
break;
case LengthHighByte:
datalength = received;
framestatus = LengthLowByte;
break;
case LengthLowByte:
datalength = (datalength * 256) + received;
savedDataLength = datalength;
Serial.print("length ");
Serial.print(datalength);
Serial.print(", ");
framestatus = PayloadCapture;
break;
case PayloadCapture:
*payloadbuffer++ = received;
printByteData(received);
Serial.print(" ");
datalength--;
checksum += received;
if (datalength == 0){
framestatus = CheckChecksum;
*payloadbuffer = '\0';
Serial.print("received, ");
}
break;
case CheckChecksum:
checksum += received;
if (checksum == 0xFF){
Serial.println("Checksum valid.");
xbeeFrameDecode(buf, savedDataLength);
}
else {
Serial.println("Checksum invalid.");
}
framestatus = WaitForFrameStart;
break;
default:
break;
}
}
}
void xbeeFrameDecode(char* buffer, int length){
switch ( *buffer){
case 0x90: {
Serial.println("Receive Data Frame");
buffer++; //skip over the frame type
length--;
Serial.print("Source 64 bit address: ");
for(int i=0; i<8; i++){ //address the frame came from
printByteData(*buffer);
if (i == 3)
Serial.print(" ");
buffer++;
length--;
}
Serial.println();
Serial.print("Source 16 bit network address: ");
for(int i=0; i<2; i++){ //16 bit network address the frame came from
printByteData(*buffer);
buffer++;
length--;
}
Serial.println();
Serial.print("Receive options: "); // options byte
printByteData(*buffer);
Serial.println();
buffer++;
length--;
while(length-- > 0){ //assuming the actual data is ascii
Serial.print(*buffer++);
}
break;
}
case 0x88:{
Serial.println("AT Command Response Frame");
break;
}
case 0x8B: {
Serial.println("Transmit Status Frame");
break;
}
default: {
Serial.println("Unimplemented Frame Type");
break;
}
}
}
void printByteData(uint8_t Byte){
Serial.print((uint8_t)Byte >> 4, HEX);
Serial.print((uint8_t)Byte & 0x0f, HEX);
}
SoftwareSerial xbeeSerial = SoftwareSerial(3, 2);
/*
at commands begin with a frame delimiter
then the length in two bites
the hex number 8 (meaning AT command
the number 1 meaning I want a response back
the command to be executed
any parameters to the command
a checksum
*/
// The command and parameters are here
char ATND[]={
0x08, 0x01, 'N', 'D'}; //node discover
char ATID[]={
0x08, 0x01, 'I', 'D', 0x12, 0x34}; // Pan id to use
char ATOP[]={
0x08, 0x01, 'O', 'P'}; //read operating pan id
char ATII[]={
0x08, 0x01, 'I', 'I', 0x17, 0xE8}; // Initial 16 bit PAN ID
char ATSC[]={
0x08, 0x01, 'S', 'C', 0x02}; //only allow chanel 0x0C
char ATZS[]={
0x08, 0x01, 'Z', 'S', 0x00}; //zigbee addressing type 0
char TX[]={0x10, 0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, // 64 bit hardware address
0x88,0x0c, // network address
0x00,0x00, // broadcast radius and options
'A',}; // finally, the actual data
char cmdbuf [100];
unsigned int cmdlen;
byte checksum;
void sendATcommand(char* command, int length){
// first calculate the length and fill it in
checksum = 0;
cmdbuf[0] = 0x7E; //command start signal
cmdlen = length; //the command characters & overhead
cmdbuf[1] = cmdlen >> 8;
cmdbuf[2] = cmdlen & 0xFF;
//copy command string into buffer
int i = 0;
for ( ; i < length; i++){
cmdbuf[i + 3] = command[i];
checksum += command[i];
}
cmdbuf[i+3] = 0xFF - checksum;
Serial.print("Packet sent ");
for (i=0; i < cmdlen + 4; i++){
printByteData(cmdbuf[i]);
Serial.print(" ");
}
Serial.println();
for(i=0; i < cmdlen+4; i++){
xbeeSerial.print(cmdbuf[i]);
}
}
void setup() {
Serial.begin(9600);
// set the data rate for the SoftwareSerial port
xbeeSerial.begin(9600);
Serial.println("Serial ports initialized");
}
uint8_t received;
#define WaitForFrameStart 1
#define LengthHighByte 2
#define LengthLowByte 3
#define PayloadCapture 4
#define CheckChecksum 5
int framestatus = WaitForFrameStart;
int datalength = 0;
int savedDataLength;
char buf[100];
char *payloadbuffer;
char inputbuf[50], constructed[50];
char* bufptr = inputbuf;
int count = 0;
void loop() // run over and over again
{
if(Serial.available()){
switch (Serial.read()){
case '1':
sendATcommand(ATSC, sizeof(ATSC));
break;
case '2':
sendATcommand(ATID, sizeof(ATID));
break;
case '3':
sendATcommand(ATOP, sizeof(ATOP));
break;
case '4':
sendATcommand(ATII, sizeof(ATII));
break;
case '5':
sendATcommand(ATZS, sizeof(ATZS));
break;
case '6':
sendATcommand(ATND, sizeof(ATND));
break;
case '7':
sendATcommand(TX, sizeof(TX));
break;
default:
break;
}
Serial.flush();
}
if(millis() % 10000 == 0)
sendATcommand(TX, sizeof(TX));
checkXbee();
}
void checkXbee(){
if (xbeeSerial.available()) {
received = (uint8_t)xbeeSerial.read();
switch( framestatus ){
case WaitForFrameStart:
if(received != 0x7E)
break;
else {
framestatus = LengthHighByte;
// Serial.print("Frame start, ");
checksum = 0;
payloadbuffer = buf;
}
break;
case LengthHighByte:
datalength = received;
framestatus = LengthLowByte;
break;
case LengthLowByte:
datalength = (datalength * 256) + received;
savedDataLength = datalength;
Serial.print("length ");
Serial.print(datalength);
Serial.print(", ");
framestatus = PayloadCapture;
break;
case PayloadCapture:
*payloadbuffer++ = received;
printByteData(received);
Serial.print(" ");
datalength--;
checksum += received;
if (datalength == 0){
framestatus = CheckChecksum;
*payloadbuffer = '\0';
Serial.print("received, ");
}
break;
case CheckChecksum:
checksum += received;
if (checksum == 0xFF){
Serial.println("Checksum valid.");
xbeeFrameDecode(buf, savedDataLength);
}
else {
Serial.println("Checksum invalid.");
}
framestatus = WaitForFrameStart;
break;
default:
break;
}
}
}
void xbeeFrameDecode(char* buffer, int length){
switch ( *buffer){
case 0x90: {
Serial.println("Receive Data Frame");
buffer++; //skip over the frame type
length--;
Serial.print("Source 64 bit address: ");
for(int i=0; i<8; i++){ //address the frame came from
printByteData(*buffer);
if (i == 3)
Serial.print(" ");
buffer++;
length--;
}
Serial.println();
Serial.print("Source 16 bit network address: ");
for(int i=0; i<2; i++){ //16 bit network address the frame came from
printByteData(*buffer);
buffer++;
length--;
}
Serial.println();
Serial.print("Receive options: "); // options byte
printByteData(*buffer);
Serial.println();
buffer++;
length--;
while(length-- > 0){ //assuming the actual data is ascii
Serial.print(*buffer++);
}
break;
}
case 0x88:{
Serial.println("AT Command Response Frame");
break;
}
case 0x8B: {
Serial.println("Transmit Status Frame");
break;
}
default: {
Serial.println("Unimplemented Frame Type");
break;
}
}
}
void printByteData(uint8_t Byte){
Serial.print((uint8_t)Byte >> 4, HEX);
Serial.print((uint8_t)Byte & 0x0f, HEX);
}
There's a confusing paragraph in the Digi documentation for the Series 2 devices. Around page 99 under the description for the two API modes they say:
Escape characters. When sending or receiving a UART data frame, specific data values must be escaped
(flagged) so they do not interfere with the data frame sequencing. To escape an interfering data byte,
insert 0x7D and follow it with the byte to be escaped XOR’d with 0x20
Most people read this as requiring both API modes to escape the special characters. Not true. You only have to escape the special characters if you're using API mode 2. This is to allow the XON and XOFF ascii codes to be used for flow control. I haven't tried flow control with an XBee yet, so I don't know if it will work. So, using API mode 1 will allow all the features and you don't have to worry about escaping the special characters.
One other thing that isn't made clear in the documentation or any of the how-to guides I've looked at. You can mix and match API mode and transparent mode on these devices. For example the XBee I use to monitor what is going on is configured for transparent mode and it can see the broadcast sentences from every device broadcasting just fine. The packet headers and such are stripped off and the data is delivered out the serial line. This is a nice way to see what is going on over your network.
Additionally, you can mix API modes. A device using API mode 1 can talk to another device running API mode 2 just fine. So, however you have a device set up in terms of the API mode, it can talk to the other devices on your network. This is nice if you're updating your network and have some devices in mode 1, others in transparent and yet others in API mode 2. This is actually the state of my network right now (Feb 11, 2013) because I'm updating to use the Arduino XBee library in various devices. Right this second, the Pool Controller <link> is using transparent mode; the Acid Pump is using API mode 1, and the House Controller is using API mode 2. Eventually, they all will be using API mode 2 and the XBee library.
It gets hot here in the desert and I would like to know how hot it is outside, and I want to be able to do it from my recliner, under the air conditioner, sipping a beer. It would also be nice to record this somewhere and be able to point at it and brag. So, prowling around the web I found several examples of temperature sensors hooked to arduinos and a few examples of the sensors hooked directly to an XBee. Lady Ada has a great project page on the Tweet-a-Watt which is a power sensor hooked to an XBee. So, I grabbed an XBee, programmed it to send analog input from one of its pins and stuck it to the side of a 5V wall wart.
It sends an analog reading every minute to my controller which does the calculations to convert from analog voltage to temperature and serves it on a web page. The controller also sends the temperature to Pachube as a part of my set of data feeds.
No, it's not waterproof. I'll look into a proper enclosure and protecting it from sun and rain after I get a little experience with it. I have plenty of time, it doesn't rain very often and there is no morning dew. I'm more likely to have a failure because a pack rat steals it and makes it part of his nest.
One thing that was interesting is that the analog inputs on the XBee have a 1.2V maximum input and the LM34 temperature sensor has a 10mv per degree F output; that makes my maximum temperature 120F. That may not sound like much of a problem, but remember, this is Arizona. We pretty regularly have days that peak over 120F during the hottest part of the year. I used a pair of 10K resistors to divide it down so my max is 240F, that should be enough...
Let me note that setting this up was fairly easy, which means that one can have temperature sensors anywhere there is a power plug. Heck, if you're willing to change batteries, you can put one anywhere at all. That opens the possibility of placing sensors around the house to control recirculation fans for smoothing out temperatures. An outdoor sensor could use a solar charger and be maintenance free for a considerable period of time.
This device cost me around $28 to build and did not require a microprocessor at the sensor end. I send everything to a device I already have and it puts the data on the network. I could add another device somewhere else for the same cost. I could add another sensor, perhaps a light sensor, to the same device for less than a dollar.
In the graph above you can see how the temperature spikes way up when the sun hits the wall the sensor is plugged into. This is real, and my dogs sunbathe near that spot in the morning. After the sun rises a bit the device is pretty accurate at measuring the air temperature. It will be fun to watch this over time to see what happens as the summer season passes. This graph is almost real time and reflects a day's readings.
Update, July 7, 2012: I finally carried through on my threat to build an enclosure for this device and put it into permanent operation. It is working all the time now measuring the outside temperature. This makes the graph above accurate for local temperature and trends. The description of what I did is here <link>.
Update, July 7, 2012: I finally carried through on my threat to build an enclosure for this device and put it into permanent operation. It is working all the time now measuring the outside temperature. This makes the graph above accurate for local temperature and trends. The description of what I did is here <link>.
Awesome! I am trying to do something similar by creating a home temperature station containing both wired and wireless temperature sensors (with Xbee).
ReplyDeleteI am using an Arduino with Ethernet shield to upload data to Nimbits and a google doc so I have the data logging and accessible from anywhere.
Don't you just love these little XBees? I've never looked at Nimbits, I'll have to check it out soon.
ReplyDeleteI do like the simplicity of your creation, Make sense to use the Xbee I/O's instead of a uC. Judging by the pic you posted and the Pachube log as well. I see you reach over 150 Degrees regularly. In my opinion I would not have the sensor mounted to the outside wall so closely. If the wall is in direct sunlight, it will start to collect and radiate heat from the sun. making your sensor reading in-accurate. Still very simple and sweet.
ReplyDeleteBest Regards-
Yes, it's too darn close to the wall. And, the sensor is too darn close to the power supply. So I actually have two problems going on. I'm going to build one of those weather station enclosures and get the sensor away from the house and in the shade all day. Just have to get the time and inclination to continue on this project.
ReplyDeleteIt is nice being able to read the temperature any place in the house though.
Nice, can you post more details about how you attached the Lm34 to the xbee?
ReplyDeletemaybe this is useful for you, im using for a similar idea this kits
http://www.seeedstudio.com/depot/wireless-sensor-node-solar-kit-p-919.html?cPath=138
fairly unexpensive and work!
I would post a picture, but ever since I tucked the device inside an enclosure outside on a fence post, it's hard to get to. Basically though, I just hooked one end to power, the other to ground and the sensor output to a voltage divider of two 10K resistors. I took the XBee input from the center of the voltage divider.
ReplyDeleteI described the outdoor enclosure here: http://www.desert-home.com/2012/07/outdoor-temperature.html and there is a picture there that sort of shows the temperature sensor....sort of. Ah heck, I'll get a screwdriver and open it up and get a picture of the way I did it; other people have asked. It's not pretty because I didn't think I'd keep the device. However, it worked so darn well that I couldn't resist putting it out where it could do some real readings.
Regarding your device, THAT IS SO COOL!! Tell me though, how did you set up the charger for the LIPO; is there a schematic.
I like the box, but putting the sensor inside the box presents a problem for getting measurements in my area. The box will tend to concentrate the heat and the sensor will read the wrong values. I'd have to move the sensor outside and create some other kind of enclosure to handle it. This kind of thing would be great for sensing soil moisture, or something like that. Even relay control could be done to some degree if one were to use a latching relay to keep the power usage down. In my particular area, solar cells don't last very long unless they have actual glass covering the sensors. The extreme UV of my area will bake the other materials to a mostly opaque yellow over about a year and the cell quits working. Solar yard lights don't work long.
Don't misunderstand, I think your device is really, really nice, but it would be really cool if there were provisions for putting the sensor (whatever kind one happens to use) outside the box. You could use the extra space to provide some solder pads to put voltage dividers, op amps, or whatever the user needs to adapt the signal to their needs. Then people like me could get a bird house, put the board inside, mount the solar cell on the roof and the sensor to the bottom in the air and shade to have a cool decorative sensor hanging from a tree limb in the yard.
I also noticed that there were people that wanted code to use the device. When I get one, I'll put together an example of how to read one. But, only for series 2 XBees. My home network is exclusively series 2 because I wanted the built in store forward for remote devices.
So, later today I'll get a picture and put it on this page as an edit; look for it in the text above somewhere. Then, I'll order one of the devices and wait patiently (sigh) for it to arrive to try it out. Expect a blog posting to describe how it worked out for me.
The charger is a CN3063 so it automatically takes care of the LiPo, Solar Charger or USB source. Since the Xbee carrier (think of it as a motherboard) has already a couple of empty connectors its very easy to use one of them for the LM3x sensor, and if you need to stick it out the box well, that is nothing a dremmel can not solve! :)
DeleteWiki page for it:
http://www.seeedstudio.com/wiki/Grove_-_XBee_Carrier#Charging
thanks for the extra pics
OK, pictures are in place. Take a look at http://www.desert-home.com/2013/02/outdoor-temperature-part-3.html . I'm actually glad you talked me into this because now I can just point to a web page to show how I did it when people ask.
ReplyDeleteThis site is awesome!! I am so thankful David took the time to create this site. I tried for over a month to get Xbees to communicate in API mode and all attempts failed until I found this site. Even there I I ran to a snag. The program would transmit to the coordinator but as soon s I entered a destination address communications failed. The secret to solving this problem is to set API mode to 2.
ReplyDeleteThank you. Actually, I should make a bigger deal about the API mode in the various places because it is real annoying to have to find it the way you did.
ReplyDeleteFirst and foremost thank you! These tutorials are by far the most helpful I've found so far regarding xbee use. I noticed you said that API and transparent mode can be used in one network. I have my sensor in AT mode to send direct I/O data to the coordinator which is in API mode 2. However I would like to send a packet of rf data from coordinator to sensor and pass it directly into a serial.lcd. From what I've read any data coming into sensor is just relayed to DOUT. Is this correct and does the data coming out of DOUT include the API frame data or just the RF data packed into it?
ReplyDeleteAPI mode and AT mode are between the XBee and its attached serial device. What actually travel over RF is different and much more complex, so you should be able to do exactly what you want. Hand something from your program to the API mode 2 coordinator formatted into a frame with the start sentinel all the way to the checksum and have the data pop out the other end as just data with the frame removed.
ReplyDeleteHowever, direct I/O is not supposed to work in AT mode. Around page 95 of the XBee pro user's guide they say that direct I/O is only implemented in API mode. So, if you're using XBee direct I/O as in sending the state of the XBee digital pin 1 back to the coordinator, I don't see how you're getting it to work now. On the other hand, if you have a sensor attached to Data In and it's sending ascii data back to the coordinator and you want to hook a display up to Data Out, that could work.
If you only have the two devices, you probably won't get any trouble out of using transparent mode, but in some cases where the data rate is fairly large, you may get pauses and strange behavior because of the data being shaped into packets for transmission. That's why streaming data is impractical on an XBee.
Hi Dave - do you have any more info on how you connected up the thermostat/thermocouple to the XBee (schematics, instructions, code etc)?
ReplyDeleteNo, I don't. However, there are examples out there already. This guy did one http://nootropicdesign.com/projectlab/2009/11/01/wireless-temperature-sensor/ . He went the hard way by doing the entire thing, display and all. Basically the only difference between his sensor and mine is that I had to use a voltage divider between the sensor and the XBee because it gets too hot here. If you google for XBee temperature, you'll turn up several others. When you look at his schematic of the XBee, you'll see how simple it actually is.
ReplyDeleteSomeday, I'm going to add humidity, and light sensors to this little thing and that will probably require a schematic.
Dave, firstly sensational blog. The information is truly inspiring.
ReplyDeleteI am just starting to look at energy monitoring and control around my house and I need to make a decision about the type of radios I will use. Why did you choose the XBee Series 1 as apposed to rfm12b's (say) which are used extensively in the Open Energy Monitor community. I want to make a solid decision on this because it seems like the further you go down one radio path the more committed you are (and possibly more you regret).
Thanks
Mitch
OK, truth time. I started with XBees because I wanted to do as little work as possible to get them going. I chose Series 2, NOTICE that I use series 2 not series 1, because they were the most recently developed and would be maintained the longest. Then, I found out that they work incredibly well.
DeleteI know, you look on the web and there is example after example of the little devices screwing up. People not being able to configure them, get them to talk to each other, transmissions dropping out, etc. I just don't have that problem with the 12 I have running in my network. Yes, 12 of them chattering away doing whatever I tell them to do.
The biggest thing in their favor is that they have networking built right into them. You have two of them and want a third, but it's too far away from the controller ... simple set them up such that there is one in the middle that can forward the data. Get several of them around the house and communication between them is 100% with no additional code that I have to write. They automatically check for receipt and resend if necessary, route around a device that quits because I knocked the plug out. They just don't seem to fail. I'm still using the first one I ever bought, it's my controller up in the attic that I seldom see.
They cost more than the 2 buck devices, but save me hours and hours of headaches troubleshooting RF problems. I save on costs by adapting them myself. I have one that is just hooked to a wall wart measuring temperature outside. That would have cost me a processor as well if I used anything else.
There are lots of folk that use the little cheap radios, and I can't blame them for it. They work just fine for many people. I wanted something that I could use and didn't have to think about, I wanted it to do the retries on its own, not have to write code to do it myself.
I am working with XBee-PRO ZBs & I am able to make a coordinator & endpoints talk through XCTU, but when I connect the endpoint to a circuit, my xbee usb adapter doesn't get a lock. Both endpoints & coordinator are in AT mode. What am I doing wrong? I ran a voltmeter across the Vcc & Gnd pins & they are both getting juice. So what's going? Can someone please explain?
ReplyDeleteI don't want to make a bunch of assumptions and lead you the wrong way. When you have them talking, how are they connected? Do you have multiple USB adapters hooked into a laptop, have them wired up to something else, etc. What do you mean by lock? I need a little more information to make a suggestion.
DeleteHowever, the XBee Pro line is notorious for sucking power during transmission. Many wall wart power supplies just can't give them enough to transmit well. You may need to carefully watch the voltage going in while the XBee is transmitting. I've seen those little jewels suck a wall wart down to the point where they just shut off. Notice, this is ONLY during the period where it is transmitting; all the rest of the time it looks fine.
Dave,
DeleteGreat blog you have here. I stumbled upon it while researching XBee. Oddly enough, I am working on my own home automation system and had recently gotten my system to run using a raspberry pi shortly before catching your blog.
One thing I am stuck on, is the packet declaration within the data of the xbee transactions themselves. Do you have any suggestions or examples of what you are sticking within the "data" of an xbee transmit packet, for instance, that allows for scalability and expansion into data packets that you don't even know exist yet?
-Jeff
Jeff: Most of the stuff I do with XBees is of my own creation. That means I can do anything I want to. So, I took the tactic of straight text between the devices and their supporting processor. For example, I send something on the order of "device, on" to turn it on. The device will respond, "device, thingon" Simple text is the key.
DeleteThings that send status send text back to the controller as well, "garage,door1 open" is an example of that kind of thing. Needless to say, it's a bit incoherent from one device to another. I developed different techniques of encoding and decoding the text over time and each device is different in some fashion. With the incredible capabilities of python on the Raspberry Pi, I may go back to each device and change it to a common method.
It would be nice to have longer more involved strings as the command and status, "garage, water heater is on, door 1 is closed, door 2 is closed" That kind of thing. See, originally, I was developing for an Arduino to receive everything and it was much harder to take text apart; now it's really easy.
The nice thing about text is that it can be infinitely expanded to fit whatever I want. "Garage, raise the lift 12 inches" would be an example (if I ever get a lift). Additionally, when I sniff the network to chase problems, I can read what is being transmitted. This cuts debug time down a lot. Fancy packets with bits and flags and stuff just isn't necessary any more. Heck, take a look at HTML, it's all text.
You bring up the good point of debugging. It'd be a lot easier to see some human readable text vs. bytes that you'd have to look up to troubleshoot anything. In reality, there's not enough data being passed around that 9600 baud can't easily handle it anyways. I'll have to thinka bout this topic some more :-)
DeleteAnd the Arduino and XBee are capable of getting higher baud rates if you need them. I have a couple that go 57.6K
DeleteThis comment has been removed by the author.
ReplyDeleteHow exactly the broadcast mode will work?
ReplyDeleteSuppose I have 2 hop network. 1---2---3. 1 will broadcast the message and 2 will receive it. Can node 3 receive that broadcast message (sent by node 1 via node 2)?? Can node 2 will automatically broadcast that message again or we need to perform any extra operations??
Because transmit status response in broadcast mode will be received in 1.6 second where as in unicast mode I got response withing 200 ms