Is it possible to stop SPI bus and turn MISO, MOSI and SCK pins to INPUTS?

Maybe I should stop trying to help debug this cause I'm really not clear on your setup and code. When you go to (STOP) sleep, the Application Watchdog won't run since FreeRTOS is not running. Are you referring to an external hardware watchdog?

That’s an interesting point on the Application Watchdog - further advice from Dave at Particle was to increase the default stack to 1800 - ApplicationWatchdog wd(MCHK, restartResume, 1800);

I have just tried something else with the sensor current issue which is set the GPIO pins to INPUT before I turn the power rail off to the peripherals - seems to work once - I see less than 2mA which is good - I will need to see what the hardware guys come up with. Thanks for your help.

@armor, Dave’s advice on the Watchdog stack still stands as it has been observed that System.reset() clobbers the small stack allocated to the Watchdog task. I still stand on the fact that during STOP sleep, nothing runs except the RTC and the peripheral clocks and FreeRTOS doesn’t run using hardware timers. Besides, what’s the point of have a watchdog wake and reset when you are trying to save power!

1 Like

@armor, I just confirmed that the Application Watchdog will not and cannot run while the device is in STOP or STANDBY (deep sleep) modes. Are you using an external hardware watchdog?

No - just what I included in my reply above.

@armor, then the issue of not sleeping is not caused by the Application Watchdog. However, the stack size issue still stands and if System.reset() gets called from within the Watchdog, it will SOS without the larger stack.

Correct. One thing I am trying to understand is that when I test this with test software (cut down version of application) on the actual PCB, the first time I go to sleep after a reset or flash the power consumption in sleep is 2mA, after waking and then repeating the conditions to go to sleep the sleep current draw is 10mA? I am wracking my brain to think of a cause.

@armor, since pin states are maintained in STOP sleep, it sounds like something is changing from the first sleep to subsequent sleeps in regards to pin states. 8ma of current is a lot so you have to consider a device staying on or a bunch of external pull-ups or pull-downs creating parasitic current flow or even a unforeseen parasitic current path. The condition in question would be a result of the code you run AFTER or affected by your first call to sleep. Do you store any state in eeprom that affects subsequent wake configurations?

Rick, I have done a lot more digging into the libraries for the tft and sd. It seemed strange that the first time I call sleep it works and I get a current similar to the one you get in tests (2.32mA). So I was looking at what was going on after the wake from sleep to essentially see if there was something being set that then got the System.sleep() into a fault condition. This fault condition is manifested with a current of 10-11mA and a voltage of 2.8V on A5 where this should be 0V. Essentially, if do an sd.begin() after the wake and restore of power to the peripherals then the next sleep will exhibit the fault condition. I have been using SdFat library (on the basis this is the most used of several) - I have had a look in the library and see that there are static defines of variables and thread controls which are difficult to understand given the level of conditional compiles. Could you suggest the best alternative sd library please? Thanks

There is something going on. It might be in the SDFat library, but that’s probably the best library available. It shouldn’t be necessary to SPI.end() and change the pin mode before sleep; that should be automatic. I think there’s something that’s causing the SD card to go into a strange state. This post implies that some early versions of SdFat had a bug related to that, but I don’t know if that exists in the Particle port or not.

This is the circuit I tested with:

And this is the code:

#include "Particle.h"

SYSTEM_THREAD(ENABLED);

#include "SdCardLogHandlerRK.h"

const int SD_CHIP_SELECT = A2;
SdFat sd;

SdCardLogHandler logHandler(sd, SD_CHIP_SELECT, SPI_FULL_SPEED);


void buttonHandler();

bool doSleep = false;
int counter = 0;
unsigned long lastCounterTime = 0;


void setup() {
	Serial.begin(9600);
	System.on(button_click, buttonHandler);

	sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED);
}

void loop() {

	if (doSleep) {
		doSleep = false;
		Log.info("about to sleep");

		System.sleep(WKP, RISING, 30);

		Log.info("woke from sleep");
	}

	if (millis() - lastCounterTime >= 1000) {
		lastCounterTime = millis();
		Log.info("testing counter=%d", counter++);
	}
}

void buttonHandler() {
	doSleep = true;
}

With these libraries:

dependencies.SdFat=0.0.7
dependencies.SdCardLogHandlerRK=0.0.4

With the SD card reader completely removed from the circuit I got 3 mA, as expected.

With the SD card reader present, I get 13.5 mA, which isn’t right, but consistent.

If I remove the VCC from the card reader after entering sleep, the usage goes down to 3 mA. The surprising part is that if I plug it back in, it stays at 3 mA. This implies that the card is getting into a bad state and not going into sleep mode.

Same with removing GND. However, it should not be necessary to put a MOSFET on the SD card reader. It should automatically go into sleep mode.

1 Like

@rickkas7, I was never able to get an SD card to sleep and had to use a low-side FET to turn it off. In my case I was deep sleeping the Photon so the firmware including SDFat was restarting on every wake.

2 Likes

@peekay123 @rickkas7 I thought it be polite to provide an update of where I have got to. Since I originally started this thread I have taken the PCB through a revision cycle and received a couple of prototypes to test yesterday. Using 0.8.0-RC.4 I can now reliably enter sleep and wake on a pulse on WKP pin. The current is 1.65mA which is well within the design objective of 2mA. I have found the following which maybe useful to others trying power management with SPI bus devices and I2C.

  1. SPI bus pull-up resistors are all 100K - SPI_FULL_SPEED / 60MHz is stable and reliable.
  2. The switched peripheral supply has a diode to stop a back feed of current through the LDO.
  3. Just using System.sleep(WKP, RISING, period); I can get the current down to 39.3mA
  4. Power to peripherals (TFT, SD Card controller, I2C GPIO expander, I2C temperature sensor, touch button controllers) must be turn off immediately before calling System.sleep() otherwise it does not enter sleep but is not looping either! Cloud variables are accessible, WiFi is on.
  5. I confirmed with the author of the SDFat library that SPI.end() is not required, indeed I found that if I called it then sleep would not be entered and I had the same state as in 4. Once the power is removed to the SD card controller (similar to removing the card) then a sd.begin() must be called as part of the wake-up procedure.
  6. If use pinMode(pin, INPUT) for the TFTCS, SDCS, DCRS, RST pins before removing power to the peripherals then the sleep current comes down to 1.65mA.

I then tried using System.sleep(SLEEP_MODE_DEEP,0); and strangely with this I was expecting current 0.1mA but saw 2.16mA.

[UPDATE] - the Deep Sleep current was due to there being voltage on the SPI bus pins on the photon. This turned out to be a misunderstanding in the revision design where the power supply to the SD card reader was being taken from the photon 3V3 and not the switched 3V3 supply - fortunately just a BoM change. Now working at 1.5mA when normal sleeping and 0.15mA when in deep sleep - potentially 8-10 weeks with the backup battery.

1 Like