Boron does not like my code


#1

Hi folks,
I’m a novice and I’m struggling with this simple code.

I have similar code running on a Xenon and it’s working fine. But when I run it on the Boron, it breathes cyan but stops responding to pings and stops doing it’s gateway function. I have to reset it to safe mode in order to reflash Tinker and get it back running again.

The difference between the code below and the working Xenon code is that I’m using the fuelGage function here, but I’m using “analogRead(BATT)” on the Xenon.

Can someone point me in the right direction? Thank you!

///  BORON SOLAR EXPERIMENTS  ////

double voltage;
double soc;

//////////////////////////////// SETUP SECTION (RUNS ONCE)  //////////////////////////////////////////

void setup() {
    
    Particle.variable("voltage", &voltage, DOUBLE);
    Particle.variable("soc", &soc, DOUBLE);
    
    Particle.connect();

}

/////////////////////////////MAIN LOOP (LOOPS CONTINUOUSLY)  ///////////////////////////

void loop() {
    
       delay(10000);   //Don't send too often

     // Read the sensors 
       FuelGauge fuel;
       voltage = fuel.getVCell();
       delay(500);
       soc = fuel.getSoC();

     // Convert doubles to a string that can be published
        String voltageS = String(voltage);
        String stateOfChargeS = String(soc);

     // send to webhook     
        Particle.publish("B_voltage", voltageS, PRIVATE);
        Particle.publish("B_SOC", stateOfChargeS, PRIVATE);
        
//        delay(50000);  //Send data about once per minute
        
}

#2

First some minor points

This is the ancient (to be depricated) way of writing it, nowadays we’d write it like this

    Particle.variable("voltage", voltage);
    Particle.variable("soc", soc);

Also, since you are running in default SYSTEM_MODE(AUTOMATIC) Particle.connect() shouldn’t be called in setup().

You should also try to avoid delay() - especially 10000 or more milliseconds - in loop().
Rather go with something like this

void loop() {
  static uint32_t msDelay = 0;
  if (millis() - msDelay < 10000) return; // bail out when time isn't due yet
  msDelay = millis(); 
  // do the work when it's time to
  ...
}

I think these extensive delays are actually causing the apparent loss of connectivity where it’s actually only degraded responsiveness due to starving the system process of processing time.

I’d also rather use a global FuelGauge fuel; and reuse that over and over, than constructing/destroying it each time anew.

And finally, instead of two separate events I’d wrap both values in one string and send that
e.g. as JSON string that can easily be parsed by the webhook

  char evtData[64];
  snprintf(evtData, sizeof(evtData), "{\"Voltage\":\"%.1f\", \"SoC\":\"%.1f\"}", voltage, soc);
  Particle.publish("B_Data", evtData, PRIVATE);

#3

Thanks so much for taking the time to look at this. I will implement the changes and test.

I like the idea of combining publishes in one. But even after googling “snprintf” I have no idea how you came up with all of the syntax to make these lines:

  char evtData[64];
  snprintf(evtData, sizeof(evtData), "{\"Voltage\":\"%.1f\", \"SoC\":\"%.1f\"}", voltage, soc);
  Particle.publish("B_Data", evtData, PRIVATE);

I have a lot more to learn than I thought!


#4

To best learn about snprintf() you should first look up printf() which expains the basics.
snprintf() only differs in two points, it dosn’t directly print to an output channel but into a buffer (that’s the s part for store) and the n part referes to a limited number of bytes to store.

http://www.cplusplus.com/reference/cstdio/snprintf

But to cut things short, my statement above just injects the values into a string {"Voltage":"...", "SoC":"..."} where the ellipses (...) are replaced with the respective floating point number with one decimal place (%.1f).

The “funny” way to embed double quotes in a string which in turn is also wrapped in double quotes is called escaping ("this string contains two \"embedded\" double quotes").


#5

I can confirm the changes fixed the problem, thank you!!!


#6

Could you post your working code? I am running into the same issues that you were, but am not having any success. After I flash my device, I am also not able to re-flash it until I put it into safe mode.

I am running 8.0.rc.26 on my Boron

Here is my code:

///  BORON SOLAR EXPERIMENTS  ////

double voltage;
double soc;

//////////////////////////////// SETUP SECTION (RUNS ONCE)  //////////////////////////////////////////

void setup() {
    
    Particle.variable("voltage", voltage);
    Particle.variable("soc", soc);
    Particle.publish("Setup complete");

}

/////////////////////////////MAIN LOOP (LOOPS CONTINUOUSLY)  ///////////////////////////

