ZB1 XBee Receiver
This program configures an XBee radio via the serial port, reads
serial data from XBee and outputs the received strings to an ZB1-LCD2
LCD screen.
This program is adapted from the "XBee Analog Duplex Transmission" examples
in "Making Things Talk", O'Reilly, First Edition, Sep-2007. See pages
193-206.
This program will display data that is transmitted by the ZB1
XBee transmitter program
ZB1 XBee Receiver
/*
Adapted from the "XBee Analog Duplex Sender" program in "Making
Things Talk", O'Reilly, First Edition, Sep-2007. See pages 193-206.
This sketch configures an XBee radio via the serial port,
reads serial data from XBee and outputs the received
strings to an ZB1-LCD2 LCD screen.
(* jcl *)
*/
#include <avr/interrupt.h>
#include <avr/io.h>
#include <LCD4Bit.h>
#define OFF LOW
#define ON HIGH
// Hardware on the ZB1 board
#define STATUS_LED 7 // ZB1 (PD7)
// Hardware on the ZB1-LCD2
#define LED1 3 // D4 (PD3)
#define LED2 4 // D2 (PD4)
#define BUZZER 10 // SPKR1 (PB2)
#define LCD_BACKLIGHT 5 // Q1 (PD5)
#define BUTTON1 PC4 // S11 (PC4)
#define BUTTON2 PC5 // S12 (PC5)
// button interrupts
#define BUTTON1_INT PCINT12
#define BUTTON2_INT PCINT13
boolean volatile button1 = LOW;
boolean volatile button2 = LOW;
#define set_backlight(state) digitalWrite(LCD_BACKLIGHT, state ? HIGH : LOW)
#define set_buzzer(state) digitalWrite(BUZZER, state)
#define set_led1(state) digitalWrite(LED1, state)
#define set_led2(state) digitalWrite(LED2, state)
LCD4Bit lcd = LCD4Bit(2);
int inByte= -1; // incoming byte from serial RX
char inString[6]; // string for incoming serial data
int stringPos = 0; // string index counter
void setup() {
char *msg = "wiblock MTT XB DEMO";
// configure serial communications:
// Compensating for the 12MHz XTAL
// 12800 = (16/12) * 9600
Serial.begin(12800);
zb1_lcd2_init();
lcd.init();
lcd.clear();
lcd.printIn(msg);
blink(3);
// set XBee's destination address:
setDestination();
// blink the TX LED indicating that the main program's about to start:
blink(3);
// PCI1 will trigger if any enabled PCINT14..8 pin toggles
//
PCICR |= (1 << PCIE1);
PCMSK1 |= (1 << BUTTON1_INT);
PCMSK1 |= (1 << BUTTON2_INT);
}
void setDestination() {
long count = 0;
// put the radio in command mode:
Serial.print("+++");
// wait for the radio to respond with "OK\r"
char thisByte = 0;
while (thisByte != '\r') {
if (Serial.available() > 0) {
thisByte = Serial.read();
}
if (count++ > 100000) break;
}
if (count <= 100000) {
// set the destination address, using 16-bit addressing.
// if you're using two radios, one radio's destination
// should be the other radio's MY address, and vice versa:
Serial.print("ATDH0, DL1234\r");
// set my address using 16-bit addressing:
Serial.print("ATMY5678\r");
// set the PAN ID. If you're working in a place where many people
// are using XBees, you should set your own PAN ID distinct
// from other projects.
Serial.print("ATID1111\r");
// put the radio in data mode:
Serial.print("ATCN\r");
} else {
blink(5);
}
}
void loop() {
// listen for incoming serial data:
if (Serial.available() > 0) handleSerial();
if (button1) digitalWrite(LED1, HIGH);
else digitalWrite(LED1, LOW);
if (button2) {
digitalWrite(LED2, HIGH);
beep(200);
button2 = 0;
digitalWrite(LED2, LOW);
}
}
void handleSerial() {
inByte = Serial.read();
// save only ASCII numeric characters (ASCII 0 - 9):
if ((inByte >= '0') && (inByte <= '9')){
inString[stringPos] = inByte;
stringPos++;
}
// if you get an ASCII carriage return:
if (inByte == '\r') {
inString[5] = 0;
// output string to LCD
lcd.cursorTo(2, 0); //line=2, x=0.
lcd.printIn(inString);
// clear the string with spaces
for (int c = 0; c < 6; c++) {
inString[c] = ' ';
}
// reset the string pointer:
stringPos = 0;
}
}
void beep(int n) {
for (int i = 0; i < n; i++) {
digitalWrite(BUZZER, HIGH);
delay(1);
digitalWrite(BUZZER, LOW);
delay(1);
}
}
// Blink the status LED
void blink(int n) {
for (int i = 0; i < n; i++) {
digitalWrite(STATUS_LED, HIGH);
delay(200);
digitalWrite(STATUS_LED, LOW);
delay(200);
}
delay(1000);
}
// button1 toggles the backlight
// button2 beeps the piezo speaker
ISR( PCINT1_vect )
{
if (PINC & _BV(BUTTON1)) {
if (button1) {
button1 = 0;
set_backlight(OFF);
} else {
button1 = 1;
set_backlight(ON);
}
}
if (PINC & _BV(BUTTON2)) {
if (button2 == 0) button2 = 1;
}
}
void zb1_lcd2_init() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(STATUS_LED, OUTPUT); //we'll use the debug LED to output a heartbeat
pinMode(LCD_BACKLIGHT, OUTPUT); // backlight
pinMode(BUZZER, OUTPUT);
set_buzzer(LOW);
set_led1(OFF);
set_led2(OFF);
set_backlight(OFF);
}