GoBetwine Freeze/Crash with Leonardo

I have an Arduino Leonardo that is used with hardware to provide inputs to Windows. Those inputs have to be reported to an XML file every ~100ms. After several failed attempts at writing the bridge between the two myself, I came across GoBetwine (latest version).

The XML file is short, and with its ability to edit text files, GoBetwine successfully is updating the XML file with its new values with no larger than a 250ms delay. However, once GoBetwine reaches its approximately 66th command, it ceases to respond. Copying & editing of the XML ceases, and the only response that can be found is if the Arduino continues its output, GoBetwine's memory usage continues to grow, according to Windows.

Here's what GoBetwine is doing every loop (using GoBetwine's default command names):
#S|CPFIL[]# //Copies a blank XML template to a subfolder where the string will be written
#S|LGFIL|[] //Fills the XML with its needed variables and syntax
#S|CPFIL[]# //Copies the edited XML to the real XML's directory

Up until the ~66th command (22nd loop), everything works. The Arduino Leonardo functions fine on its own and continues to do so even after GoBetwine stops. The Leonardo does not require any input from GoBetwine. Adding delays to the Arduino did nothing to help; the crashes are related proportionally to the number of commands performed since opening GoBetwine. After crashing, GoBetwine's cooperation is random, usually crashing after completing its first command. After some time or attempts, GoBetwine will work again.

To summarize GoBetwine's behavior:

  • GoBetwine is able to read as many serial.prints the Arduino spits out as long as they are not commands (although it lags behind)
  • GoBetwine stops responding after ~66 commands
  • GoBetwine continues to consume more memory despite no response
  • The type of command does not matter (making the LGFIL comments and then vice versa the CPFILs)
  • Delaying the Arduino's output does not change anything
  • Windows does not pronounce the program as not responding, but the program cannot be interacted with
  • The crash's cause persists even after exiting GoBetwine, but only randomly.
  • GoBetwine never fails to complete its last issued command, meaning the error is occurring inbetween commands.
    (ie: the entire string is written, and the last copy command successfully copied)

An additional concern with GoBetwine:
Since the output occurs several times a second, GoBetwine's log file (gobetwine.txt) will quickly become several kb in size. The time that GoBetwine will be in constant use will be anywhere from 30 minutes to an hour, meaning the log file may become several mb in size. Eventually, most programs become slowed once opening large text files. Is there any command to purge the log file, or would you need to tell Windows to restrict programs from editing any files in the directory to prevent GoBetwine from writing to the log?

I will look at this problem, i can't see that it should be specifically related to Leonardo. Maybee there is a bug

Mikael

Eventually, most programs become slowed once opening large text files.

Opening a file, seeking to the last position, and being ready to write has nothing to do with the size of the file. A seek() of 0 takes nearly as long to execute as a seek() of 10000000.

Opening and closing a file (saving each time the file is closed) does take time. GoBetwino doesn't open and close the log file each time it wants to write. At least, I don't think that it does.

Actually It does open and close the file for every write.

Mikael

As Mikael stated, GoBetwino does open and close its text log after each log message.

Here's some more information on the situation:

I am running Windows 7 Ultimate x64. Microsoft service pack and the other stuff should be up to date; although knowing Windows that doesn't mean they're the version GoBetwino wants.

Here's the Arduino code without the extra mathematical and logical fluff:
note: ANG, HYP, and selectV are INT variables

void setup() {                
//  Setup_timer2();

  // initialize the digital pin as an output.
  pinMode(scopePin1, OUTPUT);     
  pinMode(scopePin2, OUTPUT);     
  pinMode(modeLed, OUTPUT);     
  pinMode(Ain4,  INPUT);     
  digitalWrite(Ain4, HIGH);   // enable the internal pullup resistor
  pinMode(Sw01,  INPUT);     
  digitalWrite(Sw01, HIGH);   // enable the internal pullup resistor
  pinMode(Sw02,  INPUT);     
  digitalWrite(Sw02, HIGH);   // enable the internal pullup resistor
  pinMode(SwSel,  INPUT);     
  digitalWrite(SwSel, HIGH);   // enable the internal pullup resistor

  delay(1000);
  Serial.begin(57600);  
  Serial.println("startup - waiting 1 more second");
  Keyboard.begin();
  Mouse.begin();
  delay(1000);
}

void loop () {
delay(10);
        
        Serial.println("#S|COPYXYS|[]#");
        
        delay(10);
        
        Serial.print("#S|LOGXYS|[");
        Serial.print(ANG);
        Serial.print("\"/></Key><Key name=\"hwX\"><Value int=\"");
        Serial.print(HYP);
        Serial.print("\"/></Key><Key name=\"hwS\"><Value int=\"");
        Serial.print(selectV);
        Serial.print("\"/></Key></Section></Bank>");
        Serial.println("]#");
        
        delay(10);
        
        Serial.println("#S|TESTXYS|[]#");
}

#ifdef SERIAL_ENABLED
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
} /* */
#endif

COPYXYS and TESTXS are the copy file commands, and LOGXYS is the write to log command.

I also did a few more tests:

  • "Reinstalling" GoBetwino by extracting it into a new folder does not correct the error.
  • Unplugging the Arduino while GoBetwino is frozen unfreezes it, resulting in the error of "port COM12 does not exist" with all commands that were "queued" while frozen. The Arduino doesn't have to be unplugged, ending GoBetwino's process and "updating" the code also resets the error. However, GoBetwino still only performs ~66 commands before freezing again.
  • While GoBetwino refuses to interact beyond a single command with the Arduino, Arduino's compiler and Windows still recognizes its output.
  • I retested the Arduino with default commands that come with GoBetwino (the time command). GoBetwino only lasts about 10 commands of this type.

