Tag Archives: xbee

Arduino +RF Link Transmitter/Receiver (434MHz) + ZUMO shield

A few months ago I create some tutorials about how to use Arduino and the XBee to do radio-frequency.

Python + Arduino + XBee + Zumo robot

XBee 002: radio-chat between PC and Arduino

XBee 001 Basic example: radio-chat between 2 PC

Today I’m going to show you how to do it with the cheap RF link modules.

So, first of all, thanks to Coolcomponents for providing an excellent customer service (basically, even if you order one or two components, they deliver within one or two days at a very low extra cost).

transbluecoolcomplogo4Second, materials. I’m reusing 2 Arduino boards (Duemilanove with chip Atmega 328, and UNO), and the Zumo robot from previous post, plus 2 LEDs, one potentiometer, a few wires, one battery (not in the picture), a small cardboard box, and the RF modules (which I bought from Coolcomponents):

RF Link Transmitter – 434MHz

RF Link Receiver – 4800bps (434MHz)

IMAG2568

Before starting the main project, let’s do a warm up with a basic example on how to work with these RF modules.

Introduction project.

We start by naming the connectors in the RF link modules (spreadsheet for receiver / transmitter). It is good to bend the antenna pins, otherwise when using a breadboard they will be inserted into the breadboard connectors and result in range reduction.

rf-link

Now for the circuit. We basically read an analog value from the variable resistor on the Duemilanove board, transmit it using the RF transmitter to the RF receiver connected to the UNO board, and light red/yellow LED depending on the value.

RF-link

The value of the resistor in the potentiometer is not important as we will convert it to a value between 0 and 5V. For the LEDs, as they are standard ones, it is OK to attach them to digital outputs.

The next step is the code. In order to achieve a good signal (these modules has a lot of noise), we need to get the RadioHead library (Originally it was VirtualWire, but it has been discontinued and now RadioHead is the one being used). You can download the last version, from here. (If you wonder how to connect these circuits to the Arduino, look at the “Detailed description here).

Once you have it, add it to the Arduino IDE.

virtualwire library

Once the library is added to the Arduino library list, everything is ready to upload the code. Here it is the code for the transmitter.

// Modified version of ask_transmitter.pde by RadioHead
// -*- mode: C++ -*-
// Simple example of how to use RadioHead to transmit messages
// with a simple ASK transmitter in a very simple way.
// Implements a simplex (one-way) transmitter with an TX-C1 module
#include <RH_ASK.h>
#include <SPI.h> // Not actually used but needed to compile
RH_ASK driver;

void setup()
{   
  //LED indicates message sent.
  pinMode(13,OUTPUT); 
  Serial.begin(9600);
  //For some reason, this is needed to initialize the driver
  if (!driver.init())
  {
    Serial.println("init failed");
  }
}

void loop()
{
  char msg[4];
  //Read the voltage in the potentiometer.
  float voltage= analogRead(0)* (5.0 / 1023.0);
  //Convert it to string
  dtostrf(voltage,1,1,msg);  

  //Send the message and wait to check if it was sent.
  driver.send((uint8_t *)msg, strlen(msg));
  driver.waitPacketSent(); 
        
  //Flash LED to indicate message sent.
  digitalWrite(13,1);
  delay(200);
  digitalWrite(13,0);
  delay(200);
}

This is for the receiver.

