├── README.md ├── TTN_NodeRed ├── README.md └── flow.json ├── TTN_TTGOLora32 ├── .gitignore ├── .travis.yml ├── README.md ├── lib │ └── readme.txt ├── platformio.ini └── src │ └── main.cpp ├── TTN_TTGOLora32_BLEBridge ├── .gitignore ├── .travis.yml ├── README.md ├── lib │ └── readme.txt ├── platformio.ini └── src │ └── main.cpp ├── TTN_TTGOLora32_OTAA ├── .gitignore ├── .travis.yml ├── README.md ├── lib │ └── readme.txt ├── platformio.ini └── src │ └── main.cpp ├── WIFI_Scanner ├── .gitignore ├── lib │ └── readme.txt ├── platformio.ini └── src │ └── main.cpp └── images └── OTAA_parameters.png /README.md: -------------------------------------------------------------------------------- 1 | # TTGO LoRa32 ESP32 Oled board 2 | 3 | This repository holds some sample code, using platformio IDE, for using this board peripherals: 4 | 5 | - Lora - Use the sx127x radio to connect to the TheThingsNetwork 6 | - BLE - Esp32 Bluetooth 7 | - WIFI - Native WIFI 8 | 9 | The following examples are on this repository: 10 | 11 | ## TTN ABP (TTN_TTGOLora32 folder) 12 | 13 | This code uses the Lora chip to connect to the Things Network, using ABP to join the network. 14 | 15 | ## TTN OTAA (TTN_TTGOLora32_OTAA folder) 16 | 17 | This code also connects to TheThingsNetwork, but this time using Over The Air Activation. 18 | 19 | ## TTN NodeRed 20 | 21 | The TTN Node red folder contains a node-red flow that by using the Node-Red TTN node, receives data from the above examples (either ABP or OTAA), and sends back information to the node regarding the signal uplink rssi strenght for that message. 22 | If the TTGO board is range of a gateway with downlink capacity (all of them, except a few single channel gateways), then the board displays the received data (which is the signal strenght) on the OLED. 23 | 24 | ## BLEBridge (TTN_TTGOLora32_BLEBridge folder) 25 | 26 | The BLE Bridge is a simple example of bridging data from the BLE transceiver to the TheThingsNetwork Lorawan. 27 | 28 | # WiFi Scanner 29 | 30 | Simple Wifi scanner that shows found WIFI networks on the Oled. 31 | -------------------------------------------------------------------------------- /TTN_NodeRed/README.md: -------------------------------------------------------------------------------- 1 | # Node-Red sample flow 2 | 3 | Use this flow just for testing, since sending downlink data for each uplink might break the TTN user agreement. 4 | 5 | This flow receives data sent from the nodes, calculates the recived RSSI and SNR, and sends it back to the node where it is displayed 6 | on the OLED screen. 7 | 8 | 9 | -------------------------------------------------------------------------------- /TTN_NodeRed/flow.json: -------------------------------------------------------------------------------- 1 | [{"id":"665ef0d1.e89168","type":"debug","z":"9b3686b0.61c56","name":"","active":true,"console":"false","complete":"true","x":470,"y":100,"wires":[]},{"id":"f883418.75dbbc","type":"file","z":"9b3686b0.61c56","name":"TTN LOG 2","filename":"/home/odroid/ttn_log2.log","appendNewline":true,"createDir":true,"overwriteFile":"false","x":494.5,"y":268,"wires":[]},{"id":"f8535d97.22d098","type":"ttn message","z":"9b3686b0.61c56","name":"TTN APP ttndevexp","app":"b59d5696.cde318","dev_id":"","field":"","x":176.5,"y":254,"wires":[["665ef0d1.e89168","f883418.75dbbc","37ca8ca9.9402ec"]]},{"id":"37ca8ca9.9402ec","type":"function","z":"9b3686b0.61c56","name":"Build node data object","func":"// Build an object that allows us to track\n// node data better than just having the payload\n\n//For the debug inject node. Comment out when in real use\n//var inmsg = msg.payload;\nvar inmsg = msg; // from the TTN node\n\nvar newmsg = {};\nvar devicedata = {};\nvar betterRSSI = -1000; // Start with a low impossible value\nvar betterSNR = -1000;\n\n// WARNING only works with String data\n// Use TTN decode functions is a better idea\nvar nodercvdata = inmsg.payload.toString(\"utf-8\");\n\ndevicedata.device = inmsg.dev_id;\ndevicedata.deviceserial = inmsg.hardware_serial;\ndevicedata.rcvtime = inmsg.metadata.time;\ndevicedata.nodedata = nodercvdata;\n\n// Iterate over the gateway data to get the best RSSI and SNR data\nvar gws = inmsg.metadata.gateways;\n\nfor ( var i = 0 ; i < gws.length; i++ ) {\n var gw = gws[i];\n if ( gw.rssi > betterRSSI )\n betterRSSI = gw.rssi;\n \n if ( gw.snr > betterSNR )\n betterSNR = gw.snr;\n}\n\ndevicedata.rssi = betterRSSI;\ndevicedata.snr = betterSNR;\n\nnewmsg.payload = devicedata;\n\nreturn newmsg;","outputs":1,"noerr":0,"x":520,"y":220,"wires":[["66b5a8bf.2ff748","ed62c061.9050e8","429ccbb7.fa59c4","af434ae.b88c5b8"]]},{"id":"3255a76f.1d60a","type":"inject","z":"9b3686b0.61c56","name":"","topic":"","payload":"{\"app_id\":\"ttndevexp\",\"dev_id\":\"arduino32u4\",\"hardware_serial\":\"0026C63B3D6FBD7F\",\"port\":1,\"counter\":0,\"payload_raw\":{\"type\":\"Buffer\",\"data\":[84,101,115,116,101,32,76,79,82,65,51,50,85,52,73,73,32,110,111,100,101,33]},\"metadata\":{\"time\":\"2017-11-10T14:20:43.957320553Z\",\"frequency\":868.1,\"modulation\":\"LORA\",\"data_rate\":\"SF9BW125\",\"coding_rate\":\"4/5\",\"gateways\":[{\"gtw_id\":\"eui-b827ebfffec28ff1\",\"timestamp\":1218059196,\"time\":\"2017-11-10T14:20:43.886053Z\",\"channel\":0,\"rssi\":-117,\"snr\":-7.8,\"rf_chain\":1,\"latitude\":38.73755,\"longitude\":-9.138655,\"altitude\":138,\"location_source\":\"registry\"},{\"gtw_id\":\"eui-0000024b080e06fa\",\"timestamp\":1431639812,\"time\":\"2017-11-10T14:20:43.87745Z\",\"channel\":0,\"rssi\":-106,\"snr\":9.8,\"rf_chain\":1,\"latitude\":38.74648,\"longitude\":-9.16781,\"altitude\":154}]},\"payload\":{\"type\":\"Buffer\",\"data\":[84,101,115,116,101,32,76,79,82,65,51,50,85,52,73,73,32,110,111,100,101,33]},\"_msgid\":\"d4e2d343.898c6\"}","payloadType":"json","repeat":"","crontab":"","once":false,"x":685.5,"y":101,"wires":[[]]},{"id":"66b5a8bf.2ff748","type":"debug","z":"9b3686b0.61c56","name":"","active":false,"console":"false","complete":"payload","x":930,"y":220,"wires":[]},{"id":"ed62c061.9050e8","type":"debug","z":"9b3686b0.61c56","name":"","active":false,"console":"false","complete":"true","x":905.5,"y":310,"wires":[]},{"id":"429ccbb7.fa59c4","type":"file","z":"9b3686b0.61c56","name":"Store node data","filename":"/home/odroid/node_data","appendNewline":true,"createDir":false,"overwriteFile":"false","x":720,"y":320,"wires":[]},{"id":"c9ab4f64.db87d","type":"ttn send","z":"9b3686b0.61c56","name":"","app":"b59d5696.cde318","dev_id":"","port":"","x":1060,"y":80,"wires":[]},{"id":"af434ae.b88c5b8","type":"function","z":"9b3686b0.61c56","name":"set Payload","func":"msg.dev_id = msg.payload.device;\nmsg.payload = Buffer.from(\"RSSI: \" + msg.payload.rssi + \" S: \" + msg.payload.snr);\n\nreturn msg;","outputs":1,"noerr":0,"x":730,"y":160,"wires":[["c9ab4f64.db87d","ea1ac2d1.b8229"]]},{"id":"ea1ac2d1.b8229","type":"debug","z":"9b3686b0.61c56","name":"","active":true,"console":"false","complete":"true","x":1110,"y":180,"wires":[]},{"id":"b59d5696.cde318","type":"ttn app","z":"","appId":"MYAPPID_CHANGEME","region":"eu","accessKey":"PUT_YOUR_CREDENTIALS_HERE"}] 2 | -------------------------------------------------------------------------------- /TTN_TTGOLora32/.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .clang_complete 4 | .gcc-flags.json 5 | -------------------------------------------------------------------------------- /TTN_TTGOLora32/.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < http://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < http://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < http://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choice one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # 39 | # script: 40 | # - platformio run 41 | 42 | 43 | # 44 | # Template #2: The project is intended to by used as a library with examples 45 | # 46 | 47 | # language: python 48 | # python: 49 | # - "2.7" 50 | # 51 | # sudo: false 52 | # cache: 53 | # directories: 54 | # - "~/.platformio" 55 | # 56 | # env: 57 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 58 | # - PLATFORMIO_CI_SRC=examples/file.ino 59 | # - PLATFORMIO_CI_SRC=path/to/test/directory 60 | # 61 | # install: 62 | # - pip install -U platformio 63 | # 64 | # script: 65 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 66 | -------------------------------------------------------------------------------- /TTN_TTGOLora32/README.md: -------------------------------------------------------------------------------- 1 | # TTN TTGO LoRa32 2 | 3 | Simple sketch, using PlatformIO IDE, to use the TTGO LoRa32 board as a node for The Things Network. 4 | 5 | The code uses IBM LMIC version for Arduino, but not streamlined for low memory devices. 6 | 7 | For more information goto: https://wp.me/p8SNr-sR -> Wordpress blog 8 | -------------------------------------------------------------------------------- /TTN_TTGOLora32/lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | |--Bar 12 | | | |--docs 13 | | | |--examples 14 | | | |--src 15 | | | |- Bar.c 16 | | | |- Bar.h 17 | | |--Foo 18 | | | |- Foo.c 19 | | | |- Foo.h 20 | | |- readme.txt --> THIS FILE 21 | |- platformio.ini 22 | |--src 23 | |- main.c 24 | 25 | Then in `src/main.c` you should use: 26 | 27 | #include 28 | #include 29 | 30 | // rest H/C/CPP code 31 | 32 | PlatformIO will find your libraries automatically, configure preprocessor's 33 | include paths and build them. 34 | 35 | More information about PlatformIO Library Dependency Finder 36 | - http://docs.platformio.org/page/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /TTN_TTGOLora32/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | [env:heltec_wifi_lora_32] 12 | platform = espressif32 13 | board = heltec_wifi_lora_32 14 | framework = arduino 15 | lib_deps = 562, 852 16 | -------------------------------------------------------------------------------- /TTN_TTGOLora32/src/main.cpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // https://github.com/gonzalocasas/arduino-uno-dragino-lorawan/blob/master/LICENSE 3 | // Based on examples from https://github.com/matthijskooijman/arduino-lmic 4 | // Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman 5 | // Modified by github FGCDAM user https://github.com/fcgdam 6 | 7 | #include 8 | #include "lmic.h" 9 | #include 10 | #include 11 | #include 12 | #include "soc/efuse_reg.h" 13 | 14 | #define LEDPIN 2 15 | 16 | #define OLED_I2C_ADDR 0x3C 17 | #define OLED_RESET 16 18 | #define OLED_SDA 4 19 | #define OLED_SCL 15 20 | 21 | unsigned int counter = 0; 22 | 23 | SSD1306 display (OLED_I2C_ADDR, OLED_SDA, OLED_SCL); 24 | 25 | /************************************* 26 | * TODO: Change the following keys 27 | * NwkSKey: network session key, AppSKey: application session key, and DevAddr: end-device address 28 | *************************************/ 29 | static u1_t NWKSKEY[16] = { ... }; // Paste here the key in MSB format 30 | 31 | static u1_t APPSKEY[16] = { ... }; // Paste here the key in MSB format 32 | 33 | static u4_t DEVADDR = 0x00000000; // Put here the device id in hexadecimal form. 34 | 35 | void os_getArtEui (u1_t* buf) { } 36 | void os_getDevEui (u1_t* buf) { } 37 | void os_getDevKey (u1_t* buf) { } 38 | 39 | static osjob_t sendjob; 40 | 41 | // Schedule TX every this many seconds (might become longer due to duty 42 | // cycle limitations). 43 | const unsigned TX_INTERVAL = 60; 44 | char TTN_response[30]; 45 | 46 | // Pin mapping 47 | const lmic_pinmap lmic_pins = { 48 | .nss = 18, 49 | .rxtx = LMIC_UNUSED_PIN, 50 | .rst = 14, 51 | .dio = {26, 33, 32} // Pins for the Heltec ESP32 Lora board/ TTGO Lora32 with 3D metal antenna 52 | }; 53 | 54 | void do_send(osjob_t* j){ 55 | // Payload to send (uplink) 56 | static uint8_t message[] = "Hello World!"; 57 | 58 | // Check if there is not a current TX/RX job running 59 | if (LMIC.opmode & OP_TXRXPEND) { 60 | Serial.println(F("OP_TXRXPEND, not sending")); 61 | } else { 62 | // Prepare upstream data transmission at the next possible time. 63 | LMIC_setTxData2(1, message, sizeof(message)-1, 0); 64 | Serial.println(F("Sending uplink packet...")); 65 | digitalWrite(LEDPIN, HIGH); 66 | display.clear(); 67 | display.drawString (0, 0, "Sending uplink packet..."); 68 | display.drawString (0, 50, String (++counter)); 69 | display.display (); 70 | } 71 | // Next TX is scheduled after TX_COMPLETE event. 72 | } 73 | 74 | void onEvent (ev_t ev) { 75 | if (ev == EV_TXCOMPLETE) { 76 | display.clear(); 77 | display.drawString (0, 0, "EV_TXCOMPLETE event!"); 78 | 79 | 80 | Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)")); 81 | if (LMIC.txrxFlags & TXRX_ACK) { 82 | Serial.println(F("Received ack")); 83 | display.drawString (0, 20, "Received ACK."); 84 | } 85 | 86 | if (LMIC.dataLen) { 87 | int i = 0; 88 | // data received in rx slot after tx 89 | Serial.print(F("Data Received: ")); 90 | Serial.write(LMIC.frame+LMIC.dataBeg, LMIC.dataLen); 91 | Serial.println(); 92 | 93 | display.drawString (0, 20, "Received DATA."); 94 | for ( i = 0 ; i < LMIC.dataLen ; i++ ) 95 | TTN_response[i] = LMIC.frame[LMIC.dataBeg+i]; 96 | 97 | TTN_response[i] = 0; 98 | display.drawString (0, 32, String(TTN_response)); 99 | } 100 | 101 | // Schedule next transmission 102 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); 103 | digitalWrite(LEDPIN, LOW); 104 | display.drawString (0, 50, String (counter)); 105 | display.display (); 106 | } 107 | } 108 | 109 | int getChipRevision() 110 | { 111 | return (REG_READ(EFUSE_BLK0_RDATA3_REG) >> (EFUSE_RD_CHIP_VER_REV1_S)&&EFUSE_RD_CHIP_VER_REV1_V) ; 112 | } 113 | 114 | void printESPRevision() { 115 | Serial.print("REG_READ(EFUSE_BLK0_RDATA3_REG): "); 116 | Serial.println(REG_READ(EFUSE_BLK0_RDATA3_REG), BIN); 117 | 118 | Serial.print("EFUSE_RD_CHIP_VER_REV1_S: "); 119 | Serial.println(EFUSE_RD_CHIP_VER_REV1_S, BIN); 120 | 121 | Serial.print("EFUSE_RD_CHIP_VER_REV1_V: "); 122 | Serial.println(EFUSE_RD_CHIP_VER_REV1_V, BIN); 123 | 124 | Serial.println(); 125 | 126 | Serial.print("Chip Revision (official version): "); 127 | Serial.println(getChipRevision()); 128 | 129 | Serial.print("Chip Revision from shift Operation "); 130 | Serial.println(REG_READ(EFUSE_BLK0_RDATA3_REG) >> 15, BIN); 131 | 132 | } 133 | 134 | void setup() { 135 | Serial.begin(115200); 136 | delay(1500); // Give time for the seral monitor to start up 137 | Serial.println(F("Starting...")); 138 | 139 | printESPRevision(); 140 | 141 | // Use the Blue pin to signal transmission. 142 | pinMode(LEDPIN,OUTPUT); 143 | 144 | // reset the OLED 145 | pinMode(OLED_RESET,OUTPUT); 146 | digitalWrite(OLED_RESET, LOW); 147 | delay(50); 148 | digitalWrite(OLED_RESET, HIGH); 149 | 150 | display.init (); 151 | display.flipScreenVertically (); 152 | display.setFont (ArialMT_Plain_10); 153 | 154 | display.setTextAlignment (TEXT_ALIGN_LEFT); 155 | 156 | display.drawString (0, 0, "Init!"); 157 | display.display (); 158 | 159 | if ( DEVADDR == 0x00 ) { // Device is misconfigured with an invalid or not defined device id. 160 | int i = 0; 161 | 162 | while ( true ) { 163 | display.clear(); 164 | display.drawString (0, 0, "INIT FAILED! "); 165 | display.drawString (0, 9, "Device ID is not SET!"); 166 | 167 | display.drawString (0, 18, "Invalid TTN settings!"); 168 | display.drawString (0, 27, "Set NWSKEY and APPSKEY!"); 169 | 170 | display.drawString( 0, 36, "Correct and reset."); 171 | 172 | display.drawString( 0, 45, "Waiting for user action..."); 173 | if ( i == 0 ) 174 | display.drawString( 0, 54, "." ); 175 | else 176 | display.drawString( 0, 54, "*" ); 177 | i++; 178 | i = i % 2; 179 | display.display (); 180 | delay( 1000 ); 181 | } 182 | 183 | } 184 | 185 | // LMIC init 186 | os_init(); 187 | 188 | display.drawString (0, 8, "LMIC was initiated!"); 189 | display.display (); 190 | 191 | // Reset the MAC state. Session and pending data transfers will be discarded. 192 | LMIC_reset(); 193 | 194 | display.drawString (0, 16, "LMIC reset -> OK!"); 195 | display.display (); 196 | 197 | // Set up the channels used by the Things Network, which corresponds 198 | // to the defaults of most gateways. Without this, only three base 199 | // channels from the LoRaWAN specification are used, which certainly 200 | // works, so it is good for debugging, but can overload those 201 | // frequencies, so be sure to configure the full frequency range of 202 | // your network here (unless your network autoconfigures them). 203 | // Setting up channels should happen after LMIC_setSession, as that 204 | // configures the minimal channel set. 205 | LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 206 | LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band 207 | LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 208 | LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 209 | LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 210 | LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 211 | LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 212 | LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 213 | LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band 214 | // TTN defines an additional channel at 869.525Mhz using SF9 for class B 215 | // devices' ping slots. LMIC does not have an easy way to define set this 216 | // frequency and support for class B is spotty and untested, so this 217 | // frequency is not configured here. 218 | display.drawString (0, 24, "LMIC setChannels -> OK!"); 219 | display.display (); 220 | 221 | 222 | // Set static session parameters. 223 | LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY); 224 | 225 | // Disable link check validation 226 | LMIC_setLinkCheckMode(0); 227 | 228 | // TTN uses SF9 for its RX2 window. 229 | LMIC.dn2Dr = DR_SF9; 230 | 231 | // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library) 232 | //LMIC_setDrTxpow(DR_SF11,14); 233 | LMIC_setDrTxpow(DR_SF9,14); 234 | 235 | display.drawString (0, 32, "LMIC setup -> OK!"); 236 | display.display (); 237 | 238 | for ( int i = 0 ; i < 5 ; i++ ) { 239 | delay ( 1000 ); 240 | 241 | display.drawString (0+i*8, 50, "."); 242 | display.display (); 243 | } 244 | 245 | Serial.println("LMIC setup done."); 246 | Serial.println("Starting transmit job."); 247 | 248 | // Start job 249 | do_send(&sendjob); 250 | } 251 | 252 | void loop() { 253 | os_runloop_once(); 254 | } 255 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_BLEBridge/.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .clang_complete 4 | .gcc-flags.json 5 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_BLEBridge/.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < http://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < http://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < http://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choice one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # 39 | # script: 40 | # - platformio run 41 | 42 | 43 | # 44 | # Template #2: The project is intended to by used as a library with examples 45 | # 46 | 47 | # language: python 48 | # python: 49 | # - "2.7" 50 | # 51 | # sudo: false 52 | # cache: 53 | # directories: 54 | # - "~/.platformio" 55 | # 56 | # env: 57 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 58 | # - PLATFORMIO_CI_SRC=examples/file.ino 59 | # - PLATFORMIO_CI_SRC=path/to/test/directory 60 | # 61 | # install: 62 | # - pip install -U platformio 63 | # 64 | # script: 65 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 66 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_BLEBridge/README.md: -------------------------------------------------------------------------------- 1 | # TTN TTGO LoRa32 BLE BRIDGE 2 | 3 | Simple sketch, using PlatformIO IDE, to use the TTGO LoRa32 board as a node for The Things Network and bridge data received from the BLE interface to TTN. 4 | 5 | The code uses IBM LMIC version for Arduino, but not streamlined for low memory devices. 6 | 7 | For more information goto: https://primalcortex.wordpress.com/2017/12/06/simple-ble-bridge-to-ttn-lora-using-the-ttgo-esp32-lora32-board/ 8 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_BLEBridge/lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | |--Bar 12 | | | |--docs 13 | | | |--examples 14 | | | |--src 15 | | | |- Bar.c 16 | | | |- Bar.h 17 | | |--Foo 18 | | | |- Foo.c 19 | | | |- Foo.h 20 | | |- readme.txt --> THIS FILE 21 | |- platformio.ini 22 | |--src 23 | |- main.c 24 | 25 | Then in `src/main.c` you should use: 26 | 27 | #include 28 | #include 29 | 30 | // rest H/C/CPP code 31 | 32 | PlatformIO will find your libraries automatically, configure preprocessor's 33 | include paths and build them. 34 | 35 | More information about PlatformIO Library Dependency Finder 36 | - http://docs.platformio.org/page/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_BLEBridge/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | [env:heltec_wifi_lora_32] 12 | platform = espressif32 13 | board = heltec_wifi_lora_32 14 | framework = arduino 15 | lib_deps = 562, 852, 1841 16 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_BLEBridge/src/main.cpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // https://github.com/gonzalocasas/arduino-uno-dragino-lorawan/blob/master/LICENSE 3 | // Based on examples from https://github.com/matthijskooijman/arduino-lmic 4 | // Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman 5 | // Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp 6 | // Ported to Arduino ESP32 by Evandro Copercini 7 | // Create a BLE server that, once we receive a connection, will send periodic notifications. 8 | // The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E 9 | // Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE" 10 | // Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with "NOTIFY" 11 | 12 | 13 | #include 14 | #include "lmic.h" 15 | #include 16 | #include 17 | #include 18 | #include "soc/efuse_reg.h" 19 | 20 | // BLE - Bluetooth Low Energy support 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | // UART UUIDS 27 | #define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // NORDIC UART service UUID 28 | #define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" 29 | #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" 30 | 31 | BLECharacteristic *pCharacteristic; 32 | bool deviceConnected = false; 33 | uint8_t txValue = 0; 34 | 35 | #define LEDPIN 2 36 | 37 | #define OLED_I2C_ADDR 0x3C 38 | #define OLED_RESET 16 39 | #define OLED_SDA 4 40 | #define OLED_SCL 15 41 | 42 | unsigned int counter = 0; 43 | 44 | SSD1306 display (OLED_I2C_ADDR, OLED_SDA, OLED_SCL); 45 | 46 | /************************************* 47 | * TODO: Change the following keys 48 | * NwkSKey: network session key, AppSKey: application session key, and DevAddr: end-device address 49 | *************************************/ 50 | static u1_t NWKSKEY[16] = { .... }; // Paste here the key in MSB format 51 | 52 | static u1_t APPSKEY[16] = { .... }; // Paste here the key in MSB format 53 | 54 | static u4_t DEVADDR = 0x00000000; // Put here the device id in hexadecimal form. 55 | 56 | void os_getArtEui (u1_t* buf) { } 57 | void os_getDevEui (u1_t* buf) { } 58 | void os_getDevKey (u1_t* buf) { } 59 | 60 | static osjob_t sendjob; 61 | 62 | // Schedule TX every this many seconds (might become longer due to duty 63 | // cycle limitations). 64 | const unsigned TX_INTERVAL = 60; 65 | #define TTNMESSAGELENGHT 32 66 | 67 | char TTN_response[TTNMESSAGELENGHT]; 68 | uint8_t TTN_message[TTNMESSAGELENGHT]; 69 | unsigned int TTN_messageIndex = 0; 70 | 71 | // Pin mapping 72 | const lmic_pinmap lmic_pins = { 73 | .nss = 18, 74 | .rxtx = LMIC_UNUSED_PIN, 75 | .rst = 14, 76 | .dio = {26, 33, 32} // Pins for the Heltec ESP32 Lora board/ TTGO Lora32 with 3D metal antenna 77 | }; 78 | 79 | // BLE support 80 | class UARTBLEServerCallback: public BLEServerCallbacks { 81 | void onConnect(BLEServer* pServer) { 82 | Serial.println("Remote BLE device connected!"); 83 | deviceConnected = true; 84 | }; 85 | 86 | void onDisconnect(BLEServer* pServer) { 87 | Serial.println("Remote BLE device DISCONNECTED!"); 88 | deviceConnected = false; 89 | } 90 | }; 91 | 92 | class UARTBLEDataCallback: public BLECharacteristicCallbacks { 93 | void onWrite(BLECharacteristic *pCharacteristic) { 94 | std::string rxValue = pCharacteristic->getValue(); 95 | 96 | if (rxValue.length() > 0) { 97 | Serial.println("*********"); 98 | Serial.print("Received Value: "); 99 | for (int i = 0; i < rxValue.length(); i++) { 100 | Serial.print(rxValue[i]); 101 | TTN_message[TTN_messageIndex++] = rxValue[i]; 102 | if ( TTN_messageIndex >= TTNMESSAGELENGHT) break; 103 | } 104 | 105 | Serial.println(); 106 | Serial.println("*********"); 107 | } 108 | } 109 | }; 110 | 111 | void do_send(osjob_t* j){ 112 | 113 | // Check if we have a message... 114 | if ( TTN_messageIndex == 0 ) { 115 | Serial.println(F("No data to send...")); 116 | display.clear(); 117 | display.drawString (0, 0, "No data to send..."); 118 | display.display (); 119 | 120 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); 121 | 122 | return; 123 | } 124 | 125 | // Check if there is not a current TX/RX job running 126 | if (LMIC.opmode & OP_TXRXPEND) { 127 | Serial.println(F("OP_TXRXPEND, not sending")); 128 | } else { 129 | // Prepare upstream data transmission at the next possible time. 130 | for ( int i = 0 ; i < TTN_messageIndex; i++) { 131 | Serial.print(TTN_message[i]); 132 | } 133 | LMIC_setTxData2(1, TTN_message, TTN_messageIndex, 0); 134 | Serial.println(F("Sending uplink packet...")); 135 | digitalWrite(LEDPIN, HIGH); 136 | display.clear(); 137 | display.drawString (0, 0, "Sending uplink packet..."); 138 | display.drawString (0, 50, String (++counter)); 139 | display.display (); 140 | TTN_messageIndex = 0; // Reset for the next message 141 | } 142 | // Next TX is scheduled after TX_COMPLETE event. 143 | } 144 | 145 | void onEvent (ev_t ev) { 146 | if (ev == EV_TXCOMPLETE) { 147 | display.clear(); 148 | display.drawString (0, 0, "EV_TXCOMPLETE event!"); 149 | 150 | 151 | Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)")); 152 | if (LMIC.txrxFlags & TXRX_ACK) { 153 | Serial.println(F("Received ack")); 154 | display.drawString (0, 20, "Received ACK."); 155 | } 156 | 157 | if (LMIC.dataLen) { 158 | int i = 0; 159 | // data received in rx slot after tx 160 | Serial.print(F("Data Received: ")); 161 | Serial.write(LMIC.frame+LMIC.dataBeg, LMIC.dataLen); 162 | Serial.println(); 163 | 164 | display.drawString (0, 20, "Received DATA."); 165 | for ( i = 0 ; i < LMIC.dataLen ; i++ ) 166 | TTN_response[i] = LMIC.frame[LMIC.dataBeg+i]; 167 | TTN_response[i] = 0; 168 | display.drawString (0, 32, String(TTN_response)); 169 | } 170 | 171 | // Schedule next transmission 172 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); 173 | digitalWrite(LEDPIN, LOW); 174 | display.drawString (0, 50, String (counter)); 175 | display.display (); 176 | 177 | // Just for simplicity we notify the BLE device that an EV_TXCOMPLETE event happend 178 | pCharacteristic->setValue("EV_TXCOMPLETE"); 179 | pCharacteristic->notify(); 180 | } 181 | } 182 | 183 | int getChipRevision() 184 | { 185 | return (REG_READ(EFUSE_BLK0_RDATA3_REG) >> (EFUSE_RD_CHIP_VER_REV1_S)&&EFUSE_RD_CHIP_VER_REV1_V) ; 186 | } 187 | 188 | void printESPRevision() { 189 | Serial.print("REG_READ(EFUSE_BLK0_RDATA3_REG): "); 190 | Serial.println(REG_READ(EFUSE_BLK0_RDATA3_REG), BIN); 191 | 192 | Serial.print("EFUSE_RD_CHIP_VER_REV1_S: "); 193 | Serial.println(EFUSE_RD_CHIP_VER_REV1_S, BIN); 194 | 195 | Serial.print("EFUSE_RD_CHIP_VER_REV1_V: "); 196 | Serial.println(EFUSE_RD_CHIP_VER_REV1_V, BIN); 197 | 198 | Serial.println(); 199 | 200 | Serial.print("Chip Revision (official version): "); 201 | Serial.println(getChipRevision()); 202 | 203 | Serial.print("Chip Revision from shift Operation "); 204 | Serial.println(REG_READ(EFUSE_BLK0_RDATA3_REG) >> 15, BIN); 205 | 206 | } 207 | 208 | void initBLE() { 209 | 210 | // Create the BLE Device 211 | BLEDevice::init("TTGOLORAESP32"); 212 | 213 | // Create the BLE Server 214 | BLEServer *pServer = BLEDevice::createServer(); 215 | pServer->setCallbacks(new UARTBLEServerCallback()); 216 | 217 | // Create the BLE Service 218 | BLEService *pService = pServer->createService(SERVICE_UUID); 219 | 220 | // Create a BLE Characteristic 221 | pCharacteristic = pService->createCharacteristic( 222 | CHARACTERISTIC_UUID_TX, 223 | BLECharacteristic::PROPERTY_NOTIFY 224 | ); 225 | 226 | pCharacteristic->addDescriptor(new BLE2902()); 227 | 228 | BLECharacteristic *pCharacteristic = pService->createCharacteristic( 229 | CHARACTERISTIC_UUID_RX, 230 | BLECharacteristic::PROPERTY_WRITE 231 | ); 232 | 233 | pCharacteristic->setCallbacks(new UARTBLEDataCallback()); 234 | 235 | // Start the service 236 | pService->start(); 237 | 238 | // Start advertising 239 | pServer->getAdvertising()->start(); 240 | } 241 | 242 | 243 | void setup() { 244 | Serial.begin(115200); 245 | delay(1500); // Give time for the seral monitor to start up 246 | Serial.println(F("Starting...")); 247 | 248 | printESPRevision(); 249 | 250 | Serial.println(F("Init BLE...")); 251 | initBLE(); 252 | 253 | // Use the Blue pin to signal transmission. 254 | pinMode(LEDPIN,OUTPUT); 255 | 256 | // reset the OLED 257 | pinMode(OLED_RESET,OUTPUT); 258 | digitalWrite(OLED_RESET, LOW); 259 | delay(50); 260 | digitalWrite(OLED_RESET, HIGH); 261 | 262 | display.init (); 263 | display.flipScreenVertically (); 264 | display.setFont (ArialMT_Plain_10); 265 | 266 | display.setTextAlignment (TEXT_ALIGN_LEFT); 267 | 268 | display.drawString (0, 0, "Init!"); 269 | display.display (); 270 | 271 | // LMIC init 272 | os_init(); 273 | 274 | // Reset the MAC state. Session and pending data transfers will be discarded. 275 | LMIC_reset(); 276 | 277 | // Set up the channels used by the Things Network, which corresponds 278 | // to the defaults of most gateways. Without this, only three base 279 | // channels from the LoRaWAN specification are used, which certainly 280 | // works, so it is good for debugging, but can overload those 281 | // frequencies, so be sure to configure the full frequency range of 282 | // your network here (unless your network autoconfigures them). 283 | // Setting up channels should happen after LMIC_setSession, as that 284 | // configures the minimal channel set. 285 | LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 286 | LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band 287 | LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 288 | LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 289 | LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 290 | LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 291 | LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 292 | LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 293 | LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band 294 | // TTN defines an additional channel at 869.525Mhz using SF9 for class B 295 | // devices' ping slots. LMIC does not have an easy way to define set this 296 | // frequency and support for class B is spotty and untested, so this 297 | // frequency is not configured here. 298 | 299 | // Set static session parameters. 300 | LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY); 301 | 302 | // Disable link check validation 303 | LMIC_setLinkCheckMode(0); 304 | 305 | // TTN uses SF9 for its RX2 window. 306 | LMIC.dn2Dr = DR_SF9; 307 | 308 | // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library) 309 | //LMIC_setDrTxpow(DR_SF11,14); 310 | LMIC_setDrTxpow(DR_SF9,14); 311 | 312 | // Start job 313 | do_send(&sendjob); 314 | } 315 | 316 | void loop() { 317 | os_runloop_once(); 318 | } 319 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_OTAA/.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .clang_complete 4 | .gcc-flags.json 5 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_OTAA/.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < http://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < http://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < http://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choice one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # 39 | # script: 40 | # - platformio run 41 | 42 | 43 | # 44 | # Template #2: The project is intended to by used as a library with examples 45 | # 46 | 47 | # language: python 48 | # python: 49 | # - "2.7" 50 | # 51 | # sudo: false 52 | # cache: 53 | # directories: 54 | # - "~/.platformio" 55 | # 56 | # env: 57 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 58 | # - PLATFORMIO_CI_SRC=examples/file.ino 59 | # - PLATFORMIO_CI_SRC=path/to/test/directory 60 | # 61 | # install: 62 | # - pip install -U platformio 63 | # 64 | # script: 65 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 66 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_OTAA/README.md: -------------------------------------------------------------------------------- 1 | # TTN node with OTAA 2 | 3 | This code implements a simple node that joins the network of the TheThings Network using Over The Air activation (OTTA). 4 | 5 | The information from the TTN console must be copied to the src/main.c file as required. 6 | 7 | Example of the data that must be copied from the console. Please note the difference between LSB and MSB formats for the keys. 8 | 9 | ![TTN Console Data](../images/OTAA_parameters.png?raw=true "TTN Console Data") 10 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_OTAA/lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | |--Bar 12 | | | |--docs 13 | | | |--examples 14 | | | |--src 15 | | | |- Bar.c 16 | | | |- Bar.h 17 | | |--Foo 18 | | | |- Foo.c 19 | | | |- Foo.h 20 | | |- readme.txt --> THIS FILE 21 | |- platformio.ini 22 | |--src 23 | |- main.c 24 | 25 | Then in `src/main.c` you should use: 26 | 27 | #include 28 | #include 29 | 30 | // rest H/C/CPP code 31 | 32 | PlatformIO will find your libraries automatically, configure preprocessor's 33 | include paths and build them. 34 | 35 | More information about PlatformIO Library Dependency Finder 36 | - http://docs.platformio.org/page/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_OTAA/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | [env:heltec_wifi_lora_32] 12 | platform = espressif32 13 | board = heltec_wifi_lora_32 14 | monitor_speed=115200 15 | framework = arduino 16 | lib_deps = 562, 852 17 | -------------------------------------------------------------------------------- /TTN_TTGOLora32_OTAA/src/main.cpp: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // https://github.com/gonzalocasas/arduino-uno-dragino-lorawan/blob/master/LICENSE 3 | // Based on examples from https://github.com/matthijskooijman/arduino-lmic 4 | // Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman 5 | 6 | #include 7 | #include "lmic.h" 8 | #include 9 | #include 10 | #include 11 | 12 | #define LEDPIN 2 13 | 14 | #define OLED_I2C_ADDR 0x3C 15 | #define OLED_RESET 16 16 | #define OLED_SDA 4 17 | #define OLED_SCL 15 18 | 19 | unsigned int counter = 0; 20 | char TTN_response[30]; 21 | 22 | SSD1306 display (OLED_I2C_ADDR, OLED_SDA, OLED_SCL); 23 | 24 | // This EUI must be in little-endian format, so least-significant-byte 25 | // first. When copying an EUI from ttnctl output, this means to reverse 26 | // the bytes. 27 | 28 | // Copy the value from Device EUI from the TTN console in LSB mode. 29 | static const u1_t PROGMEM DEVEUI[8]= { ... }; 30 | void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);} 31 | 32 | // Copy the value from Application EUI from the TTN console in LSB mode 33 | static const u1_t PROGMEM APPEUI[8]= { ... }; 34 | void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);} 35 | 36 | // This key should be in big endian format (or, since it is not really a 37 | // number but a block of memory, endianness does not really apply). In 38 | // practice, a key taken from ttnctl can be copied as-is. Anyway its in MSB mode. 39 | static const u1_t PROGMEM APPKEY[16] = { ... }; 40 | void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);} 41 | 42 | static osjob_t sendjob; 43 | 44 | // Schedule TX every this many seconds (might become longer due to duty 45 | // cycle limitations). 46 | const unsigned TX_INTERVAL = 120; 47 | 48 | // Pin mapping 49 | const lmic_pinmap lmic_pins = { 50 | .nss = 18, 51 | .rxtx = LMIC_UNUSED_PIN, 52 | .rst = 14, 53 | .dio = {26, 33, 32} // Pins for the Heltec ESP32 Lora board/ TTGO Lora32 with 3D metal antenna 54 | }; 55 | 56 | void do_send(osjob_t* j){ 57 | // Payload to send (uplink) 58 | static uint8_t message[] = "Hello OTAA!"; 59 | 60 | // Check if there is not a current TX/RX job running 61 | if (LMIC.opmode & OP_TXRXPEND) { 62 | Serial.println(F("OP_TXRXPEND, not sending")); 63 | } else { 64 | // Prepare upstream data transmission at the next possible time. 65 | LMIC_setTxData2(1, message, sizeof(message)-1, 0); 66 | Serial.println(F("Sending uplink packet...")); 67 | digitalWrite(LEDPIN, HIGH); 68 | display.clear(); 69 | display.drawString (0, 0, "Sending uplink packet..."); 70 | display.drawString (0, 50, String (++counter)); 71 | display.display (); 72 | } 73 | // Next TX is scheduled after TX_COMPLETE event. 74 | } 75 | 76 | void onEvent (ev_t ev) { 77 | Serial.print(os_getTime()); 78 | Serial.print(": "); 79 | switch(ev) { 80 | case EV_TXCOMPLETE: 81 | Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)")); 82 | display.clear(); 83 | display.drawString (0, 0, "EV_TXCOMPLETE event!"); 84 | 85 | if (LMIC.txrxFlags & TXRX_ACK) { 86 | Serial.println(F("Received ack")); 87 | display.drawString (0, 20, "Received ACK."); 88 | } 89 | 90 | if (LMIC.dataLen) { 91 | int i = 0; 92 | // data received in rx slot after tx 93 | Serial.print(F("Data Received: ")); 94 | Serial.write(LMIC.frame+LMIC.dataBeg, LMIC.dataLen); 95 | Serial.println(); 96 | Serial.println(LMIC.rssi); 97 | 98 | display.drawString (0, 9, "Received DATA."); 99 | for ( i = 0 ; i < LMIC.dataLen ; i++ ) 100 | TTN_response[i] = LMIC.frame[LMIC.dataBeg+i]; 101 | TTN_response[i] = 0; 102 | display.drawString (0, 22, String(TTN_response)); 103 | display.drawString (0, 32, String(LMIC.rssi)); 104 | display.drawString (64,32, String(LMIC.snr)); 105 | } 106 | 107 | // Schedule next transmission 108 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); 109 | digitalWrite(LEDPIN, LOW); 110 | display.drawString (0, 50, String (counter)); 111 | display.display (); 112 | // Schedule next transmission 113 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); 114 | break; 115 | case EV_JOINING: 116 | Serial.println(F("EV_JOINING: -> Joining...")); 117 | display.drawString(0,16 , "OTAA joining...."); 118 | display.display(); 119 | break; 120 | case EV_JOINED: { 121 | Serial.println(F("EV_JOINED")); 122 | display.clear(); 123 | display.drawString(0 , 0 , "Joined!"); 124 | display.display(); 125 | // Disable link check validation (automatically enabled 126 | // during join, but not supported by TTN at this time). 127 | LMIC_setLinkCheckMode(0); 128 | } 129 | break; 130 | case EV_RXCOMPLETE: 131 | // data received in ping slot 132 | Serial.println(F("EV_RXCOMPLETE")); 133 | break; 134 | case EV_LINK_DEAD: 135 | Serial.println(F("EV_LINK_DEAD")); 136 | break; 137 | case EV_LINK_ALIVE: 138 | Serial.println(F("EV_LINK_ALIVE")); 139 | break; 140 | default: 141 | Serial.println(F("Unknown event")); 142 | break; 143 | } 144 | 145 | } 146 | 147 | void setup() { 148 | Serial.begin(115200); 149 | delay(2500); // Give time to the serial monitor to pick up 150 | Serial.println(F("Starting...")); 151 | 152 | // Use the Blue pin to signal transmission. 153 | pinMode(LEDPIN,OUTPUT); 154 | 155 | //Set up and reset the OLED 156 | pinMode(OLED_RESET, OUTPUT); 157 | digitalWrite(OLED_RESET, LOW); 158 | delay(50); 159 | digitalWrite(OLED_RESET, HIGH); 160 | 161 | display.init (); 162 | display.flipScreenVertically (); 163 | display.setFont (ArialMT_Plain_10); 164 | 165 | display.setTextAlignment (TEXT_ALIGN_LEFT); 166 | 167 | display.drawString (0, 0, "Starting...."); 168 | display.display (); 169 | 170 | // LMIC init 171 | os_init(); 172 | 173 | // Reset the MAC state. Session and pending data transfers will be discarded. 174 | LMIC_reset(); 175 | LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100); 176 | // Set up the channels used by the Things Network, which corresponds 177 | // to the defaults of most gateways. Without this, only three base 178 | // channels from the LoRaWAN specification are used, which certainly 179 | // works, so it is good for debugging, but can overload those 180 | // frequencies, so be sure to configure the full frequency range of 181 | // your network here (unless your network autoconfigures them). 182 | // Setting up channels should happen after LMIC_setSession, as that 183 | // configures the minimal channel set. 184 | 185 | LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 186 | LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band 187 | LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 188 | LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 189 | LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 190 | LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 191 | LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 192 | LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 193 | LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band 194 | // TTN defines an additional channel at 869.525Mhz using SF9 for class B 195 | // devices' ping slots. LMIC does not have an easy way to define set this 196 | // frequency and support for class B is spotty and untested, so this 197 | // frequency is not configured here. 198 | 199 | // Disable link check validation 200 | LMIC_setLinkCheckMode(0); 201 | 202 | // TTN uses SF9 for its RX2 window. 203 | LMIC.dn2Dr = DR_SF9; 204 | 205 | // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library) 206 | //LMIC_setDrTxpow(DR_SF11,14); 207 | LMIC_setDrTxpow(DR_SF9,14); 208 | 209 | // Start job 210 | do_send(&sendjob); // Will fire up also the join 211 | //LMIC_startJoining(); 212 | } 213 | 214 | void loop() { 215 | os_runloop_once(); 216 | } 217 | -------------------------------------------------------------------------------- /WIFI_Scanner/.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .clang_complete 4 | .gcc-flags.json 5 | -------------------------------------------------------------------------------- /WIFI_Scanner/lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | |--Bar 12 | | | |--docs 13 | | | |--examples 14 | | | |--src 15 | | | |- Bar.c 16 | | | |- Bar.h 17 | | |--Foo 18 | | | |- Foo.c 19 | | | |- Foo.h 20 | | |- readme.txt --> THIS FILE 21 | |- platformio.ini 22 | |--src 23 | |- main.c 24 | 25 | Then in `src/main.c` you should use: 26 | 27 | #include 28 | #include 29 | 30 | // rest H/C/CPP code 31 | 32 | PlatformIO will find your libraries automatically, configure preprocessor's 33 | include paths and build them. 34 | 35 | More information about PlatformIO Library Dependency Finder 36 | - http://docs.platformio.org/page/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /WIFI_Scanner/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | [env:heltec_wifi_lora_32] 12 | platform = espressif32 13 | board = heltec_wifi_lora_32 14 | framework = arduino 15 | -------------------------------------------------------------------------------- /WIFI_Scanner/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "WiFi.h" 3 | #include "Wire.h" 4 | #include "SSD1306.h" 5 | 6 | SSD1306 display (0x3c, 4, 15); 7 | 8 | void setup() 9 | { 10 | Serial.begin(115200); 11 | 12 | pinMode (16, OUTPUT); 13 | digitalWrite (16, LOW); // set GPIO16 low to reset OLED 14 | delay (50); 15 | digitalWrite (16, HIGH); // while OLED is running, GPIO16 must go high 16 | // Set WiFi to station mode and disconnect from an AP if it was previously connected 17 | WiFi.mode(WIFI_STA); 18 | WiFi.disconnect(); 19 | delay(100); 20 | 21 | Serial.println("Setup done"); 22 | 23 | display.init (); 24 | display.flipScreenVertically (); 25 | display.setFont (ArialMT_Plain_10); 26 | delay(1000); 27 | } 28 | 29 | void loop() 30 | { 31 | Serial.println("scan start"); 32 | display.clear(); 33 | display.setTextAlignment (TEXT_ALIGN_LEFT); 34 | display.setFont (ArialMT_Plain_10); 35 | 36 | display.drawString (0, 0, "Scanning"); 37 | display.display(); 38 | 39 | // WiFi.scanNetworks will return the number of networks found 40 | int n = WiFi.scanNetworks(); 41 | Serial.println("scan done"); 42 | if (n == 0) { 43 | display.clear(); 44 | Serial.println("no networks found"); 45 | display.clear(); 46 | display.drawString(0,0,"No networks found"); 47 | 48 | } else { 49 | display.clear(); 50 | Serial.print(n); 51 | Serial.println(" networks found"); 52 | for (int i = 0; i < n; ++i) { 53 | // Print SSID and RSSI for each network found 54 | Serial.print(i + 1); 55 | Serial.print(": "); 56 | Serial.print(WiFi.SSID(i)); 57 | display.drawString( 0 , i*8 , String(WiFi.SSID(i))); 58 | Serial.print(" ("); 59 | Serial.print(WiFi.RSSI(i)); 60 | display.drawString( 90 , i*8 ,String(WiFi.RSSI(i))); 61 | Serial.print(")"); 62 | Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*"); 63 | delay(10); 64 | } 65 | } 66 | Serial.println(""); 67 | 68 | display.display(); 69 | // Wait a bit before scanning again 70 | delay(5000); 71 | } 72 | -------------------------------------------------------------------------------- /images/OTAA_parameters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcgdam/TTGO_LoRa32/8cca25140e60e9dc953702ff599540d0bae648b4/images/OTAA_parameters.png --------------------------------------------------------------------------------