Wednesday, January 20, 2016

Bluetooth (BLE) Robot Remote Control using an iPhone - Part 2

Introduction


If you want to use an iPhone as your controller then Bluetooth is one of the better communication options for directing your robot / drone / whatever.

In Part 2 we will cover the iPhone app required to control your BLE device. The AVA BLE Remote is available as a free download from iTunes. We will first cover how the app works and then how it was coded. For those who don't want to write their own controller, feel free to use ours. We have included the ability to customise the characters sent in response to a command.

We suggest you read Part 1 to understand the overall design but here is a quick recap.

This app has been designed to work with a Bluno board from DFRobot. The Bluno is a combination of an Arduino and a Bluetooth shield. It uses Bluetooth Low Energy (BLE), which is compatible with iOS 7.0+ devices: iPhone 5+,iPad 3+,iPad Mini,and iPod 5th Gen (note that Bluetooth LE capability is required).




Getting Started: The Connection Screen


When the app starts, it will open the connection tab and display any compatible BLE devices which are within range. To connect to a device just tap on its name. If the connection is successful, the word connected will be displayed and the communication indicator "LEDs" will turn from flashing blue to green. You can start a manual search for BLE devices by tapping the search (magnifying glass) icon in the top right of the connection screen. You can stop the search by tapping the disconnect device button (a cross) in the top left.

If you are already connected to a BLE device, tapping the disconnect device button will disconnect you. You can only attach to one BLE device at a time.



Setting a Task


Tasks are a behavioural robotics concept, but of course you can use them as you wish. You don't need to use tasks at all, if you want you can just use the next tab (Control) to direct your robot. Tasks are useful if you want the robot to do more than one thing. In our case, the robot only responds to remote control commands when the remote task has been set.

The idea is that each task is made up of subset of core behaviours. By combining different behaviours you can create a robot task. For example, the default tasks provided with the app are mapped to the following core behaviours in AVA.

Task ID        Name        Behaviours

     0               Status        BID_STOP
     1               Remote     BID_MANUAL
     2               Patrol        BID_AVOID, BID_ESCAPE, BID_POWER
     3               Follow IR BID_PIR_ATTRACT, BID_AVOID, BID_ESCAPE, BID_POWER
     4               Avoid IR   BID_PIR_REPEL, BID_AVOID, BID_ESCAPE, BID_POWER

By combining simple core behaviours you can get emergent complex task following behaviours which degrade gracefully when the robot faces unexpected situations. In our robot, each of the behaviours are set a priority. This priority decides which behaviour takes precedence. If the priorities are the same then the code will deal with them in the order presented (which gives an implied priority). You can refresh your knowledge on behavioural robotics by reading our earlier post on different approaches to robot AI.

Behaviour                        Priority                      Inputs                               Outputs 

BID_STOP                            1                            cliff, collision sensors       left & right motor stop
BID_MANUAL                    2                            BLE remote                       left & right motor controls
BID_ESCAPE                       3                            distance sensors, heading  left & right motor controls
BID_AVOID                         4                            distance sensors                 left & right motor controls
BID_POWER                        5                            batt voltage, homing          left & right motor controls
BID_PIR_ATTRACT           6                            PIR                                     left & right motor controls
BID_PIR_REPEL                 6                            PIR                                     left & right motor controls

The Task tab in the iPhone app allows you to send a tasking message to your Bluno. It is the responsibility of the robot code to assign current behaviours based on the assigned task.

Tapping a task will transmit the tasking ID (e.g. 1) via Bluetooth. Tap the add button (+) to add your own tasks. Tap Edit to delete or rearrange the tasks. Tapping "Default Tasks" will reload the task list that comes with the app.




Controlling your BLE Device


The Control tab acts as a virtual gamepad for your BLE device. The currently selected task is displayed at the top of the screen. Tapping the function keys (F1 to F4) will send the designated character via Bluetooth to your Bluno. Similarly, tapping the directional dPad or stop button will send the character assigned to those buttons. You can change the characters which are transmitted from the key mapping option in the console tab. The default mappings are:

F1    w
F2    x
F3    y
F4    z

Up Arrow         f
Down Arrow    b
Left Arrow       l
Right Arrow     r
Stop                  s

The speed slider will send the selected speed encapsulated with less than and greater than brackets.

Messages received back from the Bluno are displayed at the bottom of the screen.




The Console


The console tab allows you to send any character strings that you wish to the Bluno. Just type the message in the text field and tap Send. Any received messages will be displayed below.

The console tab also contains the system log which records various events, such as device discovery, connection, data transmission and disconnection. You can email the system log by tapping the mail button in the top right of the screen.

Tap the settings (gear icon) button if you wish to change the keys mapped to the Control buttons.




iOS Code


The iOS code is pretty straight forward and made much easier by the Bluno frameworks provided by DFRobot. You will need to include the following classes in your code.

