Arduino Restarts after Delay With Usb.Task()

I am using the following code for reading a bar-code scanner (which I will later be using to send a web request with). There is a commented portion that just prints a period after a one second delay five times, if more than two seconds of delay are uncommented, the Arduino will seemingly restart after scanning a code (as the setup() function runs over again). Without any delays in these portions, the scanner works fine.

#include <hidboot.h>
#include <usbhub.h>

char barcode[64]; //global barcode array
int index = 0; //global index
int process = 0;

class KbdRptParser : public KeyboardReportParser
{
  protected:

    void OnKeyDown	(uint8_t mod, uint8_t key);
    void OnKeyPressed(uint8_t key);
};


void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
  uint8_t c = OemToAscii(mod, key);

  if (c)
    OnKeyPressed(c);
}

void KbdRptParser::OnKeyPressed(uint8_t key)
{
  if((int)key == 19)
  {
    barcode[index] = '\0';
    index++;
    Serial.println(barcode);
    
    /*
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.println(F("."));
     */
     
    process = 1;
  }
  else
  {
    barcode[index] = (char)key;
    index++;
  }
  
}

USB     Usb;
HIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);

KbdRptParser Prs;



void setup()
{
  Serial.begin( 115200 );
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif

  if (Usb.Init() == -1)
    Serial.println("OSC did not start.");
  Serial.println(F("Start"));

  pinMode(2, INPUT);

  delay( 200 );

  HidKeyboard.SetReportParser(0, &Prs);
}

void loop()
{
  Usb.Task();
  if(process)
  {
    /*
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.println(F("."));
     */
       
    int i;
    for(i = 0; i < sizeof(barcode); i++)
    {
      barcode[i] = '\0';
    }
    index = 0;

    process = 0;
  }
}

I cannot figure out why this is happening.

Put some protection on index++ and you will probably be able to spot the cause of the overrun.

And if you try with char barcode[[color=red]128[/color]]; instead ?

How big is what you scan? And is there new stuff coming in after receiving the key 19?? Resetting your index would help once you print

aarg: Put some protection on index++ and you will probably be able to spot the cause of the overrun.

How would I do that? unsure of what that means? I've been printing index while debugging and it has never gone over 30 or so (for a long barcode).

J-M-L: And if you try with char barcode[[color=red]128[/color]]; instead ?

How big is what you scan? And is there new stuff coming in after receiving the key 19?? Resetting your index would help once you print

I have tried with 128 and 256, doesn't change anything as far as i can tell. I am reading the bar-code scanner as if it were an HID keyboard and after printing the chars that are read from the scanner, I am almost entirely sure that 19 signifies the end of a bar-code. The issue is not the scanning right now, without the aforementioned delay()'s it works perfectly fine (as in it prints the correct bar-codes without any issues).

To protect means you add a test no to overflow the buffer.

Assuming 19 is indeed the end marker, consider a small modification of your code , something like this

#include <hidboot.h>
#include <usbhub.h>

// ===========
// this is a poor OO design, the buffer should be within the KbdRptParser class and not exposed 
// directly but through a method call. Same for processed flag
// keeping it as is but probably good for you to consider changing
// ===========

const byte maxBufferSize = 64;
char barcode[maxBufferSize+1]; //global barcode array with room for a trailing '\0'
byte index = 0; //global index, does not need to be an int given the size of your buffer
boolean processed = false; // don't use an int for a truth value, that's what boolean are for

class KbdRptParser : public KeyboardReportParser
{
  protected:
    void OnKeyDown	(uint8_t mod, uint8_t key);
    void OnKeyPressed(uint8_t key);
};

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
  uint8_t c = OemToAscii(mod, key);
  if (c) OnKeyPressed(c);
}

void KbdRptParser::OnKeyPressed(uint8_t key)
{
  if((key == 19)
  {
    barcode[index] = '\0'; 
    processed = true;
  }  else  {
    if (index >= maxBufferSize) { // check for overflow
        Serial.print(F("buffer full, increase buffer size. Dropping :"));
        Serial.println((char) key);
    } else {   
        barcode[index++] = (char)key;
    }
  }
}

// ==========================

USB     Usb;
HIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);

KbdRptParser Prs;

void setup()
{
  Serial.begin( 115200 );
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif

  if (Usb.Init() == -1)  {
      Serial.println("OSC did not start.");
      while (true); // no need to go further
   }

  Serial.println(F("Start"));
  pinMode(2, INPUT);
  delay( 200 );
  HidKeyboard.SetReportParser(0, &Prs);
}

void loop()
{
  Usb.Task();
   if (processed) {
       Serial.println(barcode);
       index =0; // start a new scan
       processed = false;
   }
}

Just typed these changes on my phone so not sure if it compiles might have left a few spelling mistakes but give it a try

J-M-L:
To protect means you add a test no to overflow the buffer.

Assuming 19 is indeed the end marker, consider a small modification of your code , something like this

#include <hidboot.h>

#include <usbhub.h>

// ===========
// this is a poor OO design, the buffer should be within the KbdRptParser class and not exposed
// directly but through a method call. Same for processed flag
// keeping it as is but probably good for you to consider changing
// ===========

