ESP32 USB stick

A collection of notes on how to use the tools available for the ESP32 MCU on the ESP32 USB stick and descriptions for a number of applications ready to use with the ESP32 USB stick.

Stick it to me.

Use the menu on the left to jump to a topic of interest.

Currently looking to see if there is enough interest to put the USB stick into production if there is interest, be sure to let us know.


ESP32 USB stick design

The ESP32 is a very capable MCU with Wi-Fi and Bluetooth support. There are plenty of development boards available for it but when looking for something readily available in USB stick format with proper protective housing, not a lot showed up.

Even Aliexpress did not come to the rescue this time.

When discussing this situation with some friends at Tech4U it was decided to create the ESP32 USB stick that could be produced in small batches and preferably would not cost an arm and a leg. Together we came up with the following design goals:

  • Needs to be portable, must be easy to throw into a laptop bag without damaging it.
  • Needs to be easy to assemble, preferably fit inside an off-the-shelf USB housing.
  • Must be able to use as a development board, both Espressif ESP-IDF support and Arduino support.
  • Must have out of the box serial driver support on any OS.
  • Must be able to work from a USB power bank, a USB port or USB wall charger.
  • Try to keep the cost down as much as possible.

    Choosing a housing was first and quickly it was decided to go with a standard Hammond enclosure as we had used it in a previous project. It is reasonably priced in low volumes. And even comes in different colors.

    Next up: the USB to serial interface. The normal go-to USB serial chip to use would have been an FTDI FT232. It has excellent driver support on various operating systems and is easy to interface. But when looking a little closer it is harder and harder to source at reasonable prices.

    An alternative was quickly found in the form of an EFM 32 Happy Gecko. Going with a microcontroller instead of a dedicated USB to serial chip gives the possibility of switching the ESP32 between 'NORMAL' and 'PROGRAM' mode without the need for buttons.

    Having no buttons helps the design goal 'easy to assemble' tremendously. No buttons means no hole drilling in the standard USB housing. The switch between 'NORMAL' and 'PROGRAM' mode is done by having the microcontroller spying on the serial stream for specific trigger commands.

    The final major component choice left was the one for the ESP32. We went with a ESP32-WROOM-32. The same one that is used on most available development kits.

    A first schematic was created. A board was layed out and ordered. And until the boards come back we can enjoy the 3D rendering.

    ESP32 USB rev1

    On the software side the first task to accomplish is to create the CDC serial driver for the Happy Gecko. Luckily Silabs Simplicity Studio comes with lots of excellent examples. Leaving us with the task of coming up with a protocol to switch the ESP32 between 'NORMAL' and 'PROGRAM' mode.

    When powered up, the ESP32 USB stick will boot the ESP32 module into 'NORMAL' mode and the EFM32 will be in 'transparant' mode happily sending all bytes sent and received over the USB serial to the ESP32.

    When triggered by a keyword the ESP32 USB stick will be in a sub-mode that recognizes a limited number of 'AT' commands that will reboot the ESP32 in the appropriate mode.

    The following simple protocol was devised and implemented:

    A5DBA5DB-A5DBA5DB\r\n --> trigger to break the EFM32 out of transparant mode
    AT+PROGRAM\r\n --> Send the ESP32 to program mode
    AT+NORMAL\r\n --> Send the ESP32 to normal mode

    Testing it with Terra Term shows that it working as expected:

    ESP32 USB BOOT Normal ESP32 USB BOOT Program

    To make development a lot easier without the constant need for opening Terra Term for writing the trigger word and preferred mode (and forgetting to close the COM port), a simple Windows application was made.

    The application will automatically find the USB stick, open the associated COM port, write the trigger word followed by the correct AT command and close the COM port again.

    ESP32 Mode switch GUI ESP32 Mode switch GUI

    The ESP32 mode switch tool is available right here. Unzip into a seperate directory, insert the USB stick and start it. No further configuration is needed.

    One good day, after staring at the 3D render for long enough, the prototype boards arrived.

    Revision 1 HW

    The EFM32 code was previously tested against a standard ESP32 development kit. Would everything work as expected on the final hardware?

    Short answer: yes. And it also fit perfectly in the selected case (as you can see in the picture above).

    Now, one of the major design goals for the ESP32 USB stick is the ability to be able to use it as a development board. To test this, the Arduino setup tutorial was followed.

    Arduino was setup as follows:

    Board selected: "ESP32 Dev Module"
    COM port selected: COM10 in this case. It is the one that identifies itself as 'Silicon Labs CDC Serial port' in device manager.
    Baud rate set to: 115200
    Example opened: BLE_scan
    Set the USB stick to PROGRAM using the ESP32 mode switch tool
    Sketch upload

    Upload success!

    SUCCESS

    Set board to NORMAL mode using the ESP32 mode switch tool
    Start Arduino serial monitor

    Output on serial monitor also works as expected.

    SUCCESS

    Great, Arduino is working. Now let's test the ESP-IDF Development Framework.

    The IDF version installed is v4.2.2 (although at time of writing latest stable release is v4.3). Install was done following the Get started instructions on the Espressif website and at the end of the install on a Windows system the 'ESP-IDF Command Prompt' is available.

    Set the ESP32 USB stick to PROGRAM mode using the ESP32 mode switch tool.
    Open the 'ESP-IDF Command Prompt'.
    Set directory to the project.
    'idf.py build'.
    'idf.py -p COM10 -b 115200 flash'.

    IDF OK

    OK, so we have the technology! Now what can we do with it? .......


    Sphero R2-D2 controller

    R2-D2

    Somewhere last year there was a very good deal on the Sphero R2-D2 droid it even came with the Force Band controller (more about this one later).

    It basically is a Bluetooth BLE controlled robot using an unknown protocol it has an app for both IOS and Android.

    Looks like Sphero is going to phase out support for the app on October 1, 2021 but (for now) will still offer their EDU App for it. Having an app is nice, but would it be possible to control the R2-D2 droid directly from a PC or Raspberry Pi?

    A quick search on the Internet shows that a number of people already have had a closer look at the Sphero protocol before:

    bbraun showed the basic protocol.
    Andrea Stagi delved even deeper into it.

    Knowing that it is possible to control the Sphero R2-D2 droid from anything else but the Sphero app, it must be possible to control R2-D2 with the ESP32 USB stick.

    With that in mind, the following goals were set:

  • Control the Sphero R2-D2 droid with the ESP32 USB stick.
  • Do it using a simple 'AT command' interface (which should make it work with any OS that can control a COM port and would make it scriptable in any language).

    To start off, there are some excellent Buetooth examples in the Espressif ESP-IDF Github and building on the GATT client example it is possible to get the needed Bluetooth support to start poking the Sphero protocol.

    From the information found on the Internet, the recipe for talking to the R2-D2 droid is the following:

    1. Find the device.
    2. Connect to the device.
    3. Write 'usetheforce...band' or '757365746865666F7263652E2E2E62616E64' to service handle 0x15 (21 decimal).
    4. Send 'wakup' packet '8D0A130D00D5D8' to service handle 0x1C (28 decimal).
    5. Start sending out 'magic' packets to let the robot do interesting stuff.

    To make it possible to interact with the R2-D2 droid (or any other BLE device for that matter) and to find out more about the Sphero protocol, the following minimal set of 'AT commands' was devised:

    AT+DON : Start BLE device discovery for 30 seconds.
    AT+DREPORT : Present a numbered list of discovered devices.
    AT+CONNECT=[nr] : Connect to device from the list with [nr].
    AT+DISCONNECT : When connected, disconnect device.
    AT+SDON : Discover the services on a connected BLE device.
    AT+SDREPORT : List the discovered services of the device.
    AT+WRITE=[service],[HEX values] : Write HEX values to a service on a connected device.
    AT+READ=[service] : Read a service on a connected device.

    The 'AT commands' need to be sent with both a CR and LF and to see what you are typing, turn on the 'local echo' in your terminal program. On Windows Terra Term is a very good choice that allows you to set the required options.

    Let's try out the new 'AT commands':

    Sphero poke 1

    OK, so that worked. 5 devices were found. The R2-D2 droid is number 3 in the list and has BLE name 'D2-79CC'. After connecting to it, it is revealed that it has 5 services to poke around in. And as expected, after a number of seconds it automatically disconnects because we have not told it the 'magic word'.

    Let's see what happens when we do tell it the 'magic word' and take it out of sleep mode.

    Sphero poke 2

    It's alive! The R2-D2 droid starts flashing its front LED between red and blue. That's.... not very exciting.....

    Now let's automate the connection / disconnection process with a number of AT commands (and implement the Sphero protocol encoding/decoding as documented by Andrea Stagi for good measure).

    AT+R2D2FIND : Connect to first available R2-D2 droid, take it out of sleep and trigger an animation.
    AT+R2D2FIND=[name] : Connect to R2-D2 droid with [name].
    AT+R2D2END : Send the R2-D2 droid to sleep and disconnect.
    AT+SPHEROLOG=0|1 : Turn off / on logging of Sphero messages received.

    Sphero poke 3

    Next step is to extend the 'AT command' set with the messages that will allow us to animate and control R2-D2.

    AT+R2D2ANIM=[0..55] : Play R2-D2 animation.
    AT+R2D2MOVE=[speed],[heading],[0|1] : Move R2-D2. Speed 0..99 , heading 0..359, forward or backward.
    AT+R2D2MSTOP : Stop all R2-D2 movement immediately.
    AT+R2D2STANCE=[1|2|3] : Set R2-D2 stance. 1 is tripod. 2 is bipod, 3 is wobble.
    AT+R2D2ROT=[angle] : Rotate R2-D2 top (-160..180).

    Typing the 'AT commands' in Terra Term gets frustrating quite quick. How about automating it a little more with an application.

    This is the droid you are looking for

    Download Force Control v1.0 right here. The application needs an ESP32 USB stick to work. Unzip the application in a separate directory, no further configuration needed.

    As Andrea Stagi already found out, it is possible to get acceloremeter data from the R2-D2 droid. So let's add support for it.

    AT+R2D2XYZON : start reporting 5 packets per second.
    AT+R2D2XYZON=[packets per second] : start reporting at [packets per second] rate.
    AT+R2D2XYZOFF : Turn off reporting.

    Turning on packet reporting will output lines with the following layout:

    +R2XYZ:[X orientation],[Y orientation],[Z orientation],
    [G in X],[G in Y],[G in Z],
    [absolute position X],[absolute position Y],
    [speed in X],[speed in Y]

    This is according to the following orientations.

    Up Side Down

    Example output stream after sending an 'AT+R2D2MOVE' command moving the droid forward with speed 40, heading 0:

    +R2XYZ:28,-1,2,-0.01,-0.45,0.84,0.00,0.00,-0.00,0.00
    +R2XYZ:30,-1,1,-0.03,-0.50,0.83,0.00,0.01,-0.00,0.05
    +R2XYZ:21,-1,1,0.03,-0.26,0.85,0.00,0.02,-0.00,0.05
    +R2XYZ:26,-1,1,-0.02,-0.37,0.83,0.00,0.02,-0.00,0.06
    +R2XYZ:24,0,1,-0.00,-0.35,0.93,0.00,0.04,-0.00,0.07

    That more or less gives us full control over the R2-D2 droid.

    To try it out on a standard ESP32 development kit there is a binary release up on Github. NOTE: Windows applications specifically look for the ESP32 USB stick and will not work with a standard development kit.


    Bonus: Sphero Force Band controller

    Or how to play Pac-Man using nothing but the Force.

    As mentioned before, the R2-D2 droid came with a Force Band controller.

    R2-D2

    On a hunch, the BLE traffic coming from the Force band was sniffed which resulted in some very familiar packets. Then trying to connect to the Force band in the same manner as normally connecting to the R2-D2 droid yielded immediate success.

    Turns out the Force Band can be controlled as well and supports a subset of commands similar to the R2-D2 droid. Now What can we do with this?

    The Force band basically is a 6-axis IMU. All the hard processing is done inside the unit. It is packaged in a very nice and usable form factor and can be set to output the status of the IMU at a programmable rate.

    Could the Force Band be used as an input device and if so, could it be used to play Pac-Man?

    First thing needed to do is to add some appropriate AT commands to the ESP32 USB stick.

    AT+FBFIND : Connect to first available Force Band.
    AT+FBFIND=[name] : Connect to Force Band with [name].
    AT+FBEND : Disconnect from Force Band.
    AT+FBXYZON : Start sending IMU measurements at a rate of 6 packets per second.
    AT+FBXYZON=[rate] : Start sending IMU measurements at a rate of [rate] packets per second.

    Next thing to do is make sense of the data coming out of the Force Band.

    Raw output shows that it is different from the acceloremeter data from the R2-D2 droid.

    8D001802FFC18C310AC0D12BD54230D863BDEDE5B73E9BE8983F76F07F5DD8
    8D001802FFC18C24BDC0D1546F4230D895BDE5D24A3E9FEBA63F76ECBEFAD8
    8D001802FFC18C28AFC0D16B344230D9CDBDF610353E9BF7F53F74F2B563D8

    Breaking down the first packet the following values are revealed:

    8D001802FF : Sphero header
    C18C310A : float -17.523944854736328
    C0D12BD5 : float -6.536600589752197
    4230D863 : float 44.2113151550293
    BDEDE5B7 : float -0.1161608025431633
    3E9BE898 : float 0.30450892448425293
    3F76F07F : float 0.9646071791648865
    5DD8 : Sphero footer

    Turning on IMU reporting from a Force Band with the AT+FBXYZON command will output a stream with the following layout:

    +FBXYZ:[X orientation],[Y orientation],[Z orientation],[G in X],[G in Y],[G in Z]

    Example output:

    +FBXYZ:-16,-6,44,-0.13,0.29,0.96
    +FBXYZ:-16,-6,44,-0.11,0.29,0.96
    +FBXYZ:-16,-6,44,-0.12,0.30,0.97

    Great, but how can we play Pac-Man with this?

    Step 1: Add support for the Force Band to the Force Control application.

    Use The Force

    Step 2: Plug in the ESP32 USB stick. Put the Force Band on your wrist. Turn on the Force Band, do not choose an activity when asked. Press 'Find Force Band' in the Force Control application. Point the hand with the Force Band on it towards the screen. Press 'Center Force Band'. Try out the on screen joystick to see if you can control it (press 'Center Force Band' again as needed).

    stick that.

    Step 3: Startup MAME from a cmd line with the following options: 'mame -window pacman -keyboardprovider dinput'.

    Step 4: Press the 'Simulate Keyboard' button in the Force Control application and set the window focus to the MAME window.

    Step 5: Play Pac-Man using the Force.

    Wacka wacka.


    Support for ESP_8_BIT

    One of the best hacks and uses for an ESP32 ever. Play Atari 8-bit, Sega Master System / Game Gear or NES games with nothing more than an ESP32 + Bluetooth Classic/EDR keyboard, joystick or WiiMote.

    See: Rossum Github page or the article at Hackaday that first drew my attention to it.

    Only one conclusion possible: MUST.... HAVE.... SUPPORT.... for it in the ESP32 USB stick.

    The hardware changes needed to support it look minimal.

    Changes

    And after bugging the friends at Tech4U long enough they relented and made a new board spin with the necessary changes.

    ESP8 bit board

    This time around we did not have to stare at the 3D render for too long.

    Rev 2. board.

    Solder some RCA jacks to the shiny new board. Not the greatest soldering job, but remember, we are doing this for science.

    RCA jacks

    Let's dig out the WiiMote from the pile of gaming peripherals and try this out.

    That works great. Now let's put our USB stick in a nice and shiny box.

    RCA jacks in a box

    ColecoVision support for ESP_8_BIT

    Only thing that would make ESP_8_BIT even better is if it also supports the ColecoVision. But that's why the source code is there right?

    Based on the ESP_8_BIT SMS emulator we now have a brand new ColecoVision emulator as well. New project dubbed ESP_8_BIT_PLUS with Source code available on Github.

    SG-1000 support for ESP_8_BIT

    The Sega SG-1000 is from a hardware point of view almost identical to the ColecoVision. So with a little tweaking we now also have support for that.

    New project dubbed ESP_8_BIT_MINUS with Source code available on Github.


    Going low level, ESP AT command support

    Espressif, the maker of the ESP32 has put a lot of work into making the features of the ESP32 chip available with simple AT commands. More information about this ESP-AT firmware can be found on the Espressif website.

    Having the power and ease of use of these AT commands in the ESP32 USB stick would be a very nice addition. The binary releases for this firmware are available on the Espressif site. Would it be possible to just download and re-program the ESP32 USB stick to be able to use it?

    Of course nothing is ever that easy. First problem to pop up is the hardware connection for the AT serial interface. Out of the box, the firmware expects the AT interface to be connected to UART1 with (RX GPIO16, TX GPIO17, CTS GPIO15, RTS GPIO14) while we only have UART0 connected with (RX GPIO3, TX GPIO1).

    Second problem to pop up is the Rules and regulations governing WLAN channels. To make a USB stick with this firmware available around the world, different configurations need to be made.

    Lucky for us, Espressif did have the foresight to make these parameters customizable.

    The module used on the ESP32 USB stick is an ESP32-WROOM-32 and at the time of writing the latest version firmware for this module is v2.2.0.0.

    Looking inside this zip file, we find the file 'factory_WROOM-32.bin'. This is a programmable firmware. According to the documentation, the Factory Parameter Bin file will be at hex location 0x30000 let's have a look at it with HxD.

    HxD Before

    Let's change this to parameters we can actually work with.

    HxD After

    Now let's program this firmware by using the Flash Download Tool.

    Set the USB stick to PROGRAM mode.
    Start the flash download tool.
    Select the newly created firmware file.
    Program.

    Program AT firmware

    Set the USB stick to NORMAL mode.
    Fire-up Terra Term.
    Setup terminal to transmit both a CR and a LF.
    Try out BLE in client role.

    That works

    We now have AT-firmware support.


    ESP32 Wi-Fi Penetration Test Tool support

    Having had success in making the AT-firmware available on the ESP32 USB stick, would it be just as easy to support other good tools. Maybe a Wi-Fi penetration test tool in handy USB stick format? ......

    Having seen the article at Hackaday about the tool made by risinek, it had to be tried out.

    To test it out, mr risinek's Github page kindly offers a build for us.

    Set the USB stick to PROGRAM mode.
    Fire up the flash download tool.

    FLASH GORDON IS ALIVE!

    And try it out.

    Is it evil?

    Wow, that is almost too easy. Maybe just stick to Playing games?