- BLEDevice
- BLEUtility
- DFBlunoDevice
- DFBlunoManager

The download link for the entire Xcode project is provided below, but here are the highlights. Most of the heavy lifting is done by the DFBlunoManager class. This is a shared instance (singleton), so you just access it in your classes using:

 blunoManager = [DFBlunoManager sharedInstance];

The first step is scanning for and connecting with available Bluetooth LE (BLE) devices. Scanning is as simple as:

[blunoManager scan];

The results of the scan are handled by the DFBlunoDelegate, so you will need to have one of your classes conform to this protocol. We used the TabBarViewController as this is nice and central. Within our TabBarViewController, there are a couple of delegate methods which get notified when a scan is performed.

#pragma mark- DFBlunoDelegate

- (void)bleDidUpdateState: (BOOL)bleSupported
{
    NSString *logString;
    NSString *timeStamp = [formatter stringFromDate: [NSDate date]];
    
    if (bleSupported) {
        logString = [NSString stringWithFormat: @"%@: Scanning for BLE devices\n", timeStamp];
        [blunoManager scan];
    } else {
        logString = [NSString stringWithFormat: @"%@: BLE not supported\n", timeStamp];
    }
    
    [self log: logString];
}

- (void)didDiscoverDevice: (DFBlunoDevice *)device
{
    NSString *timeStamp = [formatter stringFromDate: [NSDate date]];
    NSString *logString = [NSString stringWithFormat: @"%@: New device discovered - %@\n", timeStamp, device.identifier];
    
    [self log: logString];
    
    BOOL bRepeat = NO;
    
    for (DFBlunoDevice *bleDevice in appDelegate.deviceArray) {
        if ([bleDevice isEqual: device]) {
            bRepeat = YES;
            break;
        }
    }
    
    if (!bRepeat) {
        [appDelegate.deviceArray addObject: device];
        
        NSString *logString = [NSString stringWithFormat: @"%@: Device added to BLE list\n", timeStamp];
        
        [self log: logString];
    }
    
    [connectionViewController.tbDevices reloadData];
}

We use these to update the table tbDevices in the ConnectionViewController. Once you have found an eligible device, you connect to it using:

[blunoManager connectToDevice: device];

In particular, since we use a table view to list the devices in range we allow the user to connect to a specific device by tapping on the row in the table that corresponds to that device. The device data is stored in deviceArray (which is a property of the application delegate). We also have a property in the application delegate which points to the currently active device (blunoDevice). The relevant code from the ConnectionViewController is:

#pragma mark- Table View Delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DFBlunoDevice *device = [appDelegate.deviceArray objectAtIndex:indexPath.row];
    
    if (appDelegate.blunoDevice == nil) {
        appDelegate.blunoDevice = device;
        [blunoManager connectToDevice: appDelegate.blunoDevice];
    } else if ([device isEqual: appDelegate.blunoDevice]) {
        if (!appDelegate.blunoDevice.bReadyToWrite) {
            [blunoManager connectToDevice: appDelegate.blunoDevice];
        }
    } else {
        if (appDelegate.blunoDevice.bReadyToWrite) {
            [blunoManager disconnectToDevice: appDelegate.blunoDevice];
            appDelegate.blunoDevice = nil;
        }
        
        [blunoManager connectToDevice: device];
    }
    
    [self.activityIndicator stopAnimating];
    self.activityIndicator.hidden = YES;
    [tableView deselectRowAtIndexPath: indexPath animated: YES];
}

Once you are connected to the remote device, sending data to it is performed by the following method (found in the application delegate).

#pragma mark - Bluno Communications

- (void)sendString: (NSString *)msg {
    if (self.blunoDevice.bReadyToWrite) {
        NSData *data = [msg dataUsingEncoding: NSUTF8StringEncoding];
        
        [blunoManager writeDataToDevice: data Device: self.blunoDevice];
    }
}

The DFBlunoDelegate will let you know what happens via two methods.

- (void)didWriteData: (DFBlunoDevice*)device
{
    //  NSLog(@"%s", __func__);
    
    NSString *timeStamp = [formatter stringFromDate: [NSDate date]];
    NSString *logString = [NSString stringWithFormat: @"%@: Data written\n", timeStamp];
    
    appDelegate.state = Transmitting;
    [self log: logString];
}

- (void)didReceiveData: (NSData *)data Device: (DFBlunoDevice *)device
{
    //  NSLog(@"%s", __func__);
    
    NSString *timeStamp = [formatter stringFromDate: [NSDate date]];
    NSString *receivedTextString = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
    
    //  NSLog(@"ASCII Rx: %d",[receivedTextString characterAtIndex: 0]);
    
    if (receivedTextString && receivedTextString.length > 0 && ![receivedTextString isEqualToString: @"\n"]) {
        NSString *logString = [NSString stringWithFormat: @"%@: Rx - %@\n", timeStamp, receivedTextString];
        manualViewController.txtReceivedMsg.text = receivedTextString;
        consoleViewController.txtReceivedMsg.text = receivedTextString;
        [self log: logString];
    }
    
    appDelegate.state = Receiving;
    consoleViewController.txtSendMsg.text = @"";
}


