Components and supplies
Waveshare Sim7000E NB-IoT Hat
Arduino Nano Every
Luner IoT SIM
DHT22 Temperature Sensor
Apps and platforms
Luner IoT Suite
Arduino IDE
Project description
Code
Demo Sketch
arduino
1#include "dht.h" 2 3 4// Waveshare Sim7000E NB-IoT HAT 5#define PIN_DTR 4 6 7// AM2302 (DHT22) 8#define PIN_DHT 5 9 10// number of loops to wait for the end of initialization 11#define TECHNOLOGY_INIT_WAITING 7 12 13#define LEN_MODEM_AT 4 14const unsigned char MODEM_AT[LEN_MODEM_AT] = {'a', 't', '\r', '\n'}; 15 16 17#define LEN_MODEM_AT_CREG 10 18const unsigned char MODEM_AT_CREG[LEN_MODEM_AT_CREG] = {'a', 't', '+', 'c', 'r', 'e', 'g', '?', '\r', '\n'}; 19 20#define LEN_MODEM_CREG 8 21const char MODEM_CREG[LEN_MODEM_CREG] = {'+', 'C', 'R', 'E', 'G', ':', ' ', '\\0'}; 22 23#define LEN_MODEM_AT_CSIM 8 24const unsigned char MODEM_AT_CSIM[LEN_MODEM_AT_CSIM] = {'a', 't', '+', 'c', 's', 'i', 'm', '='}; 25 26#define LEN_MODEM_CSIM 8 27const char MODEM_CSIM[LEN_MODEM_CSIM] = {'+', 'C', 'S', 'I', 'M', ':', ' ', '\\0'}; 28 29#define LEN_APDU_HEADER 5 30 31const char APDU_MANAGE_CHANNEL[LEN_APDU_HEADER] = { 0x00, 0x70, 0x00, 0x00, 0x00 }; 32 33const char APDU_SELECT[LEN_APDU_HEADER] = { 0x00, 0xa4, 0x04, 0x00, 0x00 }; 34 35#define LEN_APDU_PUT_DATA 5 36const char APDU_PUT_DATA[LEN_APDU_PUT_DATA] = { 0x00, 0xda, 0x02, 0xc1, 0x00 }; 37 38#define LEN_AID_SAFE2 12 39const char AID_SAFE2[LEN_AID_SAFE2] = {0xf0, 0x70, 0x6F, 0x64, 0x67, 0x73, 0x61, 0x66, 0x65, 0x32, 0x01, 0x01 }; 40 41#define LEN_MODEM_OK 4 42const char MODEM_OK[LEN_MODEM_OK] = {'O', 'K', '\r', '\\0'}; 43 44#define LEN_MODEM_ERROR 7 45const char MODEM_ERROR[LEN_MODEM_ERROR] = {'E', 'R', 'R', 'O', 'R', '\r', '\\0'}; 46 47#define LEN_1_CHAR_MAX 10 48#define LEN_2_CHARS_MAX 100 49 50#define CR '\r' 51#define EOL '\n' 52 53#define LEN_IO_BUFFER 255 54char buf[LEN_IO_BUFFER]; 55 56#define LEN_DATA_BUF 4 57unsigned char dataBuf[LEN_DATA_BUF]; 58 59unsigned char regFlag; 60 61dht sensor; 62 63 64char registered(char * resp) { 65 char b = *resp; 66 b &= 0x0f; 67 resp++; 68 if (*resp != CR) { 69 // 2-chars <stat> value 70 b *= 10; 71 b += *resp - 0x30; 72 } 73 switch (b) { 74 case 1: // 1: registered, home network 75 case 5: // 5: registered, roaming 76 case 6: // 6: registered for "SMS only", home network (applicable only when <AcTStatus> 77 // indicates E-UTRAN) 78 case 7: // 7: registered for "SMS only", roaming (applicable only when <AcTStatus> indicates 79 // E-UTRAN) 80 case 9: // 9: registered for "CSFB not preferred", home network (applicable only when 81 // <AcTStatus> indicates E-UTRAN) 82 case 10:// 10:registered for "CSFB not preferred", roaming (applicable only when <AcTStatus> 83 // indicates E-UTRAN) 84 return true; 85 86 case 0: // 0: not registered, the MT is not currently searching a new operator to register to 87 case 2: // 2: not registered, but the MT is currently searching a new operator to register to 88 case 3: // 3: registration denied 89 case 4: // 4: unknown (e.g. out of GERAN/UTRAN/E-UTRAN coverage) 90 case 8: // 8: attached for emergency bearer services only (see 3GPP TS 24.008 [12] and 3GPP 91 // TS 24.301 [68] that specify the condition when the MS is considered as attached 92 // for emergency bearer services) 93 default: 94 return false; 95 } 96} 97 98void logData(char * dataBuf, char len) { 99 int dataLen = (unsigned char)len; 100 int blockLen; 101 int ofs = 0; 102 while (dataLen > 0) { 103 blockLen = Serial.availableForWrite(); 104 if (blockLen < 1) { 105 delay(1); 106 continue; 107 } 108 if (blockLen > dataLen) { 109 blockLen = dataLen; 110 } 111 Serial.write(&dataBuf[ofs], blockLen); 112 ofs += blockLen; 113 dataLen -= blockLen; 114 } 115 Serial.flush(); 116} 117 118 119void atCommand(char * cmdBuf, char len) { 120 int cmdLen = (unsigned char)len; 121 int blockLen; 122 int ofs = 0; 123 while (cmdLen > 0) { 124 blockLen = Serial1.availableForWrite(); 125 if (blockLen < 1) { 126 delay(1); 127 continue; 128 } 129 if (blockLen > cmdLen) { 130 blockLen = cmdLen; 131 } 132 Serial1.write(&cmdBuf[ofs], blockLen); 133 ofs += blockLen; 134 cmdLen -= blockLen; 135 } 136 Serial1.flush(); 137} 138 139#define CNTR_MAX 10000 140 141char atResponse(char * respBuf) { 142 // read AT response 143 char b = 0; 144 short cntr = 0; 145 char * ptr; 146 int len = 0; 147 int blockLen; 148 //delay(10); 149 // initialize for timeout 150 respBuf[0] = 0; 151 do { 152 blockLen = Serial1.readBytesUntil(EOL, &respBuf[len], (int)(LEN_IO_BUFFER - len)); 153 if (blockLen > 0) { 154 len += blockLen; 155 respBuf[len++] = EOL; 156 respBuf[len] = 0; 157 } 158 159 ptr = strstr(respBuf, MODEM_OK); 160 if (ptr == NULL) { 161 ptr = strstr(respBuf, MODEM_ERROR); 162 } 163 164 } while (ptr == NULL); 165 return len; 166} 167 168char decimalPut(int v, char * dst) { 169 char ofs = 0; 170 // number of chars populated 171 char cnt = 1; 172 char b; 173 // safety check - shall be redesigned for negative numbers 174 if (v < 0) { 175 v = 0; 176 } 177 if (v >= LEN_1_CHAR_MAX) { 178 ofs++; 179 cnt++; 180 } 181 if (v >= LEN_2_CHARS_MAX) { 182 ofs++; 183 cnt++; 184 } 185 // at least 1 digit shall be populated 186 do { 187 b = (char)(v % 10); 188 dst[ofs--] = '0' + b; 189 v -= b; 190 v /= 10; 191 } while (v > 0); 192 return cnt; 193} 194 195const char HEX_CONVERSION[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 196 197void hexPut(char b, char * dst) { 198 dst[0] = HEX_CONVERSION[(b >> 4) & 0x0f]; 199 dst[1] = HEX_CONVERSION[b & 0x0f]; 200} 201 202#define LEN_BYTE_HEX 2 203 204char buildAtCsim(char * cmdBuf, char cla, const char * apduBuf, char * dataBuf, unsigned char dataLen) { 205 int len = LEN_APDU_HEADER; 206 char ofs = 0; 207 if (dataBuf != NULL) { 208 len += dataLen; 209 } 210 memcpy(cmdBuf, MODEM_AT_CSIM, LEN_MODEM_AT_CSIM); 211 ofs = LEN_MODEM_AT_CSIM; 212 ofs += decimalPut(len << 1, &cmdBuf[ofs]); 213 cmdBuf[ofs++] = ','; 214 cmdBuf[ofs++] = '"'; 215 216 // put CLA 217 hexPut(apduBuf[0] | cla, &cmdBuf[ofs]); 218 ofs += LEN_BYTE_HEX; 219 // put INS, P1, P2 220 for (char i=1; i<4; i++) { 221 hexPut(apduBuf[i], &cmdBuf[ofs]); 222 ofs += LEN_BYTE_HEX; 223 } 224 // put LEN 225 hexPut(dataLen, &cmdBuf[ofs]); 226 ofs += LEN_BYTE_HEX; 227 if ((dataLen > 0) && (dataBuf != NULL)) { 228 // put Data 229 for (char i=0; i<dataLen; i++) { 230 hexPut(dataBuf[i], &cmdBuf[ofs]); 231 ofs += LEN_BYTE_HEX; 232 } 233 } 234 235 cmdBuf[ofs++] = '"'; 236 cmdBuf[ofs++] = '\r'; 237 cmdBuf[ofs++] = '\n'; 238 cmdBuf[ofs] = 0; 239 return ofs; 240} 241 242#define ERR_INVALID_CSIM_RESPONSE 0x01 243#define ERR_INVALID_OPEN_CHANNEL_RESPONSE 0x02 244#define ERR_INVALID_CHANNEL_ID 0x03 245 246#define OFS_APDU_P1 0x02 247#define OFS_APDU_P2 0x03 248 249#define MODE_CHANNEL_CLOSE 0x80 250 251 252 253char send(unsigned char * dataPtr, char dataLen) { 254 255 char cmdLen = 0; 256 char respLen = 0; 257 char chan = 0; 258 // put AT SIM command: Open Supplementary Logical Channel 259 //Serial.println("put 'at+csim: 00 70 00 00 01'"); 260 cmdLen = buildAtCsim(buf, 0, APDU_MANAGE_CHANNEL, NULL, 1); 261 //Serial.println(buf); 262 //Serial.flush(); 263 atCommand(buf, cmdLen); 264 respLen = atResponse(buf); 265 logData(buf, respLen); 266 // analyze response 267 char * ptr; 268 ptr = strstr(buf, MODEM_CSIM); 269 if (ptr == NULL) { 270 Serial.println("CSIM not detected in the response"); 271 return ERR_INVALID_CSIM_RESPONSE; 272 } 273 274 if ((ptr[LEN_MODEM_CSIM - 1] != '6') || 275 (ptr[LEN_MODEM_CSIM + 0] != ',') || 276 (ptr[LEN_MODEM_CSIM + 1] != '"') || 277 (ptr[LEN_MODEM_CSIM + 2] != '0')) { 278 279 Serial.println("Unexpected response for MANAGE CHANNEL"); 280 return ERR_INVALID_OPEN_CHANNEL_RESPONSE; 281 } 282 283 // extract channel ID 284 chan = ptr[LEN_MODEM_CSIM + 3] - '0'; 285 if ((chan <= 0) || (chan >= 4)) { 286 Serial.print("Unexpected response (chan ID) for MANAGE CHANNEL: "); 287 Serial.println(chan); 288 return ERR_INVALID_CHANNEL_ID; 289 } 290 // SELECT (by AID) SAFE2 291 cmdLen = buildAtCsim(buf, chan, APDU_SELECT, (char *)AID_SAFE2, LEN_AID_SAFE2); 292 //Serial.println(buf); 293 //Serial.flush(); 294 atCommand(buf, cmdLen); 295 respLen = atResponse(buf); 296 logData(buf, respLen); 297 298 // PUT DATA (from dataBuffer) 299 cmdLen = buildAtCsim(buf, chan, APDU_PUT_DATA, (char *)dataPtr, dataLen); 300 //Serial.println(buf); 301 //Serial.flush(); 302 atCommand(buf, cmdLen); 303 respLen = atResponse(buf); 304 logData(buf, respLen); 305 306 // close supplementary logical channel 307 char apdu_close_channel[LEN_APDU_HEADER]; 308 memcpy(apdu_close_channel, APDU_MANAGE_CHANNEL, LEN_APDU_HEADER); 309 apdu_close_channel[OFS_APDU_P1] = MODE_CHANNEL_CLOSE; 310 apdu_close_channel[OFS_APDU_P2] = chan; 311 cmdLen = buildAtCsim(buf, 0, apdu_close_channel, NULL, 0); 312 //Serial.println(buf); 313 //Serial.flush(); 314 atCommand(buf, cmdLen); 315 respLen = atResponse(buf); 316 logData(buf, respLen); 317} 318 319 320void setup() { 321 // configure pins (DTR - mandatory) 322 pinMode(LED_BUILTIN, OUTPUT); 323 pinMode(PIN_DTR, OUTPUT); 324 325 326 // Open serial communications and wait for port to open: 327 Serial.begin(57600); 328 while (!Serial) { 329 ; // wait for serial port to connect 330 } 331 Serial.println("nano started!"); 332 333 // wake up Sim7000 UART 334 digitalWrite(PIN_DTR, LOW); 335 delay(1000); 336 337 // set the data rate for the modem port 338 Serial1.begin(57600); 339 340 regFlag = false; 341 char ready = 0; 342 unsigned char b = 0; 343 unsigned char pos = 0; 344 do { 345 // put AT command 346 Serial.println("put 'at'"); 347 Serial1.write(MODEM_AT, LEN_MODEM_AT); 348 delay(100); 349 // modem could not respond during initialization 350 if (Serial1.available()) { 351 ready = 1; 352 while (Serial1.available()) { 353 b = Serial1.read(); 354 Serial.write(b); 355 delay(10); 356 } 357 } 358 delay(300); 359 } while (ready == 0); 360 361 unsigned char cntr = 0; 362 while (cntr < TECHNOLOGY_INIT_WAITING) { 363 // turn the LED on 364 digitalWrite(LED_BUILTIN, HIGH); 365 // wait for a half of a second 366 delay(500); 367 368 // put AT command 369 Serial.println("put 'at+creg?'"); 370 atCommand(MODEM_AT_CREG, LEN_MODEM_AT_CREG); 371 // read AT response 372 pos = atResponse(buf); 373 374 // turn the LED off by making the voltage LOW 375 digitalWrite(LED_BUILTIN, LOW); 376 377 // analyze response 378 char * ptr; 379 ptr = strstr(buf, MODEM_CREG); 380 if (ptr != NULL) { 381 regFlag = registered(&ptr[LEN_MODEM_CREG + 1]); 382 Serial.write(ptr[LEN_MODEM_CREG - 1]); 383 Serial.write(':'); 384 Serial.write(ptr[LEN_MODEM_CREG + 1]); 385 Serial.println(); 386 } else { 387 Serial.println("not found `+CREG`"); 388 } 389 if (regFlag) { 390 cntr++; 391 } 392 Serial.print("cntr: "); 393 Serial.println(cntr); 394 // wait 1 sec before repeat 395 delay(1000); 396 } 397 Serial.println("setup finished"); 398} 399 400void loop() { 401 402 if (sensor.read22(PIN_DHT) != DHTLIB_OK) { 403 //float h = dht.readHumidity(); 404 //float t = dht.readTemperature(); 405 406 //if (isnan(h) || isnan(t)) { 407 Serial.println("Failed to read from the sensor"); 408 delay(10000); 409 return; 410 } 411 float h = sensor.humidity; 412 float t = sensor.temperature; 413 int ih = round(h); 414 int it = round(t); 415 416 Serial.print("Humidity: "); 417 Serial.println(ih); 418 Serial.print("Temperature: "); 419 Serial.println(it); 420 Serial.println(); 421 422 // put humidity as BigEndian short 423 dataBuf[0] = (unsigned char)(ih >> 8); 424 dataBuf[1] = (unsigned char)(ih & 0xff); 425 // put Temperature as BigEndian short 426 dataBuf[2] = (unsigned char)(it >> 8); 427 dataBuf[3] = (unsigned char)(it & 0xff); 428 429 // Dump sensor data 430 char b; 431 Serial.print("HT data:"); 432 for (byte i = 0; i < LEN_DATA_BUF; i++) { 433 b = dataBuf[i]; 434 if (b < 0x10) { 435 Serial.print("0"); 436 } 437 Serial.print(b, HEX); 438 } 439 Serial.println(); 440 441 send(&dataBuf[0], LEN_DATA_BUF); 442 443 unsigned char minutes = 30; 444 unsigned char secs; 445 while (minutes > 0) { 446 for (secs=0; secs < 60; secs++) { 447 delay(1000); 448 } 449 minutes -= 1; 450 Serial.print('.'); 451 } 452} 453
Downloadable files
Connection schema
Arduino Nano Every + Sim7000E + DHT22
Connection schema
Connection schema
Arduino Nano Every + Sim7000E + DHT22
Connection schema
Comments
Only logged in users can leave comments
kostiantynchertov
0 Followers
•0 Projects
Table of contents
Intro
2
0