Home > ARM, USB > FEZ Panda and USB Host

FEZ Panda and USB Host

As I promised in my previous post, I would show you how to get USB Host working on the FEZ Panda.

FEZ Panda - USB Host Cable


When I first glanced at the LPC2387 datasheet (the ARM on the Panda), I notice that it actually supported USB Host. Then I thought why it wasn’t possible to use USB Host on the Panda, and I quickly found out that it was because it required some hardware modifications.

USB Cable Wiring


The difference in the hardware between USB Client and USB Host is that the Host is powering the Client, and the Panda had a protection diode so no power would go “out” the USB port. Another thing to notice is that USB Host requires two 15K resistors to pull D+ and D- to ground.

FEZ Panda - USB Host cable wiring


SMD solution
So how did I do it? I didn’t want to modify the FEZ Panda board, as the USB port would then be a permanent USB Host port. Instead I thought it would be nice just to have a cable for the USB Host thing, which should include the two resistors, and a power wire for the +5V power supply.
The first image in this post is my cable, and the second image shows the connections, where there is soldered two 15K SMD 0805 resistors inside. This took a long time to make because it was so small, and SMD resistors can’t handle much force. On a longer term basis it would be better to make an adapter PCB instead.

USB Host cable Schematic

Above you can see the simple schematic of the changes that has to be made to the cable, including where to solder/connect the two 15K resistors.


Thru Hole solution
Instead of using SMD resistors I recommend you to use Thru Hole resistors, and they can handle a lot more force, and the joint will also be more reliable.

FEZ Panda - USB Host Cable


The assembly method is the same as with the SMD resistors. If you don’t have any 15K resistors in hand, we have also tested it with a 12K instead, and everything seems to be running fine with that too.

FEZ Panda - USB Host cable wiring


Oh, and please notice the USB Mini-B to USB Female A adapter at the end. This can be bought at Amazon for $1.87!

USB Connector Pinout


After I made the cable the last thing I had to do was to update the firmware on the FEZ Panda, as the firmware (USBizi) for the FEZ Panda, didn’t support USB Host until V4.1.5.0, though the processor did. After I uninstalled the old firmware/SDK, downloaded the new one, and installed it, I was ready to update the firmware. I just followed this simple Youtube guide:

After the firmware was updated, I connected a cable from the MODE pin to GND to enable Serial Port (COM1) debugging, as the USB port will now be used for USB Host functions.
Then I just followed the “USB Host – Mass Storage” chapter in the Beginners Guide to .NETMF.

To help you guys getting started, I used this code to test the USB Host function. The applications outputs which device is connected, and if a Mass Storage device is detected, the files- and folder tree is shown too.

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;

using Microsoft.SPOT.IO;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.USBHost;
using System.IO;

using System.IO.Ports;
using System.Text;


namespace FEZ_Panda_Application1
{
    public class Program
    {
        static bool ledState = false;
        static OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, ledState);

        static SerialPort UART = new SerialPort("COM2", 115200);


        // Hold a static reference in case the GC kicks in and disposes it
        // automatically, note that we only support one in this example!
        static PersistentStorage ps;

        public static void Main()
        {
            UART.Open();

            WriteSerial("Starting...");

            // Subscribe to RemovableMedia events
            RemovableMedia.Insert += RemovableMedia_Insert;
            RemovableMedia.Eject += RemovableMedia_Eject;

            // Subscribe to USB events
            USBHostController.DeviceConnectedEvent += DeviceConnectedEvent;
            USBHostController.DeviceDisconnectedEvent += DeviceDisconnectedEvent;
            // Sleep forever
            //Thread.Sleep(Timeout.Infinite);

            int read_count = 0;
            byte[] rx_byte = new byte[1];

            while (true)
            {
                // read one byte
                read_count = UART.Read(rx_byte, 0, 1);
                if (read_count > 0) // do we have data?
                {
                    //WriteSerial("I recieved: " + (char)rx_byte[0]);
                    switch ((char)rx_byte[0])
                    {
                        case 'W':
                            WriteSerial("Writing content to test file:");
                            WriteTestFile("Hello there!");
                            WriteSerial("   Hello there!");
                            break;
                        case 'R':
                            WriteSerial("Reading content from test file:");                            
                            WriteSerial("   " + ReadTestFile());
                            break;
                    }
                }
            }
        }

