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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /** Dragonfly Cellular Low Power Example
00002  * This program will run forever doing the following
00003  *      bring up the cellular link
00004  *      ping Google's DNS server
00005  *      properly power off the radio
00006  *      go to sleep
00007  *
00008  * There are two methods for properly powering off the cellular radio
00009  *  1) Software shutdown
00010  *      - use Cellular::sendBasicCommand() to issue AT#SHDN to the radio and make sure it is successful
00011  *      - poll vdd1_8_mon - when the radio powers off this line will go to 0 (at least 10s after AT#SHDN)
00012  *      - drop the radio_reset line to 0 (pin PC_13) so the radio control chip doesn't attempt to restart the radio
00013  *      - (optional) drop the radio_pwr line to 0
00014  *          + this eliminates all current draw from the radio when it is powered off but increases the time it takes to reconnect to the network
00015  *  2) Hardware shutdown
00016  *      - drop the radio_reset line to 0 (pin PC_13) so the radio control chip doesn't attempt to restart the radio
00017  *      - poll vdd1_8_mon - when the radio powers off this line will go to 0 (at least 10s after radio_reset was dropped)
00018  *      - (optional) drop the radio_pwr line to 0
00019  *          + this eliminates all current draw from the radio when it is powered off but increases the time it takes to reconnect to the network
00020  *
00021  * NOTE: This example changes the baud rate of the debug port to 115200 baud!
00022  * NOTE: A SIM card is required for GSM radios to connect to the network!
00023  * NOTE: CDMA cellular radios need to be provisioned before use!
00024  */
00025 
00026 #include "mbed.h"
00027 #include "mtsas.h"
00028 #include "WakeUp.h"
00029 #include "SpiFlash25.h"
00030 
00031 // This line controls the regulator's battery charger.
00032 // BC_NCE = 0 enables the battery charger
00033 // BC_NCE = 1 disables the battery charger
00034 DigitalOut bc_nce(PB_2);
00035 
00036 // These lines are used to control the maximum current draw of the regulator
00037 //        | 100mA mode | 500mA mode| 1A mode  |
00038 // --------------------------------------------
00039 // BC_EN1 |      0     |     1     |    0     |
00040 // BC_EN2 |      0     |     0     |    1     |
00041 // --------------------------------------------
00042 // Default is 1A mode
00043 DigitalOut bc_en1(PC_14, 0);
00044 DigitalOut bc_en2(PC_15, 1);
00045 
00046 // This line is used to reset or perform a HW shutdown the radio
00047 // Set it low and keep it low to perform a HW shutdown
00048 // Toggle it low and then high again to reset the radio
00049 DigitalOut radio_reset(PC_13, 1);
00050 
00051 // This line controls power to the radio
00052 // 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
00053 DigitalOut radio_pwr(PC_3, 1);
00054 
00055 // This line is 1 when the radio has sufficient power
00056 // It goes to 0 after the radio has successfully shut down
00057 DigitalIn vdd1_8_mon(PC_5);
00058 
00059 SpiFlash25 flash(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS1);
00060 
00061 bool init_mtsas();
00062 void enterStopMode(const uint32_t interval);
00063 
00064 // The MTSSerialFlowControl object represents the physical serial link between the processor and the cellular radio.
00065 mts::MTSSerialFlowControl* io;
00066 // The Cellular object represents the cellular radio.
00067 mts::Cellular* radio;
00068 
00069 // An APN is required for GSM radios.
00070 static const char apn[] = "";
00071 
00072 bool radio_ok = false;
00073 
00074 int main() {
00075     // Disable the battery charger unless a battery is attached.
00076     bc_nce = 1;
00077     
00078     uint32_t sleep_time = 10;
00079     Timer tmr;
00080     
00081     // Change the baud rate of the debug port from the default 9600 to 115200.
00082     Serial debug(USBTX, USBRX);
00083     debug.baud(115200);
00084     
00085     //Sets the log level to INFO, higher log levels produce more log output.
00086     //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
00087     mts::MTSLog::setLogLevel(mts::MTSLog::INFO_LEVEL);
00088     radio_ok = init_mtsas();
00089     if (! radio_ok) {
00090         while (true) {
00091             logError("failed to initialize cellular radio");
00092             wait(1);
00093         }
00094     }
00095     
00096     while (true) {
00097         logInfo("changing regulator to 1A mode");
00098         bc_en1 = 0;
00099         bc_en2 = 1;
00100         logInfo("waking up the SPI flash");
00101         flash.wakeup();
00102         logInfo("powering on radio");
00103         radio_pwr = 1;
00104         radio_reset = 1;
00105         int tries = 0;
00106         
00107         while (radio->sendBasicCommand("AT", 1000) != MTS_SUCCESS) {
00108             wait(1);
00109             tries++;
00110             if (tries % 25 == 0) {
00111                 logWarning("no response from radio after 25 tries (total tries %d) - resetting radio", tries);
00112                 radio_reset = 0;
00113                 wait_ms(10);
00114                 radio_reset = 1;
00115             }
00116             printf(".");
00117         }
00118         printf("\r\n");
00119         
00120         logInfo("setting APN");
00121         if (radio->setApn(apn) != MTS_SUCCESS)
00122             logError("failed to set APN to \"%s\"", apn);
00123         logInfo("bringing up the link");
00124         if (! radio->connect()) {
00125             logError("failed to bring up the link");
00126         } else {
00127             for (int i = 0; i < 10; i++) {
00128                 logInfo("pinging");
00129                 if (! radio->ping("www.google.com"))
00130                     logError("failed to ping");
00131                 else
00132                     logInfo("ping succeeded");
00133             }
00134             logInfo("finished - bringing down link");
00135             radio->disconnect();
00136         }
00137         
00138         // power down the radio
00139         logInfo("powering down radio");
00140         radio_reset = 0;
00141         logInfo("waiting up to 30s for vdd1_8_mon to go low");
00142         tmr.reset();
00143         tmr.start();
00144         // wait up to 30s for the radio to shut down
00145         while (vdd1_8_mon != 0 && tmr.read() < 30) {
00146             wait(1);
00147             printf(".");
00148         }
00149         tmr.stop();
00150         printf("\r\n");
00151         if (vdd1_8_mon != 0 && tmr.read() >= 30) {
00152             logError("radio did not shut down! aborting iteration");
00153             continue;
00154         }
00155             
00156         logInfo("radio powered off after %fs", tmr.read());
00157         radio_pwr = 0;
00158         logInfo("putting the SPI flash in deep power down");
00159         flash.deep_power_down();
00160         logInfo("putting regulator in 100mA mode");
00161         bc_en1 = 0;
00162         bc_en2 = 0;
00163         
00164         logInfo("going to sleep for %lu seconds", sleep_time);
00165         enterStopMode(sleep_time);
00166     }
00167     
00168     return 0;
00169 }
00170 
00171 bool init_mtsas() {
00172     io = new mts::MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS);
00173     if (! io)
00174         return false;
00175         
00176     // radio default baud rate is 115200
00177     io->baud(115200);
00178     radio = mts::CellularFactory::create(io);
00179     if (! radio)
00180         return false;
00181         
00182     // Transport must be set properly before any TCPSocketConnection or UDPSocket objects are created
00183     Transport::setTransport(radio);
00184     
00185     return true;
00186 }
00187 
00188 #define RTC_ALARMA_DISABLE() do { \
00189     RTC->ISR &= ~RTC_ISR_ALRAF; \
00190     RTC->WPR = 0xCA; \
00191     RTC->WPR = 0x53; \
00192     RTC->CR &= ~(RTC_CR_ALRAE | RTC_CR_ALRAIE); \
00193     RTC->WPR = 0xFF; \
00194 } while (0)
00195 
00196 void enterStopMode(const uint32_t interval) {
00197     // disable ADC - it can consume power in stop mode
00198     ADC1->CR2 &= ~ADC_CR2_ADON;
00199 
00200     // enable debugging during stop mode
00201     HAL_EnableDBGStopMode();
00202 
00203     // put regulators into low-power mode
00204     HAL_PWREx_EnableMainRegulatorLowVoltage();
00205     HAL_PWREx_EnableLowRegulatorLowVoltage();
00206 
00207     // power down flash
00208     HAL_PWREx_EnableFlashPowerDown();
00209     
00210     // configure RTC Alarm A to wake the device up
00211     WakeUp::set(interval);
00212 
00213     // make sure wakeup flag is cleared
00214     PWR->CR |= PWR_CR_CWUF;
00215 
00216     logInfo("entering stop mode %08x", RTC->ISR);
00217     fflush(stdout);
00218 
00219     // enter stop mode - don't execute past here until woken up
00220     HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
00221 
00222     // HSI (High Speed Internal) oscillator is selected when coming out of stop mode - set up clocking
00223     SetSysClock();
00224 
00225     // disable RTC alarm A and RTC alarm A interrupt
00226     RTC_ALARMA_DISABLE();
00227 
00228     // clear wakeup flag in power control register
00229     PWR->CR |= PWR_CR_CWUF;
00230 
00231     // put regulators back into to full-power mode
00232     HAL_PWREx_DisableMainRegulatorLowVoltage();
00233     HAL_PWREx_DisableLowRegulatorLowVoltage();
00234 
00235     // turn the flash back on
00236     HAL_PWREx_DisableFlashPowerDown();
00237 
00238     // enable the ADC
00239     ADC1->CR2 |= ADC_CR2_ADON;
00240 
00241     // disable debugging during stop mode
00242     HAL_DisableDBGStopMode();
00243 }