Server.disconnect() and WLAN_POWER_EN

I attempted to use server.disconnect() for the first time to confirm the operation of the WLAN_POWER_EN pin of the IMP003 using the Deliberate Disconnection code here, which I modified to connect every 60 seconds and not send SensorData to the agent:


`function mainLoop() {
	// Schedule the next sample in 2 seconds
	imp.wakeup(2.0, mainLoop);
	if (time() - downTime > 60 && reconnectAttemptFlag == false) {
		// Every 60 seconds, attempt to connect to WiFi
		reconnectAttemptFlag = true;
		// Attempt to connect to server, 30sec timeout
		PowerEnState = imp.getpoweren();
		server.connect(connectHandler, 30.0);
	}
}
function connectHandler(reason) {
	reconnectAttemptFlag = false;
	downTime = time();
	if (reason == SERVER_CONNECTED) {
		// Device has successfully connected
		server.log("Device temporarily online to save data");
		// Relay data to agent
		//agent.send("save.data", sensorData);
		//sensorData = {};
		// Warn about sleep
		server.log("Device is now going offline");
		server.flush(10.0);
		server.disconnect();
	}
}
downTime <- 0;
reconnectAttemptFlag <- false;
//sensorData <- {};
server.setsendtimeoutpolicy(RETURN_ON_ERROR, WAIT_TIL_SENT, 30.0);
server.log("Device is running, but going offline");
server.disconnect();
imp.wakeup(2.0, mainLoop);
downTime = time();
`

The server log updated every ~60 seconds as expected but the WLAN_POWER_EN remained high. WLAN_POWER_EN is supposed to go low when server.disconnect() is called isn’t it? Am I missing something?

WLAN_POWER_EN does go off.

If you modify the code about to make the variable PowerEnState a global:

PowerEnState <- false;

then add the following lines to connectHandler() after the first server.log():

`if (PowerEnState) {
    server.log("WiFi was on");
} else {
    server.log("WiFi was off");
}`

then you’ll see:

2016-06-13 09:32:03 Streamed from "Printer": [server.log] WiFi was off

in your log, ie. PowerEnState is false - WiFi was correctly powered down when the variable was set, as you’d expect from calling server.disconnect() at the end of the code.

Hi @smittytone.

I made the recommended changes and added an extra if statement in connectionHandler():

`//Report state of WLAN_POWER_EN prior to server coming online
if (PowerEnState) {
    server.log("WiFi was on");
} else {
    server.log("WiFi was off");
}
PowerEnState = imp.getpoweren();
//Report state of WLAN_POWER_EN after the server came online
if (PowerEnState) {
    server.log("WiFi was on");
} else {
    server.log("WiFi was off");
}`

I expected to see “WiFi was off” then “WiFi was on” reported in the log but saw two “WiFi was off”. The WLAN_POWER_EN pin remained high.

It seems imp.getpoweren() “only reports whether Squirrel has explicitly activated POWER_EN using: imp.setpoweren(true); and not whether POWER_EN is enabled for any other reason, for instance when WiFi is powered up by impOS.”, so it can’t be relied upon to report the actual state of WLAN_POWER_EN.

Inserting imp.setpoweren(true) prior to server.connect() and imp.setpoweren(false) after server.disconnect() caused the WiFi state reported to the log to toggle from “WiFi was off” to “WiFi was on” but the WLAN_POWER_EN pin remained high.

The current flowing into the IMP003 is ~8mA most of the time which equates to the current drawn during the WiFi power-save mode. I’d expect current draw to drop to the order of uA but no dice.

I disconnected WLAN_POWER_EN from pin 3 (EN) of the AP2281 (via a jumper) and applied power to the IMP, expecting to see WiFi off current draw levels but current drawn toggled between 70mA and 15mA; the LED didn’t light up at all which I thought unusual.

You only get to microamp mode when you go into deep sleep (see spec sheet); when in powersave, the wifi consumption drops to around a milliamp - the rest of the power is being used by the STM32.

Power consumption will change significantly based on what peripherals you have configured (including whether blinkup is enabled) because these cause us to have to lock the bus clocks at high frequencies for performance.

If you disabled WLAN_POWER_EN the imp would constantly be trying to boot the wifi chip which likely burns some power.

Hi Hugo.

Ah, so why doesn’t server.disconnect(), even though it “turns off WIFi”, cause WLAN_POWER_EN to go low as well? Wouldn’t it be advantageous, from a power consumption perspective, to utilise WLAN_POWER_EN to remove power from WiFi when the IMP is disconnected from the server?

Reading the Imp API further I see imp.deepsleepfor() and similar calls puts the IMP into deep sleep, which I see “tri-states all the IMPs pins”. Calling imp.deepsleepfor() causes WLAN_POWER_EN to go low, or is it tri-stated? Whichever, it certainly causes the current draw to drop to difficult-to-measure levels.

It should, I believe - if it doesn’t that’s a bug. Are you using hardware.spiflash? If you are and the SPI flash is on the radio power rail, the radio rail will stay up.

The leakage from the wifi chip even with the power gate is on is <50uA, hence whether the gate is on or off is really only significant in deep sleep.

WLAN_POWER_EN has an external pulldown in our reference designs to ensure the pin goes low when not driven.

Hi Hugo.

I rechecked my code and found a small routine to check if I have flash and report some stats but didn’t disable the flash on exit. Inserting a spiflash.disable() at the end of the routine now causes the WLAN_POWER_EN to go low when server.disconnect() is called. Yes I’m using SPI flash but it’s not powered from the radio rail, it’s powered from the same rail as the CPU; I checked the voltage at the input to the flash and it is stable at 3.3V when WLAN_POWER_EN goes low.

Should I power the flash IC from the radio rail?

Does the IMP put the flash IC into sleep or deep power-down modes when spiflash.disable() is called?

The imp doesn’t put the flash into sleep or deep power down, no. Putting the flash on the radio rail is the best way to ensure that power is saved.