Library to easily communicate with XBee modules.

Dependencies:   DigiLogger

Dependents:   WaterLogger XbeeGateway XBee_Cooker ProjetReceiver ... more

Handling remote modules DIOs ADCs and PW

Digi XBee modules have pins that can be configured to perform as a digital output or input (DIO), as an analog input (ADC) or as an analog output (PWM).
This mbed library offer functionality to manage those pins on Remote Devices (the local device would typically use the mbed microcontroller). This is achieved by sending RF messages to the remote radio from the local radio attached to the mbed processor.

Information

There is no API for setting local device's DIOs/ADCs. In case you need it, it can be done by setting local parameters (See Configuring local and remote modules chapter) accordingly to specifications in the product manual.

Available methods

XBee ClassMethodDescriptionParameters
XBee802 XBeeZB XBeeDMRadioStatus set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode)Configures a remote device pin for the desired functionality: Digital Input, Digital Output, ADC or PWM. This step is required before calling the other methodsremote: remote device.
line: IO line being configured.
mode: configuration mode for the selected line.
RadioStatus get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode)Gets the current configuration of a remote device's pinremote: remote device.
line: IO line being read to get its configuration.
mode: pointer where the configuration read will be stored.
RadioStatus set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable)Enables or disables the internal pull-up resistor of a remote device's pin.remote: remote device.
line: IO line being configured.
enable: enable or not internal pull-up
RadioStatus enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable);Enables or disables sending an IO Sample when a digital input changes its value (See Handling IO Data Samples from remote modules).remote: remote device.
line: IO line being configured.
enable: enable or not change detection.
RadioStatus set_dio(const RemoteXBee& remote, IoLine line, DioVal val)Sets the value of a Digital Output to High or Lowremote: remote device.
line: DIO line being set.
val: value that will be set in the DIO line: DIO_LOW or DIO_HIGH
RadioStatus get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)Gets the value of a Digital Inputremote: remote device.
line: DIO line being read.
val: pointer where the DIO value read will be stored. DIO_LOW or DIO_HIGH.
RadioStatus get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)Gets the value of an ADCremote: remote device.
line: ADC line being read.
val: pointer where the value read from the ADC will be stored.
XBee802 XBeeDMRadioStatus set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle)Sets the value (duty cycle) of a PWMremote: remote device.
line: PWM line being set.
duty_cycle: duty cycle that will be set in the PWM line.
RadioStatus get_pwm(const RemoteXBee& remote, IoLine line, float * const duty_cycle)Gets the value (duty cycle) of a PWMremote: remote device.
line: PWM line being read.
duty_cycle: pointer where the value of the duty cycle read from the PWM will be stored.

Getting an IO Sample

The previous get_dio() and get_adc() methods will send one message to the remote node and wait for its response every time they are used. When it comes to reading more than one DIO or ADC of the same remote node, it is better to use the get_iosample() method. This method returns the same object that is passed to the IO Data Samples callbacks, querying all DIOs and ADCs in a single transaction, reducing the network traffic and guaranteeing that all lines are sampled at exactly the same time.

XBee ClassMethodDescriptionParameters
XBee802IOSample802 get_iosample(const RemoteXBee& remote)Retrieves an IO Sample from a remote node, so it can be used to get the remote node's ADC and DIO valuesremote: remote device.
XBeeZBIOSampleZB get_iosample(const RemoteXBee& remote)Retrieves an IO Sample from a remote node, so it can be used to get the remote node's ADC and DIO valuesremote: remote device.
XBeeDMIOSampleDM get_iosample(const RemoteXBee& remote)Retrieves an IO Sample from a remote node, so it can be used to get the remote node's ADC and DIO valuesremote: remote device.

ZigBee

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
 
void main()
{
	 XBeeZB xbee = XBeeZB(RADIO_TX, RADIO_RX, RADIO_RESET);
	[...]
	IOSampleZB iosample = xbee.get_iosample(RemoteXBeeZB(0x0013A200AABBCCDD));
 
	RadioStatus radioStatus;
        DioVal dio2;
        radioStatus = sample_data.get_dio(XBeeZB::DIO2_AD2, &dio2);
	[...]
	DioVal dio3;
        radioStatus = sample_data.get_dio(XBeeZB::DIO3_AD3, &dio3);
}

