USBKeyboard.h occasionally hangs

What do you think of using the serial port for debugging data?

Use print statements to announce where you are. Keep the strings short and the link fast and you shouldn't have a problem with overfilling the buffer.

If you don't like that one.

Set up a global variable and set it to different values at different places in your code.
Attach an interrupt handler to pin 3.
When it hangs. Press the interrupt button and output the value of the global variable some how. Maybe blink the value out on pin 13.

This might at least tell you where it is hanging, maybe then you can work on why.

I think those arcade buttons will be the problem. At the input points (D8 to D11) put a 0.1 uF cap to ground. That should throw away noise coming in.

Plus since these are simple buttons I think you certainly want the state change test. See reply #6.

Do both of those and then get back to us.

RandallR:
What is lost and what is left when the watch dog bites? I would assume globals and statics would not loose their values, anything else? Is there some why for your code to know that the watch dog had to wake it up?

I worked out a way of knowing you had been reset:

#include <avr/wdt.h>

// some stuff that shouldn't be there randomly
const char wantedSig [5] = { 'f', 'o', 'b', 'a', 'r' };

// compiler not to initialize these two variables
char __attribute__ ((section (".noinit"))) magicSig [5];
long __attribute__ ((section (".noinit"))) resetCount;

void setup ()
{
  
  // if signature there, we have restarted
  if (memcmp (wantedSig, magicSig, sizeof magicSig) == 0)
    resetCount++;
  else 
    {
    resetCount = 0;
    // put signature there
    memcpy (magicSig, wantedSig, sizeof magicSig);
    }
    
  Serial.begin (115200);
  Serial.print ("Reset count = ");
  Serial.println (resetCount);
  
  wdt_enable(WDTO_1S);  // reset after one second, if no "pat the dog" received
 }  // end of setup

void loop ()
{
  
Serial.println ("Entered loop ...");

Serial.println ("Point A");
delay (500);
Serial.println ("Point B");
delay (400);

wdt_reset();  // give me another second to do stuff (pat the dog)

Serial.println ("Point C");
delay (500);
Serial.println ("Point D");
delay (400);

while (true) ;   // oops, went into a loop
    
}  // end of loop

The code marked:

 __attribute__ ((section (".noinit")))

... does not get reinitialized by the compiler. So by using a field as a "signature" we can work out if we have been reset or not, fairly reliably.

That is great. I did not know about those attributes. I assume this is not ANSI standard

Doubt it. Not with the underscores there.

OK, so I'm still banging my head... Frustration grows and patience thins... but I'm still confident I will one day find the solution to my woes... In an effort to figure out what's going on I have simplified my code as much as possible and cleaned up the libraries which I downloaded to as few files as possible (or as close as I could get it).

Setup

I would like to start over explaining my setup where I am right now, step by step to make sure I'm not missing anything silly and ensure everyone is on the same page.

  1. I downloaded and installed the latest Arduino IDE 1.0.1
  2. I added the attached libraries to my arduino/libraries/UsbKeyboard folder
  3. I built the circuit found on the Practical Arduino website here http://www.practicalarduino.com/projects/virtual-usb-keyboard
  4. Added to the circuit is a single push button as defined in the Arduino Digital Button example
  5. The Arduino is powered from the USB cable and I have added a 220uF Capacitor where the USB enters the breadboard
  6. I added a 1uF Capacitor where the power enters the Arduino +5V rail to try and reduce niose
  7. i added a 1uF Capacitor where the Arcade Button enters pin 8 of the Arduino

I have compiled and installed the following code onto my Arduino board using the standard AVRISP programming method.

// Derived from this project
// http://www.practicalarduino.com/projects/virtual-usb-keyboard

// Requires the use of the "UsbKeyboard" library available from
// http://code.google.com/p/vusb-for-arduino/
#include "UsbKeyboard.h"

/*
============== PIN CONNECTIONS ==============
 D2  - USB (D+)
 D4  - USB (D-)
 D5  - USB (RESET)
 D8  - ARCADE BUTTON
 D13 - LED
 =============================================
 */

// Use the on-board LED as an activity display
int ledPin = 13;             

void setup()
{
  // Set up the activity display LED
  pinMode (ledPin, OUTPUT);
  digitalWrite (ledPin, LOW);

  //  initialize the pushbutton pins as an inputs
  pinMode(buttonPin8, INPUT);    
  
  // set the internal pull-up resistors
  digitalWrite(buttonPin8, HIGH);

  // Disable timer0 since it can mess with the USB timing. Note that
  // this means some functions such as delay() will no longer work.
  TIMSK0&=!(1<<TOIE0);

  // Clear interrupts while performing time-critical operations
  cli();

  // Force re-enumeration so the host will detect us
  usbDeviceDisconnect();
  delayMs(250);
  usbDeviceConnect();

  // Set interrupts again
  sei();

  // initialization period....
  // I find that sending keystrokes too soon can cause the USB connection
  // to fail, so instead let's just wait ten seconds while placing updates to USB
  for (int initCounter = 0; initCounter < 150; initCounter++)  {
    delayMs(45);   
    UsbKeyboard.update();
  }
}

