Wake up a Electron when powered by USB, not the lipo


#1

Hi

My goal is using the Asset Tracking Electron, I want to put the Electron in Sleep mode when USB is not charging and wake up when USB is charging.

Asset will be placed in a car and start tracking when the power come from the USB.

In the Electron documentation, where is the section about this feature to detect when the Electron is powered by the USB not the battery ?


#2

Since the Vin pin is not powered from the LiPo you can use that pin as a RISING edge wake pin.
This would be the answer to your topic title, but whan you say …

… this will only tell whether 5V is coming from USB, it doesn’t tell anything about whether or not the LiPo gets charged or not (e.g. when fullly charged already).


#3

Hi @ScruffR I don’t need to know if USB is charging, only if 5V is coming is fine for my use case.

Do you have a example about best case to use RISING ?


#4

Connect VIN to WKP pin with a 2.2k resistor in-between. Add a 3.3k resistor to ground on the WKP pin. Make sure pull-up/pull-down resistors for the WKP pin are disabled / don’t enable them in firmware.

This converts 5V to ~3.3V using a resistive voltage divider network. When VIN goes from 0V to 5V because of 5V via the usb, this creates a transition from 0V to ~3.3V on the WKP pin which the processor will listen to to wake it up from sleep.

You could then measure voltage by using WKP as an ADC pin (A7) periodically to determine when to go back to sleep.

Test it to make sure those values work for you. Keep in mind tolerances to make sure the range of voltage outputs meets your requirements.


#5

Sure, extra precautions are nothing to appologise for but if you are after a minimal approach with pragmatic risk assessment the voltage dividers are not a must have.

Some background

This is difficult to achieve since System.sleep() will apply the respective pull-resistors depending on the trigger edge. So if you don’t want an internal pull to be applied you’d need to trigger for CHANGE.
Deep sleep always has uses the internal pull-down.
A related comment/proposal exists in a pending firmware issue
https://github.com/particle-iot/device-os/issues/1149#issuecomment-257079898

However, as long you are not using A3 or A6 (aka DAC) as wake pin, you don’t need a voltage divider as all pins (apart from the two) on the Photon/Electron are 5V tolerant (for a short time even with attached internal resistors).
If the internal pull-resistors are only attached for the sleep periode and after applying 5V the device immediately wakes and reverts to pinMode(pin, INPUT) - either by having had it assigned before Stop Mode sleep or by default after deep sleep - you should be good.

When opting against the voltage divider make sure you don’t analogRead() that pin but rather use digitalRead() which will again accept 5V and rid you of the need for a voltage divider.

Sure

  // either 
  System.sleep(SLEEP_MODE_DEEP, 3600); // deep sleep for 1h or till RISING edge detected on WKP
  // or
  System.sleep(D1, RISING, 3600); // Stop mode sleep for 1h or till D1 goes HIGH
  // for that version make sure you either don't set pinMode() or 
  // exlplicitly set it to pinMode(D1, INPUT) any time before sleeping 
  // or immediately after the System.sleep() call where the code will follow 
  // on after wake

#6

Which pin can be use to validate if USB is connected with 5V is the A7 ?

Like that

System.sleep(A7, RISING, 3600);


#7

A7 is WKP and can be used with either sleep mode.


#8

Thanks @ScruffR I’ll test it and let you know


#9

Hi @ScruffR

I try to test just like this code. I don’t have installed 2.2k resistance between VIN and WKP and 3.3k from WKP to ground. Do I need to make this setup to run my code ? Actually is not working.

Note : I don’t test sleep for now, just try using attachInterrupt. When done, I’ll use the System.sleep(

Thanks

void hello(void);

void setup() {

    pinMode(A7, INPUT_PULLDOWN);    
    attachInterrupt(A7, hello, RISING);

}

void loop() {

}

void hello()
{
  Particle.publish("I am blink", PRIVATE);
}

#10

You cannot use Particle.publish() from within an ISR.

Try this instead

void hello(void);

void setup() {
    pinMode(D7, OUTPUT);
    pinMode(A7, INPUT);    
    attachInterrupt(A7, hello, RISING);
}

void hello()
{
    static uint32_t ms = 0;
    if (millis() - ms < 200) return;     // simple 200ms debounce
    ms = millis(); 
    digitalWrite(D7, !digitalRead(D7));  // toggle D7 LED
}

For this you do need an external pull-down e.g. 10k (should be possible to go higher tho’) on A7 and a connection between Vin and A7 (for safety I’d add a 470Ohm resistor to limit current in case of inadvertent OUTPUT LOW).
The external pull-down is required since this condition doesn’t apply to your test setup

So with a test code like this, where you need and external pull-down anyway, the voltage divider is the better approach after all - although I’d maybe increase the values to reduce current while USB powered (e.g. 10k + 6k8).