Example program for power saving mode of cellular modem. This program can be used with UBLOX_C030_R412M board.
Dependencies: ublox-at-cellular-interface ublox-cellular-base ublox-cellular-base-n2xx ublox-at-cellular-interface-n2xx
main.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017 u-blox 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <stdarg.h> 00017 #include "mbed.h" 00018 #include "UbloxATCellularInterface.h" 00019 #include "UbloxATCellularInterfaceN2xx.h" 00020 00021 // You must select the correct interface library for your board, by 00022 // uncommenting the correct line below. Supported combinations are 00023 // indicated with a "Y" in the table below. 00024 // 00025 // C030_U201 C030_N211 C027 C030_R41XM 00026 // UbloxATCellularInterface Y - Y Y 00027 // UbloxATCellularInterfaceN2xx - Y - - 00028 // Note: the N211 module supports only UDP, not TCP 00029 00030 // UbloxATCellularInterface and UbloxATCellularInterfaceN2xx 00031 // uses an IP stack on the cellular module and hence uses less RAM (significant on C027). 00032 // This also allows other AT command operations (e.g. sending an SMS) to happen 00033 // during a data transfer (for which you should replace the 00034 // UbloxATCellularInterface library with the UbloxATCellularInterfaceExt 00035 // library). However, it is slower than using the LWIP/PPP on the mbed 00036 // MCU interface since more string parsing is required. 00037 #define INTERFACE_CLASS UbloxATCellularInterface 00038 //#define INTERFACE_CLASS UbloxATCellularInterfaceN2xx 00039 00040 // The credentials of the SIM in the board. If PIN checking is enabled 00041 // for your SIM card you must set this to the required PIN. 00042 #define PIN "0000" 00043 00044 // Network credentials. You should set this according to your 00045 // network/SIM card. For C030 non-N2xx boards, leave the parameters as NULL 00046 // otherwise, if you do not know the APN for your network, you may 00047 // either try the fairly common "internet" for the APN (and leave the 00048 // username and password NULL), or you may leave all three as NULL and then 00049 // a lookup will be attempted for a small number of known networks 00050 // (see APN_db.h in mbed-os/features/netsocket/cellular/utils). 00051 #define APN NULL 00052 #define USERNAME NULL 00053 #define PASSWORD NULL 00054 00055 // Uncomment the following line to enable Icellular Current measurement. 00056 // Current drawn by modem is printed on serial every 2 seconds. 00057 #define CURRENT_MEASUREMENT 00058 00059 // LEDs 00060 DigitalOut ledRed(LED1, 1); 00061 DigitalOut ledGreen(LED2, 1); 00062 DigitalOut ledBlue(LED3, 1); 00063 00064 // The user button 00065 volatile bool buttonPressed = false; 00066 #ifdef TARGET_UBLOX_C030_R412M 00067 volatile bool modem_asleep = false; 00068 #ifdef CURRENT_MEASUREMENT 00069 AnalogIn ain_icellular(MDMCURRENTSENSE); 00070 Thread icell_thread; 00071 #endif 00072 #endif 00073 00074 static rtos::Mutex trace_mutex; 00075 00076 static void good() { 00077 ledGreen = 0; 00078 ledBlue = 1; 00079 ledRed = 1; 00080 } 00081 00082 static void bad() { 00083 ledRed = 0; 00084 ledGreen = 1; 00085 ledBlue = 1; 00086 } 00087 00088 static void event() { 00089 ledBlue = 0; 00090 ledRed = 1; 00091 ledGreen = 1; 00092 } 00093 00094 static void pulseEvent() { 00095 event(); 00096 wait_ms(500); 00097 good(); 00098 } 00099 00100 static void ledOff() { 00101 ledBlue = 1; 00102 ledRed = 1; 00103 ledGreen = 1; 00104 } 00105 00106 static void print_function(const char *format, ...) 00107 { 00108 trace_mutex.lock(); 00109 va_list arglist; 00110 va_start( arglist, format ); 00111 vprintf(format, arglist); 00112 va_end( arglist ); 00113 trace_mutex.unlock(); 00114 } 00115 00116 static void printNtpTime(char * buf, int len) 00117 { 00118 time_t timestamp = 0; 00119 struct tm *localTime; 00120 char timeString[25]; 00121 time_t TIME1970 = 2208988800U; 00122 00123 if (len >= 43) { 00124 timestamp |= ((int) *(buf + 40)) << 24; 00125 timestamp |= ((int) *(buf + 41)) << 16; 00126 timestamp |= ((int) *(buf + 42)) << 8; 00127 timestamp |= ((int) *(buf + 43)); 00128 timestamp -= TIME1970; 00129 localTime = localtime(×tamp); 00130 if (localTime) { 00131 if (strftime(timeString, sizeof(timeString), "%a %b %d %H:%M:%S %Y", localTime) > 0) { 00132 print_function("NTP timestamp is %s.\n", timeString); 00133 } 00134 } 00135 } 00136 } 00137 00138 static void cbButton() 00139 { 00140 buttonPressed = true; 00141 } 00142 00143 void init_modem(INTERFACE_CLASS *interface) { 00144 int x; 00145 00146 for (x = 0; interface->connect(PIN) != 0; x++) { 00147 if (x > 0) { 00148 bad(); 00149 print_function("Retrying (have you checked that an antenna is plugged in and your APN is correct?)...\n"); 00150 } 00151 } 00152 } 00153 #ifdef TARGET_UBLOX_C030_R412M 00154 void psm_going_in_cb(void *param) 00155 { 00156 print_function("PSM callback function:: Modem going in to sleep\n"); 00157 modem_asleep = true; 00158 } 00159 #ifdef CURRENT_MEASUREMENT 00160 float calculate_icellular_samples() { 00161 float ain=0.0f; 00162 float icellular_val; 00163 const int c_number_of_analog_samples = 50; 00164 00165 ain = 0; 00166 for(int i = 0; i < c_number_of_analog_samples; i++) { 00167 ain = (ain + ain_icellular.read()); 00168 Thread::wait(20); 00169 } 00170 ain = ain/c_number_of_analog_samples; 00171 icellular_val = (ain*1.8*1000)/7.0f; 00172 00173 00174 print_function("Voltage in mV: %f\n", icellular_val * 7.0f); 00175 print_function("Current draw in mA: %f\n\n", icellular_val); 00176 00177 return icellular_val; 00178 } 00179 00180 void icell_thread_handler() { 00181 00182 while(1) { 00183 calculate_icellular_samples(); 00184 } 00185 } 00186 #endif 00187 #endif 00188 00189 /* This example program for the u-blox C030-R410M board instantiates 00190 * the UbloxATCellularInterface and uses it to make a simple sockets 00191 * connection to a server, using 2.pool.ntp.org for UDP and 00192 * developer.mbed.org for TCP. It also showcases the 3GPP PSM feature. 00193 * For a more comprehensive example, where higher layer protocols 00194 * make use of the same sockets interface, see example-ublox-mbed-client. 00195 * Progress may be monitored with a serial terminal running at 9600 baud. 00196 * The LED on the C030 board will turn green when this program is 00197 * operating correctly, pulse blue when a sockets operation is completed 00198 * and turn red if there is a failure. 00199 */ 00200 int main() 00201 { 00202 #ifdef TARGET_UBLOX_C030_R412M 00203 #ifdef CURRENT_MEASUREMENT 00204 //current monitoring using Icellular 00205 icell_thread.start(icell_thread_handler); 00206 #endif 00207 int status = 0, pt = 0, at = 0; 00208 #endif 00209 INTERFACE_CLASS *interface = new INTERFACE_CLASS(); 00210 // If you need to debug the cellular interface, comment out the 00211 // instantiation above and uncomment the one below. 00212 // For the N2xx interface, change xxx to MBED_CONF_UBLOX_CELL_BAUD_RATE, 00213 // while for the non-N2xx interface change it to MBED_CONF_UBLOX_CELL_N2XX_BAUD_RATE. 00214 // INTERFACE_CLASS *interface = new INTERFACE_CLASS(MDMTXD, MDMRXD, 00215 // xxx, 00216 // true); 00217 00218 UDPSocket sockUdp; 00219 SocketAddress udpServer; 00220 SocketAddress udpSenderAddress; 00221 char buf[1024]; 00222 int x; 00223 #ifdef TARGET_UBLOX_C027 00224 // No user button on C027 00225 InterruptIn userButton(NC); 00226 #else 00227 InterruptIn userButton(SW0); 00228 #endif 00229 00230 // Attach a function to the user button 00231 userButton.rise(&cbButton); 00232 00233 good(); 00234 print_function("Initializing modem, please wait.\n"); 00235 if (interface->init(PIN) == false) //setup modem 00236 { 00237 int mno_profile; 00238 int ret_val = false; 00239 interface->get_mno_profile(&mno_profile); 00240 if((UbloxATCellularInterface::MNOProfile)mno_profile == (UbloxATCellularInterface::MNOProfile)0) 00241 { 00242 print_function("Setting MNO profile..\r"); 00243 if(interface->set_mno_profile(UbloxATCellularInterface::STANDARD_EU)) 00244 { 00245 print_function("MNO Profile set and rebooting the module\n"); 00246 interface->reboot_modem(); 00247 wait_ms(5000); //give modem a little time 00248 ret_val = interface->init(PIN); 00249 } 00250 } 00251 if(ret_val == false) 00252 { 00253 bad(); 00254 print_function("Failed to Initialize modem\n"); 00255 while(1); 00256 } 00257 } 00258 print_function("Initialization complete.\n"); 00259 pulseEvent(); 00260 00261 #ifdef TARGET_UBLOX_C030_R412M 00262 print_function("Enabling PSM...\n"); 00263 if (interface->set_power_saving_mode(120, 30)) { //enable PSM 00264 print_function("PSM enabled. Attaching CB function and rebooting the module\n"); 00265 interface->attach_cb_psm_going_in(&psm_going_in_cb, NULL); //register callback 00266 00267 //reset modem so that PSM settings can take effect 00268 interface->reboot_modem(); 00269 wait_ms(5000); //give modem a little time 00270 00271 print_function("please wait up to 180 seconds for network registration to complete...\n"); 00272 //try to re-init modem and perform registration 00273 interface->set_credentials(APN, USERNAME, PASSWORD); 00274 for (x = 0; interface->connect(PIN) != 0; x++) { 00275 if (x > 0) { 00276 bad(); 00277 print_function("Retrying (have you checked that an antenna is plugged in and your APN is correct?)...\n"); 00278 } 00279 } 00280 00281 interface->get_power_saving_mode(&status, &pt, &at); //read assigned values 00282 print_function("PSM status: %s\nAssigned Periodic TAU: %d\nAssigned Active time: %d\n", status ? "enabled" : "disabled", pt, at); 00283 pulseEvent(); 00284 } 00285 00286 //sometimes modem goes in to PSM before we can do any UDP/TCP transfers 00287 if (modem_asleep == true) { 00288 print_function("Modem is in PSM, waking up and initializing it\n"); 00289 interface->wakeup_modem(); //this wakes up the modem and also CellularBase gets synced with modem state. 00290 init_modem(interface); 00291 modem_asleep = false; 00292 print_function("Initialization complete\n"); 00293 } 00294 #endif 00295 00296 print_function("\nGetting the IP address of \"2.pool.ntp.org\"...\n"); 00297 if ((interface->gethostbyname("2.pool.ntp.org", &udpServer) == 0)) { 00298 pulseEvent(); 00299 00300 udpServer.set_port(123); 00301 print_function("\"2.pool.ntp.org\" address: %s on port %d.\n", udpServer.get_ip_address(), udpServer.get_port()); 00302 00303 print_function("Performing socket operations in a loop (until the user button is pressed on C030 or forever on C027)...\n"); 00304 while (!buttonPressed) { 00305 #ifdef TARGET_UBLOX_C030_R412M 00306 if (modem_asleep == true) { 00307 print_function("Modem is in PSM, waking up and initializing it\n"); 00308 interface->wakeup_modem(); //this wakes up the modem and also CellularBase gets synced with modem state. 00309 init_modem(interface); 00310 modem_asleep = false; 00311 print_function("Initialization complete\n"); 00312 wait_ms(5000); 00313 } else { 00314 #endif 00315 print_function("Opening a UDP socket...\n"); 00316 if ((sockUdp.open(interface)) == 0) { 00317 // UDP Sockets 00318 pulseEvent(); 00319 print_function("UDP socket open.\n"); 00320 sockUdp.set_timeout(20000); 00321 print_function("Sending time request to \"2.pool.ntp.org\" over UDP socket...\n"); 00322 memset (buf, 0, sizeof(buf)); 00323 *buf = '\x1b'; 00324 if (sockUdp.sendto(udpServer, (void *) buf, 48) == 48) { 00325 pulseEvent(); 00326 print_function("Socket send completed, waiting for UDP response...\n"); 00327 x = sockUdp.recvfrom(&udpSenderAddress, buf, sizeof (buf)); 00328 if (x > 0) { 00329 pulseEvent(); 00330 print_function("Received %d byte response from server %s on UDP socket:\n" 00331 "-------------------------------------------------------\n", 00332 x, udpSenderAddress.get_ip_address()); 00333 printNtpTime(buf, x); 00334 print_function("-------------------------------------------------------\n"); 00335 } 00336 } 00337 print_function("Closing socket...\n"); 00338 sockUdp.close(); 00339 pulseEvent(); 00340 print_function("Socket closed.\n"); 00341 } 00342 #ifdef TARGET_UBLOX_C030_R412M 00343 while(modem_asleep == false) { //modem is awake, let it go to sleep again 00344 print_function("Waiting for modem to go to PSM sleep\n"); 00345 wait_ms(5000); 00346 } 00347 } 00348 #endif /* TARGET_UBLOX_C030_R412M */ 00349 00350 00351 wait_ms(20000); 00352 #ifndef TARGET_UBLOX_C027 00353 print_function("\n\n[Checking if user button has been pressed]\n"); 00354 #endif 00355 } 00356 00357 pulseEvent(); 00358 print_function("User button was pressed, stopping...\n"); 00359 interface->disconnect(); 00360 ledOff(); 00361 print_function("Stopped.\n"); 00362 } else { 00363 bad(); 00364 print_function("Unable to get IP address of \"2.pool.ntp.org\".\n"); 00365 } 00366 } 00367 00368 // End Of File
Generated on Tue Jul 19 2022 22:21:02 by 1.7.2