HID-serial (Rethinking V-USB HID & USnoobie bootloader)

I ran across a post on RaysHobby.net from October the other night while surfing on my tablet as the wife watched TV. The article is almost 6 months old and I found the concept rather neat. .. Ray did something different than the V-USB serial that I have used previously from RancidBacon's USBkeyboard.h library... that is, he made a HID descriptor that does not emulate a keyboard but is a bi-directional HID device... therefore, a small host application is required to connect to the HID interface.

http://rayshobby.net/?p=7363

Repeating... a small application is run on the OS (Win, Linus, iOS) and that application is written in Processing. The application presents itself as a terminal window with minimum options. No COM: ports are enumerated and the Keyboard is not disturbed - you can still edit code while the Arduino sends over USB to the HID interface. And yet, if you regain focus of the terminal app, you can send keystrokes to the running Arduino program. Ray provided 4 rather simple examples. What I am going to do in this post is to give you just one application that combines many of the features because none of them singularly really does justice to his library.

I compiled under 1.0.5r2 on Windows. I used this executable for the Windows OS:

As stated, I merged several examples into this sketch

  • Blinking LED on standard pin
  • Analog A0 display with line count
  • Analog channel x (0 thru 5) capability... Ex: Type A2 and click Send button
  • Help ... Ex: Type ? and click Send button
  • Echo... Type anything up to 29 characters and click Send button (or press Enter)

I have done many V-USB projects with the HID keyboard, but the ability to easily send keystrokes to the Arduino (USnoobie) is a really interesting option which I think I may come to use. But for now, here is the product of my playing...

// *******************************
// HID Serial:  http://rayshobby.net/?p=7363 
// Mod 20140308: Ray Burnette to enhance example, add Streaming
// This program opens an HID serial channel and shows how to send
// and receive messages from a host computer. To use it, you need
// to run the HIDSerialMonitor from a host computer (by OS Ver)
// http://github.com/rayshobby/hid-serial
// The program repeatedly prints out the value on a specific analog pin.
// Typing '?' and clicking "Send" will print the HELP function.
// Arduino 1.0.5r2
// Binary sketch size: 4,376 bytes (of a 28,672 byte maximum)
// *******************************
#include <Streaming.h>
#include <HIDSerial.h>

HIDSerial serial ;

unsigned long t = 0 ;
unsigned char buffer[32] ;
unsigned char adcCh = 0 ;
int led = 13 ;
long count ;

void HELP (void)  // invoked when app identifies '?' as the first character in buffer
{
  serial << "Application Help: \n \r" ;
  serial << "- type An where n is 0 - 5 to \n \r" ;
  serial << "  display an analog channel value \n \r" ;
  serial << "- type upto 29 characters to have \n \r" ;
  serial << "  them echoed to the terminal \n \r" ;
  return ;
}


void setup() {
  pinMode(led, OUTPUT);
  serial.begin();
  // there is no need to put anything out to the HID console at this time
  // because it is HID terminal is now connected until after the device is enumerated,
  // so we will just come in to the current HID stream after the terminal connects
}


void loop()
{  
  int value;
  digitalWrite(led, LOW);

  if (millis() > t + 1000)
  {
    t = millis();
    digitalWrite(led, HIGH);
    // serial.write('A');  
    // serial.print(adcCh);
    // serial.print(" = ");
    // serial.println(analogRead(adcCh));
    serial << ++count << ": " ;
    serial << "A" << adcCh << " = " << analogRead(adcCh) << "\n \r" ;
  }

  if ( serial.available() )
  {
    int size = serial.read(buffer);
    if (size!=0)
    {
      //serial.write((const uint8_t*)buffer, size);
      if (( buffer[0] == 'a' || buffer[0] == 'A') && ( buffer[1] >= '0' && buffer[1] <= '5') )
      {
        adcCh = buffer[1] - '0' ;
        // serial.write('A');
        serial << "Analog Pin: A" ;
        serial.print(adcCh) ;
        // serial.println(" selected.");
        serial << " selected \n \r" ;
       }

      else if (buffer[0] == '?')
      {
        HELP () ;
      }
      else
      { // Echo anything not parsed as a command: A0 / A1... A5
        // serial.write((const uint8_t*)buffer, size);
        serial << "Echoing: " << size  << " characters: \n \r";
        serial.write((const uint8_t*)buffer, size) ;
        // serial.write('\n');
        serial << "\n \r" ;
      }
    }
  }
  serial.poll();
}

Ray (no relation to the other Ray!)

Things to note:
USnoobie is a product of Frank Zhao http://eleccelerator.com/
The library HIDserial.h is a product of Rayshobby Shop: http://rayshobby.net/
The library UsbKeyboard.h is a product of Philip J. Lindsay Project Log : Arduino USB - ProjectLogArduinoUSB
EVERYthing you need for USnoobie to build your own can be found: USnooBie

Added:
The last picture shows the repeating every 1000mS of the value of A0 (default bootup condition) then I sent keyboard commands:
? (for Help)
now is the time (to echo the characters to the terminal)
A2 (to change monitoring from A0 to A2)

More Screen Shots of USB enumeration under Windows.

Note: The USnooBie bootloader enumerates as a USBasp device. After programming and rebooting the application sketch, the 328 enumerates as a HID device. The USnoobie documentation explains how to place the uC into bootloader mode by using RESET and D7 in tandem. If just inserted into USB port, the device enumerates based upon the application program library HIDserial. The USnooBie bootloader is running from a 12MHz crystal. There are bootloader files for 16MHz, too, but the HIDserial library tosses errors if compiles are attempted with any board setting by F_CPU=12000000L and my guess is that some tweaking would resolve this issue... but, you are on your own if you wish to go down that road.