        static void DeviceConnectedEvent(USBH_Device device)
        {
            string USBDeviceType = "";

            switch (device.TYPE)
            {
                case USBH_DeviceType.HID:
                    USBDeviceType = "HID";
                    break;
                case USBH_DeviceType.Hub:
                    USBDeviceType = "Hub";
                    break;
                case USBH_DeviceType.Joystick:
                    USBDeviceType = "Joystick";
                    break;
                case USBH_DeviceType.Keyboard:
                    USBDeviceType = "Keyboard";
                    break;
                case USBH_DeviceType.MassStorage:
                    USBDeviceType = "Mass Storage";
                    break;
                case USBH_DeviceType.Mouse:
                    USBDeviceType = "Mouse";
                    break;
                case USBH_DeviceType.Printer:
                    USBDeviceType = "Printer";
                    break;
                case USBH_DeviceType.Serial_CDC:
                case USBH_DeviceType.Serial_FTDI:
                case USBH_DeviceType.Serial_Prolific:
                case USBH_DeviceType.Serial_Sierra_C885:
                case USBH_DeviceType.Serial_SiLabs:
                    USBDeviceType = "USB to Serial converter";
                    break;
                case USBH_DeviceType.Sierra_Installer:
                    USBDeviceType = "Sierra Installer";
                    break;
                case USBH_DeviceType.Unknown:
                    USBDeviceType = "Unknown";
                    break;
                default:
                    USBDeviceType = "Unknown";
                    break;
            }

            WriteSerial("USB Device connected: " + USBDeviceType);
            WriteSerial("ID: " + device.ID + ", Interface: " + device.INTERFACE_INDEX + ", Type: " + device.TYPE);

            led.Write(true);

            if (device.TYPE == USBH_DeviceType.MassStorage)
            {
                WriteSerial("Mounting Mass Storage...");
                ps = new PersistentStorage(device);
                ps.MountFileSystem();                
            }
        }

        static void DeviceDisconnectedEvent(USBH_Device device)
        {
            WriteSerial("USB Device disconnected...");
            led.Write(false);
        }

        static void RemovableMedia_Insert(object sender, MediaEventArgs e)
        {
            WriteSerial("Storage \"" + e.Volume.RootDirectory + "\" is inserted.");
            WriteSerial("Getting files and folders:");
            WriteSerial("");
            if (e.Volume.IsFormatted)
            {
                WriteFilesAndFolders(e.Volume.RootDirectory, e);
            }
            else
            {
                WriteSerial("Storage is not formatted. Format on PC with FAT32/FAT16 first.");
            }
            WriteSerial("");
        }
       
        static void RemovableMedia_Eject(object sender, MediaEventArgs e)
        {
            WriteSerial("Storage \"" + e.Volume.RootDirectory + "\" is ejected.");
        }


        static string[] files, filesSub;
        static string[] folders, foldersSub;
        static void WriteFilesAndFolders(string path, MediaEventArgs e)
        {
            files = Directory.GetFiles(path);
            folders = Directory.GetDirectories(path);
            WriteSerial("Files available on " + path + ":");
            for (int i = 0; i < files.Length; i++)
                WriteSerial("   " + files[i]);

            WriteSerial("Folders available on " + path + ":");
            for (int i = 0; i < folders.Length; i++)
            {
                WriteSerial("   " + folders[i]);
                WriteSerial("");
                WriteSubFilesAndFolders(folders[i], e);
            }
        }

        static void WriteSubFilesAndFolders(string path, MediaEventArgs e)
        {
            filesSub = Directory.GetFiles(path);
            foldersSub = Directory.GetDirectories(path);
            WriteSerial("Files available on " + path + ":");
            for (int i = 0; i < filesSub.Length; i++)
                WriteSerial("   " + filesSub[i]);

            WriteSerial("Folders available on " + path + ":");
            for (int i = 0; i < foldersSub.Length; i++)
            {
                WriteSerial("   " + foldersSub[i]);
                WriteSerial("");
                WriteSubFilesAndFolders(foldersSub[i], e);
            }
        }

        static void WriteTestFile(string dataToWrite)
        {
            if (VolumeInfo.GetVolumes().Length < 1) return;
            // Assume one storage device is available,
            // access it through NETMF          
            string rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory;
            FileStream FileHandle = new FileStream(rootDirectory + @"\hello.txt", FileMode.Create);
            byte[] data = Encoding.UTF8.GetBytes(dataToWrite);
            // write the data and close the file
            FileHandle.Write(data, 0, data.Length);
            FileHandle.Close();
        }

