Restoring Bridge after Linino Reboot

Hi, I have a project that runs a shell command from the 32U4 every minute on Linino. Everything works great for days on end until the AR9331 is reset, at which point the sketch freezes because it can no longer access the Bridge. Tried general searching, Bridge documentation, and Process documentation to no avail. Any advice on how to only run the process if the Bridge is available? And how to restore the Bridge after the AR9331 is reset? I have tried using Bridge.begin() just before running the process, but it still locks up the 32U4 sketch. Thanks, code is below.

void setup() {
  Bridge.begin();
}//end setup

void loop(){
  if (intervalElapsed){
    runProcess(command);
  }
}

void runProcess(String command){
  Process p;
  p.runShellCommand(command);
}
void setup() {
  Bridge.begin();
}//end setup

void loop(){
  if (intervalElapsed){
    runProcess(command);
  }
}

void runProcess(String command){
  Process p;
  p.runShellCommand(command);
}

I have a sneaking suspicion this isn't the entire code... If you want good help, you need to help us out and not leave anything out that might help us help you.

theDuke540:
I have a sneaking suspicion this isn’t the entire code… If you want good help, you need to help us out and not leave anything out that might help us help you.

Haha, you are exactly right… I do believe the issue lies with how the Bridge/Process libraries - and/or my code - cannot handle a Linino restart. Essentially I have been looking for a way to check if the Bridge is functional before running a Process on it. Here is my full code. Thanks to all in advance for your time and suggestions!

#include <Bridge.h>
#include <Process.h>
#include <Console.h>
#include <DHT22.h>

#define DHTPIN 2

// how often to run the pin read (in milliseconds)
const unsigned long RUN_INTERVAL_MILLIS = 60000; 
const unsigned long AVE_INTERVAL = 1000;

// the last time we ran the pin read (initialized to 60 seconds ago,
// so the pins are read immediately when we start up)
unsigned long lastRun = 0;//= (unsigned long)- 60000;
unsigned long lastAveRun = (unsigned long)- 1000;

// variables for setting up time 
Process date;                 // process used to get the date
String timeString;

DHT22 DHT1(DHTPIN);
const int ledPin = 13;

//a0 info
const int a0Pin = 0;
//i.e. 1023 arduino input = 300 ug reading = 5 V
const float a0scale = 300; //reading equal to full scale of 1023 units (e.g. 5 V with standard ref.)
const float a1scale = 1;
const float a2scale = 1;

int a0Inc = 0;

float a0Num = 0; //a0
float temp1; //a1
float humi1; //a2

int pAvail;

void setup() {
  pinMode(ledPin, OUTPUT);
  delay(3000);
  Process p;
  pAvail = p.available();

  Bridge.begin();
  Console.begin();

  // run an initial date process. Should return:
  if (!date.running())  {
    date.begin("date");
    date.addParameter("+%D +%T");
    date.run();
    Console.println(date.readString());
  }

  for(int x = 0; x < 50; x++){
    digitalWrite(ledPin, !digitalRead(ledPin));
    delay(50);
  }

  digitalWrite(ledPin, LOW);
}//end setup