802.15.4

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
 
void main()
{
	 XBee802 xbee = XBee802(RADIO_TX, RADIO_RX, RADIO_RESET);
	[...]
	IOSample802 iosample = xbee.get_iosample(RemoteXBee802(0x0013A200AABBCCDD));
 
	RadioStatus radioStatus;
	DioVal dio0;
        radioStatus = sample_data.get_dio(XBee802::DIO0_AD0, &dio3);
	[...]
        DioVal dio2;
        radioStatus = sample_data.get_dio(XBee802::DIO2_AD2, &dio2);
}

XBeeDM

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
 
void main()
{
	 XBeeDM xbee = XBeeDM(RADIO_TX, RADIO_RX, RADIO_RESET);
	[...]
	IOSampleDM iosample = xbee.get_iosample(RemoteXBeeDM(0x0013A200AABBCCDD));
 
	RadioStatus radioStatus;
	DioVal dio0;
        radioStatus = sample_data.get_dio(XBeeDM::DIO0_AD0, &dio3);
	[...]
        DioVal dio2;
        radioStatus = sample_data.get_dio(XBeeDM::DIO2_AD2, &dio2);
}

The same functionality is offered for all modules, although the pin (IoLine) names and functionality available on those pins are different:

Line parameter

XBee devicePinDigital InputDigital OutputADCPWM
ZigBeeDIO0_AD0YesYesYes
DIO1_AD1YesYesYes
DIO2_AD2YesYesYes
DIO3_AD3YesYesYes
DIO4YesYes
DIO5YesYes
DIO6YesYes
DIO7YesYes
DIO10YesYes
DIO11YesYes
DIO12YesYes
SUPPLY_VOLTAGE*Yes
802.15.4DIO0_AD0YesYesYes
DIO1_AD1YesYesYes
DIO2_AD2YesYesYes
DIO3_AD3YesYesYes
DIO4_AD4YesYesYes
DIO5_AD5YesYesYes
DIO6YesYes
DIO7YesYes
DI8Yes
PWM0Yes
PWM1Yes
DigiMeshDIO0_AD0YesYesYes
DIO1_AD1YesYesYes
DIO2_AD2YesYesYes
DIO3_AD3YesYesYes
DIO4YesYes
DIO5YesYes
DIO6YesYes
DIO7YesYes
DIO8YesYes
DIO9YesYes
DIO10_PWM0YesYesYes
DIO11_PWM1YesYesYes
DIO12YesYes

Information

  • SUPPLY_VOLTAGE is not a real pin. Its ADC value can be queried to get the remote module supply voltage if enabled. See V+ AT command for more information.

Mode parameter

IoMode enum used in set_pin_config() and get_pin_config()methods can take following values: Disabled, SpecialFunc, Adc, Pwm, DigitalInput, DigitalOutLow and DigitalOutHigh.

DIO value parameter

DioVal enum used in set_dio() and get_dio() methods can take following values: DIO_LOW and DIO_HIGH.

ADC value parameter

get_adc() method takes an uint16_t as value argument. The value stored in val represent the analog value of the pin ranging from 0 to 0x3FF.

PWM value parameter

set_pwm() and get_remote_pwm() methods take a float as duty_cycle argument ranging from 0.0 to 100.0.

Examples

To simplify the examples and make them independent of the hardware and the XBee variant, the following pins are used in this examples set:

LinePinValue
DIO2/ADC218ADC (Analog Input)
DIO3/ADC317Digital Input
RSSI/DIO106PWM (Analog Output)
DIO411Digital Output

/media/uploads/hbujanda/dio_adc_schem.png

Information

All the examples that use Digital IOs and ADC/PWM use the specified pins.


The first step for each example is to create the local and the remote devices. They can be either ZigBee, 802.15.4 or DigiMesh devices:

#include "XBeeLib.h"
  
using namespace XBeeLib;
 