//  Modified version of ask_receiver.pde by RadioHead
// -*- mode: C++ -*-
// Simple example of how to use RadioHead to receive messages
// with a simple ASK transmitter in a very simple way.
// Implements a simplex (one-way) receiver with an Rx-B1 module
#include <RH_ASK.h>
#include <SPI.h> // Not actualy used but needed to compile
RH_ASK driver;
float Sensor1Data;
char Sensor1CharMsg[4];
void setup()
{
  //LED indicates message sent.
  pinMode(13, OUTPUT);
  Serial.begin(9600); // Debugging only.
  //For some reason, this is needed to initialize the driver.
  if (!driver.init()) {
    Serial.println("init failed");
  }
  //These are for the LEDs
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);

}
void loop()
{
  uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
  uint8_t buflen = sizeof(buf);
  if (driver.recv(buf, &buflen)) // Non-blocking
  {
    int i;
    // Message with a good checksum received, dump it.
    for (i = 0; i < buflen; i++) { // Fill Sensor1CharMsg Char array with corresponding // chars from buffer. Sensor1CharMsg[i] = char(buf[i]); } // Null terminate the char array // This needs to be done otherwise problems will occur // when the incoming messages has less digits than the // one before. Sensor1CharMsg[buflen] = '\0'; // Convert Sensor1CharMsg Char array to integer Sensor1Data = atof(Sensor1CharMsg); //Turn on the corresponding LED if (Sensor1Data > 3) {
      digitalWrite(5, HIGH);
      digitalWrite(6, LOW);
    }
    if (Sensor1Data < 2) {

      digitalWrite(5, LOW);
      digitalWrite(6, HIGH);
    }

    //Flash to indicate message received.
    digitalWrite(13, 1);
    delay(200);
    digitalWrite(13, 0);
    delay(200);
  }
}

And Voilà! With this you are able to light the red or the yellow LED just by adjusting the potentiometer.

This very basic example can be used to transmit a signal form a sensor, to do some wireless projects, or for isntance, to control a device like the ZUMO shield.

RF-link and the ZUMO.

First important thing. The ZUMO shield uses most of the timers in the Arduino board, in particular, the timer1 which is also required for the RadioHead library. So, we need to change the RadioHead library to use timer2. In order to do so, we need to edit the RadioHead library. Simply look for the library and open …Documents\Arduino\libraries\RadioHead\RH_ASK.cpp using a text editor. You need to uncomment //#define RH_ASK_ARDUINO_USE_TIMER2

radiohead

This line should be also added into your Arduino code for the receiver.

The circuits for the new project can be seen below. Basically, instead of reading one analog value, we are now reading 2, one for forward/backwards control, and the other for turning left/right. The second Arduino just sits on top of the ZUMO shield and uses a couple of wires to connect to the RF receiver.

RF-link-zumo

The code for the new transmitter is

// Modified version of ask_transmitter.pde by RadioHead
// -*- mode: C++ -*-
// Simple example of how to use RadioHead to transmit messages
// with a simple ASK transmitter in a very simple way.
// Implements a simplex (one-way) transmitter with an TX-C1 module
#include <RH_ASK.h>
#include <SPI.h> // Not actually used but needed to compile
RH_ASK driver;

void setup()
{
  //LED indicates message sent.
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  //For some reason, this is needed to initialize the driver.
  if (!driver.init())
  {
    Serial.println("init failed");
  }
}

void loop()
{
  char msg[8];
  //Read the voltage in the potentiometer.
  //This one encodes forward/neutral/backwards
  float voltage1 = analogRead(0) * (5.0 / 1023.0);
  //Read the voltage in the potentiometer.
  //This one encodes left/neutral/rigth
  float voltage2 = analogRead(1) * (5.0 / 1023.0);
  if (voltage1 > 2.6) {
    msg[0] = 'f';
  } else if (voltage1 < 2.4) { msg[0] = 'b'; } else { msg[0] = 'n'; } if (voltage2 > 2.6) {

    msg[1] = 'r';
  } else if (voltage2 < 2.4) {
    msg[1] = 'l';
  }
  else {
    msg[1] = 'n';
  }

  //Send the message and wait to check if it was sent.
  driver.send((uint8_t *)msg, strlen(msg));
  driver.waitPacketSent();

  //Flash LED to indicate message sent.
  digitalWrite(13, 1);
  delay(20);
  digitalWrite(13, 0);
  delay(20);
}

This time, just to make this example more general, we transmit characters. F for forward, b for backwards, n for neutral, l for left and r for right. The code for the receiver is

