Tuesday, May 12, 2015

Lab 6.1: Pinging a Buzzer


The idea: by using Pythonwe read a number 'n' from the keyboard and create a random string that is made of 'n' characters, which we encapsulate in an XBee frame and send it serially to the USB connected XBee. That one in turn sends it to another XBee that is connected to an Arduino. The Arduino decapsulates the frame and plays a song based on the 'n' characters it receives.



How to do it? The project is more about software than hardware, since we are playing with how the XBee protocol and its frames. Thus, in Python we create and XBee Transmit request frame which we decapsulate in Arduino in order to make sense of the data.

Video



Schematics



Materials used

  • 1 Arduino Uno
  • 2 XBees Explorer
  • 2 XBee
  • 2 Breadboards
  • 1 Buzzer
  • 1 LED

Software needed

  • XCTU - here
  • Python - here.
  • XBee library for Python - here.
  • Pyserial library for Python - here.
  • XBee library for Arduino - here.

Steps

  1. Set one XBee to Coordinator API mode
    1. In XCTU - Set PAN ID to BBBB
    2. In XCTU - Set API Mode to 2
    3. Connect this Xbee to Arduino (Rx to Tx and Tx to Rx)
  2. Set one XBee to Router API mode
    1. In XTCU - Set PAN ID to BBBB
    2. In XCTU - Set API Mode to 2
    3. Connect this Xbee to Computer
  3. Upload Arduino code on Arduino
  4. Run Python code on computer

Code:

1.Python code

from platform import system
from xbee.zigbee import ZigBee
import random
import string
import serial
import time
from datetime import datetime

ser = serial.Serial('COM19', 9600)
xbee = ZigBee(ser, escaped=True) #needed to use Zigbee instead of XBee in order to responses to be interpreted correctly
DEST_ADDR_LONG = "\x00\x13\xA2\x00\x40\x8B\x96\x2E" #destination Zigbee 64 bit address
#discover the short 16-bit address -> faster messages
xbee.send("tx",data="\x00\x03",dest_addr_long=DEST_ADDR_LONG,dest_addr="\xff\xfe")
response = xbee.wait_read_frame()
short_addr = response["dest_addr"]

input = raw_input('Enter the number of forevernotes you want your theme to have:')
#mario song encoded for our arduino to play it
#the letter s represents a break
mario = "4s4ss4sss~s4ss7sssssIsss ~sssIsssTsssspss]sss[sPsIsss4s7s9sss5s7ss4ss~s2s]ss ~sssIsssTsssspss]sss[sPsIsss4s7s9sss5s7ss4ss~s2s]ss"


if input.isdigit():
    n = string.atoi(input)
else: n = 0

# Continuously read and print packets
i = 0
while True:
    try:
        #if your input is "mario", play it TADAAA
        if input == "mario":
            for c in mario:
                tstart = datetime.now()
                xbee.send('tx',
                          frame_id='A',
                          dest_addr_long=DEST_ADDR_LONG,
                          dest_addr=short_addr,
                          data=c)
                print c
                time.sleep(0.1)
            response = xbee.wait_read_frame()
            tend = datetime.now()
            print tend-tstart
        #otherwise continuously create a random song made of n notes and play it 5 times
        else:
            i = i + 1
            if i % 5 == 0:
                input = ''.join(random.choice("qwertyuiop[`1234567890-=zb") for _ in range(n))
            print "sending data"
                        
            for c in input:
                xbee.send('tx',
                          frame_id='A',
                          dest_addr_long=DEST_ADDR_LONG,
                          dest_addr=short_addr,
                          data=c)
                print c
                time.sleep(0.1)
        #time.sleep(2) #NO REST FOR THE WICKED
    except KeyboardInterrupt:
        break

ser.close()
2.Arduino code
/*
WSN LAB 6.1 - Zigbee API & Arduino
*/

#include <XBee.h>
// Pins
const int ledPin = 13;
const int speakerPin = 12;

// Lower octave tones
int tones[] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494};
//            mid C  C#   D    D#   E    F    F#   G    G#   A    A#   B
// Higher octave tones
int tones2[] = {523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 1047};
//               C    C#   D    D#   E    F    F#   G    G#   A    A#   B    C
char incomingChar;      // a variable to read incoming serial data into
/** XBee objects */
XBee xbee;
XBeeResponse response;
// create reusable response objects for responses we expect to handle
ZBRxResponse rx;