In our app we use these to update the log file in the console and print out any data received from the remote device.

Finally, to disconnect a device, just use:

[blunoManager disconnectToDevice: appDelegate.blunoDevice];

You will need to replace appDelegate.blunoDevice with whatever you have called your Bluno Device object.

The complete source code is available at the Reefwing Code Repository.

Bluno Code


The Bluno code was covered in Part 1 of this series. Sample code to allow you to test the app is available from the Reefwing Gist Repository (https://gist.github.com/reefwing/eab05c12b615070732c3).

Wednesday, January 6, 2016

Bluetooth (BLE) Robot Remote Control using an iPhone - Part 1

Overview


Any self respecting autonomous robot needs a remote control / telemetry mode. This is useful for testing and most importantly fun! There are lots of different ways that you could approach this (e.g. hard wired, WiFi, or RF) but we liked the idea of using our iPhone as the controller and this seemed like a good excuse to play around with Bluetooth.

Figure 1. The Bluno - Arduino Uno + BLE.

As this is a fairly meaty subject, we will break it up into three posts. Each post will cover the following:

  1. Bluno - An Arduino board combined with a Bluetooth 4 Low Energy module produced by DFRobot (see Figure 1). In our design this acts as the middle-ware, providing a bridge between our iPhone app and the Arduino Mega 2560 which acts as our main robot controller. You could control a simple robot directly from the Bluno. We also used the Bluno accessory shield, mostly to provide an indication of what is happening via its OLED display. However, this doesn't leave a lot of spare pins (3 digital and 2 analog to be precise).
  2. iOS App - I will provide the source code for this and make it available for download from iTunes once I have finished debugging. It should be flexible enough to use in your own robot design. I have included the ability to remap the keys should you wish to use different characters to the ones I selected.
  3. Mega 2560 Integration - This is the final step in allowing your robot to be controlled via an iPhone app. The Bluno communicates with the Mega 2560 using the serial 3 comms port. We could have used the I2C bus, but as this is used for logging it could be tied up when a critical stop command was trying to be sent from the remote. As a remote command is one of the highest priority behaviours, it made sense for it to have its own dedicated communication channel.

The Design


The wiring is simple. As shown in Figure 2, the Bluno connects to our Mega 2560 using 2 wires. Pins 4 and 5 of the Bluno connects to pins 14 and 15 on the Mega 2560 (the Serial 3 Tx and Rx pins). That's it, the magic happens in the software. We have described in an earlier post how the Mega 2560 controls our HB-25 Motor Controllers. Bluno uses a TI CC2540 BT 4.0 chip to provide BLE functionality. We will use this to communicate with the iPhone.

Figure 2. AVA Schematic.


The Hardware


We are using the SoftwareSerial library on the Bluno so you can use any 2 spare digital pins, but if you also use the accessory shield (Figure 3) then you wont have many other options. The accessory shield provides quite a bit of capability.


128x64 OLED Screen                                    Display messages from your phone interface.
Buzzer                                                            Enable Sound notifications or simple music.
DHT11 Temperature & Humidity Sensor     For environmental monitoring.
1.5A Relay                                                     Device switch or integrating with other electronics.
Helical Potentiometer                                    Transfer real time data to your phone
RGB LED                                                      Display full colour RGB
Mini Joystick                                                 Tells your phone which direction is pressed


The pins used by BLE module and the accessory shield are:

0    BLE Rx (also used for programming and for the terminal comms).
1    BLE Tx (also used for programming and for the terminal comms).
2    DHT11 Temp / Humidity sensor.
3    RGB LED (blue control).
4    Spare - used for serial Rx, connects to Mega 2560 Tx.
5    Spare - used for serial Tx, connects to Mega 2560 Rx.
6    OLED RESET
7    OLED DC
8    Buzzer
9    RGB LED (red control)
10  RGB LED (green control)
11  Relay
12  Spare
13  LED

A0    Joystick
A1    Knob (potentiometer)
A2    Spare
A3    Spare
A4    I2C - SDA
A5    I2C - SCL

Figure 3. The DFRobot Accessory Shield.

Looking at Figure 3 you will note our first design problem. None of the pins are accessible without breaking out the soldering iron. To allow us to connect our 2 serial wires we purchased a prototyping screw terminal shield from DFRobot (Figure 4).

Figure 4. Prototyping Screw Terminal Shield.

The proto shield is sandwiched between the Bluno and the accessory shield (Figure 5). Excellent we now have access to pins 4 and 5, BUT now the OLED display no longer works. Design problem number 2. For some unfathomable reason (particularly since all these products come from the same supplier) the proto shield is 2 pins short. The missing pins are the I2C SDA and SCL (used to control the OLED). There are a number of ways you can fix this, but the easiest is to get an Arduino Header Kit (like the one shown in Figure 5) and use the 6 pin header to bridge between the Bluno and the accessory shield. There are holes in the proto shield to allow this (albeit not exactly in the right spot). Cut off the 4 unused pins to prevent them shorting on anything. You can solder the header kit onto the proto board if you want but we didn't find this necessary.

Figure 5. Arduino Header Kit.

The images below (Figure 6) show the boards connected together and mounted on AVA. The yellow and brown wires are the serial comms to the Mega 2560 and the red and green are power and go to the distribution board on the bottom deck. The board adjacent to the Bluno is used for monitoring of the 2 x 12V SLA batteries. The panel voltmeter displays the current battery voltage (11.5 VDC).



Figure 6. Bluno, Proto and Accessory Shield.

The Software


You can download the Bluno software from the Reefwing Gist Repository. The code is pretty straight forward. The Bluno waits until it receives data on its serial port from the BLE module and passes it to the Mega via another serial port. The RGB LED flashes blue once a second while waiting for data. It will flash green once when data is received. The iOS app allows you to select a number of tasks for the robot to perform. In Figure 6, you can see that the current task is task 2: Patrol. When task 1, Remote Control is selected, the RGB LED goes a solid red.

The main code loop is shown below. As we will see in the next post, the iPhone app sends a character code to indicate the command required (e.g. 's' means stop).

if (Serial.available())  {
        char data = Serial.read();
        commsDetected = true;
        switch (data) {
            case 's':
                Serial.write("Ack - STOP");
                megaSerial.write(data);
                break;
            case 'f':
                Serial.write("Ack - Forward");
                megaSerial.write(data);
                break;
            case 'b':
                Serial.write("Ack - Back");
                megaSerial.write(data);
                break;
            case 'l':
                Serial.write("Ack - Left");
                megaSerial.write(data);
                break;
            case 'r':
                Serial.write("Ack - Right");
                megaSerial.write(data);
                break;
            case 'w':
                Serial.write("Ack - F1");
                megaSerial.write(data);
                break;
            case 'x':
                Serial.write("Ack - F2");
                megaSerial.write(data);
                break;
            case 'y':
                Serial.write("Ack - F3");
                megaSerial.write(data);
                break;
            case 'z':
                Serial.write("Ack - F4");
                megaSerial.write(data);
                break;
            case '0':
                task = statusReport;
                taskDescription = "T0: Status";
                Serial.print(taskDescription);
                megaSerial.write(data);
                remoteControlled = false;
                break;
            case '1':
                task = remoteControl;
                taskDescription = "T1: Remote";
                Serial.print(taskDescription);
                megaSerial.write(data);
                remoteControlled = true;
                break;
            case '2':
                task = patrol;
                taskDescription = "T2: Patrol";
                Serial.print(taskDescription);
                megaSerial.write(data);
                remoteControlled = false;
                break;
            case '3':
                task = followIR;
                taskDescription = "T3: Follow IR";
                Serial.print(taskDescription);
                megaSerial.write(data);
                remoteControlled = false;
                break;
            case '4':
                task = avoidIR;
                taskDescription = "T4: Avoid IR";
                Serial.print(taskDescription);
                megaSerial.write(data);
                remoteControlled = false;
                break;
            default:
                char errorMsg[32];
                String error = "Unknown Command - ";
                error += data;
                error.toCharArray(errorMsg, 32);
                Serial.write(errorMsg);
                break;
        }
        Serial.println();
    }

Friday, December 25, 2015

Robot Christmas

AVA Disco Mode


The robot received a set of Ikea Dioder LED strips for Christmas. Below is a quick video of AVA in disco mode. There will be a separate post on controlling these strips using an Arduino at some stage.




AVA Christmas


In keeping with the Christmas theme here is AVA singing a Christmas Carol using the EMIC 2 Speech Synthesizer. The Emic 2 Text-to-Speech Module is a multi-language voice synthesizer that converts a stream of digital text into speech. You can select either the Epson (default) or DECtalk parsers.


Note that the Emic 2 uses DECtalk version 5.0.E1. The Flame of Hope web site has a heap of DECtalk songs but they are for earlier versions of the DECtalk parser and require tweaking to work with the EMIC 2. Thanks to Ron on the Parallax forum for these tips on converting the text files:

  • you often have to change an "L" to "LL"
  • sometimes you need a space between any character preceding the "ey" phonetic symbol.

The following is the string used to produce the song in the video above, should you wish to try out your EMIC 2's singing ability.


"[:phone arpa speak on][:rate 190][:n2][:dv ap 200 sm 100 ri 100][R EY<200,17>N<100>DRAO<200,24>PS<100>AO<200>N<100>ROW<300,19>ZIX<200,17>Z<100>AE<150>N<100>D<50>WIH<300,12>SKRR<200,17>Z<100>AO<200>N<100>KIH<300,19>TAH<150,17>N<100>Z<50>_<300>BRAY<200>T<100>KAO<300,24>PRR<300>K EH<300,19>TEL<200,17>Z<100>AE<150>N<100>D<50>War<200,12>M<100>WUH<300,17>LL EH<200>N<100>MIH<300,19>TAH<150,17>N<100>Z<50>_<300>BRAW<200>N<100>PEY<300,24>PRR<300,22>PAE<300,17>KIH<300,19>JHIX<200,15>Z<100>TAY<200>D<100>AH<200,22>P<100>WIH<200,20>TH<100>STRIH<300,13>NX<200>Z<100>_<300>DHIY<200,12>Z<100>AR<300,13>AX<300,15>FYU<300,17>AH<200,18>V<100>MAY<300,20>FEY<300,22>VRR<300,24>EH<200,22>T<100>THIH<500,16>NX<300>Z<100>][:n0]"


Arduino Code



To make it easy for our Arduino Mega 2650 to communicate with the EMIC2 we created a library called synthesizer.h. As you can see the Arduino connects to the EMIC 2 via one of its serial ports.



To use this class, I have created a robot class which looks like:



Then in the main.ino file all you need to do is:



You don't have to use C++ classes like I did but it makes it easier to maintain your code. You can also ignore the bits which refer to the motors and other sensors, I just leave it in here for completeness.


Wednesday, December 23, 2015

Moving to embedXcode...

The Problem


We have been using the Arduino IDE to develop on. Which is fine (and free) but it does have some limitations. In particular, we ran into the problem of having too many tabs (files) in our main controller sketch. This came about as a result of another issue, which is not unrelated.

As with most people we started developing our robot code organically using mostly straight c with c++ functionality reserved for included libraries. By the time you add 13 sensors, speech synthesis, speech recognition, 2 motor controllers, serial comms for the Bluetooth remote (which will be described in a subsequent post) and an I2C bus connecting the real time clock, pressure / altitude module and 2 auxiliary Arduino's used for display and logging, the code gets messy and hard to maintain. A simplified schematic of the robot so far is shown below. The schematic was produced using Fritzing which I have mentioned previously and strongly recommend.



As an aside, we are using SPI for the logging Arduino to communicate with its OLED shield, so we have all the available communication options covered (with the possible exceptions of WiFi and RF - stay tuned)!

To fix the messy, unmaintainable code issue, we started to translate our c code into c++ classes where it made sense. This made the code much more modular but each class requires a new tab which brings us back to the first issue mentioned above. Once the number of tabs fill up the top row of the IDE, it becomes a bit of a pain to move to the tabs not displayed. There is a keyboard shortcut to go to the next and previous tab, but that is a bit clunky and was the straw that sent me on a search for a better IDE to develop Arduino code on.


The other short comings of the Arduino IDE are:
  1. No code completion; and
  2. The syntax highlighting is a bit hit and miss. You could fix a particular issue by editing the keywords.txt file in the appropriate library but that is pretty fragile.

The Solution


A quick google search will turn up LOTS of different options for programming the Arduino. Our preferred solution would incorporate the following:
  1. Minimal learning curve;
  2. Preferably free;
  3. Works on a Mac;
  4. Can upload a sketch from within the IDE;
  5. Includes a serial terminal similar to the serial monitor provided by the Arduino IDE; 
  6. Has code completion and syntax highlighting; and
  7. Handles multiple files well; and
  8. Doesn't create any new issues.
With this shopping list in mind, the field quickly narrows to a plug in for Xcode called embedXcode. This ticks all our requirements and has (almost) no learning curve since we use Xcode for our App Development work.



The other IDE we considered was Eclipse which is the basis of Android Studio that we use for Android Development. What swayed or decision was that the setup looked a lot easier for Xcode and we were more familiar with this IDE as well. Have a look at this blog by a chap in the US, he had the same issues but decided on Eclipse. Going with what you are already familiar with makes a lot of sense.

Setting up embedXcode


This is straight forward and described in detail in the (large) user manual. In summary:
  1. Install Xcode if you don't have it already.
  2. Download embedXcode. We went for the free version to evaluate how good the plug in is. Should it work out we will either upgrade to embedXcode+ or pay a donation. We want to encourage ongoing development of the plugin. We know that Xcode changes frequently and with each new release normally breaks legacy code.
  3. Install the plug in and open up Xcode. That's it! You should now have the option to open a new embedXcode AVR project (see below).

Importing Sketches


Unfortunately you can't just import sketches that you have done with the Arduino IDE. There is a process that you need to follow:
  1. Open a new project in Xcode. You can call it the same name as your sketch. Make sure you select the correct board type (e.g. Uno) in the new project options. The scope options are sketch or library and this also sets the extension of the main file (.ino for sketches and .cpp for libraries).
  2. Open your sketch in the Arduino IDE and copy the contents into the ino file in your Xcode project. There is some pre-processor definitions used for code sensing at the top of the ino template file in Xcode. Don't overwrite these unless you know what you are doing (e.g. if you are using a recent Arduino you can replace the lot with #include "Arduino.h".
  3. The next step is to find your Arduino libraries folder in Finder and drag it across to the Sketchbook group. When the choose options for adding these files dialog comes up, don't select "copy items if needed" (unless you want multiple copies of your library files), select index in "add to targets" (see below). You also need to change the type from plain text to "c++ source". This option is found in the right hand pane of Xcode after selecting the main sketch (shown in the second screenshot below).
  4. The thing I stuffed up initially was not also listing the libraries used in the makefile. If you get an error saying a library can't be found, this may be the answer To fix it, select the makefile in the left hand pane and add the names of the libraries used.  There are two types of libraries you will use most often, application libraries and user defined libraries. Generally, the application libraries are the ones defined using <> (e.g.  #define <SoftwareSerial>) and the user libraries are defined using"" (e.g. #define "blunoAccessory"). However the <TimerOne> library was an exception to this rule and needed to be defined as a user library (e.g. "APP_LIBS_LIST = SoftwareSerial" and "USER_LIBS_LIST = U8glib blunoAccessory TimerOne". Different libraries are separated by a space and don't show the file extension. Read the user manual if you are still confused, it covers this topic in some detail.



Once you have completed the four steps above, you should be able to build (compile) your project, but only if your board is connected.

New Issues?


The only issues which have arisen so far are fairly minor apart from the speed of compilation and uploading. This is significantly slower than the Arduino IDE. If you purchased  embedXcode+ then you have two options:

  1. Build -> All targets which builds and links everything, and is slow.
  2. Make -> Fast -> additional targets only, which builds the main sketch and the libraries in the local folder, so it is much faster (up to 10x according to the developer).

If you only downloaded the free version then you are stuck with option 1. Other areas to be aware of are:
  1. You can't Build (compile) a project unless you are connected to your board via USB. This is a bit of a pain as you could just compile using the Arduino IDE without being connected to the board. Solved this. From the Product menu item select Scheme -> Build.
  2. Instead of Serial Monitor in the Arduino IDE you use Terminal on the Mac. The default baud rate for terminal is 9600. Which is ok if that is the baud rate you want to use on the serial port but I have a sketch which communicates with a BlueTooth LE shield on the same comm port that needs 115200 baud. Theoretically you can change the baud rate in Terminal using stty (e.g. stty 115200), but this doesn't seem to work. I have also tried "screen /dev/tty.usbmodemfd121 115200", but no cigar. I will keep working on this but the work around for now is to use 9600 baud if you can or use the old Arduino Serial Monitor if all else fails. Other solutions are welcome, so feel free to comment below. I have found the answer to this as well. There is an option in the makefile that you can use to set the baud rate, namely:  "SERIAL_BAUDRATE = 115200".
  3. Getting code sense to work for me took a bit of tweaking. First make sure that the sketch (ino file) has index selected for Target Membership (click on this file to check). Save the file and close the project. A small update is required to the user manual instructions. In the current version of Xcode (v7.2), projects is now a separate dialogue to Organiser but it is still found under the Windows menu in Xcode. Delete your derived data for your project and then reopen your project. After indexing, code sense for the Arduino specific definitions should work. You can change the syntax colouring in preferences, fonts and color.

If anything else comes up, I will add it here. All in all I am pretty happy with this solution. We will still use the Arduino IDE for simple sketches but for something as complicated as a robot, an IDE like Xcode is essential. Well done embedXcode!

Update 27th December 2015


I was so impressed with embedXcode that I upgraded to embedXcode+. This is worth doing if you use the plugin regularly. It also encourages the developer to keep supporting the product which is important given the frequent updates to Xcode.

Error: Serial port not available (Step2.mk)




If you come across this error (I did), there is a simple fix. First open up terminal and find out the name of your serial port. Type the following command: ls /dev/tty.usb*


This will provide the name of your serial port. Copy this and then open the main Makefile in Xcode uncomment the line:

#BOARD_PORT = /dev/tty.usbmodem*

and specify either a more general name:  e.g. BOARD_PORT = /dev/tty.usbmodem*

or the specific USB port name of the board that you got from Terminal e.g. in my case:

BOARD_PORT = /dev/tty.usbmodemfd121









Wednesday, December 9, 2015

Parallax HB-25 Motor Control Library for Arduino

Moving AVA


We are using the Arlo robotics platform from Parallax to build up AVA. As you can see in the schematic below, this incorporates two HB-25 motor controllers (Part Number: #29144) which look after the left and right wheels.


After an exhaustive search we were not able to find an existing Arduino library for the HB25, so we were forced to write our own. This involved delving into the incomplete version of C++ which Arduino uses. Before getting to this, let's look at how you can control the HB25 just treating it as a servo, which will be fine for most folks.

Wiring the HB-25




If you are using the Parallax Motor Mount and wheel kits (part numbers #28962 - aluminium or #28963 - plastic) then the red cable should be connected to M1 on the HB-25 and the blue cable should be connected to M2. If these are reversed then the FORWARD and REVERSE commands will be reversed.



Make sure that the jumper is in place for mode 1 operation. In this mode, you need a separate digital output on your Arduino for each HB-25 that you want to control.

Controlling the HB-25


From the HB-25 data sheet, we can establish the following:

  1. The HB-25 operates like a servo. You only need to send a single pulse (in mode 1) to change direction or speed. Pulse width determines the HB-25 output.
  2. Valid pulse widths are 0.8 ms to 2.2 ms. If the HB-25 receives a pulse width which is outside this range, the motor will be stopped until it receives a valid pulse.
  3. The minimum time between pulses (HOLD_OFF_TIME) is 5.25 ms + pulse time (max 2.2 ms). Thus the worst case hold off time needs to be 7.45 ms. We have used 8 ms.
  4. The maximum time between pulses is unlimited, since a single pulse will be latched by the HB-25. An exception to this would be if the Communication Timeout feature of the HB-25 has been enabled. You can read more about this on the HB-25 data sheet (https://www.parallax.com/downloads/hb-25-motor-controller-product-documentation).
  5. Regardless of the mode, the HB-25 signal pin should be brought low immediately upon power up. The Library does this when you instantiate a HB25MotorControl object.
  6. Pulse width (1 ms = 1000 microseconds) will control the HB-25 as follows:

                        - 1.0 ms Full Reverse
                        - 1.5 ms Neutral (STOP)
                        - 2.0 ms Full Forward

Arduino Code


So making use of the above, we can control a HB-25 using the following Arduino code. Note that you will need to set controlPin to whatever digital output pin is connected to your HB-25. After you have initialised your HB-25 you can control it by writing a value between 1000 and 2000 to it using the servo.writeMicroseconds() method. You need to ensure that two commands are not sent within the minimum hold off time. This is taken care of for you in the library below.

#include <Servo.h>

#define REVERSE       1000
#define STOP          1500
#define FORWARD       2000
#define HOLD_OFF_TIME 8

Servo servo;

// HB-25 initialisation time (5ms)
delay(5);                                           
pinMode(controlPin, OUTPUT);
// Set control pin low on power up
digitalWrite(controlPin, LOW);  
// Attach HB-25 to the control pin & set valid range                    
servo.attach(controlPin, 800, 2200);
servo.writeMicroseconds(STOP);

Arduino Library


To make using the HB-25 a bit easier and to hide some of the complexity we wrote an Arduino library for it. This consists of four files (click to download):

1. HB25MotorControl.h;
2. HB25MotorControl.cpp;
3. Keywords.txt; and
4. HB-25_Test.ino

To use this library, you need to create a new folder in your Arduino libraries folder called HB25MotorControl. Copy HB25MotorControl.h, HB25MotorControl.cpp and keywords.txt into this folder. Then create a sub-folder called examples and place HB-25_Test.ino into that.

You need to restart the Arduino IDE (if it is already open) to be able to see and use this library.

The example sketch should demonstrate how you use the library, but at its simplest:

#include <Servo.h>
#include <HB25MotorControl.h>

const byte controlPin = 9;              //  Pin Definition

HB25MotorControl motorControl(controlPin);

void setup() {
  motorControl.begin();
  motorControl.moveAtSpeed(500);
}

void loop() {
  
}

Valid speed ranges for the forwardAtSpeed and reverseAtSpeed methods are 0 (stop) to 500 (maximum speed). For rampToSpeed and moveAtSpeed you can use from -500 (full reverse) to 500 (full forward). As before, a speed of 0 will stop the motor.

Feel free to modify and reuse the library as you like. If you do improve it, then let us know. Attribution is nice but not necessary, and as usual this library comes with no warranties, so use at your own risk.

Tuesday, November 24, 2015

Voice Display Board Completed

1.0 Recap


In a couple of earlier posts we described the design and construction of a voice display and driver board which would emulate that used by Kitt in the Knight Rider TV show. This has now been completed and mounted on AVA.



When we connected the voice display unit to the EMIC 2 Speech Synthesizer which AVA uses to talk, we discovered a problem. The display was driven hard on, even when AVA was silent. A quick measure with the multimeter showed that the EMIC 2 has a constant 2.4 VDC offset. As discussed in the earlier post, the LM3915 displays full scale at 1.25 V, so that was why all the LED's were on.

This is not unusual and a lot of the Arduino MP3 shields do the same thing. Unfortunately when we were testing the prototype, the EMIC 2 hadn't arrived from the USA so I tested using the piezo analog output on the Arduino (which doesn't have a DC offset).

2.0 High Pass Filter


There are a number of ways that you can remove the DC component of a signal, so that you are just left with the AC component. You could use an isolation transformer, but we didn't have one in the spare parts bucket. We did have a heap of resistors and capacitors so we decided to try a high pass filter.

A high pass filter, as the name suggests, passes signals above a selected cut-off point, ƒc eliminating any low frequency signals from the waveform. The circuit for a first order high pass filter looks like the following.

It delivers a response curve (courtesy of http://www.electronics-tutorials.ws/filter/filter_3.html):


It is generally accepted that the range of frequencies audible to humans is 20Hz to 20kHz. Consequently we will design our HP filter with an fc of 20Hz. The formula to calculate fc for a first order high pass filter is:


You can pick two variables and solve for the third, or you can go to an online filter design calculator, and let it do the hard work for you.

We selected an fc of 20Hz and a capacitor of 0.01uF (because we had one of this value), and the design site spat out a resistor value of 820k. If you plug in these values into the formula above you will get an fc of 19.4 Hz which is fine. The filter design site will even plot frequency and transient analysis graphs for you.



3.0 Conclusion


Adding the high pass filter between the EMIC 2 Speech Synthesizer and the voice display module did the trick. It removed the DC bias and allowed the speech signal to pass through. Here is a video of AVA speaking with the voice display module installed.


Saturday, October 31, 2015

Sharp GP2Y0A02YK0F IR Distance Sensor (20-150 cm) Arduino Library

Distance Measuring Options


If you are building an autonomous robot then you need to have some sort of obstacle avoiding sensors. I have attached a Parallax PING ultrasonic sensor to the front of AVA using a servo (so that I can scan 180 degrees). Ultrasonic sensors are generally pretty accurate but since they use reflected sound to calculate distance, they don't perform well if the obstacle is sound absorbing. Ultrasonic sensors can also miss thin objects or objects that reflect the sound away from the sensor. However, the range of ultrasonic sensors is much better than IR. For the PING, the available sensing range is 2 cm to 3 m.

To address the ultrasonic issues, I also mounted a Sharp IR Distance Sensor (GP2Y0A02YK0F) above the PING. The IR sensors don't perform well outside but indoors there accuracy is good enough as long as you stay within the quoted detection limits. IR sensors are generally cheaper than ultrasonic, their beams are more directional (narrower) and reflectivity of the surface is more important than the sound absorbing properties of potential obstacles.

Putting the two sensors together is complementary and allows the short comings of both sensors to be addressed (to an extent).

Sharp GP2Y0A02YK0F IR Distance Sensor (20-150 cm) 



Sharp manufactures a range of IR Distance Sensors. For the front sensor I selected the GP2Y0A02YK0F, which has a usable detection range of 20 to 150 cm's.

The Sharp GP2Y0A02YK0F measures distances in the 20–150 cm range using a reflected beam of infrared light.  By using triangulation to calculate the distance measured, this sensor can provide consistent readings that are less influenced by surface reflectivity, operating time, or environmental temperature.  The Sharp GP2Y0A02YK0F outputs an analog voltage corresponding to the distance to the reflecting object.

If you have a look at the GP2Y0A02YK0F datasheet, you will see that the analog voltage output does not have a linear relationship to distance. You can also see that the values go crazy below about 20 cm.


Noah over at the Arduino Mega Blog has reversed engineered this plot to work out the relationship between distance and the output voltage.

distance = 10650.08 * sensorValue ^ (-0.935) - 10 cm

Sharp GP2Y0A02YK0F IR Distance Sensor Arduino Library


To connect to an Arduino and get a distance you could just use Noah's formula above, but sometimes it is easier to wrap the complexity up in a library. I did a search and didn't find an existing library, so I decided to do one myself. Partly because I haven't done one before.

I did find a library for the GP2Y0A21YK IR Distance sensor (10 - 80 cm), but the characteristics must be different to the GP2Y0A02YK0F as the distances provided by the library are way off. Noah's formula on the other hand, provides very good correlation with the distances measured by the PING. For consistency, I based my library on what jeroendoggen did for his.

You can download the Sharp GP2Y0A02YK0F IR Distance Sensor (20-150 cm) Arduino Library files, and then follow these instructions to use it:

Instructions:

  • Create a directory called GP2Y0A02YK0F within the libraries sub directory where your Arduino sketches are saved.
  • Copy GP2Y0A02YK0F.h, GP2Y0A02YK0F.cpp and keywords.txt into the GP2Y0A02YK0F directory.
  • Within the GP2Y0A02YK0F directory, create a sub directory called examples.
  • Copy DisplayCM.ino into the examples sub directory.
  • Restart the Arduino IDE to see the new library.

Sharp GP2Y0A02YK0F Mounted on AVA


The following photo shows the Sharp IR sensor mounted above the front PING on AVA. I have fitted a sensor shield to the Arduino Mega which makes it very easy to connect the various sensors to the micro controller.