B402 Halting on Bootup When Attempting to Connect with the Particle Cloud (Video in Post)

I’m running into a situation where there is a halt condition on boot while the B402 is trying to connect to the particle cloud on boot. This causes the OLED screen and joystick to not work while the OS is trying to connect. I have attached a video of the issue for reference. Is this typical behavior? Does anyone know of a possible workaround to the issue?

I guess you are running default SYSTEM_MODE(AUTOMATIC) and also not using SYSTEM_THREAD(ENABLED) if so, then the behaviour you see is expected.

The docs will state that too :wink:
https://docs.particle.io/reference/device-os/firmware/boron/#automatic-mode

2 Likes

I think you may be right. I’m gonna check out that. In the meantime for those interested, here is my setup() code:

void setup() {
    //set the IO pins to be either input or output pins
    pinMode(ignition,OUTPUT);   digitalWrite(ignition,0);
    pinMode(gen_cut,OUTPUT);    digitalWrite(gen_cut,0);
    pinMode(gen_running,INPUT_PULLDOWN);
    //set pin modes and interrupts for button inputs
    pinMode(BUTTON_LEFT, INPUT_PULLUP); attachInterrupt(BUTTON_LEFT,    isr_button_left,    FALLING);
    pinMode(BUTTON_RIGHT, INPUT_PULLUP);attachInterrupt(BUTTON_RIGHT,   isr_button_right,   FALLING);
    pinMode(BUTTON_UP, INPUT_PULLUP);   attachInterrupt(BUTTON_UP,      isr_button_up,      FALLING);
    pinMode(BUTTON_DOWN, INPUT_PULLUP); attachInterrupt(BUTTON_DOWN,    isr_button_down,    FALLING);
    pinMode(BUTTON_A, INPUT_PULLUP);    attachInterrupt(BUTTON_A,       isr_button_a,       FALLING);
    //pinMode(BUTTON_B, INPUT_PULLUP);    attachInterrupt(BUTTON_B,       isr_button_b,       FALLING);
    
    //work out if values have been stored in EEPROM already
    int default_config_values; EEPROM.get(EEPROM_NOT_DEFAULT_ADDRESS,default_config_values);
    if(default_config_values==99) {for(int i=1;i<=MAX_CONFIG_MENU_ITEM;i++) {EEPROM.get(ConfigMenuData[i].eeprom_address,ConfigMenuData[i].value);}}    //if we should use the stored values, then update our data structure
    
    //load all of the variable addresses into the config data structure
    ConfigMenuData[1].var_address = &gen_start_voltage;     ConfigMenuData[2].var_address = &ignition_attempts;
    ConfigMenuData[3].var_address = &ignition_settle;       ConfigMenuData[4].var_address = &gen_stop_voltage;
    ConfigMenuData[5].var_address = &reporting_period;      ConfigMenuData[6].var_address = &tmz_correction;
    EEPROM.get(EEPROM_GEN_RUNTIME,gen_runtime_total);                    //read eeprom for gen timer
    Wire.begin();                                                        // initialize i2c
    oled.begin();                                                        // initialize the oled
    
    interrupts();                                                        // enable interrupts (already enabled by default?)
    Particle.connect();                                                  //finally connect to cloud - time sync happens automatically as part of this call
    drawActiveScreen();                                                  // draw the current screen
    
    Time.zone(tmz_correction);                                           //set the time zone so that local time can be got when we used Time.local()
    
    debug_waiter        = millis();
    info_screen_waiter  = millis();
    button_press_counter = millis();
    max_wait=((ignition_settle * ignition_attempts)/1000);
    startup_send_flag = true;                                                 // firstboot flag for event startup
    reporting_timer.start();
    Particle.function("generatorOff", generatorOff);
    Particle.function("generatorOn", generatorOn);
    Particle.function("resetTimer", resetTimer);
    Particle.variable("voltage_adc", voltage_adc);
    Particle.variable("running", running);
    Particle.variable("ignition ", ignition );
    Particle.variable("GEN ON", gen_running);
    Particle.variable("GEN OFF", gen_cut );


   }

You should not have blanks in your variable names
https://docs.particle.io/reference/device-os/firmware/boron/#particle-variable-

You should also have your variable/function registration as far up in setup() as possible.
Registration is already possible without an active connection.

BTW, interrupts() are on by default, so no need for that call in setup() either.

And for code readability it’s discouraged to use multiple commands in one line - especially when you go beyond 80 character width.

is much harder to grasp with one look than this

  if(default_config_values == 99) { //if we should use the stored values, then update our data structure
    for(int i=1; i <= MAX_CONFIG_MENU_ITEM; i++) { 
      EPROM.get(ConfigMenuData[i].eeprom_address, ConfigMenuData[i].value);
    }
  }    

You don’t want to be scrolling right/left/right when you follow some code - especially when you want someone else to understand it :wink:

1 Like

For the lurkers who come here looking for a solution in the future:
User ScruffR was correct - Particle cloud functionality is halting unless you declare in your code.
Make sure to include:

SYSTEM_MODE(AUTOMATIC)
SYSTEM_THREAD(ENABLED)

In your code BEFORE the setup() portion. There is additional functionality that can be found with Particle documentation: https://docs.particle.io/reference/device-os/firmware/boron/#system-thread

This is the default, so it can be omitted.

However, when you want to use SEMI_AUTOMATIC or MANUAL mode you need to explicitly state that.

Is the way to allow setup() and loop() to run in AUTOMATIC mode independently of connection state.

3 Likes

@hansA -

Glad to see @ScruffR helped out, so all I can add is Welcome to Particle forums :slight_smile:

Regards,
Friedl.