void loop() {


  // get the number of milliseconds this sketch has been running
  unsigned long now = millis();
  
  //if (Bridge.){ Console.println("Bridge running");}
  //else {Console.println("Bridge not running");}

  //build average values
  if (now - lastAveRun >= AVE_INTERVAL) {
    lastAveRun = now;
    a0Num += analogRead(a0Pin);
    a0Inc ++;
    digitalWrite(ledPin, !digitalRead(ledPin));
  }

  // run again if it's been RUN_INTERVAL_MILLIS milliseconds since we last ran
  if (now - lastRun >= RUN_INTERVAL_MILLIS) {
    lastRun = now;
      Console.print("p.avail: ");
  Console.println(pAvail);
    
    //need to check bridge here
    Bridge.begin();
    if (!date.running())  {     // get the date and time
      date.begin("date");
      date.addParameter("+%D +%T");
      date.run();
    }//end if    
    // put the date and time into a string variable
    while (date.available()>0) {
      timeString = date.readString(); 
    }//end while

    //need to check bridge here
    String latestDate = getLatestDate();  
    
    Console.println("Latest:  " + latestDate);
    Console.println("Current: " + intDate(timeString));
    
    getDHT();
       
    if (a0Inc > 0) {
      float a0Ave = a0Num/a0Inc;
      a0Num = 0;
      a0Inc = 0;
      if (intDate(timeString) > latestDate) {
        digitalWrite(ledPin, HIGH);
        Console.print(timeString);
        Console.print("a0ave: ");
        Console.println(a0ave);
        runSqlQuery(timeString,a0ave,a0scale,temp1,a1scale,humi1,a2scale);
        for(int x = 0; x < 40; x++){
          digitalWrite(ledPin, !digitalRead(ledPin));
          delay(25);
        }
      } //end if: date check
      else {
        //current date is older than latest date - do not write to DB
        for (int x = 0; x < 5; x++){
          digitalWrite(ledPin, !digitalRead(ledPin));
          delay(200); 
        }//end for
      }//end else
    } //end if
    else {
    }//end else dustInc !> 0
  }//end if: query every 60 seconds 
}// end loop


 // function to run the appending of the data to the database
 unsigned int runSqlQuery(String date, float a0, float a0scale, float a1, float a1scale, float a2, float a2scale){

   Process p;
   String cmd = "sqlite3 ";
   String paramstring1 = "-line ";
   // set the path and name of database
   String paramstring2 ="/mnt/sda1/arduino/www/data.db ";
   // insert a row with time and sensor data 
    String paramstring3 ="'INSERT INTO raw (\"date\",\"a0\",\"a0scale\",\"a1\",\"a1scale\",\"a2\",\"a2scale\") VALUES (\""+date+"\","+a0+","+a0scale+","+a1+","+a1scale+","+a2+","+a2scale+");'";
   // get the error code
   String paramstring4 =" ; echo $?";
   Console.println(p.available());
   Console.println("runSqlQuery");
   Bridge.begin();
   p.runShellCommand(cmd + paramstring1 + paramstring2 + paramstring3+ paramstring4);
   Console.println(p.available());
     // Read process output with stream method
   while (p.available()>0) {
    char c = p.read();
    Console.println(p.available());
    Console.print(c);
    }
  Console.flush();
  }
  
  String getLatestDate() {
  

    Process p;
    String cmd = "sqlite3 ";
    String par1 = "-line ";
    //db path
    String par2 = "/mnt/sda1/arduino/www/data.db ";
    String par3 = "'SELECT date FROM raw ORDER BY rowid DESC LIMIT 1;'";
    String par4 = " ;";// echo $?";
    Console.println("getLatestDate");
    //need to check bridge here
    Bridge.begin();
    p.runShellCommand(cmd + par1 + par2 + par3 + par4);

    //do nothing while cmd running
    while (p.running());
    
    //read shell output
    String output = "";
    int i = 0;
    while (p.available()>0){
//      String result = p.parse();
      i ++;
      char c = p.read();
      if (i > 8 && i < 27) { //start with 9th character, which should be start of date
        output = output + c;
      }   
    }
    //Console.println(intDate(output));
    //Console.flush();
    return intDate(output);
  }
  
String intDate(String date) {
  String year = date.substring(6,8); //' + 'output.charAt(7)');
  String month = date.substring(0,2); //String(output.charAt(0) + output.charAt(1));
  String day = date.substring(3,5); //String(output.charAt(3) + output.charAt(4));
  String hour = date.substring(10,12); //String(output.charAt(10) + output.charAt(11));
  String minute = date.substring(13,15); //String(output.charAt(13) + output.charAt(14));
  String second = date.substring(16,18); //String(output.charAt(16) + output.charAt(17));
  String fullDate = year + month + day + hour + minute + second;    
  return fullDate;
}

void getDHT(){
  DHT22_ERROR_t errorCode;
  errorCode = DHT1.readData();
  switch(errorCode){
    case DHT_ERROR_NONE:
      temp1 = DHT1.getTemperatureC();
      humi1 = DHT1.getHumidity();
  }
}

Everything works great for days on end until the AR9331 is reset,

What is causing the AR9331 to reset?

I have tried using Bridge.begin() just before running the process, but it still locks up the 32U4 sketch

calling Bridge.begin() locks up the sketch? Can you explain.

Any advice on how to only run the process if the Bridge is available?

