├── platformio.ini ├── lib └── readme.txt ├── README.md └── src └── main.cpp /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter, extra scripting 4 | ; Upload options: custom port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; 7 | ; Please visit documentation for the other options and examples 8 | ; http://docs.platformio.org/en/stable/projectconf.html 9 | 10 | [env:feather32u4] 11 | platform = atmelavr 12 | board = feather32u4 13 | framework = arduino 14 | lib_deps= 852, 652 15 | ;upload_port = /dev/ttyACM0 16 | -------------------------------------------------------------------------------- /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/en/stable/librarymanager/ldf.html 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TTN Lorawan node with the AtMega 32u4 LORA32U4 2 | ============================================== 3 | 4 | For further information see https://wp.me/p8SNr-s1 and https://primalcortex.wordpress.com/2017/11/10/using-the-bsfrance-lora32u4-board-to-connect-to-the-things-network-lorawan/ 5 | 6 | Instalation: 7 | ------------ 8 | This code uses the platformio IDE. 9 | 10 | WARNING: If using this code for some other board, please change the LMIC pins for your specific board: 11 | 12 | My own developed board with the Hallard Wemos Lora shield: 13 | 14 |
15 | const lmic_pinmap lmic_pins = {
16 |     .nss = 9,
17 |     .rxtx = LMIC_UNUSED_PIN,
18 |     .rst = LMIC_UNUSED_PIN,
19 |     .dio = {8, 8, LMIC_UNUSED_PIN}  // Since the Wemos Lora Shield merges the pin with diodes, just use the same pin number
20 | };
21 | 
22 | 23 | The BSFrance ATMega32U4 Lora board: 24 |
25 | const lmic_pinmap lmic_pins = {
26 |     .nss = 8,
27 |     .rxtx = LMIC_UNUSED_PIN,
28 |     .rst = 4,
29 |     .dio = {7, 6 , LMIC_UNUSED_PIN}
30 | };
31 | 
32 | 33 | But a wire jumper must be connected between the DIO1 pin and pin 6 of the board. 34 | -------------------------------------------------------------------------------- /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 | #define BSFRANCEBOARD 1 7 | #define LOWPOWER 1 8 | 9 | #include 10 | #include "lmic.h" 11 | #include 12 | #include 13 | 14 | // https://github.com/thesolarnomad/lora-serialization 15 | #include // Use the encoder to format and transmit data. 16 | 17 | #define LEDPIN 13 18 | #if BSFRANCEBOARD 19 | #define VBATPIN A9 20 | #endif 21 | 22 | /************************************* 23 | * TODO: Change the following keys 24 | * NwkSKey: network session key, AppSKey: application session key, and DevAddr: end-device address 25 | *************************************/ 26 | static u1_t NWKSKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 27 | 28 | static u1_t APPSKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 29 | 30 | static u4_t DEVADDR = 0x00000000; // Put here the device id in hexadecimal form. 31 | 32 | // These callbacks are only used in over-the-air activation, so they are 33 | // left empty here (we cannot leave them out completely unless 34 | // DISABLE_JOIN is set in config.h, otherwise the linker will complain). 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 | 45 | // Pin mapping 46 | // These settings are for the user made board with the Atmega32u4 and the Wemos RFM95 shield. 47 | /* 48 | const lmic_pinmap lmic_pins = { 49 | .nss = 9, 50 | .rxtx = LMIC_UNUSED_PIN, 51 | .rst = LMIC_UNUSED_PIN, 52 | .dio = {8, 8, LMIC_UNUSED_PIN} // Since the Wemos Lora Shield merges the pin with diodes, just use the same pin number }; 53 | */ 54 | 55 | // These settings are for the BSFrance LORA32U4 board. Remember: pin 6 must be connected to DIO6 through a jumper wire! 56 | const lmic_pinmap lmic_pins = { 57 | .nss = 8, 58 | .rxtx = LMIC_UNUSED_PIN, 59 | .rst = 4, 60 | .dio = {7, 6 , LMIC_UNUSED_PIN} 61 | }; 62 | 63 | // The BSFrance Lora32U4 board has a voltage divider from the LiPo connector that allows 64 | // to measure battery voltage. 65 | #if BSFRANCEBOARD 66 | float getBatVoltage() { 67 | float measuredvbat = analogRead(VBATPIN); 68 | measuredvbat *= 2; // Voltage is devided by two by bridge resistor so multiply back 69 | measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage 70 | measuredvbat /= 1024; // convert to voltage 71 | Serial.print("VBat: " ); Serial.println(measuredvbat); 72 | return measuredvbat; 73 | } 74 | #endif 75 | 76 | 77 | void do_send(osjob_t* j){ 78 | // Check if there is not a current TX/RX job running 79 | if (LMIC.opmode & OP_TXRXPEND) { 80 | Serial.println(F("OP_TXRXPEND, not sending")); 81 | } else { 82 | // Prepare upstream data transmission at the next possible time. 83 | #if BSFRANCEBOARD 84 | float vbat = getBatVoltage(); 85 | uint8_t message[2]; 86 | message[0] = (uint8_t)vbat; // Integer part 87 | message[1] = (uint8_t)((vbat-message[0])*100); 88 | LMIC_setTxData2(1, message, 2 ,0); 89 | #else 90 | static uint8_t message[] = "Hello World!"; 91 | LMIC_setTxData2(1, message, sizeof(message)-1, 0); 92 | #endif 93 | Serial.println(F("Sending uplink packet...")); 94 | // Lit up the led to signal transmission . Should not be used if aiming to save power... 95 | digitalWrite(LEDPIN,HIGH); 96 | } 97 | // Next TX is scheduled after TX_COMPLETE event. 98 | } 99 | 100 | void onEvent (ev_t ev) { 101 | if (ev == EV_TXCOMPLETE) { 102 | Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)")); 103 | // Schedule next transmission 104 | os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); 105 | digitalWrite(LEDPIN,LOW); 106 | } 107 | } 108 | 109 | void setup() { 110 | //while (!Serial); // Wait for the serial port to wake up, otherwise Linux has trouble to connect. 111 | pinMode(LEDPIN,OUTPUT); 112 | for ( int i = 0 ; i < 3 ; i++) { 113 | digitalWrite(LEDPIN,HIGH); 114 | delay(500); 115 | digitalWrite(LEDPIN,LOW); 116 | delay(500); 117 | } 118 | 119 | Serial.begin(115200); 120 | Serial.println(F("Starting...")); 121 | 122 | // LMIC init 123 | os_init(); 124 | 125 | // Reset the MAC state. Session and pending data transfers will be discarded. 126 | LMIC_reset(); 127 | 128 | // Set up the channels used by the Things Network, which corresponds 129 | // to the defaults of most gateways. Without this, only three base 130 | // channels from the LoRaWAN specification are used, which certainly 131 | // works, so it is good for debugging, but can overload those 132 | // frequencies, so be sure to configure the full frequency range of 133 | // your network here (unless your network autoconfigures them). 134 | // Setting up channels should happen after LMIC_setSession, as that 135 | // configures the minimal channel set. 136 | LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 137 | LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band 138 | LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 139 | LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 140 | LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 141 | LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 142 | LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 143 | LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band 144 | LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band 145 | // TTN defines an additional channel at 869.525Mhz using SF9 for class B 146 | // devices' ping slots. LMIC does not have an easy way to define set this 147 | // frequency and support for class B is spotty and untested, so this 148 | // frequency is not configured here. 149 | 150 | // Set static session parameters. 151 | LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY); 152 | 153 | // Disable link check validation 154 | LMIC_setLinkCheckMode(0); 155 | 156 | // TTN uses SF9 for its RX2 window. 157 | LMIC.dn2Dr = DR_SF9; 158 | 159 | // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library) 160 | //LMIC_setDrTxpow(DR_SF11,14); 161 | LMIC_setDrTxpow(DR_SF9,14); 162 | 163 | // Start job 164 | do_send(&sendjob); 165 | } 166 | 167 | void loop() { 168 | os_runloop_once(); 169 | } 170 | --------------------------------------------------------------------------------