void loop()
{
  UsbKeyboard.update();
  
  digitalWrite (ledPin, HIGH);
  
  // Send Down Arrow through USB
  UsbKeyboard.sendKeyStroke(0x51);
  
  digitalWrite (ledPin, LOW);  
  
  delayMs(40);  
  
}

// Define our own delay function so that we don't have to rely on
// operation of timer0, the interrupt used by the internal delay()
void delayMs(unsigned int ms)
{
  for (int i = 0; i < ms; i++) {
    delayMicroseconds(1000);
  }
}

My Problem

So my problem is the action of pushing the button appears to cause enough noise to hang the Arduino (or the USB Bus?). Using the code above, the button is not defined in the sketch and I am not even worried about it's state, I simply send a down keystroke roughly every 50 ms. before calling the UsbKeyboard.sendKeyStroke function I first turn on the LED which I then turn off immediately after the function is complete. Every single time the Arduino hangs, the light is on.

Interestingly I can even remove the orange wire between the button and the Arduino pin and the board will still hang. I believe this may be important as it leads me to believe that it MIGHT noise affecting the USB bus itself.

As usual the floor is open for discussion.

Thanks for any input!

Dave

UsbKeyboard.zip (40.4 KB)

It appears from your sketch that you are not even reading your input button. Your just sending down arrows. And you are saying that even this hangs? That would kinda rule out any switch bounce.

Does this mean that if I use your library, my virtual keyboard is going to hang as well?

I will let you know my results.

Exactly! I wanted to make sure that it wasn't the code for the switch that was hanging my project and your are exactly correct in that the sketch simply sends down arrows. And yes, it randomly hangs with the LED on when I push the button a bunch of times. Would love to know, (A) if you get it running and (B) if yours ends up hanging as well.

huntd69:
3) I built the circuit found on the Practical Arduino website here practicalarduino.com

Not quite. From that page:

