Testing sketch to set up a never-previously-connected LTE XBee running in bypass mode.
Testing sketch to set up a never-previously-connected LTE XBee running in bypass mode.
1/** =========================================================================
2 * @example{lineno} LTExBee_FirstConnectionBypass.ino
3 * @brief Testing sketch to set up a never-previously-connected LTE XBee running
6 * @m_examplenavigation{page_extra_helper_sketches,}
7 * ======================================================================= */
9#define TINY_GSM_MODEM_SARAR4
10#define TINY_GSM_RX_BUFFER 64
11#define TINY_GSM_YIELD_MS 2
12#define TINY_GSM_DEBUG Serial
16#include <StreamDebugger.h>
17#include <TinyGsmClient.h>
19StreamDebugger debugger(Serial1, Serial);
20TinyGsm gsmModem(debugger);
22const char* apn = "m2m";
25 // Set the reset pin HIGH to ensure the Bee does not continually reset
27 digitalWrite(20, HIGH);
29 // Set the sleep_rq pin LOW to wake the Bee
31 digitalWrite(23, LOW);
33 // Set the input pin mode
36 // Set console baud rate
40 // Set XBee module baud rate
43 // Wait for warm-up, probably overkill
49 DBG(F("Putting XBee into command mode..."));
50 for (uint8_t i = 0; i < 5; i++) {
51 /** First, wait the required guard time before entering command mode. */
53 /** Now, enter command mode to set all pin I/O functionality. */
54 gsmModem.streamWrite(GF("+++"));
55 success = gsmModem.waitResponse(2000, GF("OK\r")) == 1;
59 DBG(F("Setting I/O Pins..."));
60 /** Enable pin sleep functionality on `DIO9`.
61 * NOTE: Only the `DTR_N/SLEEP_RQ/DIO8` pin (9 on the bee socket) can be
62 * used for this pin sleep/wake. */
63 gsmModem.sendAT(GF("D8"), 1);
64 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
65 /** Enable status indication on `DIO9` - it will be HIGH when the XBee
67 * NOTE: Only the `ON/SLEEP_N/DIO9` pin (13 on the bee socket) can be
68 * used for direct status indication. */
69 gsmModem.sendAT(GF("D9"), 1);
70 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
71 /** Enable CTS on `DIO7` - it will be `LOW` when it is clear to send
72 * data to the XBee. This can be used as proxy for status indication if
73 * that pin is not readable.
74 * NOTE: Only the `CTS_N/DIO7` pin (12 on the bee socket) can be used
76 gsmModem.sendAT(GF("D7"), 1);
77 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
78 /** Enable association indication on `DIO5` - this is should be directly
79 * attached to an LED if possible.
80 * - Solid light indicates no connection
81 * - Single blink indicates connection
82 * - double blink indicates connection but failed TCP link on last
85 * NOTE: Only the `Associate/DIO5` pin (15 on the bee socket) can be
86 * used for this function. */
87 gsmModem.sendAT(GF("D5"), 1);
88 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
89 /** Enable RSSI PWM output on `DIO10` - this should be directly attached
90 * to an LED if possible. A higher PWM duty cycle (and thus brighter
91 * LED) indicates better signal quality.
92 * NOTE: Only the `DIO10/PWM0` pin (6 on the bee socket) can be used for
94 gsmModem.sendAT(GF("P0"), 1);
95 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
96 /** Enable pin sleep on the XBee. */
97 DBG(F("Setting Sleep Options..."));
98 gsmModem.sendAT(GF("SM"), 1);
99 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
100 DBG(F("Setting Other Options..."));
101 /** Disable remote manager, USB Direct, and LTE PSM.
102 * NOTE: LTE-M's PSM (Power Save Mode) sounds good, but there's no easy
103 * way on the LTE-M Bee to wake the cell chip itself from PSM, so we'll
104 * use the Digi pin sleep instead. */
105 gsmModem.sendAT(GF("DO"), 0);
106 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
107 /* Make sure USB direct is NOT enabled on the XBee3 units. */
108 gsmModem.sendAT(GF("P1"), 0);
109 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
110 // DBG(F("Setting Cellular Carrier Options..."));
111 // // Carrier Profile - 1 = No profile/SIM ICCID selected
112 // gsmModem.sendAT(GF("CP"),1);
113 // success &= gsmModem.waitResponse(GF("OK\r")) == 1;
114 // // Cellular network technology - LTE-M/NB IoT
115 // gsmModem.sendAT(GF("N#"),0);
116 // success &= gsmModem.waitResponse(GF("OK\r")) == 1;
117 // Make sure airplane mode is off - bypass and airplane mode are
119 DBG(F("Making sure airplane mode is off..."));
120 gsmModem.sendAT(GF("AM"), 0);
121 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
122 DBG(F("Turning on Bypass Mode..."));
123 /** Enable bypass mode. */
124 gsmModem.sendAT(GF("AP5"));
125 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
126 /** Write changes to flash. */
127 gsmModem.sendAT(GF("WR"));
128 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
129 /** Apply changes. */
130 gsmModem.sendAT(GF("AC"));
131 success &= gsmModem.waitResponse(GF("OK\r")) == 1;
132 // Finally, force a reset to actually enter bypass mode - this
133 // effectively exits command mode.
134 DBG(F("Resetting the module to reboot in bypass mode..."));
135 gsmModem.sendAT(GF("FR"));
136 success &= gsmModem.waitResponse(5000L, GF("OK\r")) == 1;
137 // Allow 5s for the unit to reset.
139 // Re-initialize the TinyGSM SARA R4 instance.
140 DBG(F("Attempting to reconnect to the u-blox SARA R410M module..."));
141 success &= gsmModem.init();
142 gsmModem.getModemName();
150 DBG(F("Setting Cellular Carrier Options..."));
151 // Turn off the cellular radio while making network changes
152 gsmModem.sendAT(GF("+CFUN=0"));
153 gsmModem.waitResponse();
154 // Mobile Network Operator Profile
156 // - 1: SIM ICCID selected
161 // - 6: China Telecom
167 // - 31: Deutsche Telekom
171 // - 44: Claro Brasil
173 // - 46: Orange France
175 // - 100: Standard Europe
176 // - 101: Standard Europe No-ePCO (The factory-programmed configuration of
177 // this profile is the same of the standard Europe profile (<MNO>=100), but
178 // the ePCO is disabled.)
179 // - 102: Standard Japan (global)
180 // - 198: AT&T 2-4-12 (The factory programmed configuration of this profile
181 // is the same of the AT&T profile (<MNO>=2), but the LTE band 5 is
183 // - 201: GCF-PTCRB (This profile is meant only for conformance testing.)
184 gsmModem.sendAT(GF("+UMNOPROF="), 1);
185 gsmModem.waitResponse();
186 // Selected network technology - 7: LTE Cat.M1
188 // Fallback network technology - 7: LTE Cat.M1
190 // NOTE: As of 2020 in the USA, AT&T and Verizon only use LTE-M
191 // T-Mobile uses NB-IOT
192 gsmModem.sendAT(GF("+URAT="), 7, ',', 8);
193 gsmModem.waitResponse();
194 // Set the band mask manually if needed
195 // bit 0 = band 1; bit 127 = band 128
196 // gsmModem.sendAT(GF("+UBANDMASK="), 0, ',', 134217732);
197 // gsmModem.waitResponse();
198 // Restart the module to apply changes and bring back to full functionality
201 // Check again for the carrier profile (to ensure it took)
202 // If 1/SIM select was used, this will show what the SIM picked
203 gsmModem.sendAT(GF("+UMNOPROF?"));
204 gsmModem.waitResponse();
206 // Scan for networks - this is probably really slow
207 DBG(F("Scanning for networks. This may take up to 3 minutes"));
208 gsmModem.sendAT(GF("+COPS=0"));
209 gsmModem.waitResponse();
210 gsmModem.sendAT(GF("+COPS=?"));
211 gsmModem.waitResponse(180000L);
213 // Wait forever for a connection
214 DBG(F("Waiting for network registration"));
215 while (!gsmModem.isNetworkConnected()) {
216 int csq = gsmModem.getSignalQuality();
217 DBG("Signal quality:", csq);
221 // Print some stuff after connected
222 String ccid = gsmModem.getSimCCID();
225 String imei = gsmModem.getIMEI();
228 String imsi = gsmModem.getIMSI();
231 String cop = gsmModem.getOperator();
232 DBG("Operator:", cop);
234 IPAddress local = gsmModem.localIP();
235 DBG("Local IP:", local);
240 DBG("Powering down.");
243 // And do nothing forever more