//  Modified version of ask_receiver.pde by RadioHead
// -*- mode: C++ -*-
// Simple example of how to use RadioHead to receive messages
// with a simple ASK transmitter in a very simple way.
// Implements a simplex (one-way) receiver with an Rx-B1 module
#include <RH_ASK.h>
#include <SPI.h> // Not actualy used but needed to compile
//Enable timmer2 instead of timmer1
#define RH_ASK_ARDUINO_USE_TIMER2
RH_ASK driver(2000, 11, 12, 13, false);;
#include <ZumoMotors.h>
ZumoMotors motors;
float Sensor1Data;
char Sensor1CharMsg[4];
int left_speed, right_speed;
void setup()
{
  //LED indicates message sent.
  pinMode(13, OUTPUT);
  Serial.begin(9600); // Debugging only.
  //For some reason, this is needed to initialize the driver.
  if (!driver.init()) {
    Serial.println("init failed");
  }
}
void loop()
{
  uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
  uint8_t buflen = sizeof(buf);
  if (driver.recv(buf, &buflen)) // Non-blocking
  {
    int i;
    // Message with a good checksum received, dump it.
    for (i = 0; i < buflen; i++)
    {
      // Fill Sensor1CharMsg Char array with corresponding
      // chars from buffer.
      Sensor1CharMsg[i] = char(buf[i]);
    }
    // Null terminate the char array
    // This needs to be done otherwise problems will occur
    // when the incoming messages has less digits than the
    // one before.
    Sensor1CharMsg[buflen] = '\0';
    // Convert Sensor1CharMsg Char array to integer
    Sensor1Data = atof(Sensor1CharMsg);    

    //Choose the correct speeds depending on the command
    if (Sensor1CharMsg[0] == 'f') {
      left_speed = 200;
      right_speed = 200;
    }
    if (Sensor1CharMsg[0] == 'b') {
      left_speed = -200;
      right_speed = -200;
    }
    if (Sensor1CharMsg[0] == 'n') {
      left_speed = 0;
      right_speed = 0;
    }
    if (Sensor1CharMsg[1] == 'l') {
      left_speed = left_speed + 100;
      right_speed = right_speed - 100;
    }
    if (Sensor1CharMsg[1] == 'r') {
      left_speed = left_speed - 100;
      right_speed = right_speed + 100;
    }
    if (Sensor1CharMsg[1] == 'n') {
      left_speed = left_speed;
      right_speed = right_speed;
    }

    //Activate motors
    ZumoMotors::setSpeeds(left_speed, right_speed);

    //Flash to indicate message received.
    digitalWrite(13, 1);
    delay(200);
    digitalWrite(13, 0);
    delay(200);

  }
}

Now it is a matter of uploading the code to the Arduinos and pack things inside the cardboard box…

IMAG3170

…and you are ready to have some fun with the ZUMO shield.

Compared with the XBee the range is not great, but these modules are by far cheaper than the XBee, and they can be improved by adding antennas.

Python + Arduino + XBee + Zumo robot

One year ago, I received many things from Coolcomponents.

transbluecoolcomplogo4

among these things, was a Zumo Robot for Arduino.

Today I’m going to show you how to control the Zumo remotely from the computer using an Arduino UNO board and two Xbee. Basically, it’s the continuation of my previous tutorial:

XBee 002: radio-chat between PC and Arduino

this time the Arduino will be driving the Zumo instead of lightning LEDs.

Materials:

  • Breadboard
  • 2 XBee with USB adaptor
  • Arduino UNO
  • Zumo Robot
  • Few wires for connections

IMAG5211

As you can see, I already have done 2 modifications. One of them is that I soldered the wires to the Zumo in order to have connection with my all my Arduino pins. The other modification is that my breadboard is glued on the back of the Arduino.

Step 1. Install Zumo libraries on Arduino IDE. You are going to need these libraries in order to send commands to the Zumo shield. Go to Zumo-shield on GitHub and on the rigth hand side, download as a zip. Once you have that file, decompress it, and move each library folder (Pushbutton, QTRSensors, ZumoBuzzer, ZumoExamples, ZumoMotors, and ZumoReflectanceSensorArray) into the “libraries” subdirectory inside your Arduino sketchbook directory. You can view your sketchbook location by selecting File→Preferences in the Arduino environment; if there is not already a “libraries” folder in that location, you should create it yourself. After installing the library, restart the Arduino environment so it can find the Zumo Shield libraries and their examples. You will know that it is properly installed because it will show in the IDE Examples like this:

