mbed Starter Kit Experiment Guide

This Tutorial is Retired!

This tutorial covers concepts or technologies that are no longer current. It's still here for you to read and enjoy, but may not be as useful as our newest tutorials.

Pages
Contributors: Shawn Hymel
Favorited Favorite 8

Experiment 6: USB Host and Threading

In this tutorial, we turn the mbed LPC1768 into a USB host. For this, we will use mbed's USBHost library and the USB Type A Female Breakout. Leave the LCD connected, as we will use it to display characters from a USB keyboard. Additionally, we introduce the concept of threading so that we can essentially do 2 things at once (specifically, listen for keystrokes and blink an LED).

IMPORTANT: You will need a USB keyboard for this tutorial.

mbed USB host keyboard circuit

Suggested Reading

The Circuit

This circuit can be made with parts in the SparkFun mbed Starter Kit. Also, keep in mind that the LPC1768 box contains a USB mini-B cable for programming and power.

Parts List

To follow this experiment, you would will need the following materials if you did not order the SparkFun mbed starter kit. You may not need everything though depending on what you have. Add it to your cart, read through the guide, and adjust the cart as necessary.

In addition to the listed parts, you will also need a USB keyboard to complete the tutorial.

Schematic

mbed USB Host schematic

Click on schematic to view larger image.

Connections

Connect the LPC1768 to the LCD and USB breakout in the following fashion. Note that the LCD uses the same connections as in Part 3.

Fritzing Diagram

mbed usb host fritzing

Hookup Table

Place the LPC1768 in a breadboard with pin VOUT in position i1 and pin 20 in position b20.

Connect the rest of the components as follows:

Component Breadboard
uLCD-144-G2* h26 (RES) h27 (GND) h28 (RX) h29 (TX) h30 (+5V)
USB Type A Female Breakout b26 (VCC) b27 (D-) b28 (D+) b29 (GND)
Jumper Wire j2 d26
Jumper Wire e26 f30
Jumper Wire a1 ( - )
Jumper Wire a9 f28
Jumper Wire a10 f29
Jumper Wire a11 f26
Jumper Wire ( - ) f27
Jumper Wire j9 e27
Jumper Wire j10 e28
Jumper Wire ( - ) e29

* Pins not listed are not used.

The Code

For this tutorial, we will be using the LCD and USB Host libraries. In our main.cpp, we create a thread that runs the USB Host function separately from the rest of the program. This allows us to blink an LED and have it not interrupt or be interrupted by keyboard input.

Libraries

Navigate to the mbed.org, login, and navigate to your Compiler.

Create a new program with the "Blinky LED Hello World" template. Name it something like "usb_host."

Navigate to the following pages and import each library into your "usb_host" program.

The mbed library should already be imported if you used the "Blinky" template.

mbed USB Host libraries

Program

Click on "main.cpp" in your project, remove the template code, and copy in the following code.

language:c
// USB host keyboard and LCD demo

#include "mbed.h"
#include "USBHostKeyboard.h"
#include "uLCD_4DGL.h"

// LED to demonstrate multi-threading
DigitalOut led(LED1);

// Graphic LCD - TX, RX, and RES pins
uLCD_4DGL uLCD(p9,p10,p11);

// Callback function from thread
void onKey(uint8_t key) {
    uLCD.printf("%c", key);
}

// Function that runs continuously in the thread
void keyboard_task(void const *) {

    USBHostKeyboard keyboard;

    while(1) {

        // Try to connect a USB keyboard
        uLCD.printf("Waiting...\n");
        while(!keyboard.connect()) {
            Thread::wait(500);
        }
        uLCD.printf("Connected!\n");

        // When connected, attach handler called on keyboard event
        keyboard.attach(onKey);

        // Wait until the keyboard is disconnected
        while(keyboard.connected()) {
            Thread::wait(500);
        }
        uLCD.printf("\nDisconnected!\n");
    }
}

// Main - the program enters here
int main() {

    // Initialize LCD
    uLCD.baudrate(115200);
    uLCD.background_color(BLACK);
    uLCD.cls();
    uLCD.locate(0,0); 

    // Create a thread that runs a function (keyboard_task)
    Thread keyboardTask(keyboard_task, NULL, osPriorityNormal, 256 * 4);

    // Flash an LED forever
    while(1) {
        led=!led;
        Thread::wait(500);
    }
}

Run

Compile the program and copy the downloaded file to the mbed. Connect a USB keyboard to the USB breakout board.

mbed with USB breakout board and keyboard

Press the mbed's restart button, and the LCD should show "Waiting..." If the keyboard was connected properly, you should see "Connected" on the LCD. Once you see "Connected," start typing! You will see your keystrokes appear on the LCD.

NOTE #1: If you have some trouble getting the keyboard to connect, make sure the keyboard is plugged in and try resetting the mbed.

NOTE #2: The USBHost library is in beta and has some issues connecting USB devices sometimes. Not all keyboards will work with this demo.

Also, if you try typing too fast, you will see repeat keys. This is because the mbed does not process two simultaneous key presses correctly.

mbed running keyboard demo on LCD

Concepts

We covered two important concepts in this tutorial: USB and threading. Both create a unique set of opportunities for embedded systems.

Callbacks

In our program, we define an onKey() function. This is a callback.

onKey(uint8_t key) is a function that is declared in the USBHostKeyboard library, but the definition is left to us to implement. Callbacks are executed whenever an event occurs in another piece of code (within the USBHostKeyboard code, in this case).

We define onKey() in our code (it prints the received character to the LCD), and then we pass the onKey() function to our USBHostKeyboard object with the following line:

language:c
keyboard.attach(onKey);

This lets the USBHostKeyboard object know where to find the onKey() callback function. After that, whenever a keystroke occurs on the connected keyboard, the onKey() function is called.

USB Host

Universal Serial Bus (USB) has been around for many years. Created in the mid-1990s, USB has been the most popular way to connect peripherals to computers. As a result, many embedded systems support USB communications.

While many embedded systems can support being a USB Device, having USB Host capabilities is only seen in more powerful processors. Being able to act as a host means that we can plug in a number of devices normally reserved for computers: keyboards, mice, flash drives, etc. If you really want to get involved in USB development, this book is a great place to start.

Threading

If you are carefully reviewing the code, you might have noticed the keyword "Thread" appear. This is a function built into the mbed library that allows us to run multiple processes at the same time (well, not quite. The processor relies on a technique called Scheduling to determine which process gets run, since only one can run at a time in reality). It is important to understand that our mbed is powerful enough to allow us to run multiple threads (many, smaller microcontrollers, such as the ATmega 328p, of Arduino fame, have trouble with multiple threads).

When a Thread is created, as in our USB Host example, it calls the function given in its parameters (keyboard_task, in this case). The threaded function runs while the rest of the program continues at the same time (in theory, the "Flash an LED forever" section runs while "keyboard_task" is executing simultaneously).

If you would like more control over threads and the scheduling, take a look at mbed's Real Time Operating System (RTOS) library.

Going Further

Adding USB lets us connect many different peripherals to our mbed. Additionally, we learned about threading, which lets us run multiple processes at the same time.

Beyond the Tutorial

  • Make the backspace key actually delete characters on the LCD
  • Use the graphics functions of the LCD to control a ball with the keyboard's arrow keys
  • Use a mouse to control a ball around the LCD (Hint: see USBHostMouse)
  • Read some files on a USB flash drive (Hint: see USBHostMSD)

Digging Deeper