Wiblocks --- ZB1 XBee Receive

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);
}