void setup()
{
  Serial.begin(9600);

  pinMode(ledPin, OUTPUT);
  pinMode(speakerPin, OUTPUT);

  xbee = XBee();
  response = XBeeResponse();
  rx = ZBRxResponse();
}

void loop()
{
  // This will read any data that is available:
  xbee.readPacket();
  if (xbee.getResponse().isAvailable())
  {
    if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE)
    {
      xbee.getResponse().getZBRxResponse(rx);
      Serial.println(rx.getData(0));
      digitalWrite(ledPin, HIGH); // turn the led on indicating that you received an XBee frame
      incomingChar = rx.getData(0);//convert the received data to Char
      Serial.print("Playing character:");
      Serial.println(incomingChar);

      // play a different note depending on the
      // value received from XBee:
      switch (incomingChar) {
        case 'Q':
        case 'q':
          tone(speakerPin, tones[0]);
          delay(100);
          break;
        case 'W':
        case 'w':
          tone(speakerPin, tones[1]);
          delay(100);
          break;
        case 'e':
        case 'E':
          tone(speakerPin, tones[2]);
          delay(100);
          break;
        case 'r':
        case 'R':
          tone(speakerPin, tones[3]);
          delay(100);
          break;
        case 't':
        case 'T':
          tone(speakerPin, tones[4]);
          delay(100);
          break;
        case 'y':
        case 'Y':
          tone(speakerPin, tones[5]);
          delay(100);
          break;
        case 'u':
        case 'U':
          tone(speakerPin, tones[6]);
          delay(100);
          break;
        case 'i':
        case 'I':
          tone(speakerPin, tones[7]);
          delay(100);
          break;
        case 'o':
        case 'O':
          tone(speakerPin, tones[8]);
          delay(100);
          break;
        case 'p':
        case 'P':
          tone(speakerPin, tones[9]);
          delay(100);
          break;
        case '[':
        case '{':
          tone(speakerPin, tones[10]);
          delay(100);
          break;
        case ']':
        case '}':
          tone(speakerPin, tones[11]);
          delay(100);
          break;

        case 'a':
        case 'A':
          tone(speakerPin, tones2[0]);
          delay(100);
          break;
        case 'd':
        case 'D':
          tone(speakerPin, tones2[2]);
          delay(100);
          break;
        case 'f':
        case 'F':
          tone(speakerPin, tones2[3]);
          delay(100);
          break;
        case 'g':
        case 'G':
          tone(speakerPin, tones2[4]);
          delay(100);
          break;
        case 'h':
        case 'H':
          tone(speakerPin, tones2[5]);
          delay(100);
          break;
        case 'j':
        case 'J':
          tone(speakerPin, tones2[6]);
          delay(100);
          break;
        case 'k':
        case 'K':
          tone(speakerPin, tones2[7]);
          delay(100);
          break;
        case 'l':
        case 'L':
          tone(speakerPin, tones2[8]);
          delay(100);
          break;

        case '`':
        case '~':
          tone(speakerPin, tones2[0]);
          delay(100);
          break;
        case '1':
        case '!':
          tone(speakerPin, tones2[1]);
          delay(100);
          break;
        case '2':
        case '@':
          tone(speakerPin, tones2[2]);
          delay(100);
          break;
        case '3':
        case '#':
          tone(speakerPin, tones2[3]);
          delay(100);
          break;
        case '4':
        case '$':
          tone(speakerPin, tones2[4]);
          delay(100);
          break;
        case '5':
        case '%':
          tone(speakerPin, tones2[5]);
          delay(100);
          break;
        case '6':
        case '^':
          tone(speakerPin, tones2[6]);
          delay(100);
          break;
        case '7':
        case '&':
          tone(speakerPin, tones2[7]);
          delay(100);
          break;
        case '8':
        case '*':
          tone(speakerPin, tones2[8]);
          delay(100);
          break;
        case '9':
        case '(':
          tone(speakerPin, tones2[9]);
          delay(100);
          break;
        case '0':
        case ')':
          tone(speakerPin, tones2[10]);
          delay(100);
          break;
        case '-':
        case '_':
          tone(speakerPin, tones2[11]);
          delay(100);
          break;
        case '=':
        case '+':
          tone(speakerPin, tones2[12]);
          delay(100);
          break;
      }
    }
  }
  //stop the buzzer and turn the LED off as soon as it's done processing the serial buffer
  noTone(speakerPin);
  digitalWrite(ledPin, LOW);

}

No comments:

Post a Comment