Xbee sleep mode question

So I have a copy of Wireless Sensor Networks and using knowledge gained from that book, I have successfully created a working Xbee series 2 network.

I have one Xbee connected to an Arduino Leonardo and configured as a coordinator. I have a second Xbee on a breadboard configured as an endpoint. It has a switch connected to D0 and is configured to send that switch state to the coordinator.

The Leonardo has a program listening for packets and decodes the D0 pin state and toggles an LED to follow the button press. Push the momentary button and the LED comes on, release and it goes off. So far so good.

What I want, however, is for the endpoint to have one button and do the same thing, except I want it to sleep between button presses. That is I want the button to wake it and send the data. Thing "garage door opener" with the Xbee and a battery and a switch and the ability to preserve battery life.

Well, I don't really care about "the data." The data is "someone pressed the button." If someone presses the button, I need to trip a digital output from low to high for a few tenths of a second, then shut it back off. That's it. Well, I say that, but I would actually like to potentially have a few buttons that do different things, so I do care about "the data", too.

I tried putting the end point in pin wake mode and tying the same switch output to pin wake, but I get weird behavior when I do that. Which I kind of expected. I'm guessing there's a way to do what I want, it just requires some more work. Any pointers? The book seems to run out of steam here...

--Donnie

I haven't tried it, but on page 91 of the XBee ZB product manual, it says:

IO Sampling
End devices can be configured to send one or more IO samples when they wake from sleep. To enable IO sampling on an end device, the IR command must be set to a non-zero value, and at least one analog or digital IO pin must be enabled for sampling (D0 - D9, P0-P2 commands). If IO sampling is enabled, an end device sends an IO sample when it wakes and starts the ST timer. It will continue sampling at the IR rate until the sleep timer (ST) has expired. See chapter 8 for details.

Thanks, sounds like exactly what I need.

--Donnie

So I did some more poking at that document, but don't see any clues. Starting to look more like I'm going to need to use a separate button to wake it. But the only way to wake it for a time period is to add logic outside the XBee -or- do the pin and cyclic wake and then make the cycle SUPER long, so that I can set a reasonable time on the "go back to sleep" portion. Doesn't appear there's any way to keep it awake otherwise longer than the button press itself (unless I add more electronics using a timer or something, but I fear the power usage side of that since it would be powered all the time).

The separate button to wake thing isn't the end of the world, but I am surprised that there isn't more of a way to make the one button thing happen. Adding more "stuff" to the front side then becomes even more tricky if I did want additional buttons to trigger other things, too. grumble

I misread the pin-wake thing first, and thought I needed to take pin 9 high to wake it. That was perfect, since I was also just taking D0 high for my button input. So I tied that to pin 9. But then I could see that I had it backwards. Ugh. But switching them both to stay high and pull low on the button press (then inverting my output on the software side of the coordinator connected to the arduino) doesn't seem to want to send data at all. I think it's "waking" on the low signal but then since the input is low it's not sending any data because it doesn't see that as an input change at all.

--Donnie

Haven't looked into all the details, but wouldn't it just be a matter of putting the button on the sleep pin, configuring for pin sleep and cyclic sleep, then setting the sleep time (ST) to be shorter than the I/O sample rate (IR)? One I/O pin does need to be configured for sampling, but we don't care which or what its value is (probably a pullup resistor would be appropriate for minimum power consumption).

So the button should wake the module, send one I/O sample, then go back to sleep. As stated above, we don't care about "data", mere reception of the I/O sample means "the button was pushed".

Yeah, I'm seeing a little weirdness, but I think that can be made to work. But what it won't do is let me have multiple buttons, any of which would wake but would send a different signal.

So I still think the easiest thing might be a separate wake button and then a button for each command I want. The wake will be on a short timer and will have an output LED to let me know it's awake. I think that will work for a multi-button solution.

--Donnie

Ah, I missed the multiple button requirement. Of course another alternative is adding a microcontroller for more flexibility.

I don't want to add a uC to this end to save on power. It's not needed really, anyway. I feel like I'm getting in the ballpark, especially since I'm willing to live with a wake button. So here's where I am:

The end point has a wake button on pin nine that's high and pulls low when you push the button. Then there is a button on D0 and another on D1, both of which are low and pull high when you push their respective buttons. I currently have an LED on pin 13 so I can see when this end is awake.

The coordinator is plugged into an Xbee shield which is plugged into a Leonardo board. Outputs 10 and 11 are connected to LEDs and resistors. Here is the arduino code:

