2019-09-19 03:40:34 +00:00
|
|
|
/*
|
|
|
|
main.cpp - TinyLora BMP280 Firmware
|
|
|
|
Copyright (c) 2019, Stefan Brand
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
|
|
|
list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
3. Neither the name of the copyright holder nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived from
|
|
|
|
this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
#include <Arduino.h>
|
|
|
|
#include <avr/sleep.h>
|
|
|
|
#include <avr/wdt.h>
|
|
|
|
#include "tinySPI.h"
|
|
|
|
#include "LoRaWAN.h"
|
|
|
|
|
2019-09-20 10:16:20 +00:00
|
|
|
|
|
|
|
// secconfig.h Configures TTN Keys and used Sensor
|
2019-09-19 03:40:34 +00:00
|
|
|
#include "secconfig.h"
|
|
|
|
|
2019-09-20 10:16:20 +00:00
|
|
|
#ifdef HAS_BME280
|
|
|
|
#include <BME280.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAS_SHT21
|
|
|
|
#include <SHT21.h>
|
|
|
|
#endif
|
|
|
|
|
2019-09-19 03:40:34 +00:00
|
|
|
// Initialize RFM95W and LoraWAN
|
|
|
|
#define DIO0 PIN_B0
|
|
|
|
#define NSS PIN_B1
|
|
|
|
RFM95 rfm(DIO0,NSS);
|
|
|
|
LoRaWAN lora = LoRaWAN(rfm);
|
2019-09-19 08:40:46 +00:00
|
|
|
uint16_t Frame_Counter_Tx = 0x0000;
|
2019-09-19 03:40:34 +00:00
|
|
|
|
|
|
|
// If set LED will blink when sending
|
|
|
|
#define LED_PIN PIN_A7
|
|
|
|
|
2019-09-20 10:16:20 +00:00
|
|
|
// Sensorclass and deepsleep interval (for measurement about every 10Min)
|
|
|
|
#ifdef HAS_BME280
|
2019-09-19 03:40:34 +00:00
|
|
|
BME280 sensor;
|
2019-09-20 10:16:20 +00:00
|
|
|
#define SLEEP_TIME 528
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAS_SHT21
|
|
|
|
SHT21 sensor;
|
|
|
|
#define SLEEP_TIME 544
|
|
|
|
#endif
|
2019-09-19 03:40:34 +00:00
|
|
|
|
|
|
|
// Global Variable used for deep sleep
|
2019-09-19 08:40:46 +00:00
|
|
|
uint16_t sleep_interval;
|
2019-09-19 03:40:34 +00:00
|
|
|
|
|
|
|
// Setup Wakeup Interrupt Timer
|
|
|
|
void init_wdt()
|
|
|
|
{
|
|
|
|
MCUSR &= ~(1<<WDRF);
|
|
|
|
// Start timed sequence
|
|
|
|
// Set Watchdog Change Enable bit
|
|
|
|
WDTCSR |= (1<<WDCE) | (1<<WDE);
|
2019-09-19 08:40:46 +00:00
|
|
|
// Set new prescaler (8 sec), unset reset enable
|
2019-09-19 03:40:34 +00:00
|
|
|
// enable WDT interrupt
|
2019-09-19 11:49:24 +00:00
|
|
|
WDTCSR = (1<<WDIE)|(1<<WDP3)|(1<<WDP0);
|
2019-09-19 03:40:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Enter Sleepmode, Sleep for s Seconds
|
2019-09-19 08:40:46 +00:00
|
|
|
void sleep(uint16_t s)
|
2019-09-19 03:40:34 +00:00
|
|
|
{
|
2019-09-19 08:40:46 +00:00
|
|
|
s = s/8;
|
2019-09-19 03:40:34 +00:00
|
|
|
sleep_interval = 0;
|
|
|
|
while (sleep_interval < s) {
|
|
|
|
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
|
|
|
sleep_mode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Watchdog Callback for Sleep Timer
|
|
|
|
ISR(WATCHDOG_vect) {
|
|
|
|
sleep_interval++; // set global flag
|
|
|
|
// Start timed sequence
|
|
|
|
// Set Watchdog Change Enable bit
|
|
|
|
WDTCSR |= (1<<WDCE) | (1<<WDE);
|
2019-09-19 08:40:46 +00:00
|
|
|
// Set new prescaler (8 sec), unset reset enable
|
2019-09-19 03:40:34 +00:00
|
|
|
// enable WDT interrupt
|
2019-09-19 11:49:24 +00:00
|
|
|
WDTCSR = (1<<WDIE)|(1<<WDP3)|(1<<WDP0);
|
2019-09-19 03:40:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get Battery Voltage
|
2019-09-19 11:49:24 +00:00
|
|
|
int32_t readVcc() {
|
2019-09-19 03:40:34 +00:00
|
|
|
bitClear(PRR, PRADC);
|
|
|
|
ADCSRA |= bit(ADEN); // Enable the ADC
|
2019-09-19 11:49:24 +00:00
|
|
|
int32_t result;
|
2019-09-19 03:40:34 +00:00
|
|
|
ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84
|
|
|
|
delay(2); // Wait for Vref to settle
|
|
|
|
ADCSRA |= _BV(ADSC); // Convert
|
|
|
|
while (bit_is_set(ADCSRA,ADSC));
|
|
|
|
result = ADCL;
|
|
|
|
result |= ADCH<<8;
|
|
|
|
result = 1126400L / result; // Back-calculate Vcc in mV
|
|
|
|
ADCSRA &= ~ bit(ADEN);
|
|
|
|
bitSet(PRR, PRADC); // Disable the ADC to save power
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setup()
|
|
|
|
{
|
|
|
|
// Initialize Sleep Timer
|
|
|
|
init_wdt();
|
|
|
|
PRR = bit(PRTIM1);
|
|
|
|
|
|
|
|
// Setup LoraWAN
|
|
|
|
rfm.init();
|
|
|
|
lora.setKeys(NwkSkey, AppSkey, DevAddr);
|
|
|
|
|
|
|
|
// Setup LED if defined
|
|
|
|
#ifdef LED_PIN
|
|
|
|
pinMode(LED_PIN, OUTPUT);
|
|
|
|
#endif
|
|
|
|
delay(50);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void loop()
|
|
|
|
{
|
|
|
|
// Buffer to send data
|
|
|
|
int32_t data[4];
|
|
|
|
|
|
|
|
// Get Sensor Data
|
2019-09-20 10:16:20 +00:00
|
|
|
#ifdef HAS_BME280
|
2019-09-19 03:40:34 +00:00
|
|
|
sensor.getData(&data[0], &data[1], &data[2]);
|
2019-09-20 10:16:20 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAS_SHT21
|
|
|
|
data[0] = (int32_t)(sensor.getTemperature()*100);
|
|
|
|
data[1] = 0;
|
|
|
|
data[2] = (int32_t)(sensor.getHumidity()*100);
|
|
|
|
#endif
|
2019-09-19 03:40:34 +00:00
|
|
|
data[3] = readVcc();
|
|
|
|
|
|
|
|
// LED On before Sending
|
|
|
|
#ifdef LED_PIN
|
|
|
|
digitalWrite(LED_PIN, 1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Send LoRa Packet, Increment Frame Counter
|
|
|
|
lora.Send_Data((unsigned char *)data, sizeof(data), Frame_Counter_Tx);
|
|
|
|
Frame_Counter_Tx++;
|
|
|
|
|
|
|
|
// Led Off after Sending
|
|
|
|
#ifdef LED_PIN
|
|
|
|
digitalWrite(LED_PIN, 0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Sleep until next Measurement
|
|
|
|
sleep(SLEEP_TIME);
|
|
|
|
}
|