when you call Bridge.begin(), this makes sure the bridge is running. There is no need to call it more than once. Also, it's ok to declare the Process date in setup just before date.begin() because you're just creating the variable at that instant. From the Arduino Yun site:

After the processor resets, the bootloader starts, remaining active for about 8 seconds.

I know this doesn't answer your question, but I'm hoping that it at least explains why it's happening. In general I've noticed the time it takes the YUN to become fully operational after a reset is a lifetime :sleeping:.

theDuke540:

Everything works great for days on end until the AR9331 is reset,

What is causing the AR9331 to reset?

If I reset it via the OpenWRT config page or physically press 'Yun Rst'. The 32U4 needs to be able to keep going even if it loses the Bridge and needs to be able to restore the Bridge when it becomes available again.

I have tried using Bridge.begin() just before running the process, but it still locks up the 32U4 sketch

calling Bridge.begin() locks up the sketch? Can you explain.

As you may be aware, Bridge.begin() is a blocking function, therefore the sketch waits there until it can start the bridge. If i try running this function later in my sketch after setup(), it does not reconnect to the bridge. It causes the sketch to get stuck at that line of code. I confirm this by having the L13 LED flash on/off every second.

Any advice on how to only run the process if the Bridge is available?

when you call Bridge.begin(), this makes sure the bridge is running. There is no need to call it more than once. Also, it's ok to declare the Process date in setup just before date.begin() because you're just creating the variable at that instant.

But I am specifically asking about a situation where the Bridge connection is lost and I want to restore it. How can I reconnect to the Bridge without calling Bridge.begin() again?

From the Arduino Yun site:

After the processor resets, the bootloader starts, remaining active for about 8 seconds.

I know this doesn't answer your question, but I'm hoping that it at least explains why it's happening. In general I've noticed the time it takes the YUN to become fully operational after a reset is a lifetime :sleeping:.

It would be great if that was the issue, but I have waited over 5 minutes and always confirm that I can connect to the Linino side via OpenWRT config pages.

Any other ideas on how to restore a Bridge connection after Linino reboot? Also, how to confirm there is a Bridge connection before running processes?

Another potential solution would be to force the sketch to reset if Linino reboots... Thanks for any suggestions.

whisprer: Another potential solution would be to force the sketch to reset if Linino reboots... Thanks for any suggestions.

You can do that by adding reset-mcu to your /etc/rc.local

calling Bridge.begin(); more than once is useless because the beginning of the code is