Additionally I've tried about all of the options GoBetwino offers besides changing the serial type. I have tried changing the Arduino to 9600 Baud and vice versa: GoBetwino to 57600 Baud.

Hi Gunslinger

Sorry for the late answer, i have been extraordinary busy that last few weeks, add to that a semi crashed laptop......

I don't know how much code you have removed, but looking at your posted loop code, you have 3 delay(10) statements.
That means your loop as posted will run more than 300 times a second.
For each iteration through the loop, you are copying a file, logging something to a file and then copying another file.
Logging causes a file open, a file write and a file close operation.

This requires GoBetwino to parse, interpret, and execute 900 commands every second, each command involving file operations. That is probably much more than it can handle, maybe even more than your PC can handle??

Also at 57600 bits/s you can send a max of 5760 bytes every second over the serial line. With 300 commands / s each command can not exceed 19,2 bytes (average). It's hard to tell from your code but i think you are over that.

Try to slow things down (a lot for starters), and see how it goes.

Mikael

I have tried the previous code using delay(1000), as well as testing each command individually. However, with testing and looking up info on the Leonardo, the code line Serial.begin(57600) apparently does not do anything, so GoBetwino and the Arduino are working at different Baud rates if that may cause problems. In my searching I did not find any way to change, pause, or stop the Leonardo's USB CBC serial. The Leonardo USB CDC operates at 1600 MHz.

I also had tried reducing the code's output to nothing more than the following:

void loop()
{
        delay(1000);
        
        Serial.print("#S|LOGFL|[X]");
}

Every test results in GoBetwino's UI and outputs freezing at the 66th command.

I also learned that a Baud rate of 1200 will tell the Leonardo to reset (disconnect & reconnect to Windows) when whatever software is listening to it stops listening. The Leonardo remains in communication with GoBetwino while frozen, as the Leonardo does not reset until I end GoBetwino's process with Windows.

I've also found at what point in GoBetwino's processing the error is occurring. This test was done with the code shown in the prior post using delay (300) for the three delays, and it only serial.writes when the Arduino is receiving a new input from the user. The last Status messages of GoBetwino before the freeze reads the same as it's log file:

10/28/2013 3:40:28 AM,Commandstring recieved : #S|TESTXYS|[]#
10/28/2013 3:40:28 AM,Command parsed OK
10/28/2013 3:40:28 AM,Executing command : TESTXYS
10/28/2013 3:40:28 AM,copying C:\Users\Username\Desktop\Gobetwino Tests\Update\XML.txt to C:\Users\Username\Documents\XML.txt finished
10/28/2013 3:40:31 AM,Commandstring recieved : #S|COPYXYS|[]#
10/28/2013 3:40:31 AM,Command parsed OK
10/28/2013 3:40:31 AM,Executing command : COPYXYS
10/28/2013 3:40:31 AM,copying C:\Users\Username\Desktop\Gobetwino Tests\Plain\XML.txt to C:\Users\Username\Desktop\Gobetwino Tests\Update\XML.txt finished
10/28/2013 3:40:31 AM,Commandstring recieved : #S|LOGXYS|[61"/>]#
10/28/2013 3:40:31 AM,Command parsed OK
10/28/2013 3:40:31 AM,Executing command : LOGXYS
10/28/2013 3:40:31 AM,Data logged to C:\Users\Username\Desktop\Gobetwino Tests\Update\XML.txt
10/28/2013 3:40:32 AM,Commandstring recieved : #S|TESTXYS|[]#
10/28/2013 3:40:32 AM,Command parsed OK
10/28/2013 3:40:32 AM,Executing command : TESTXYS
10/28/2013 3:40:32 AM,copying C:\Users\Username\Desktop\Gobetwino Tests\Update\XML.txt to C:\Users\Username\Documents\XML.txt finished

However, the Command output does not receive/perform the last command (note times):

10/28/2013 3:40:28 AM : 0
10/28/2013 3:40:31 AM : 0
10/28/2013 3:40:31 AM : 0

As mentioned before, the error is compound for each instance of running GoBetwino. If I open GoBetwino, do 40 commands, close it; then I open GoBetwino again and try to do 40 more, it'll freeze on the 66th command since it connected to the Leonardo. Changing GoBetwino's serial port in its settings and reopening GoBetwino does not "reset" the number of commands. Only disconnecting the Leonardo from Windows seems to do it. Keep in mind that Arduino's compiler can still monitor the serial just fine, and Windows continues to perform various mouse and keyboard emulation. The problem probably lies somewhere with the way Windows handles GoBetwino's memory since the error accumulates between tests.

A possible solution is reseting or disrupting the serial connection between the two; which may "reset" Gobetwino and therefore never reach the 66th command. I have tried using Serial.end, but the Leonardo's USB connection seems to ignore the normal Serial commands.

Hi Gunslinger

I will try to make a test this weekend to see if i can replicate the problem with an ordinary Arduino. This way we should be able to establish if this is a Leonardo related problem.

EDIT: I just read your post over once again. It is a MAJOR problem if GoBetwino and Leonardo are working at different baud rates. That is bound to go wrong. I do not own a Leonardo and know very little about how it works. maybe someone more knowledgable in that area can contribute to this issue??

Mikael