int LED = 11;
int LED2 = 10;
int debugLED = 13;
int input = 0;

void setup() {
    pinMode(LED,OUTPUT);
    pinMode(LED2,OUTPUT);
    pinMode(debugLED,OUTPUT);
    Serial1.begin(9600);
    digitalWrite(LED, LOW);
    digitalWrite(LED2, LOW);
  }

  
void loop() {
  if (Serial1.available() >= 19) {
    // blipblip();
    if (Serial1.read() == 0x7E) {
      digitalWrite(debugLED, HIGH);
      delay(10);
      digitalWrite(debugLED, LOW);
      // throw away most of the frame that we don't need
      for (int i = 0; i<19; i++) {
        byte discard = Serial1.read();
      }
      // read the input byte we do need
      input = Serial1.read();
    }
  }
  
  // I know the below code is bad and won't work for simultaneous button presses.  I'll fix it.
  if (input == 1) {
    digitalWrite(LED, HIGH);
  }
  if (input == 0) {
    digitalWrite(LED, LOW);
    digitalWrite(LED2, LOW);
  }
  if (input == 2) {
    digitalWrite(LED2, HIGH);
  }
}

The coordinator has almost no interesting configuration in XCTU. The end point, however, has the interesting bits. The addressing is obviously correct and working, so the rest that's interesting is:

SM = 5
ST = 2000
SP = 0xAF0
D0 = 3
D1 = 3
IR = 32

And it works!!! Almost. It works MOST of the time. As you can see from the code, there's some debugLED flashing happening when frames are being read. Sometimes when I press wake, I see frames (via LED flashing) nearly instantly. Sometimes there's a half second or so delay. Sometimes I never see frames. Usually when it wakes on its own (every 28 seconds right now), there are no frames. If there are, there's almost always a delay. Sometimes frames happen instantaneously. (But, FWIW, I really don't care about the case where it wakes up on its own. The plan is to extend that to near infinity.) So my worry is this delay and sometimes not happening of frames getting sent. Any clue why that would happen?

Once frames are sending, my button pushes on D0 and D1 do their thing and light up the corresponding LEDs on the output of the Leonardo. But if no frames are getting sent, button pushes do nothing. Obviously I've only got a couple seconds to get my button presses done, which is fine. So most of the time it works. Sometimes no frames are going out. Pretty sure it's the sending end that isn't doing its thing, as when frames are going, I can see the wake LED kinda brighten and dim, and that always corresponds to the debugLED I can see on the receive side.

--Donnie

No clue I'm afraid. The way I read it, an I/O sample should be sent immediately after waking up. Is it possible that the XBee is not really going back to sleep all the time? Not sure if that would account for the varied behavior.

If power consumption is the only concern with adding a microcontroller, I sure wouldn't worry about that. Sleeping the MCU should make its power consumption negligible. But that would be the easy way out :smiley: maybe it can be made to work with just the XBee.

What about pullups on the sleep pin, D0 and D1, buttons to ground on D0 and D1, and rather than a wake button on the sleep pin, use diodes to form an OR gate. So one diode from the sleep pin to D0 and one from the sleep pin to D1, with the anodes connected to the sleep pin. When either button is pressed, it should wake the XBee, and the I/O sample should show which button was pressed. Just thinking out loud.

Well, I'm not sure the uC wouldn't have the same data problem I'm seeing now, as that seems to be wholly on the XBee side. So I don't think that fixes this. And if the entirety of what I'm trying to do with a uC can be solved with diodes, it's REALLY overkill. That said, while I'm sure I could figure out the uC solution, my diode game would need help. The building of an OR gate out of diodes is the kind of thing I seem to have lost over the many years since that would have been taught to me in school. :slight_smile:

I'm willing to give the diode trick a try, but not until I get the wake button thing working 100%, which means finding the solution to this data dropout I'm seeing. Not sure where to best go to figure this out, but the next step will be to add LEDs to the XBee's output pins for communication. There's at least one that tells you if it's linked up with a Coordinator/Router.

As for you first question on whether it's going to sleep, well, I have an LED on the wake/sleep output, and it's going back out, so I assume it's asleep. shrug

--Donnie

See attached for an idea of what I had in mind. Most of my XBee applications have not used the XBee's I/O capability, I've maybe played with it once or twice. It seems I always have a sensor or something that the XBee isn't capable of communicating directly with. So I let the MCU do the heavy lifting to produce the data, and then the XBee just does the communication.