Battery power Xenon

@Rftop thank toy for that. It very much pointed me in the right direction. In case anyone reads this thread in the future, SYSTEM_MODE should be SEMI_AUTOMATIC, not manual. And before the if (waitFor… statement, you need to call Parrticle.connect(). But I can confirm it works perfectly on mesh and your post was very helpful.

@shanevanj the TPL5111 was discussed upthread, but it really is a very interesting device. It would work perfectly here but I think the power consumption is low enough that I’ll get my required battery life without it. And that’s a great idea about desiccant. I think the next few times I get one in a package, I’ll toss them in the project box.

Just a note on that: The combo SEMI_AUTOMATIC and SYSTEM_THREAD(ENABLED) does exhibit in some circumstances (IMO unnecessary) blocking behaviour and not in others.
In my experience MANUAL mode behaves much more consistent in that regard and in combination with SYSTEM_THREAD(ENABLED) the need for your code permanently calling Particle.process() becomes a non-issue too.

You can read something about this here
https://github.com/particle-iot/device-os/issues/1399

2 Likes

I’ve made a lot of progress on the code for my project. I’ve got a couple of really odd things that I can’t see what is cause. I’m wondering if there’s still known issues with the mesh tech.

The Particle.publish() calls from the Xenon don’t seem to be getting through. I have maybe 5% of them showing up in the web console. It’s not a throttling issue, it’s 1 publish every 2 minutes. The Mesh.publish() data seems to be nearly flawless. So right now, I have Xenon using Mesh.publish(), and the handler on the Argon is basically doing nothing except passing it on to a Particle.publish() which seems to work.

The big problem I’m having this, is my system seems to work flawlessly for 6-18 hours and then the Xenon loses the ability to connect to the mesh. I have the sleep timer set to 2 minutes instead of 10 because I’m still testing. When it fails, I still see the Xenon wake up every 2 minutes, flashes green for my 10 second timeout window, and then goes back to sleep. The Argon is still online and appears to be working properly. My first thought was it’s a battery/low temperature issue, but if I press the reset on the Xenon without taking it out of the freezer, everything starts working perfectly again for the next 6-18 hours until it happens again, and warming it up doesn’t solve the problem.

It’s not an intermittent issue though in the sense that it never fails to connect until the time it does and then it fails every single time after that until it is reset.

@ScruffR Is it possible the blocking you’re talking about is causing the problems that I described above?

And to be clear, as long as I have SYSTEM_THREAD(ENABLED), I never have to call Particle.process()? My issue with manual was making sure I call Particle.process() appropriately.

Yes, that should be so.

So far we mainly focused on the HW side of things, but this seems to be a SW issue, so we may need to have a look at your code - I'd have a suspicion but would rather want to see the code first :wink:

This is the code running on my Xenon:

#include <DS18B20.h>

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

const int      connectionFail    = 5000 ;
const int      MAXRETRY          = 120;
const int      sleepTime         = 120;

DS18B20  ds18b20(D2, true); //Sets Pin D2 for  Temp Sensor and 
                            // this is the only sensor on bus
char     szInfo[64];
double   celsius;
long     wakeTime;

void setup() {
  ds18b20.setResolution(12);
}

void loop() {
 Particle.connect();
 if (waitFor(Particle.connected, connectionFail)) {     // if connected to the cloud, process this cycle
    getTemp();                                          // take a measurement every interval, just within Mesh network
    
    if (!isnan(celsius))
    {
      sprintf(szInfo, "%2.1f", (float)((int)(millis()-wakeTime))/1000);
      Mesh.publish("WorkingTime", szInfo);

      System.sleep(D6, RISING, sleepTime);
      wakeTime = millis();    
    }
    else
      delay(1000);
 }
 else
    System.sleep(D6, RISING, sleepTime);   // unable to connect to cloud, go to sleep and try again next time.
}

void getTemp(){
  float _temp;
  int   i = 0;

  do {
    _temp = ds18b20.getTemperature();
  } while (!ds18b20.crcCheck() && MAXRETRY > i++);

  if (i < MAXRETRY) {
    celsius = _temp;
  }
  else {
    celsius = NAN;
  }
  sprintf(szInfo, "%2.1f", celsius);
  Mesh.publish("dsTmp", szInfo);
}

It might be a timing problem.
You could add a delay(200) between the publish and the sleep statement or use something like this

  auto result = Mesh.publish("WorkingTime", szInfo);
  if (!result)
    System.sleep(D6, RISING, sleepTime);
  else
    Serial.printlnf("That didn't work (code: %d)", result);

(updated, see following posts)

If you don’t use the return value the publish call will not wait for the success feedback but if you do it will await the outcome before proceeding.

1 Like

@ScruffR Thanks. I thinkI have something else wrong though. I made that change to the code, and I get into the “else” clause of the if statement. The publish call is working successfully, the Argon gets the data, but result is false.

When I replaced Mesh.publish, with Particle.publish, the reliability seemed to be 100% (as opposed to 5% the way I had the code before), so it fixed the issue I was describing, but I don’t know why it’s returning false. I “fixed” it by adding the sleep command to both if clauses, but I still get to “That didn’t work”.

Also, I still have the issue of the xenon failing to connect every time after 6-18 hours of working fine.

How does it behave when you add delay(250) between the Mesh.publish() and the if() statement?

This might be something for @joel to chime in on.


Update:
@DevRandom, I inquired about this and Rick helped me understand that there is some inconsistency between Particle.publish() and Mesh.publish() where the former returns a (future) bool where true indicates succes but the latter returns an int with 0 (aka false) indicating success. (don't ask why - I don't understand the logic either :face_with_raised_eyebrow::upside_down_face:)

So I changed the code above to prevent future readers from falling into that trap.

BTW, here is a list of possible return codes

Currently the docs do lie about the fact too
https://docs.particle.io/reference/device-os/firmware/xenon/#publish-


(I'm sure this will be fixed in a few minutes :wink: )

I think you can safely go to 5.5V on Li+ as @ScruffR says, but I think the range for BAT_DET that maxes out at 4.6V was a design decision rather than based on safety limits. It will be good if in the next design iteration the R15/R16 is changed to be able to measure up to 5.5V. With the current design, when the Li+ input is 5.5V, there’s usually an ESD protection diode at the input that will conduct away excess current. With the current values of R15/R16, this current is around 0.6uA, not enough to cause any damage IMHO. A side concern is a constant drain of ~2.4uA@5.5V due to R15/R16. While this may not sound like much, when you are a battery, every uA counts!