Example program demonstrating proper powering down of Telit radio and putting the processor into STOP mode.

Dependencies:   WakeUp mbed mtsas SpiFlash25

Fork of Dragonfly_Cellular_Ping_Example by MultiTech

Committer:
mfiore
Date:
Tue Mar 01 17:41:47 2016 +0000
Revision:
5:e493656a4a1a
Parent:
4:91a322a2ec86
put SPI flash in low power mode too

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mfiore 3:90cf39b6ed0d 1 /** Dragonfly Cellular Low Power Example
mfiore 3:90cf39b6ed0d 2 * This program will run forever doing the following
mfiore 3:90cf39b6ed0d 3 * bring up the cellular link
mfiore 3:90cf39b6ed0d 4 * ping Google's DNS server
mfiore 3:90cf39b6ed0d 5 * properly power off the radio
mfiore 3:90cf39b6ed0d 6 * go to sleep
mfiore 3:90cf39b6ed0d 7 *
mfiore 3:90cf39b6ed0d 8 * There are two methods for properly powering off the cellular radio
mfiore 3:90cf39b6ed0d 9 * 1) Software shutdown
mfiore 4:91a322a2ec86 10 * - use Cellular::sendBasicCommand() to issue AT#SHDN to the radio and make sure it is successful
mfiore 4:91a322a2ec86 11 * - poll vdd1_8_mon - when the radio powers off this line will go to 0 (at least 10s after AT#SHDN)
mfiore 3:90cf39b6ed0d 12 * - drop the radio_reset line to 0 (pin PC_13) so the radio control chip doesn't attempt to restart the radio
mfiore 3:90cf39b6ed0d 13 * - (optional) drop the radio_pwr line to 0
mfiore 3:90cf39b6ed0d 14 * + this eliminates all current draw from the radio when it is powered off but increases the time it takes to reconnect to the network
mfiore 3:90cf39b6ed0d 15 * 2) Hardware shutdown
mfiore 3:90cf39b6ed0d 16 * - drop the radio_reset line to 0 (pin PC_13) so the radio control chip doesn't attempt to restart the radio
mfiore 3:90cf39b6ed0d 17 * - poll vdd1_8_mon - when the radio powers off this line will go to 0 (at least 10s after radio_reset was dropped)
mfiore 3:90cf39b6ed0d 18 * - (optional) drop the radio_pwr line to 0
mfiore 3:90cf39b6ed0d 19 * + this eliminates all current draw from the radio when it is powered off but increases the time it takes to reconnect to the network
mfiore 0:da114ae7c596 20 *
mfiore 0:da114ae7c596 21 * NOTE: This example changes the baud rate of the debug port to 115200 baud!
mfiore 4:91a322a2ec86 22 * NOTE: A SIM card is required for GSM radios to connect to the network!
mfiore 4:91a322a2ec86 23 * NOTE: CDMA cellular radios need to be provisioned before use!
mfiore 0:da114ae7c596 24 */
mfiore 0:da114ae7c596 25
mfiore 0:da114ae7c596 26 #include "mbed.h"
mfiore 0:da114ae7c596 27 #include "mtsas.h"
mfiore 3:90cf39b6ed0d 28 #include "WakeUp.h"
mfiore 5:e493656a4a1a 29 #include "SpiFlash25.h"
mfiore 0:da114ae7c596 30
mfiore 2:0288328818cb 31 // This line controls the regulator's battery charger.
mfiore 2:0288328818cb 32 // BC_NCE = 0 enables the battery charger
mfiore 2:0288328818cb 33 // BC_NCE = 1 disables the battery charger
mfiore 2:0288328818cb 34 DigitalOut bc_nce(PB_2);
mfiore 2:0288328818cb 35
mfiore 3:90cf39b6ed0d 36 // These lines are used to control the maximum current draw of the regulator
mfiore 3:90cf39b6ed0d 37 // | 100mA mode | 500mA mode| 1A mode |
mfiore 3:90cf39b6ed0d 38 // --------------------------------------------
mfiore 3:90cf39b6ed0d 39 // BC_EN1 | 0 | 1 | 0 |
mfiore 3:90cf39b6ed0d 40 // BC_EN2 | 0 | 0 | 1 |
mfiore 3:90cf39b6ed0d 41 // --------------------------------------------
mfiore 3:90cf39b6ed0d 42 // Default is 1A mode
mfiore 3:90cf39b6ed0d 43 DigitalOut bc_en1(PC_14, 0);
mfiore 3:90cf39b6ed0d 44 DigitalOut bc_en2(PC_15, 1);
mfiore 3:90cf39b6ed0d 45
mfiore 3:90cf39b6ed0d 46 // This line is used to reset or perform a HW shutdown the radio
mfiore 3:90cf39b6ed0d 47 // Set it low and keep it low to perform a HW shutdown
mfiore 3:90cf39b6ed0d 48 // Toggle it low and then high again to reset the radio
mfiore 3:90cf39b6ed0d 49 DigitalOut radio_reset(PC_13, 1);
mfiore 3:90cf39b6ed0d 50
mfiore 3:90cf39b6ed0d 51 // This line controls power to the radio
mfiore 3:90cf39b6ed0d 52 // It should only be dropped after the radio has been powered off via the radio_reset line or AT#SHDN command to reduce all current consumption from the radio
mfiore 3:90cf39b6ed0d 53 DigitalOut radio_pwr(PC_3, 1);
mfiore 3:90cf39b6ed0d 54
mfiore 3:90cf39b6ed0d 55 // This line is 1 when the radio has sufficient power
mfiore 3:90cf39b6ed0d 56 // It goes to 0 after the radio has successfully shut down
mfiore 3:90cf39b6ed0d 57 DigitalIn vdd1_8_mon(PC_5);
mfiore 3:90cf39b6ed0d 58
mfiore 5:e493656a4a1a 59 SpiFlash25 flash(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS1);
mfiore 5:e493656a4a1a 60
mfiore 0:da114ae7c596 61 bool init_mtsas();
mfiore 3:90cf39b6ed0d 62 void enterStopMode(const uint32_t interval);
mfiore 0:da114ae7c596 63
mfiore 1:1411b4274907 64 // The MTSSerialFlowControl object represents the physical serial link between the processor and the cellular radio.
mfiore 0:da114ae7c596 65 mts::MTSSerialFlowControl* io;
mfiore 1:1411b4274907 66 // The Cellular object represents the cellular radio.
mfiore 0:da114ae7c596 67 mts::Cellular* radio;
mfiore 0:da114ae7c596 68
mfiore 1:1411b4274907 69 // An APN is required for GSM radios.
mfiore 0:da114ae7c596 70 static const char apn[] = "";
mfiore 0:da114ae7c596 71
mfiore 0:da114ae7c596 72 bool radio_ok = false;
mfiore 0:da114ae7c596 73
mfiore 0:da114ae7c596 74 int main() {
mfiore 2:0288328818cb 75 // Disable the battery charger unless a battery is attached.
mfiore 2:0288328818cb 76 bc_nce = 1;
mfiore 2:0288328818cb 77
mfiore 3:90cf39b6ed0d 78 uint32_t sleep_time = 10;
mfiore 3:90cf39b6ed0d 79 Timer tmr;
mfiore 3:90cf39b6ed0d 80
mfiore 1:1411b4274907 81 // Change the baud rate of the debug port from the default 9600 to 115200.
mfiore 0:da114ae7c596 82 Serial debug(USBTX, USBRX);
mfiore 0:da114ae7c596 83 debug.baud(115200);
mfiore 0:da114ae7c596 84
mfiore 0:da114ae7c596 85 //Sets the log level to INFO, higher log levels produce more log output.
mfiore 0:da114ae7c596 86 //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
mfiore 0:da114ae7c596 87 mts::MTSLog::setLogLevel(mts::MTSLog::INFO_LEVEL);
mfiore 0:da114ae7c596 88 radio_ok = init_mtsas();
mfiore 0:da114ae7c596 89 if (! radio_ok) {
mfiore 0:da114ae7c596 90 while (true) {
mfiore 0:da114ae7c596 91 logError("failed to initialize cellular radio");
mfiore 0:da114ae7c596 92 wait(1);
mfiore 0:da114ae7c596 93 }
mfiore 0:da114ae7c596 94 }
mfiore 0:da114ae7c596 95
mfiore 3:90cf39b6ed0d 96 while (true) {
mfiore 3:90cf39b6ed0d 97 logInfo("changing regulator to 1A mode");
mfiore 3:90cf39b6ed0d 98 bc_en1 = 0;
mfiore 3:90cf39b6ed0d 99 bc_en2 = 1;
mfiore 5:e493656a4a1a 100 logInfo("waking up the SPI flash");
mfiore 5:e493656a4a1a 101 flash.wakeup();
mfiore 3:90cf39b6ed0d 102 logInfo("powering on radio");
mfiore 3:90cf39b6ed0d 103 radio_pwr = 1;
mfiore 3:90cf39b6ed0d 104 radio_reset = 1;
mfiore 3:90cf39b6ed0d 105 int tries = 0;
mfiore 3:90cf39b6ed0d 106
mfiore 3:90cf39b6ed0d 107 while (radio->sendBasicCommand("AT", 1000) != MTS_SUCCESS) {
mfiore 4:91a322a2ec86 108 wait(1);
mfiore 3:90cf39b6ed0d 109 tries++;
mfiore 3:90cf39b6ed0d 110 if (tries % 25 == 0) {
mfiore 3:90cf39b6ed0d 111 logWarning("no response from radio after 25 tries (total tries %d) - resetting radio", tries);
mfiore 3:90cf39b6ed0d 112 radio_reset = 0;
mfiore 3:90cf39b6ed0d 113 wait_ms(10);
mfiore 3:90cf39b6ed0d 114 radio_reset = 1;
mfiore 3:90cf39b6ed0d 115 }
mfiore 4:91a322a2ec86 116 printf(".");
mfiore 3:90cf39b6ed0d 117 }
mfiore 4:91a322a2ec86 118 printf("\r\n");
mfiore 0:da114ae7c596 119
mfiore 3:90cf39b6ed0d 120 logInfo("setting APN");
mfiore 3:90cf39b6ed0d 121 if (radio->setApn(apn) != MTS_SUCCESS)
mfiore 3:90cf39b6ed0d 122 logError("failed to set APN to \"%s\"", apn);
mfiore 3:90cf39b6ed0d 123 logInfo("bringing up the link");
mfiore 3:90cf39b6ed0d 124 if (! radio->connect()) {
mfiore 3:90cf39b6ed0d 125 logError("failed to bring up the link");
mfiore 3:90cf39b6ed0d 126 } else {
mfiore 3:90cf39b6ed0d 127 for (int i = 0; i < 10; i++) {
mfiore 3:90cf39b6ed0d 128 logInfo("pinging");
mfiore 3:90cf39b6ed0d 129 if (! radio->ping("www.google.com"))
mfiore 3:90cf39b6ed0d 130 logError("failed to ping");
mfiore 3:90cf39b6ed0d 131 else
mfiore 3:90cf39b6ed0d 132 logInfo("ping succeeded");
mfiore 3:90cf39b6ed0d 133 }
mfiore 3:90cf39b6ed0d 134 logInfo("finished - bringing down link");
mfiore 3:90cf39b6ed0d 135 radio->disconnect();
mfiore 0:da114ae7c596 136 }
mfiore 3:90cf39b6ed0d 137
mfiore 3:90cf39b6ed0d 138 // power down the radio
mfiore 3:90cf39b6ed0d 139 logInfo("powering down radio");
mfiore 3:90cf39b6ed0d 140 radio_reset = 0;
mfiore 4:91a322a2ec86 141 logInfo("waiting up to 30s for vdd1_8_mon to go low");
mfiore 3:90cf39b6ed0d 142 tmr.reset();
mfiore 3:90cf39b6ed0d 143 tmr.start();
mfiore 3:90cf39b6ed0d 144 // wait up to 30s for the radio to shut down
mfiore 4:91a322a2ec86 145 while (vdd1_8_mon != 0 && tmr.read() < 30) {
mfiore 4:91a322a2ec86 146 wait(1);
mfiore 4:91a322a2ec86 147 printf(".");
mfiore 4:91a322a2ec86 148 }
mfiore 3:90cf39b6ed0d 149 tmr.stop();
mfiore 4:91a322a2ec86 150 printf("\r\n");
mfiore 4:91a322a2ec86 151 if (vdd1_8_mon != 0 && tmr.read() >= 30) {
mfiore 4:91a322a2ec86 152 logError("radio did not shut down! aborting iteration");
mfiore 4:91a322a2ec86 153 continue;
mfiore 4:91a322a2ec86 154 }
mfiore 4:91a322a2ec86 155
mfiore 3:90cf39b6ed0d 156 logInfo("radio powered off after %fs", tmr.read());
mfiore 3:90cf39b6ed0d 157 radio_pwr = 0;
mfiore 5:e493656a4a1a 158 logInfo("putting the SPI flash in deep power down");
mfiore 5:e493656a4a1a 159 flash.deep_power_down();
mfiore 3:90cf39b6ed0d 160 logInfo("putting regulator in 100mA mode");
mfiore 3:90cf39b6ed0d 161 bc_en1 = 0;
mfiore 3:90cf39b6ed0d 162 bc_en2 = 0;
mfiore 3:90cf39b6ed0d 163
mfiore 3:90cf39b6ed0d 164 logInfo("going to sleep for %lu seconds", sleep_time);
mfiore 3:90cf39b6ed0d 165 enterStopMode(sleep_time);
mfiore 0:da114ae7c596 166 }
mfiore 0:da114ae7c596 167
mfiore 0:da114ae7c596 168 return 0;
mfiore 0:da114ae7c596 169 }
mfiore 0:da114ae7c596 170
mfiore 0:da114ae7c596 171 bool init_mtsas() {
mfiore 0:da114ae7c596 172 io = new mts::MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS);
mfiore 0:da114ae7c596 173 if (! io)
mfiore 0:da114ae7c596 174 return false;
mfiore 0:da114ae7c596 175
mfiore 0:da114ae7c596 176 // radio default baud rate is 115200
mfiore 0:da114ae7c596 177 io->baud(115200);
mfiore 0:da114ae7c596 178 radio = mts::CellularFactory::create(io);
mfiore 0:da114ae7c596 179 if (! radio)
mfiore 0:da114ae7c596 180 return false;
mfiore 0:da114ae7c596 181
mfiore 0:da114ae7c596 182 // Transport must be set properly before any TCPSocketConnection or UDPSocket objects are created
mfiore 0:da114ae7c596 183 Transport::setTransport(radio);
mfiore 0:da114ae7c596 184
mfiore 0:da114ae7c596 185 return true;
mfiore 0:da114ae7c596 186 }
mfiore 3:90cf39b6ed0d 187
mfiore 3:90cf39b6ed0d 188 #define RTC_ALARMA_DISABLE() do { \
mfiore 3:90cf39b6ed0d 189 RTC->ISR &= ~RTC_ISR_ALRAF; \
mfiore 3:90cf39b6ed0d 190 RTC->WPR = 0xCA; \
mfiore 3:90cf39b6ed0d 191 RTC->WPR = 0x53; \
mfiore 3:90cf39b6ed0d 192 RTC->CR &= ~(RTC_CR_ALRAE | RTC_CR_ALRAIE); \
mfiore 3:90cf39b6ed0d 193 RTC->WPR = 0xFF; \
mfiore 3:90cf39b6ed0d 194 } while (0)
mfiore 3:90cf39b6ed0d 195
mfiore 3:90cf39b6ed0d 196 void enterStopMode(const uint32_t interval) {
mfiore 3:90cf39b6ed0d 197 // disable ADC - it can consume power in stop mode
mfiore 3:90cf39b6ed0d 198 ADC1->CR2 &= ~ADC_CR2_ADON;
mfiore 3:90cf39b6ed0d 199
mfiore 3:90cf39b6ed0d 200 // enable debugging during stop mode
mfiore 3:90cf39b6ed0d 201 HAL_EnableDBGStopMode();
mfiore 3:90cf39b6ed0d 202
mfiore 3:90cf39b6ed0d 203 // put regulators into low-power mode
mfiore 3:90cf39b6ed0d 204 HAL_PWREx_EnableMainRegulatorLowVoltage();
mfiore 3:90cf39b6ed0d 205 HAL_PWREx_EnableLowRegulatorLowVoltage();
mfiore 3:90cf39b6ed0d 206
mfiore 3:90cf39b6ed0d 207 // power down flash
mfiore 3:90cf39b6ed0d 208 HAL_PWREx_EnableFlashPowerDown();
mfiore 3:90cf39b6ed0d 209
mfiore 3:90cf39b6ed0d 210 // configure RTC Alarm A to wake the device up
mfiore 3:90cf39b6ed0d 211 WakeUp::set(interval);
mfiore 3:90cf39b6ed0d 212
mfiore 3:90cf39b6ed0d 213 // make sure wakeup flag is cleared
mfiore 3:90cf39b6ed0d 214 PWR->CR |= PWR_CR_CWUF;
mfiore 3:90cf39b6ed0d 215
mfiore 3:90cf39b6ed0d 216 logInfo("entering stop mode %08x", RTC->ISR);
mfiore 3:90cf39b6ed0d 217 fflush(stdout);
mfiore 3:90cf39b6ed0d 218
mfiore 3:90cf39b6ed0d 219 // enter stop mode - don't execute past here until woken up
mfiore 3:90cf39b6ed0d 220 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
mfiore 3:90cf39b6ed0d 221
mfiore 3:90cf39b6ed0d 222 // HSI (High Speed Internal) oscillator is selected when coming out of stop mode - set up clocking
mfiore 3:90cf39b6ed0d 223 SetSysClock();
mfiore 3:90cf39b6ed0d 224
mfiore 3:90cf39b6ed0d 225 // disable RTC alarm A and RTC alarm A interrupt
mfiore 3:90cf39b6ed0d 226 RTC_ALARMA_DISABLE();
mfiore 3:90cf39b6ed0d 227
mfiore 3:90cf39b6ed0d 228 // clear wakeup flag in power control register
mfiore 3:90cf39b6ed0d 229 PWR->CR |= PWR_CR_CWUF;
mfiore 3:90cf39b6ed0d 230
mfiore 3:90cf39b6ed0d 231 // put regulators back into to full-power mode
mfiore 3:90cf39b6ed0d 232 HAL_PWREx_DisableMainRegulatorLowVoltage();
mfiore 3:90cf39b6ed0d 233 HAL_PWREx_DisableLowRegulatorLowVoltage();
mfiore 3:90cf39b6ed0d 234
mfiore 3:90cf39b6ed0d 235 // turn the flash back on
mfiore 3:90cf39b6ed0d 236 HAL_PWREx_DisableFlashPowerDown();
mfiore 3:90cf39b6ed0d 237
mfiore 3:90cf39b6ed0d 238 // enable the ADC
mfiore 3:90cf39b6ed0d 239 ADC1->CR2 |= ADC_CR2_ADON;
mfiore 3:90cf39b6ed0d 240
mfiore 3:90cf39b6ed0d 241 // disable debugging during stop mode
mfiore 3:90cf39b6ed0d 242 HAL_DisableDBGStopMode();
mfiore 3:90cf39b6ed0d 243 }