serial control for zumo shield

 

Step 2. Write code to drive Zumo from serial. Basically, we are going to modify the “ZumoMotor Example” to run the motors for a short period of time when a string is send through the serial port.

#include <SoftwareSerial.h>
#define Rx    4
#define Tx    5
SoftwareSerial Xbee (Rx, Tx);
#include <ZumoMotors.h>
//This script will control the Zumo motors by reading strings through the serial port.
// a w s d will control left forward bakwards and right
ZumoMotors motors;
int inByte = 0;         // incoming serial byte
int speedr = 0;         //speed of left engine
int speedl = 0;         //speed of rigth engine
void setup()
{
   Serial.begin(9600);
    Xbee.begin(9600);
}
void loop(){
  //This will speed down the engine unless a command to speed up is received
  if(abs(speedr)>0){speedr=speedr-speedr/5;}
  if(abs(speedl)>0){speedl=speedl-speedl/5;}
  motors.setRightSpeed(speedr);
  motors.setLeftSpeed(speedl);
  //If a command is received through the serial and it is a driving comand,
  //then it speeds up or down the corresponding engine
  if (Serial.available() > 0){
    inByte = Serial.read();
    switch(inByte){
      case 'a':// turn left
        speedr=speedr+400;
        break;
     case 'd': // turn right
        speedl=speedl+400;
        break;
     case 'w': // forward
        speedr=speedr+400;
        speedl=speedl+400;
        break;
     case 's':// backward
        speedr=speedr-400;
        speedl=speedl-400;
        break;
      }
  }
  if (Xbee.available() > 0){
    inByte = Xbee.read();
    switch(inByte){
      case 'a':// turn left
        speedr=speedr+400;
        break;
     case 'd': // turn right
        speedl=speedl+400;
        break;
     case 'w': // forward
        speedr=speedr+400;
        speedl=speedl+400;
        break;
     case 's':// backward
        speedr=speedr-400;
        speedl=speedl-400;
        break;
      }
  }
  delay(5);
}
 

To test how it works, simply put the Arduino on top of the Zumo shield and load the code into it. Without disconnecting the USB, turn the Zumo on and the open the serial port on the Arduino IDE.

IMAG5212

You migth notice the reference in the code to the XBee. We are going to use the XBee connected as in our previous tutorial (XBee 002: radio-chat between PC and Arduino) the only change is that here we have pins 4 and 5 free (check Zumo shield pins usage here).

Step 3. Write Python code to read Keyboard and print to serial port. First, we need to install pygame, which is a set of libraries and functions designed to program games…. and they are very handy for reading the keyboard.

First, go to the pygame downloads webpage and look for the installation file that match your system and Python version. For me it works

pygame-1.9.2a0.win32-py2.7.msi 6.4MB

Simply run it and it will be installed. Now the code for Python, which is very simple:

import sys, serial, pygame, time
pygame.init()
size= width, height = 60,40
#The next command creates a window,
#everytime you are on that window and press a key
# in the leyboard, it will be analysed and
#if it is one of the driving commands, it will be send
#through the serial port.
screen = pygame.display.set_mode(size)
screen.fill((0,0,0))
ser=serial.Serial('COM7',9600,timeout=1)
key=''
while 1:
    events = pygame.event.get()
    for event in events:
        #This is just to quit
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN:
            key=event.key
        if event.type == pygame.KEYUP:
            key=''
#The command is being send through the serial until we release the key
#Because we have a loop in the arduino and only checks the serial port every
#5 ms, by adding here a 10ms delay we make sure robot follows the orders in real time
    time.sleep(0.01)
    if key == 97:
        ser.write('a')
    elif key == 115:
        ser.write('s')
    elif key == 119:
        ser.write('w')
    elif key == 100:
        ser.write('d')

 

Step 4. Connect XBee, and enjoy (use same connection diagram for the XBee as in XBee 002: radio-chat between PC and Arduino but changing 6 and 7 pins for 4 and 5.). Our XBee is ready from the previous tutorial, and our code already includes reading XBee or USB… so everything is ready.

