├── .gitignore
├── .travis.yml
├── 3D
├── LoRa Base Case.f3d
├── LoRa Base Case.stl
├── Lora Base Case Deckel.f3d
└── Lora Base Case Deckel.stl
├── README.md
├── gerber
├── promini_rfm95.jpg
└── promini_rfm95.zip
├── img
├── case_3d.jpg
├── case_open.jpg
├── circuit.jpg
├── value_plot.jpg
└── vcc_plot.jpg
├── include
├── io_pins.h
├── lora_credentials.h.example
├── settings.h
├── version.h
└── version_build.h
├── platformio.ini
├── src
├── functions.cpp
├── functions.h
├── global.cpp
├── global.h
├── lorawan.cpp
├── lorawan.h
├── main.cpp
├── powerdown.cpp
└── powerdown.h
└── tools
└── platformio_versioning.py
/.gitignore:
--------------------------------------------------------------------------------
1 | ### PlatformIO ###
2 | .pioenvs
3 | .piolibdeps
4 | .clang_complete
5 | .gcc-flags.json
6 | .pio
7 |
8 | ### VisualStudioCode ###
9 | .vscode/*
10 | #!.vscode/settings.json
11 | !.vscode/tasks.json
12 | #!.vscode/launch.json
13 | #!.vscode/extensions.json
14 | *.bak
15 |
16 | ### VisualStudioCode Patch ###
17 | # Ignore all local history of files
18 | .history
19 |
20 | # credentials
21 | *_credentials.h
22 |
--------------------------------------------------------------------------------
/.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 < https://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 | # < https://docs.platformio.org/page/ci/travis.html >
12 | #
13 | # * User Guide for `platformio ci` command
14 | # < https://docs.platformio.org/page/userguide/cmd_ci.html >
15 | #
16 | #
17 | # Please choose 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 | # - platformio update
39 | #
40 | # script:
41 | # - platformio run
42 |
43 |
44 | #
45 | # Template #2: The project is intended to be used as a library with examples.
46 | #
47 |
48 | # language: python
49 | # python:
50 | # - "2.7"
51 | #
52 | # sudo: false
53 | # cache:
54 | # directories:
55 | # - "~/.platformio"
56 | #
57 | # env:
58 | # - PLATFORMIO_CI_SRC=path/to/test/file.c
59 | # - PLATFORMIO_CI_SRC=examples/file.ino
60 | # - PLATFORMIO_CI_SRC=path/to/test/directory
61 | #
62 | # install:
63 | # - pip install -U platformio
64 | # - platformio update
65 | #
66 | # script:
67 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
68 |
--------------------------------------------------------------------------------
/3D/LoRa Base Case.f3d:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/3D/LoRa Base Case.f3d
--------------------------------------------------------------------------------
/3D/LoRa Base Case.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/3D/LoRa Base Case.stl
--------------------------------------------------------------------------------
/3D/Lora Base Case Deckel.f3d:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/3D/Lora Base Case Deckel.f3d
--------------------------------------------------------------------------------
/3D/Lora Base Case Deckel.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/3D/Lora Base Case Deckel.stl
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Arduino Pro Mini TTN LoRaWAN sensor node
2 |
3 |
4 |
5 | `Arduino Pro Mini` TTN LoRaWAN Node with `DHT22` and `RFM95` module powered by an 18650 protected battery.
6 | The Arduino was converted to [LowPower](https://jackgruber.github.io/2019-12-27-Low-power-Arduino-Pro-Mini/) by desoldering the power LED and the voltage converter.
7 |
8 | ## Circuit
9 |
10 |
11 |
12 |
13 | ## Case
14 |
15 |
16 |
17 | ## Diagrams
18 |
19 |
20 | ### Battery voltage curve over 12 months with measure and send data all 5 minutes
21 |
22 |
23 |
24 | ## TTN payload decoder (v2)
25 |
26 | ```javascript
27 | function Decoder(bytes, port) {
28 | var decoded = {};
29 |
30 | decoded.vcc = (bytes[0] + 200)/100;
31 |
32 | if(bytes[1] != 255){
33 | decoded.humidity = bytes[1];
34 | decoded.humidity &= ~(1 << 7);
35 | if(bytes[1] >> 7 == 1) { decoded.humidity +=0.5 }
36 | }
37 |
38 | if(bytes[2] != 255 || bytes[3] != 255) decoded.temperature = ((bytes[2]<<24>>16 | bytes[3]) / 10);
39 | return decoded;
40 | }
41 | ```
42 |
43 | ## TTN payload decoder (v3)
44 |
45 | ```javascript
46 | function decodeUplink(input) {
47 | var decoded = {};
48 | decoded.vcc = (input.bytes[0] + 200)/100;
49 | if(input.bytes[1] != 255){
50 | decoded.humidity = input.bytes[1];
51 | decoded.humidity &= ~(1 << 7);
52 | if(input.bytes[1] >> 7 == 1) { decoded.humidity +=0.5 }
53 | }
54 | if(input.bytes[2] != 255 || input.bytes[3] != 255) decoded.temperature = ((input.bytes[2]<<24>>16 | input.bytes[3]) / 10);
55 |
56 | return {
57 | data: decoded,
58 | warnings: [],
59 | errors: []
60 | };
61 | }
62 | ```
63 |
--------------------------------------------------------------------------------
/gerber/promini_rfm95.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/gerber/promini_rfm95.jpg
--------------------------------------------------------------------------------
/gerber/promini_rfm95.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/gerber/promini_rfm95.zip
--------------------------------------------------------------------------------
/img/case_3d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/img/case_3d.jpg
--------------------------------------------------------------------------------
/img/case_open.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/img/case_open.jpg
--------------------------------------------------------------------------------
/img/circuit.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/img/circuit.jpg
--------------------------------------------------------------------------------
/img/value_plot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/img/value_plot.jpg
--------------------------------------------------------------------------------
/img/vcc_plot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JackGruber/Arduino-Pro-Mini-LoRa-Sensor-Node/d9527fde1e6a68f36523b1b5a9d133e53c6bb45e/img/vcc_plot.jpg
--------------------------------------------------------------------------------
/include/io_pins.h:
--------------------------------------------------------------------------------
1 | #define PIN_DHT 3
2 | #define PIN_INFO_LED 9
3 |
4 | // PIN definition for module
5 | #define PIN_LMIC_NSS 10
6 | #define PIN_LMIC_RST A0
7 | #define PIN_LMIC_DIO0 5
8 | #define PIN_LMIC_DIO1 6
9 | #define PIN_LMIC_DIO2 7
--------------------------------------------------------------------------------
/include/lora_credentials.h.example:
--------------------------------------------------------------------------------
1 | #define TTN_APPEUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // TTN Application EUI with "lsb"
2 | #define TTN_DEVEUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // TTN Device EUI with "lsb"
3 | #define TTN_APPKEY { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // TTN App Key with "msb"
4 |
--------------------------------------------------------------------------------
/include/settings.h:
--------------------------------------------------------------------------------
1 | #define LORA_TX_INTERVAL 300
2 | #define LMIC_LORA_SF DR_SF7 // LORA Data rate
3 |
--------------------------------------------------------------------------------
/include/version.h:
--------------------------------------------------------------------------------
1 | #define VERSION_MAJOR "1"
2 | #define VERSION_MINOR "0"
3 | #define VERSION_PATCH "0"
4 | #define VERSION_BUILD "0"
5 |
--------------------------------------------------------------------------------
/include/version_build.h:
--------------------------------------------------------------------------------
1 | #define BUILD_BRANCH ""
2 | #define BUILD_COMMIT ""
3 | #define BUILD_DATE ""
4 | #define BUILD_TIME ""
5 |
--------------------------------------------------------------------------------
/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 | ; https://docs.platformio.org/page/projectconf.html
10 |
11 | ; USBASP Upload command
12 | ; io run -t program --upload-port usb
13 |
14 | [env:pro8MHzatmega328]
15 | platform = atmelavr
16 | board = pro8MHzatmega328
17 | framework = arduino
18 | monitor_speed = 115200
19 | upload_protocol = usbasp
20 | extra_scripts =
21 | pre:tools/platformio_versioning.py
22 |
23 | upload_flags =
24 | -Pusb
25 | -e ; Erase chip bevor upload
26 |
27 | lib_deps =
28 | mcci-catena/MCCI LoRaWAN LMIC library @ ^4.0.0
29 | https://github.com/markruys/arduino-DHT
30 |
31 | build_flags =
32 | -D ARDUINO_LMIC_PROJECT_CONFIG_H_SUPPRESS
33 | -D CFG_eu868=1
34 | -D CFG_sx1276_radio=1
35 | -D LMIC_PRINTF_TO=Serial
36 | -D LMIC_DEBUG_LEVEL=0
37 | -D DISABLE_PING=1
38 | -D DISABLE_BEACONS=1
39 | -D LORADEV=KELLER
40 |
--------------------------------------------------------------------------------
/src/functions.cpp:
--------------------------------------------------------------------------------
1 | #include "functions.h"
2 | #include "io_pins.h"
3 | #include "global.h"
4 | #include "DHT.h"
5 |
6 | void Setup_Pins()
7 | {
8 | pinMode(PIN_INFO_LED, OUTPUT);
9 | }
10 |
11 | void Blink_Info_LED()
12 | {
13 | digitalWrite(PIN_INFO_LED, HIGH);
14 | delay(30);
15 | digitalWrite(PIN_INFO_LED, LOW);
16 | delay(30);
17 | }
18 |
19 | // https://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
20 | long ReadVcc() {
21 | // Read 1.1V reference against AVcc
22 | // set the reference to Vcc and the measurement to the internal 1.1V reference
23 | #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
24 | ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
25 | #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
26 | ADMUX = _BV(MUX5) | _BV(MUX0);
27 | #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
28 | ADMUX = _BV(MUX3) | _BV(MUX2);
29 | #else
30 | ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
31 | #endif
32 |
33 | delay(2); // Wait for Vref to settle
34 | ADCSRA |= _BV(ADSC); // Start conversion
35 | while (bitRead(ADCSRA, ADSC));
36 |
37 | uint8_t adc_low = ADCL; // must read ADCL first - it then locks ADCH
38 | uint8_t adc_high = ADCH; // unlocks both
39 | long adc_result = (adc_high<<8) | adc_low;
40 | adc_result = 1125300L / adc_result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
41 | return adc_result; // Vcc in millivolts
42 | }
43 |
44 | void ReadDHTSensor()
45 | {
46 | float t = DHTSENSOR.getTemperature();
47 | float h = DHTSENSOR.getHumidity();
48 |
49 | Serial.print("DHT: ");
50 | Serial.println(DHTSENSOR.getStatusString());
51 |
52 | HUMIDITY = h;
53 | TEMPERATURE = t;
54 |
55 | Serial.print(HUMIDITY);
56 | Serial.println(" %");
57 | Serial.print(TEMPERATURE);
58 | Serial.println(" °C");
59 | }
60 |
61 | void PrintResetReason()
62 | {
63 | uint8_t mcusr_copy = MCUSR;
64 | MCUSR = 0;
65 | Serial.print("MCUSR:");
66 | if(mcusr_copy & (1<
6 |
7 | void Setup_Pins(void);
8 | void Blink_Info_LED(void);
9 | long ReadVcc(void);
10 | void ReadDHTSensor(void);
11 | void PrintResetReason(void);
12 | #endif
--------------------------------------------------------------------------------
/src/global.cpp:
--------------------------------------------------------------------------------
1 | #include "global.h"
2 | #include "io_pins.h"
3 |
4 | float HUMIDITY = NAN;
5 | float TEMPERATURE = NAN;
6 | DHT DHTSENSOR;
7 |
--------------------------------------------------------------------------------
/src/global.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifndef _GLOBAL_H
3 | #define _GLOBAL_H
4 |
5 | #include
6 | #include
7 |
8 | extern volatile int POWER_DOWN_SLEEP_COUNTER;
9 | extern float HUMIDITY;
10 | extern float TEMPERATURE;
11 | extern DHT DHTSENSOR;
12 | #endif
--------------------------------------------------------------------------------
/src/lorawan.cpp:
--------------------------------------------------------------------------------
1 | #include "lorawan.h"
2 | #include "settings.h"
3 | #include
4 | #include
5 | #include "io_pins.h"
6 | #include "powerdown.h"
7 | #include "functions.h"
8 | #include "global.h"
9 |
10 | // Pin mapping
11 | const lmic_pinmap lmic_pins = {
12 | .nss = PIN_LMIC_NSS,
13 | .rxtx = LMIC_UNUSED_PIN,
14 | .rst = PIN_LMIC_RST,
15 | .dio = {PIN_LMIC_DIO0, PIN_LMIC_DIO1, PIN_LMIC_DIO2},
16 | };
17 |
18 | static uint8_t LORA_DATA[4];
19 |
20 | // Schedule TX every this many seconds (might become longer due to duty cycle limitations).
21 | const unsigned TX_INTERVAL = LORA_TX_INTERVAL;
22 |
23 | void os_getArtEui(u1_t *buf) { memcpy_P(buf, APPEUI, 8); }
24 | void os_getDevEui(u1_t *buf) { memcpy_P(buf, DEVEUI, 8); }
25 | void os_getDevKey(u1_t *buf) { memcpy_P(buf, APPKEY, 16); }
26 |
27 | bool GO_DEEP_SLEEP = false;
28 |
29 | void LoRaWANSetup()
30 | {
31 | Serial.println(F("LoRaWAN_Setup ..."));
32 |
33 | // LMIC init
34 | os_init();
35 |
36 | // Reset the MAC state. Session and pending data transfers will be discarded.
37 | LMIC_reset();
38 |
39 | // Let LMIC compensate for +/- 1% clock error
40 | LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
41 |
42 | // Start job
43 | LoRaWANDo_send(&sendjob);
44 | }
45 |
46 | void LoRaWANDo_send(osjob_t *j)
47 | {
48 | // Check if there is not a current TX/RX job running
49 | if (LMIC.opmode & OP_TXRXPEND)
50 | {
51 | Serial.println(F("OP_TXRXPEND, not sending"));
52 | }
53 | else
54 | {
55 | LoRaWANGetData();
56 |
57 | // Prepare upstream data transmission at the next possible time.
58 | LMIC_setTxData2(1, LORA_DATA, sizeof(LORA_DATA), 0);
59 | Serial.println(F("Packet queued"));
60 | }
61 | // Next TX is scheduled after TX_COMPLETE event.
62 | }
63 |
64 | void onEvent(ev_t ev)
65 | {
66 | Serial.print(os_getTime());
67 | Serial.print(": ");
68 | switch (ev)
69 | {
70 | case EV_SCAN_TIMEOUT:
71 | Serial.println(F("EV_SCAN_TIMEOUT"));
72 | break;
73 | case EV_BEACON_FOUND:
74 | Serial.println(F("EV_BEACON_FOUND"));
75 | break;
76 | case EV_BEACON_MISSED:
77 | Serial.println(F("EV_BEACON_MISSED"));
78 | break;
79 | case EV_BEACON_TRACKED:
80 | Serial.println(F("EV_BEACON_TRACKED"));
81 | break;
82 | case EV_JOINING:
83 | Serial.println(F("EV_JOINING"));
84 | break;
85 | case EV_JOINED:
86 | Serial.println(F("EV_JOINED"));
87 | #ifndef DISABLE_JOIN
88 | {
89 | u4_t netid = 0;
90 | devaddr_t devaddr = 0;
91 | u1_t nwkKey[16];
92 | u1_t artKey[16];
93 | LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
94 | Serial.print("netid: ");
95 | Serial.println(netid, DEC);
96 | Serial.print("devaddr: ");
97 | Serial.println(devaddr, HEX);
98 | Serial.print("artKey: ");
99 | for (size_t i = 0; i < sizeof(artKey); ++i)
100 | {
101 | Serial.print(artKey[i], HEX);
102 | }
103 | Serial.println("");
104 | Serial.print("nwkKey: ");
105 | for (size_t i = 0; i < sizeof(nwkKey); ++i)
106 | {
107 | Serial.print(nwkKey[i], HEX);
108 | }
109 | Serial.println("");
110 | }
111 | // Disable link check validation (automatically enabled
112 | // during join, but because slow data rates change max TX
113 | // size, we don't use it in this example.
114 | LMIC_setLinkCheckMode(0);
115 | #endif
116 | break;
117 | /*
118 | || This event is defined but not used in the code. No
119 | || point in wasting codespace on it.
120 | ||
121 | || case EV_SCAN_FOUND:
122 | || Serial.println(F("EV_SCAN_FOUND"));
123 | || break;
124 | */
125 | case EV_JOIN_FAILED:
126 | Serial.println(F("EV_JOIN_FAILED"));
127 | break;
128 | case EV_REJOIN_FAILED:
129 | Serial.println(F("EV_REJOIN_FAILED"));
130 | break;
131 | case EV_TXCOMPLETE:
132 | Serial.println(F("EV_TXCOMPLETE"));
133 |
134 | if (LMIC.txrxFlags & TXRX_ACK)
135 | {
136 | Serial.println(F("Received ack"));
137 | }
138 |
139 | if (LMIC.dataLen)
140 | {
141 | Serial.print(LMIC.dataLen);
142 | Serial.println(F(" bytes of payload"));
143 | }
144 |
145 | // Schedule next transmission
146 | os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), LoRaWANDo_send);
147 | GO_DEEP_SLEEP = true;
148 |
149 | break;
150 | case EV_LOST_TSYNC:
151 | Serial.println(F("EV_LOST_TSYNC"));
152 | break;
153 | case EV_RESET:
154 | Serial.println(F("EV_RESET"));
155 | break;
156 | case EV_RXCOMPLETE:
157 | // data received in ping slot
158 | Serial.println(F("EV_RXCOMPLETE"));
159 | break;
160 | case EV_LINK_DEAD:
161 | Serial.println(F("EV_LINK_DEAD"));
162 | break;
163 | case EV_LINK_ALIVE:
164 | Serial.println(F("EV_LINK_ALIVE"));
165 | break;
166 | /* This event is defined but not used in the code.
167 | case EV_SCAN_FOUND:
168 | DisplayPrintln(F("EV_SCAN_FOUND"), LORAWAN_STATE_DISPLAY_LINE);
169 | break;
170 | */
171 | case EV_TXSTART:
172 | Serial.println(F("EV_TXSTART"));
173 | break;
174 | case EV_TXCANCELED:
175 | Serial.println(F("EV_TXCANCELED"));
176 | break;
177 | case EV_RXSTART:
178 | /* do not print anything -- it wrecks timing */
179 | break;
180 | case EV_JOIN_TXCOMPLETE:
181 | Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
182 | break;
183 | default:
184 | Serial.print(F("Unknown event: "));
185 | Serial.println((unsigned)ev);
186 | break;
187 | }
188 | }
189 |
190 | void LoRaWANDo(void)
191 | {
192 | if (GO_DEEP_SLEEP == true)
193 | {
194 | PowerDownTXIntervall();
195 | GO_DEEP_SLEEP = false;
196 | }
197 | else
198 | {
199 | os_runloop_once();
200 | }
201 | }
202 |
203 | void LoRaWANGetData()
204 | {
205 | ReadDHTSensor();
206 |
207 | uint8_t vcc = (ReadVcc() / 10) - 200;
208 |
209 | uint8_t humidity_lora = HUMIDITY;
210 |
211 | int16_t temp = (TEMPERATURE * 10);
212 |
213 | if (isnan(TEMPERATURE))
214 | {
215 | LORA_DATA[2] = 255;
216 | LORA_DATA[3] = 255;
217 | }
218 | else
219 | {
220 | LORA_DATA[2] = temp >> 8;
221 | LORA_DATA[3] = temp & 0xFF;
222 | }
223 |
224 | if (isnan(HUMIDITY))
225 | {
226 | LORA_DATA[1] = 255;
227 | }
228 | else
229 | {
230 | float check = HUMIDITY - humidity_lora;
231 | LORA_DATA[1] = humidity_lora;
232 |
233 | // Bit 8 for decimal 1 = 0.5
234 | if (check > 0.251 && check < 0.751)
235 | {
236 | LORA_DATA[1] |= (1 << 7);
237 | }
238 | else if (check > 0.751)
239 | {
240 | LORA_DATA[1] = LORA_DATA[1] + 1;
241 | }
242 | }
243 |
244 | LORA_DATA[0] = vcc;
245 | }
246 |
247 | void LoRaWANVersion()
248 | {
249 | Serial.print(F("LMIC: "));
250 | Serial.print(ARDUINO_LMIC_VERSION_GET_MAJOR(ARDUINO_LMIC_VERSION));
251 | Serial.print(F("."));
252 | Serial.print(ARDUINO_LMIC_VERSION_GET_MINOR(ARDUINO_LMIC_VERSION));
253 | Serial.print(F("."));
254 | Serial.print(ARDUINO_LMIC_VERSION_GET_PATCH(ARDUINO_LMIC_VERSION));
255 | Serial.print(F("."));
256 | Serial.println(ARDUINO_LMIC_VERSION_GET_LOCAL(ARDUINO_LMIC_VERSION));
257 | }
--------------------------------------------------------------------------------
/src/lorawan.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifndef _LORAWAN_H
3 | #define _LORAWAN_H
4 |
5 | #include
6 | #include
7 | #include "lora_credentials.h"
8 |
9 | // This EUI must be in little-endian format, so least-significant-byte
10 | // first. When copying an EUI from ttnctl output, this means to reverse
11 | // the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
12 | // 0x70.
13 | static const u1_t PROGMEM APPEUI[8] = TTN_APPEUI;
14 |
15 | // This should also be in little endian format, see above.
16 | static const u1_t PROGMEM DEVEUI[8] = TTN_DEVEUI;
17 |
18 | // This key should be in big endian format (or, since it is not really a
19 | // number but a block of memory, endianness does not really apply). In
20 | // practice, a key taken from ttnctl can be copied as-is.
21 | static const u1_t PROGMEM APPKEY[16] = TTN_APPKEY;
22 |
23 | static osjob_t sendjob;
24 |
25 | void os_getArtEui(u1_t *buf);
26 | void os_getDevEui(u1_t *buf);
27 | void os_getDevKey(u1_t *buf);
28 |
29 | void LoRaWANSetup(void);
30 | void LoRaWANDo_send(osjob_t *j);
31 | void LoRaWANDo(void);
32 | void LoRaWANGetData(void);
33 | void LoRaWANVersion(void);
34 |
35 | #endif
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "io_pins.h"
3 | #include "functions.h"
4 | #include "lorawan.h"
5 | #include "global.h"
6 | #include "powerdown.h"
7 | #include "version.h"
8 | #include "version_build.h"
9 |
10 | void setup()
11 | {
12 | Serial.begin(115200);
13 | Serial.println(F("Starting DHT ..."));
14 | Serial.println("Sketch: " VERSION_MAJOR "." VERSION_MINOR "." VERSION_PATCH "." BUILD_COMMIT "-" BUILD_BRANCH);
15 | Serial.println("Builddate: " BUILD_DATE " " BUILD_TIME);
16 | PrintResetReason();
17 | LoRaWANVersion();
18 | delay(3000);
19 | DHTSENSOR.setup(PIN_DHT);
20 | PowerDownSetupWatchdog();
21 | Setup_Pins();
22 | Blink_Info_LED();
23 | LoRaWANSetup();
24 | }
25 |
26 | void loop()
27 | {
28 | LoRaWANDo();
29 | }
30 |
--------------------------------------------------------------------------------
/src/powerdown.cpp:
--------------------------------------------------------------------------------
1 | #include "powerdown.h"
2 | #include
3 | #include "settings.h"
4 |
5 | volatile int POWER_DOWN_SLEEP_COUNTER = 0;
6 |
7 |
8 | void PowerDownUpdateMicros()
9 | {
10 | extern volatile unsigned long timer0_overflow_count;
11 | PowerDown();
12 | cli();
13 | // LMIC uses micros() to keep track of the duty cycle, so
14 | // hack timer0_overflow for a rude adjustment:
15 | timer0_overflow_count+= 8 * 64 * clockCyclesPerMicrosecond();
16 | sei();
17 | }
18 |
19 | void PowerDown()
20 | {
21 | ADCSRA &= ~(1<
6 |
7 | void PowerDownUpdateMicros(void);
8 | void PowerDown(void);
9 | void PowerDownSetupWatchdog(void);
10 | void PowerDownTXIntervall(void);
11 |
12 | #endif
--------------------------------------------------------------------------------
/tools/platformio_versioning.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 |
4 | # Optional: Define Path to your local verison of https://github.com/JackGruber/auto_buildnumber
5 | # If it is not located at a position same folder as `platformio_versioning.py`
6 | autoversion = 'C:\\git\\meine\\auto_buildnumber'
7 |
8 | try:
9 | import versioning
10 | autver_ok = True
11 | except:
12 | if os.path.exists(autoversion):
13 | sys.path.insert(0, autoversion)
14 | try:
15 | import versioning
16 | autver_ok = True
17 | except:
18 | autver_ok = False
19 | else:
20 | autver_ok = False
21 |
22 | if autver_ok == True:
23 | versioning.UpdateVersionFile("include/version.h", "DEFINEHEADER", False, "include/version_build.h")
24 |
--------------------------------------------------------------------------------