void BridgeClass::begin() {
  if (started)
    return;
  started = true;

And started is never reset. With this code in mind your observation below is hard to believe:

As you may be aware, Bridge.begin() is a blocking function, therefore the sketch waits there until it can start the bridge. If i try running this function later in my sketch after setup(), it does not reconnect to the bridge. It causes the sketch to get stuck at that line of code. I confirm this by having the L13 LED flash on/off every second.

I hope this helps Best regards Jantje

Jantje:

whisprer: Another potential solution would be to force the sketch to reset if Linino reboots... Thanks for any suggestions.

You can do that by adding reset-mcu to your /etc/rc.local

Yes, thank you.

calling Bridge.begin(); more than once is useless because the beginning of the code is

void BridgeClass::begin() {
  if (started)
    return;
  started = true;

And started is never reset.

Very true... so is resetting the MCU the only way to restore the Bridge after Linino reboots?

With this code in mind your observation below is hard to believe:

As you may be aware, Bridge.begin() is a blocking function, therefore the sketch waits there until it can start the bridge. If i try running this function later in my sketch after setup(), it does not reconnect to the bridge. It causes the sketch to get stuck at that line of code. I confirm this by having the L13 LED flash on/off every second.

You are correct. It gets stuck while trying to run processes after the Bridge connection is lost. Is there any way to check if the Bridge connection is available? I would then do this before running the Process command. If the answer to my above question is yes, then being able to check for Bridge connection is pointless.

Thanks for the reply.

whisprer:

calling Bridge.begin(); more than once is useless because the beginning of the code is

void BridgeClass::begin() {
  if (started)
    return;
  started = true;

And started is never reset.

Very true... so is resetting the MCU the only way to restore the Bridge after Linino reboots?

I'm not the expert but I fear it is with the current implementation.

Jantje:

whisprer:

calling Bridge.begin(); more than once is useless because the beginning of the code is

void BridgeClass::begin() {
  if (started)
    return;
  started = true;

And started is never reset.

Very true... so is resetting the MCU the only way to restore the Bridge after Linino reboots?

I'm not the expert but I fear it is with the current implementation.

That is my suspicion, too. It is not a problem for my current project, but for other people it may be a problem!

Thanks for the dialogue.

This seems like there should be a way to determine the state of the Linino side as resetting the Linino side could be a common thing. This is something I will be looking into.

Pin 7 is connected to the AR9331 processor and it may be used as handshake signal in future. Is recommended to be careful of possible conflicts if you intend to use it as interrupt.

As people reported problems with pin 7; I thought they used pin 7 for syncing the bridge. However when I went through the code I didn't see any proof of that. Nor did I see the bridge autorestart after reset. So basically: the way how it is implemented right now the 2 reset buttons are useless when you use the bridge. And what is the use of a yun without the bridge?

Best regards Jantje

So there is still no possibility to restart the bridge after a linino reboot ? as you know reset-mcu won't help with that...

Sea2605: So there is still no possibility to restart the bridge after a linino reboot ? as you know reset-mcu won't help with that...

Can you elaborate on why reset-mcu won't help?

Jantje, I already tried to automatically reboot the 32u4 after a linino-reset by including /usr/bin/reset-mcu (tired even with a "&" at the end...) into the rc.local... even running reset-mcu over SSH won't reboot the 32u4 properly (the sketch won't load, the LCD will show 2 bars which indicates that initialization doesn't work, my python-scripts won't get executed therefore bridge/runshellcommand doesn't work...... ). And I'm looking for a solution since weeks....

that is wierd. reset-mcu only sets a pin high that powers up the reset pin of the leonardo. Can you dump the content of reset-mcu?

False alarm...I just tested the reset-mcu over ssh and it worked. Very weired.... as I remember also testing it with ssh!

BUT thanks to trying again, I solved another issue of mine ! Thanks jantje :)

Since weeks I put the reset-mcu at the end of my rc.local this way and it didn't work as intended:

sleep 35
/usr/bin/blink-start 50
sleep 2
/usr/bin/blink-stop
/opt/python/bin/python /root/TempPlotly.py

# If the infinitly looping script somehow terminates reset 32u4 and reboot linino:
/usr/bin/reset-mcu
reboot   
        
exit 0

But this was the wrong order ! This prevented the bridge to initialize because I rebooted the mcu BEFORE I rebooted the linino... Now I solved my reboot issue this way with the rc.local:

sleep 5
# Reset the 32u4 ALWAYS right when the linino is ready. This way, after some crash the bridge etc get reinitialized automatically:
/usr/bin/reset-mcu
sleep 25
/usr/bin/blink-start 50
sleep 2
/usr/bin/blink-stop
/opt/python/bin/python /root/TempPlotly.py

# If the infinitly looping script somehow terminates reboot:
reboot   
        
exit 0

Now, if my infinitly looping script somehow crashes everything reboots automatically as expected

great you got it to work Jantje

Jantje! I just tried to reset-mcu manually over ssh again (was too lazy to stand up) .... and the reset-mcu doesn't work again! the LCD gets stuck (only white-boxes), runShellCommands won't get executed etc etc... completely stuck.

...what could be the reason for this?!

What I could also observe: My sketch shows me the wifi-signal strength on my LCD... so when I start the arduino for the first time(=plug it in) the wifi has like 65-70% signal strength... Then after approx. 1 minute the linino starts my rc.local and therefore (as intended by me; see first lines of my rc.local) the reset-mcu gets executed... BUT after the restart of the 32u4 I can see that the wifi-signal droped to 37-52% and it remains that weak forever....

very weired...

Edit: Maybe the reason is altSoftSerial, which forces me to use Pin D13 as RX and Pin D5 as TX (thats also the reason, I guess, why the red LED of my yun is always on...)

I have a sketch with altsoftserial wire and the bridge. I have some really weird behavior. Seems like wire.begin gets stuck quite often.
The behavior from a cold start to a reset is different. Mostly uploading the sketch again makes tings work again (apart from alt soft serial) I still couldn’t make out what it is.
Best regards
Jantje