const byte maxBufferSize = 64;
char barcode[maxBufferSize+1]; //global barcode array with room for a trailing ‘\0’
byte index = 0; //global index, does not need to be an int given the size of your buffer
boolean processed = false; // don’t use an int for a truth value, that’s what boolean are for

class KbdRptParser : public KeyboardReportParser
{
  protected:
    void OnKeyDown (uint8_t mod, uint8_t key);
    void OnKeyPressed(uint8_t key);
};

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
  uint8_t c = OemToAscii(mod, key);
  if (c) OnKeyPressed(c);
}

void KbdRptParser::OnKeyPressed(uint8_t key)
{
  if((key == 19)
  {
    barcode[index] = ‘\0’;
    processed = true;
  }  else  {
    if (index >= maxBufferSize) { // check for overflow
        Serial.print(F(“buffer full, increase buffer size. Dropping :”));
        Serial.println((char) key);
    } else { 
        barcode[index++] = (char)key;
    }
  }
}

// ==========================

USB    Usb;
HIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);

KbdRptParser Prs;

void setup()
{
  Serial.begin( 115200 );
#if !defined(MIPSEL)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif

if (Usb.Init() == -1)  {
      Serial.println(“OSC did not start.”);
      while (true); // no need to go further
  }

Serial.println(F(“Start”));
  pinMode(2, INPUT);
  delay( 200 );
  HidKeyboard.SetReportParser(0, &Prs);
}

void loop()
{
  Usb.Task();
  if (processed) {
      Serial.println(barcode);
      index =0; // start a new scan
      processed = false;
  }
}




Just typed these changes on my phone so not sure if it compiles might have left a few spelling mistakes but give it a try

One missed parenthesis, but otherwise it compiled. I added the delays as I talked about before and the same issue persists. If I add the following lines to the loop()

  Usb.Task();
   if (processed) {
       Serial.println(barcode);
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       index =0; // start a new scan
       processed = false;
   }

The Arduino seems to restart after the first two seconds of delay (Serial Output):

void loop()
{
  Usb.Task();
   if (processed) {
       Serial.println(barcode);
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       delay(1000);
       Serial.print(F("."));
       index =0; // start a new scan
       processed = false;
   }
}

did you try the usb shield with some other device. numeric keypad? full keyboard?

Which Arduino are you running the code on? The ESP8266 device, for instance, absolutely HATES delay() and will reset if you use it.

Juraj: did you try the usb shield with some other device. numeric keypad? full keyboard?

I just tried it with a full keyboard and the same exact problem persists of the Arduino restarting if there is more than a 2 second delay.

PaulS: Which Arduino are you running the code on? The ESP8266 device, for instance, absolutely HATES delay() and will reset if you use it.

I am using an Arduino Uno Wifi wtih an Arduino USB Host Shield and the following barcode scanner

I have an Uno WiFi. I had resets with out of memory and the mcu go in reset almost immediately in setup() when I had watchdog reinitialization code in the loop. Never with delays.

I don't understand why there would be a reset here as I am not using much memory, all of my buffers aren't being overflown and I really need to fix this issue so that I can do stuff after each scan.

I really need to fix this issue so that I can do stuff after each scan.

You COULD use the blink without delay philosophy and a state machine to accomplish that "stuff" without using delay().

PaulS: You COULD use the blink without delay philosophy and a state machine to accomplish that "stuff" without using delay().

It's not that I need delay, I actually don't it's just that I need to do a web request after each scan and no matter what I try to do after each scan the same restart behavior occurs. The only thing that I can get working fully is just scanning without any other actions.

The only thing that I can get working fully is just scanning without any other actions.

What if the action is just to turn an LED on or off?

What I’m beginning to suspect is that Usb.Task() needs to be called oftener than you are calling it, when you have delay()s or try to make a request to a server.

PaulS: What if the action is just to turn an LED on or off?

What I'm beginning to suspect is that Usb.Task() needs to be called oftener than you are calling it, when you have delay()s or try to make a request to a server.

With turning on or off LED's with one LED it was fine but with multiple I remember it having the same issue.

in the doc they state

to use the Arduino UNo Wifi you need the Arduino.org IDE 1.7.9 or later

is that what you do?

J-M-L: in the doc they state

is that what you do?

Yes I am using 1.8 IDE

From .org or from .cc ?

markmazel: Yes I am using 1.8 IDE

1.8 is an Arduino.cc IDE. You need the imposter one from Arduino.org it seems. All the 1.7 ones were from that site. This site skipped straight from 1.6 to 1.8 to avoid any confusion. I think they recently merged, so the latest from this site might work. But I would look for one of the .org version and see if that helps. Especially given that that board was one of the .org products.

J-M-L: in the doc they state

is that what you do?

the IDE 1.7 remark is about the special Uno Wifi library. It uses the firmware in the ESP part of the board. And there is 1.8 mentioned if you want use the 1.8 version of that library. We don't use them. In fact we changed the firmware in the ESP of the Uno Wifi and use a better WiFi library. But it's all irrelevant here.

This problem is with the USB shield or library and here is a the Uno Wifi just an Uno R3.

@markmazel Look deeper in the usb library. I am sure the problem is there.