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