        static string ReadTestFile()
        {
            if (VolumeInfo.GetVolumes().Length < 1) return "No Mass Storage found!";
            // Assume one storage device is available,
            // access it through NETMF
            string rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory;
            if (!new FileInfo(rootDirectory + @"\hello.txt").Exists) return "File not found!";
            FileStream FileHandle = new FileStream(rootDirectory + @"\hello.txt", FileMode.Open, FileAccess.Read);
            byte[] data = new byte[100];
            // write the data and close the file
            int read_count = FileHandle.Read(data, 0, data.Length);
            FileHandle.Close();
            //Debug.Print("The size of data we read is: " + read_count.ToString());
            //Debug.Print("Data from file:");
            //Debug.Print(new string(Encoding.UTF8.GetChars(data), 0, read_count));
            return new string(Encoding.UTF8.GetChars(data), 0, read_count);
        }
        static void WriteSerial(string StringToWrite)
        {
            // convert the string to bytes
            byte[] buffer = Encoding.UTF8.GetBytes(StringToWrite + "\r\n");
            // send the bytes on the serial port
            UART.Write(buffer, 0, buffer.Length);
        }
    }
}

This video is just an example of what you can use the USB-host functionality for:

Update
Kristian has succesfully connected the PS3 Controller to the FEZ Panda, for more information, take a look at his post.

Categories: ARM, USB Tags:
  1. April 14th, 2011 at 19:56 | #1

    Hi I hope I can explain my question because my English is very bad.

    I followed your guide mounted a pcb for the adapter, but my question is if the power only 5v + fez is connected also to the host or just for pen driver ..

  2. April 14th, 2011 at 20:48 | #2

    @Alejandro
    Dear Alejandro.
    The 5V from the FEZ should be connected to the pen driver (USB Host) connector, by either shorting the protection diode, or by making a 5V cable as I did.

  3. April 20th, 2011 at 20:26 | #3

    @Thomas Jespersen

    ok tnks Thomas XD

  4. Hattman
    September 22nd, 2011 at 20:54 | #4

    Wrong, white -- , green +

  5. September 23rd, 2011 at 17:26 | #5

    @Hattman
    Thank you for finding the mistake and reminding us. The images have now been changed according to the correct pinout, found here: http://pinouts.ru/Slots/USB_pinout.shtml

  6. Nab
    April 10th, 2012 at 01:24 | #6

    can you please make a video on how to make this cable ?

  7. April 10th, 2012 at 09:00 | #7

    @Nab
    Well you should be able to make the cable from the images and description -- it isn’t that hard.
    If you have any questions please do ask and I will try to explain what you have to do to make your own cable.

  8. Nab
    April 10th, 2012 at 14:13 | #8

    @Thomas Jespersen
    in the image “FEZ Panda -- USB Host cable wiring” (under “Thru Hole solution”),
    can you please draw it to make it clearer ?

    from the angle it was taken, I can guess that both ends of the white are connected to one side of a resistor & both ends of the black are connected to the other.
    & (maybe) the reds (3 cables) & the greens are connected to one side of a resistor & the other side is left hanging !!

    I do apologize if I seem to be rude, but the connections are not clear.
    & I come from a programming background, so, I still have a long way to go with hardware.

    Thanks for sharing the idea though.

  9. April 10th, 2012 at 16:58 | #9

    @Nab
    No problem. I have now made a schematic of the connections.
    Please recheck the blog post, in the middle you will find the schematic.

    Please tell me whether this is enough or you require more specific details.

  10. Nab
    April 11th, 2012 at 23:47 | #10

    @Thomas Jespersen
    Thank you very much, now it’s crystal clear.

    this should be fun :)

  11. Ronny
    June 19th, 2012 at 14:06 | #11

    Hi,

    will this modification work for a Pandaboard ES as well? Because I look around the web for days now to get the OTG in host mode but no solution and this seems as the most promising…
    would be great to get some response.

  12. June 19th, 2012 at 14:22 | #12

    @Ronny
    If the USB port on the Pandaboard ES is an OTG port there should be some extra transistor driver circuitry for enabling the Host feature, so a fix like this will be unnecessary!
    We haven’t tried the Pandaboard ES so I can’t tell you exactly what to do but I expect you should make some changes or enabling something on the Kernel side.

    Regards Thomas

  13. Bekker
    January 9th, 2013 at 16:44 | #13

    Hi
    I tried making the cable, and hooking up a bus pirate to debug and power the Panda…
    But when i connect somthing to the usb, i dont seem to get power? what can i have done wrong? The 5+ should be connected to where excatly?

  14. January 9th, 2013 at 21:29 | #14

    @Bekker
    Did you remember the red +5V injection wire?
    This should be connected to the 5V pin on the FEZ Panda.

  1. No trackbacks yet.