void loop() {
    // Read the sensors 
  Particle.publish("Loop started");
  FuelGauge fuel;
  Particle.publish("About to read V");
  voltage = fuel.getVCell();
  Particle.publish("About to delay");
  delay(500);
  Particle.publish("About to get SoC");
  soc = fuel.getSoC();

     // Convert doubles to a string that can be published
  String voltageS = String(voltage);
  String stateOfChargeS = String(soc);

  static uint32_t msDelay = 0;
  if (millis() - msDelay < 10000) return; // bail out when time isn't due yet
  msDelay = millis(); 
  // do the work when it's time to
  char evtData[64];
  snprintf(evtData, sizeof(evtData), "{\"Voltage\":\"%.1f\", \"SoC\":\"%.1f\"}", voltage, soc);
  Particle.publish("B_Data", evtData, PRIVATE);
}

The last message that I see some through is: “About to read V”.

So it looks like the device is hanging on voltage = fuel.getVCell();

Any thoughts?


#7

Can you try building with Device OS v0.8.0-rc.27?


#8

So I am not 100% that I am doing this correct… Basically, I have the code in the WEB IDE, then I select Devices on the left, then I can see my unit. At that point, I select version 27 from the dropdown list. At that point, I click the flash button to send over my code (posted above). I see a strange flash sequence, then its back to the “breathing blue”. Still at .27

Any thoughts as to what I am doing wrong? I am starting with the unit in safe mode. This is all OTA…

Thanks


#9

Just upgraded the firmware to .27 via the CLI and DFU mode. Reflashed the code posted above, and same results.


#10

Hi tremmert,

This is what has been running successfully for a while now (weeks). It is only sending the battery voltage and state of charge % to a webhook (which I then send to emoncms for graphing etc but you don’t need that step).

It sends every 5 minutes, and increments a “watchdog” counter by 5 so the particle variable “watchdog” lets me know how long it’s been since the Boron has rebooted, in minutes.

I am not a veteran programmer, so there may be poor syntax in this example! It does seem to work however.

///  BORON SOLAR EXPERIMENTS  ////

double voltage;
double soc;
int watchdog;

FuelGauge fuel; //wake up the battery monitor routines

//////////////////////////////// SETUP SECTION (RUNS ONCE)  //////////////////////////////////////////

void setup() {
    
    Particle.variable("voltage", voltage);
    Particle.variable("soc", soc);
    Particle.variable("watchdog", watchdog);
    
    PMIC power;
    power.setChargeVoltage(4208);  // charge the battery to 4.208 volts instead of default 4.112 V
    
}

//////////////////////////////// MAIN LOOP (LOOPS CONTINUOUSLY)  ///////////////////////////////////////

void loop() {
    
     // read sensors and send data every 5 minutes
  static uint32_t msDelay = 0;
  if (millis() - msDelay < 298000) return; // bail out when time isn't due yet  // 5 MINUTES INTERVAL
        msDelay = millis(); 

     // Read the sensors //
       voltage = fuel.getVCell();
       soc = fuel.getSoC();

     // Convert doubles to a string that can be published
        String voltageS = String(voltage);
        String SocS = String(soc);

     // send to emoncms thru webhook     
        Particle.publish("BoronVoltage", voltageS, PRIVATE);
        delay(1000);
        Particle.publish("BoronSOC", SocS, PRIVATE);
        
     // Increment watchdog timer    
        watchdog = watchdog + 5;
            if (watchdog > 32000) {
            watchdog = 100;   // reset the watchdog to avoid overflow
            } 
        
        
}

#11

Jeffpeakmonitor,
Thanks for the code! I just flashed my device with your code, and BAM! Its working! I was worried that I was having issues with the hardware, but looks fine!

Ill let this run for a day or two and add the solar panel to the system tomorrow morning.

Thanks again!


#12

Actually, one more question comes to mind… Do you have a solar panel connected? If so, what size and what pins are you using?


#13

The reason why your code above wasn’t working as expected was probably due to violating the rate limit for Particle.publish()
https://docs.particle.io/reference/device-os/firmware/boron/#particle-publish-


#14

ScruffR,
I thought about that, but I don’t think think that was the cause. The device would never recover and also would not allow a re-flash until I put the device into safe mode.


#15

I’d still avoid hitting the rate limit. Hammering Particle.publish() that much may have unexpected side effects.

Your code above is trying to publish 4 to 5 (on first run even 8) events every 500ms - that’s definetly too much and may at least contribut to other issues.


#16

I started with a 1W 6V solar panel and a cheap 18650 battery, but it couldn’t keep up if there were any clouds or shadows during the day.

I switched to a 5V 2.5W panel from Amazon:
Solar panel link
And 2 Panasonic 18650 batteries:
Battery link
Now it can go a few days without solar at all, and will fully charge on an average day. This is without any sleep mode on the Boron - impressive! I look forward to when the sleep features are enabled.


#17

Jeffpeakmonitor,
Thanks for the links! Better than some trial and error…

Last question for you… Is your panel connected directly to the Boron or are you using a charge controller? If directly connected, which pins did you use?


#18

Direct connected to VUSB and GND.

Again I am no expert- maybe there is supposed to be a diode or something in there, but so far so good for direct connection.