3.6V Zener diodes (must be rated at 0.5W or less, 1W won't work)

You show 3.3V Zener diodes. I'm not saying that is the problem, but once you start straying from the circuit, especially with something rather voltage sensitive like USB, you aren't helping.

Sorry, my bad, yes they are 3.6v! I had 3.3v and 3.9v but had to order the 3.6 to get it to work.

I was unaware that USB was so voltage sensitive. If so, what about the tolerances of the resistors? The design doesn't say what the tolerances are, just the values.

I have seen some designs where instead of using zener diodes, is just runs the ATMega at a lower voltage. However, rather than have some sort of regulator, the designs simply uses the forward bias voltage drops of 2 diodes.

I was thinking about doing that and use an ISP interface to download sketches.

I was unaware that USB was so voltage sensitive.

You said yourself that the 3.9 and 3.3 zener diodes didn't work.

I tried out your sketch on my own version of that circuit (changing it to send the letter "a" so I could see it). It output "a" hundreds of times without hanging.

On your photo, I can't see the USB ground connected to your circuit ground. Is it?

Certainly, the sketch seems to work fine if left alone and switching the output character shouldn't matter. My problem only appears when I push the Arcade Button (or I also tried a standard SPST switch). Pushing the button rapidly such as might occur during a video game seems to hang the "circuit" even though there is nothing in the sketch that references Pin 8 or a button / switch on that pin. I have tried both both pulling the pin up to 5V and pulling it down to ground and both can cause the "circuit" to hang.

If you were reffering to my circuit, then yes, the USB Ground is indeed connected to the bread board's ground rail. The black wire heading out the left is a USB cable that was cut and stripped then inserted into the breadboard.

Also if I recal, even if I remove the orange jumper in my circuit, the "circuit" can hang. This all leads me to believe that it's a momentary voltage drop causing either the Arduino to hang or the USB communications to fail and leaves the Arduino waiting for the USB bus to become free. As you mentioned USB is very sensitive to voltage... But honestly I am just guessing without an oscilloscope to check these theories.

It may also just be that the breadboard is not a good circuit for data lines and that I have to build a proper circuit on a PCB.

I too ran your code on my board and it ran for a couple hours without hanging.

Is it possible that there is some noise getting onto the USB line? I'm thinking that if there was some sort of loose connection that the physical act of pushing the button could cause the noise. I would say that the watchdog might work but the restart process takes so long. Maybe if you could use the trick that Nick showed, so you might be able to shortcut the startup process.

Maybe you could commit some of your design to solder. As you can see from my photo, I built a small plug-in board for the USB interface. I may only use it of bread-boarding but it keeps everything in place. Sort of a building block if you will.

I would try adding a 0.1uF capacitor between Gnd and +5V where the wires go onto the breadboard (near the link marked 35 on your photo). I suspect that hitting the switch is sending a jitter into the power line which is upsetting the processor.

Hi Everyone,

I'm working on an identical project as huntd69. I am hoping to use the VirtualUSBKeyboard sketch to make an Uno act as a USB keyboard.

Like huntd69, my arduino freezes whenever a button is pressed.

Prior to purchasing the USB circuit hardware from Mouser, I wanted to verify that I could get the code to behave correctly. As such, I would like to have the Uno's LED on pin 13 turn off whenever I connect an input pin to the Uno's GND via a jumper.

Unfortunately, whenever I connect the input pin to GND, the Uno freezes. To monitor what is happening, I added the following code at the top of void loop():

void loop()
{
  UsbKeyboard.update();
  Serial.println("New Loop");
  Serial.println(digitalRead(BUTTON_C));
...

This produces the following output:

New Loop
1
New Loop
1
New Loop
1
New Loop
0

From this output, it seems that the Uno is successfully reading that the input pin is connected to GND once, but then freezes. I've tried multiple Unos, but all of them exhibit the same behavior.

Could you provide me with pointers to understand what is happening?

Thanks for your help!
arduinoRobo

Hey robo, I was able to resolve my issues by commiting to solder. I have no idea why, but when i commited the project to solder the hanging magically vanished! Randal had built just the USB portion of the circuit and I believe he didn't have any issues.

Anyways, if you can I would sugest soldering it together if you haven't already as a first step if at all possible. I had narrowed it down to somewhere in the USBKeyboard.h file where it was hanging (don't have my notes infront of me now) but couldn't identify the exact line. I came to the conclusion that there must have been noise or something as while it happened frequently, it wasn't every single time and it was sporatic. It wasn't code related as I pulled all of the code that referenced the switch pin out of the sketch and the MC would still sporatically hang when the button was pushed. As you mentioned, I too tried on multiple Arduino cards (Dumelinove, NANO and even a standalone). Possibly a drop in voltage as the button is closed but without an osscilloscope it is hard to tell what's going on. One thing is for sure, USB is extremely sensitive to voltages.

Solder Solder Solder... That's my three cents! :wink:

Hi huntd69,

Thanks for the advice. Once I verify that the code works as it should, I will be moving everything onto a PCB. I would like to use an embedded Arduino circuit I made in the eventual keyboard device.

At this point, however, I don't yet have any components to solder. I literally just have a commercial Uno with a jumper connected to the input pin at one end, which I then manually plug into a GND pin on the Uno while the code is running. My hope was that I could use this to verify that the button is reading (and thus the USB signals are sending) by looking at whether the LED on pin 13 goes off when the button is grounded out. For some inexplicable reason however, it is freezes every time and as soon as it reads the button once -- since I get exactly one 0 printed out to the serial monitor before nothing else prints...?

How is the input pin configured? Can you show your setup function?

Hi Nick,

Thanks for your help. Please find my header definitions and setup() function code below:

EDIT: Didn't post the latest version of the code -- posted version did not have Serial.begin(9600); at the bottom of setup().

#include "UsbKeyboard.h"

// Define the inputs to use for buttons
#define BUTTON_A 6
#define BUTTON_B 7
#define BUTTON_C 8
#define BUTTON_D 9
#define BUTTON_MSG 10
#define BUTTON_ENTER 11

// Use the on-board LED as an activity display
int ledPin = 13;

/**
 * Configure button inputs and set up the USB connection to the host
 */
void setup()
{
  // Set up the activity display LED
  pinMode (ledPin, OUTPUT);
  digitalWrite (ledPin, HIGH);

  // Set the button pins to inputs
  pinMode (BUTTON_A, INPUT);
  pinMode (BUTTON_B, INPUT);
  pinMode (BUTTON_C, INPUT);
  pinMode (BUTTON_D, INPUT);
  pinMode (BUTTON_MSG, INPUT);
  pinMode (BUTTON_ENTER, INPUT);

  // Enable the CPU's internal 20k pull-up resistors on the button
  // inputs so they default to a "high" state
  digitalWrite (BUTTON_A, HIGH);
  digitalWrite (BUTTON_B, HIGH);
  digitalWrite (BUTTON_C, HIGH);
  digitalWrite (BUTTON_D, HIGH);
  digitalWrite (BUTTON_MSG, HIGH);
  digitalWrite (BUTTON_ENTER, HIGH); 

  // Disable timer0 since it can mess with the USB timing. Note that
  // this means some functions such as delay() will no longer work.
  TIMSK0&=!(1<<TOIE0);

  // Clear interrupts while performing time-critical operations
  cli();

  // Force re-enumeration so the host will detect us
  usbDeviceDisconnect();
  delayMs(250);
  usbDeviceConnect();

  // Set interrupts again
  sei();

//Begin serial
Serial.begin(9600);
}

In my test setup, I'm trying to read pin 8, which is BUTTON_C.