By the way… you might ask why I have 2 Lego bricks on the top… it is for this

IMAG5213

XBee 002: radio-chat between PC and Arduino

The starting point of this tutorial is that I add some breakaway headers to the XBee’s USB breadboard adapter.

IMAG4302

This is the “B” module from my previous tutorial… and we will start asumming that the XBee has been set up using that tutorial.

XBee 001 Basic example: radio-chat between 2 PC

So, what are we going to do?

We will have an Arduino board connected by USB to one computer and by radio (using a pair of XBee) to another computer. Using one computer or the other we are going to switch LED on and off.

Step 1. Make the electrical connections. We connect 3 LED to pins 9,9,10 on the Arduino. Remember to use an appropriate resistor to limit the amount of current. Use the ground on the Arduino to close the circuit.

arduino-xbee

To be able to communicate with the XBee you need to power it (+5V to pin VDD and ground to VSS pin), the Arduino can provide enough power, so use it. Connect pin 7 to DIN and pin 6 to DOUT. These two pins are going to be used for serial communication between the Arduino and the XBee.

For other alternatives to communicate between a microcontroler and the XBee, the parallax webpage gives a good support here.

Step 2. The code. As you can see, the code comments explain what it does. Simply reads from Serial (USB) or from the new serial defined in ports 6 and 7 to comunicate with the XBee. Depending on what we read from the Serial, we turn on one LED or other.

//Arduino serial comunication happens through the USB or on the pins TX and RX
//including this file allows us to create another Serial port using pins 6 and 7
#include <SoftwareSerial.h> 
#define Rx    6                // DOUT to pin 6
#define Tx    7                // DIN to pin 7
SoftwareSerial Xbee (Rx, Tx);

//Some variables for the LEDs and reading the Serial
int blue_led = 8;
int green_led = 9;
int red_led = 10;
char incoming ='empty';

void setup(){
  Serial.begin(9600);  // start serial port at 9600 bps:
  Xbee.begin(9600);
  pinMode(red_led, OUTPUT); 
  pinMode(blue_led, OUTPUT); 
  pinMode(green_led, OUTPUT); 
}
  
void loop(){
  if(Serial.available()){
    //If there is data on the Serial port, read it and ligth the corresponding lights
    incoming = Serial.read();
    lights (incoming);
  }
  if(Xbee.available()){
    //If there is data on the XBeeSerial port, read it and ligth the corresponding lights
    incoming = Xbee.read();
    lights (incoming);
  }    
}
  
int lights(char incoming){
  switch (incoming){
    case 'red':
    //Turn on the red LED
    digitalWrite(red_led, HIGH);
    digitalWrite(blue_led, LOW);
    digitalWrite(green_led, LOW);
    break;
    case 'blue':
    //Turn on the blue LED    
    digitalWrite(red_led,LOW );
    digitalWrite(blue_led, HIGH);
    digitalWrite(green_led, LOW);
    break;
    case 'green':
     //Turn on the green LED
     digitalWrite(red_led, LOW);
     digitalWrite(blue_led, LOW);
     digitalWrite(green_led, HIGH);
     break;
     default :    
     // default is optional
     break;
   
  }
}
 

Upload the code to your Arduino.

Setp 3. Communicate There is 2 ways of communication. First, using the same computer that is already connected by USB with the Arduino, open the Serial Monitor in the Arduino UI and write the colour of the LED you want to be on.

xbee

And the LED turns on.

IMAG4303

As you can see my electrical set-up is not as tidy as the schematic… but it works.

The second option is using the other XBee (from our previous tutorial) and the program CoolTerm to send data through the XBee. So, disconnect the USB from the Arduino and power it with batteries (or use one computer to power and another to communicate). Connect the “A” XBee with its USB adaptor to the computer and open CoolTerm program. The only change you need to do respect to the previous tutorial is enabling Line mode under Options>Terminal. This will enable sending one string at a time instead of individual characters.

coolterm

Once this is done… it is ready for communication. Simply write the name of the colour you want.