void main()
{
     [...]
      
     XBeeZB xbee = XBeeZB(RADIO_TX, RADIO_RX, RADIO_RESET);
     xbee.init();
 
     RemoteXBeeZB remoteDevice = RemoteXBeeZB(0x0013A200AABBCCDD);
  
     [...]
}

Setting the value of a Digital Output

This example toggles the DIO4 pin every 5 seconds. If a led is connected to this pin as shown in the schematic, it should blink every 5 seconds.

Information

It's not necessary to call set_pin_config() method to use set_remote_dio() method.

[...]
 
while(true) {
    static bool led_on = false;
     
    if (led_on) {
        radioStatus = xbee.set_dio(remoteDevice, XBeeZB::DIO4, DIO_LOW);
    } else {
        radioStatus = xbee.set_dio(remoteDevice, XBeeZB::DIO4, DIO_HIGH);
    }
     
    MBED_ASSERT(radioStatus == Success);
     
    led_on = !led_on;
     
    wait(5);
}
 
[...]

Getting the value of a Digital Input

This example samples the digital value of DIO3_AD3 pin every 5 seconds. If this pin is connected to a push button as shown in the schematic, the application should report "DIO3 value = 0" if the button is pressed and "DIO3 value = 1" otherwise.

[...]
 
radioStatus = xbee.set_pin_config(remoteDevice, XBeeZB::DIO3_AD3, DigitalInput);
MBED_ASSERT(radioStatus == Success);   
 
while(true) {
    DioVal dio3_val;
     
    radioStatus = xbee.get_dio(remoteDevice, XBeeZB::DIO3_AD3, &dio3_val);
     
    MBED_ASSERT(radioStatus == Success);
     
    log_serial->printf("DIO3 value = %d\r\n", dio3_val);
     
    wait(5);
}
 
[...]

Getting the value of an ADC

This example samples the analog value of DIO2_AD2 pin every 5 seconds. If this pin is connected to a variable resistor as shown in the schematic, the application should report its value ranging from 0x0 to 0x3FF.

[...]
 
radioStatus = xbee.set_pin_config(remoteDevice, XBeeZB::DIO2_AD2, Adc);
MBED_ASSERT(radioStatus == Success);
 
while(true) {
    uint16_t adc2_val;
     
    radioStatus = xbee.get_adc(remoteDevice, XBee802::DIO2_AD2, &adc2_val);
     
    MBED_ASSERT(radioStatus == Success);
     
    log_serial->printf("ADC2 value = 0x%04x\r\n", adc2_val);
     
    wait(5);
}
 
[...]

Setting the value (duty cycle) of a PWM

This example changes the analog value of PWM0 pin. The application walks through 0.0, 50.0, 70.0 and 100.0 values every 5 seconds. If a led is connected to the PWM0 pin as shown in the schematic, it should change the intensity accordingly.

[...]
 
radioStatus = xbee.set_pin_config(remoteDevice, XBee802::PWM0, Pwm);
MBED_ASSERT(radioStatus == Success);
 
while(true) {
    static float pwm2_val_list[] = { 0.0, 50.0, 70.0, 100.0 };
    static uint8_t pwm2_val_idx = 0;
 
    log_serial->printf("Setting PWM0 to = %f\r\n", pwm2_val_list[pwm2_val_idx]);
 
    radioStatus = xbee.set_pwm(remoteDevice, XBee802::PWM0, pwm2_val_list[pwm2_val_idx]);
 
    MBED_ASSERT(radioStatus == Success);
 
    pwm2_val_idx++;
    if (pwm2_val_idx == sizeof(pwm2_val_list)/sizeof(pwm2_val_list[0])) {
        pwm2_val_idx = 0;
    }
     
    wait(5);
}
 
[...]


Here is a ready to use example:

For ZigBee modules:

Import programXBeeZB_dio_adc

ZigBee DIOs and ADCs example for mbed XBeeLib By Digi

For 802.15.4 modules:

Import programXBee802_dio_adc_pwm

802.15.4 DIOs, ADCs and PWM example for mbed XBeeLib By Digi

For DigiMesh modules:

Import programXBeeDM_dio_adc_pwm

DigiMEsh DIOs, ADCs and PWMs example for mbed XBeeLib By Digi