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
- Committer:
- mfiore
- Date:
- 2016-02-29
- Revision:
- 4:91a322a2ec86
- Parent:
- 3:90cf39b6ed0d
- Child:
- 5:e493656a4a1a
File content as of revision 4:91a322a2ec86:
/** Dragonfly Cellular Low Power Example * This program will run forever doing the following * bring up the cellular link * ping Google's DNS server * properly power off the radio * go to sleep * * There are two methods for properly powering off the cellular radio * 1) Software shutdown * - use Cellular::sendBasicCommand() to issue AT#SHDN to the radio and make sure it is successful * - poll vdd1_8_mon - when the radio powers off this line will go to 0 (at least 10s after AT#SHDN) * - drop the radio_reset line to 0 (pin PC_13) so the radio control chip doesn't attempt to restart the radio * - (optional) drop the radio_pwr line to 0 * + this eliminates all current draw from the radio when it is powered off but increases the time it takes to reconnect to the network * 2) Hardware shutdown * - drop the radio_reset line to 0 (pin PC_13) so the radio control chip doesn't attempt to restart the radio * - poll vdd1_8_mon - when the radio powers off this line will go to 0 (at least 10s after radio_reset was dropped) * - (optional) drop the radio_pwr line to 0 * + this eliminates all current draw from the radio when it is powered off but increases the time it takes to reconnect to the network * * NOTE: This example changes the baud rate of the debug port to 115200 baud! * NOTE: A SIM card is required for GSM radios to connect to the network! * NOTE: CDMA cellular radios need to be provisioned before use! */ #include "mbed.h" #include "mtsas.h" #include "WakeUp.h" // This line controls the regulator's battery charger. // BC_NCE = 0 enables the battery charger // BC_NCE = 1 disables the battery charger DigitalOut bc_nce(PB_2); // These lines are used to control the maximum current draw of the regulator // | 100mA mode | 500mA mode| 1A mode | // -------------------------------------------- // BC_EN1 | 0 | 1 | 0 | // BC_EN2 | 0 | 0 | 1 | // -------------------------------------------- // Default is 1A mode DigitalOut bc_en1(PC_14, 0); DigitalOut bc_en2(PC_15, 1); // This line is used to reset or perform a HW shutdown the radio // Set it low and keep it low to perform a HW shutdown // Toggle it low and then high again to reset the radio DigitalOut radio_reset(PC_13, 1); // This line controls power to the radio // 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 DigitalOut radio_pwr(PC_3, 1); // This line is 1 when the radio has sufficient power // It goes to 0 after the radio has successfully shut down DigitalIn vdd1_8_mon(PC_5); bool init_mtsas(); void enterStopMode(const uint32_t interval); // The MTSSerialFlowControl object represents the physical serial link between the processor and the cellular radio. mts::MTSSerialFlowControl* io; // The Cellular object represents the cellular radio. mts::Cellular* radio; // An APN is required for GSM radios. static const char apn[] = ""; bool radio_ok = false; int main() { // Disable the battery charger unless a battery is attached. bc_nce = 1; uint32_t sleep_time = 10; Timer tmr; // Change the baud rate of the debug port from the default 9600 to 115200. Serial debug(USBTX, USBRX); debug.baud(115200); //Sets the log level to INFO, higher log levels produce more log output. //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE mts::MTSLog::setLogLevel(mts::MTSLog::INFO_LEVEL); radio_ok = init_mtsas(); if (! radio_ok) { while (true) { logError("failed to initialize cellular radio"); wait(1); } } while (true) { logInfo("changing regulator to 1A mode"); bc_en1 = 0; bc_en2 = 1; logInfo("powering on radio"); radio_pwr = 1; radio_reset = 1; int tries = 0; while (radio->sendBasicCommand("AT", 1000) != MTS_SUCCESS) { wait(1); tries++; if (tries % 25 == 0) { logWarning("no response from radio after 25 tries (total tries %d) - resetting radio", tries); radio_reset = 0; wait_ms(10); radio_reset = 1; } printf("."); } printf("\r\n"); logInfo("setting APN"); if (radio->setApn(apn) != MTS_SUCCESS) logError("failed to set APN to \"%s\"", apn); logInfo("bringing up the link"); if (! radio->connect()) { logError("failed to bring up the link"); } else { for (int i = 0; i < 10; i++) { logInfo("pinging"); if (! radio->ping("www.google.com")) logError("failed to ping"); else logInfo("ping succeeded"); } logInfo("finished - bringing down link"); radio->disconnect(); } // power down the radio logInfo("powering down radio"); radio_reset = 0; logInfo("waiting up to 30s for vdd1_8_mon to go low"); tmr.reset(); tmr.start(); // wait up to 30s for the radio to shut down while (vdd1_8_mon != 0 && tmr.read() < 30) { wait(1); printf("."); } tmr.stop(); printf("\r\n"); if (vdd1_8_mon != 0 && tmr.read() >= 30) { logError("radio did not shut down! aborting iteration"); continue; } logInfo("radio powered off after %fs", tmr.read()); radio_pwr = 0; logInfo("putting regulator in 100mA mode"); bc_en1 = 0; bc_en2 = 0; logInfo("going to sleep for %lu seconds", sleep_time); enterStopMode(sleep_time); } return 0; } bool init_mtsas() { io = new mts::MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS); if (! io) return false; // radio default baud rate is 115200 io->baud(115200); radio = mts::CellularFactory::create(io); if (! radio) return false; // Transport must be set properly before any TCPSocketConnection or UDPSocket objects are created Transport::setTransport(radio); return true; } #define RTC_ALARMA_DISABLE() do { \ RTC->ISR &= ~RTC_ISR_ALRAF; \ RTC->WPR = 0xCA; \ RTC->WPR = 0x53; \ RTC->CR &= ~(RTC_CR_ALRAE | RTC_CR_ALRAIE); \ RTC->WPR = 0xFF; \ } while (0) void enterStopMode(const uint32_t interval) { // disable ADC - it can consume power in stop mode ADC1->CR2 &= ~ADC_CR2_ADON; // enable debugging during stop mode HAL_EnableDBGStopMode(); // put regulators into low-power mode HAL_PWREx_EnableMainRegulatorLowVoltage(); HAL_PWREx_EnableLowRegulatorLowVoltage(); // power down flash HAL_PWREx_EnableFlashPowerDown(); // configure RTC Alarm A to wake the device up WakeUp::set(interval); // make sure wakeup flag is cleared PWR->CR |= PWR_CR_CWUF; logInfo("entering stop mode %08x", RTC->ISR); fflush(stdout); // enter stop mode - don't execute past here until woken up HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // HSI (High Speed Internal) oscillator is selected when coming out of stop mode - set up clocking SetSysClock(); // disable RTC alarm A and RTC alarm A interrupt RTC_ALARMA_DISABLE(); // clear wakeup flag in power control register PWR->CR |= PWR_CR_CWUF; // put regulators back into to full-power mode HAL_PWREx_DisableMainRegulatorLowVoltage(); HAL_PWREx_DisableLowRegulatorLowVoltage(); // turn the flash back on HAL_PWREx_DisableFlashPowerDown(); // enable the ADC ADC1->CR2 |= ADC_CR2_ADON; // disable debugging during stop mode HAL_DisableDBGStopMode(); }