IMAG4312

Hope you find it useful… please, practise it if you can, because soon we are going to use this hack with something more funnier…

XBee 001 Basic example: radio-chat between 2 PC

A year ago I received a big order from  Adafruit industries.

adafruit

Among the things I ordered, was the camera for the Raspberry Pi, an Arduino UNO board, some accessories for the Arduino… and a pair of XBee with micro USB adapters!

IMAG4282

(Link to buy the XBee and the USB adapters).

Ok… so I know the basics about XBee… it can be used to communicate using radio signals… but I don’t know more than that! It is now time to try a few things and learn.

Fortunately, the company that fabricates the XBee has examples on its webpage, and we can follow it to learn (you and me).

Basic XBee ZB ZigBee (Series 2) Chat

The above example explains how to use 2 XBee to communicate between 2 PC. I’m going to follow it trying to simplify/update the example and adding tips when needed.

Step 1. In order to use the USB adapters, we need to install drivers for them. They are here. Look for your OS and download and install the drivers in both PC. In my case, one computer is running Windows 7 x64 and the other one is running the no longer supported Windows XP x32. The driver worked fine on both.

Step 2. Now we need a software to communicate with the XBee through the USB port. That is called CoolTerm.

coolterm

Download the one needed for your OS unzip and it is ready.

By the way… once you are in Roger Meier’s webpage… if you scroll down, you migth find a R2D2 translator which is quite funny to try.

Step 3. You need to write down the numbers on the back of the XBee (top one is the High, and bottom one is the Low), name them A-Coordinator and B-Router.

Series2Bottom-300x300

Step 4. To tell the XBee who is the Coordinator and who is the router, you need to download X-CTU form here.

Once X-CTU is installedm connect the A-Coordinator and open X-CTU. Select the COM port and click “Test / Query” to see if X-CTU can communicate with the radio. The result should look like this (If not, try to diconnect/reconnect the USB and closing/opening the program).

coolterm

Now click the “Modem Configuration” tab on the top and then drop down the “Modem:” list. Select XB24-ZB . Then choose ZIGBEE COORDINATOR AT from the “Function Set” list. Finally, click “Write” to update the firmware.

Repeat the process with the B-Router, selecting ZIGBEE ROUTER AT from the “Function set list”.

Step 5. Now we need to setup our XBee using the CoolTerm program.

A-Coordinator. Connect the XBee named A-Coordinator using the USB and open the program. In the program, click options and Re-Scan Serial Ports. You will know which port the XBee is connected by repeating this step with and without the XBee USB adapter connected.

coolterm

If it doesn’t show, most probably you need to restart the system or the drivers are not properly installed.

The parameters for the coordinator are:

  • Baudrate is set to 9600.
  • Be sure Data Bits is set to 8.
  • Be sure Parity is set to “none.”
  • Be sure Stop Bits is set to 1.
  • In the list on the left side of the options window, click “Terminal.” Be sure “Local Echo” is activated.

Now hit ok and back in the main window, press Connect. You will see a “connect” message on the bottom left corner.

coolterm

Now to set the firmware you need to write this commands very fast. The first one, +++ opens the command mode (it will close by itself in 10 s). The rest just set up the connection. ATDH is the same for all, ATDL has to be the Low number on your B-Router XBee. (If you write the commands without arguments, the device returns actual values). The ATWR command saves the changes. Remember to use it.

+++
OK
ATID 2001
OK
ATDH 0013A300
OK
ATDL 40B18506
OK
ATWR
OK

Click disconnect and remove the device.

B-Router. Now connect the XBee named B-Rooter. You need to go back to options again and look for the correct serial port (it might be different). Hit connect and repeat the commands. Now you need to put the Coordinator’s Low in the ATDL command.

coolterm

Step 6. Try it! Connect the a-Coordinator into one PC and the B-Router into the other. Open CoolTerm and choose the right COM port… (If it doesn’t work, check setup parameters with the commands ATID etc or review the steps to make sure everything works fine). In my case when it works, whatever you write in one PC or the other, appears in both! So you have your chat enabled!

IMAG4283