Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*******************************************************************************
- * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
- *
- * Permission is hereby granted, free of charge, to anyone
- * obtaining a copy of this document and accompanying files,
- * to do whatever they want with them without any restriction,
- * including, but not limited to, copying, modification and redistribution.
- * NO WARRANTY OF ANY KIND IS PROVIDED.
- *
- * This example sends a valid LoRaWAN packet with payload "Hello,
- * world!", using frequency and encryption settings matching those of
- * the (early prototype version of) The Things Network.
- *
- * Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in g1,
- * 0.1% in g2).
- *
- * Change DEVADDR to a unique address!
- * See http://thethingsnetwork.org/wiki/AddressSpace
- *
- * Do not forget to define the radio type correctly in config.h.
- *
- *******************************************************************************/
- // show debug statements; comment next line to disable debug statements
- #define DEBUG
- //start merge lowpower
- #define SLEEP
- #ifdef SLEEP
- #include "LowPower.h"
- bool next = true;
- #endif
- //end merge lowpower
- #include <lmic.h>
- #include <hal/hal.h>
- #include <SPI.h>
- #include <OneWire.h>
- // LoRaWAN NwkSKey, network session key
- // This is the default Semtech key, which is used by the prototype TTN
- // network initially.
- static const PROGMEM u1_t NWKSKEY[16] = { KEY HERE };
- // LoRaWAN AppSKey, application session key
- // This is the default Semtech key, which is used by the prototype TTN
- // network initially.
- static const u1_t PROGMEM APPSKEY[16] = { KEY HERE };
- // LoRaWAN end-device address (DevAddr)
- // See http://thethingsnetwork.org/wiki/AddressSpace
- static const u4_t DEVADDR = KEY HERE;
- // These callbacks are only used in over-the-air activation, so they are
- // left empty here (we cannot leave them out completely unless
- // DISABLE_JOIN is set in config.h, otherwise the linker will complain).
- void os_getArtEui (u1_t* buf) { }
- void os_getDevEui (u1_t* buf) { }
- void os_getDevKey (u1_t* buf) { }
- static osjob_t sendjob;
- // Schedule TX every this many seconds (might become longer due to duty
- // cycle limitations).
- const unsigned TX_INTERVAL = 60;
- // Pin mapping
- const lmic_pinmap lmic_pins = {
- .nss = 10,
- .rxtx = LMIC_UNUSED_PIN,
- .rst = 9,
- .dio = {2, 6, 7},
- };
- // DS18S20 Temperature chip i/o
- OneWire ds(5); // on pin 10
- void onEvent (ev_t ev) {
- switch(ev) {
- case EV_SCAN_TIMEOUT:
- Serial.println(F("EV_SCAN_TIMEOUT"));
- break;
- case EV_BEACON_FOUND:
- Serial.println(F("EV_BEACON_FOUND"));
- break;
- case EV_BEACON_MISSED:
- Serial.println(F("EV_BEACON_MISSED"));
- break;
- case EV_BEACON_TRACKED:
- Serial.println(F("EV_BEACON_TRACKED"));
- break;
- case EV_JOINING:
- Serial.println(F("EV_JOINING"));
- break;
- case EV_JOINED:
- Serial.println(F("EV_JOINED"));
- break;
- case EV_RFU1:
- Serial.println(F("EV_RFU1"));
- break;
- case EV_JOIN_FAILED:
- Serial.println(F("EV_JOIN_FAILED"));
- break;
- case EV_REJOIN_FAILED:
- Serial.println(F("EV_REJOIN_FAILED"));
- break;
- break;
- case EV_TXCOMPLETE:
- Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
- if(LMIC.dataLen) {
- // data received in rx slot after tx
- Serial.print(F("Data Received: "));
- Serial.write(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
- Serial.println();
- }
- // Schedule next transmission
- // start merge lowpower
- // os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); // disabled for merge
- #ifndef SLEEP
- os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
- #else
- next = true;
- #endif
- // end merge lowpower
- break;
- case EV_LOST_TSYNC:
- Serial.println(F("EV_LOST_TSYNC"));
- break;
- case EV_RESET:
- Serial.println(F("EV_RESET"));
- break;
- case EV_RXCOMPLETE:
- // data received in ping slot
- Serial.println(F("EV_RXCOMPLETE"));
- break;
- case EV_LINK_DEAD:
- Serial.println(F("EV_LINK_DEAD"));
- break;
- case EV_LINK_ALIVE:
- Serial.println(F("EV_LINK_ALIVE"));
- break;
- default:
- Serial.println(F("Unknown event"));
- break;
- }
- }
- void do_send(osjob_t* j){
- float celsius = GetTemp();
- Serial.print("Temperature: ");
- Serial.println(celsius);
- //only send when no error condition 995 before
- if (celsius <= 1000) {
- int16_t temp = int16_t(celsius * 100);
- uint8_t data[3];
- data[0] = 0x00; //first byte is send as 00 to recognise this is a temperature
- data[1] = temp >> 8;
- data[2] = temp & 0xFF;
- #ifdef DEBUG
- byte i;
- Serial.print("data send =");
- for( i = 0; i < sizeof(data); i++) {
- Serial.write(' ');
- Serial.print(data[i], HEX);
- }
- Serial.println();
- #endif
- // Check if there is not a current TX/RX job running
- if (LMIC.opmode & OP_TXRXPEND) {
- Serial.println(F("OP_TXRXPEND, not sending"));
- } else {
- // Prepare upstream data transmission at the next possible time.
- LMIC_setTxData2(1, data, sizeof(data), 0);
- Serial.println(F("Packet queued"));
- }
- } else {
- Serial.print("Error reading sensor: ");
- Serial.println(celsius);
- }
- }
- void setup() {
- Serial.begin(9600);
- Serial.println(F("Starting ....."));
- #ifdef DEBUG
- float A = GetTemp();
- Serial.print("Temp during setup: ");
- Serial.println(A);
- #endif
- #ifdef VCC_ENABLE
- // For Pinoccio Scout boards
- pinMode(VCC_ENABLE, OUTPUT);
- digitalWrite(VCC_ENABLE, HIGH);
- delay(1000);
- #endif
- // LMIC init
- os_init();
- // Reset the MAC state. Session and pending data transfers will be discarded.
- LMIC_reset();
- // Set static session parameters. Instead of dynamically establishing a session
- // by joining the network, precomputed session parameters are be provided.
- #ifdef PROGMEM
- // On AVR, these values are stored in flash and only copied to RAM
- // once. Copy them to a temporary buffer here, LMIC_setSession will
- // copy them into a buffer of its own again.
- uint8_t appskey[sizeof(APPSKEY)];
- uint8_t nwkskey[sizeof(NWKSKEY)];
- memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
- memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
- LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
- #else
- // If not running an AVR with PROGMEM, just use the arrays directly
- LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
- #endif
- // Set up the channels used by the Things Network, which corresponds
- // to the defaults of most gateways. Without this, only three base
- // channels from the LoRaWAN specification are used, which certainly
- // works, so it is good for debugging, but can overload those
- // frequencies, so be sure to configure the full frequency range of
- // your network here (unless your network autoconfigures them).
- // Setting up channels should happen after LMIC_setSession, as that
- // configures the minimal channel set.
- LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
- LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band
- LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
- LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
- LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
- LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
- LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
- LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
- LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band
- // TTN defines an additional channel at 869.525Mhz using SF9 for class B
- // devices' ping slots. LMIC does not have an easy way to define set this
- // frequency and support for class B is spotty and untested, so this
- // frequency is not configured here.
- // Disable link check validation
- LMIC_setLinkCheckMode(0);
- // Set data rate and transmit power (note: txpow seems to be ignored by the library)
- LMIC_setDrTxpow(DR_SF7,14);
- // Start job
- do_send(&sendjob);
- }
- // start merge lowpower (replaced the std loop())
- void loop() {
- #ifndef SLEEP
- os_runloop_once();
- #else
- if (next == false) {
- os_runloop_once();
- } else {
- int sleepcycles = TX_INTERVAL / 8; // calculate the number of sleepcycles (8s) given the TX_INTERVAL
- #ifdef DEBUG
- Serial.print(F("Enter sleeping for "));
- Serial.print(sleepcycles);
- Serial.println(F(" cycles of 8 seconds"));
- #endif
- delay(1000); // give the serial print chance to complete
- for (int i=0; i<sleepcycles; i++) {
- // Enter power down state for 8 s with ADC and BOD module disabled
- LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
- //LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);
- }
- #ifdef DEBUG
- Serial.println(F("Sleep complete"));
- #endif
- next = false;
- // Start job
- do_send(&sendjob);
- }
- #endif
- } //added to mail, mq
- // end merge lowpower
- float GetTemp()
- {
- byte i;
- byte present = 0;
- byte type_s;
- byte data[12];
- byte addr[8];
- float celsius, fahrenheit;
- #ifdef DEBUG
- Serial.println(" ");
- Serial.println("GetTemp function");
- #endif
- ds.reset_search();
- if ( !ds.search(addr)) {
- Serial.println("No more addresses.");
- ds.reset_search();
- delay(250);
- return(999);
- }
- #ifdef DEBUG
- Serial.print("ROM =");
- for( i = 0; i < 8; i++) {
- Serial.write(' ');
- Serial.print(addr[i], HEX);
- }
- if (OneWire::crc8(addr, 7) != addr[7]) {
- Serial.println("CRC is not valid!");
- return(998);
- }
- Serial.println();
- #endif
- // the first ROM byte indicates which chip
- switch (addr[0]) {
- case 0x10:
- #ifdef DEBUG
- Serial.println(" Chip = DS18S20"); // or old DS1820
- #endif
- type_s = 1;
- break;
- case 0x28:
- #ifdef DEBUG
- Serial.println(" Chip = DS18B20");
- #endif
- type_s = 0;
- break;
- case 0x22:
- #ifdef DEBUG
- Serial.println(" Chip = DS1822");
- #endif
- type_s = 0;
- break;
- default:
- #ifdef DEBUG
- Serial.println(" Device is not a DS18x20 family device.");
- #endif
- return(997);
- }
- ds.reset();
- ds.select(addr);
- ds.write(0x44, 1); // start conversion, with parasite power on at the end
- delay(1000); // maybe 750ms is enough, maybe not
- // we might do a ds.depower() here, but the reset will take care of it.
- present = ds.reset();
- ds.select(addr);
- ds.write(0xBE); // Read Scratchpad
- #ifdef DEBUG
- Serial.print(" Data = ");
- Serial.print(present, HEX);
- Serial.print(" ");
- #endif
- for ( i = 0; i < 9; i++) { // we need 9 bytes
- data[i] = ds.read();
- #ifdef DEBUG
- Serial.print(data[i], HEX);
- Serial.print(" ");
- #endif
- }
- #ifdef DEBUG
- Serial.print(" CRC=");
- Serial.print(OneWire::crc8(data, 8), HEX);
- Serial.println();
- #endif
- // Convert the data to actual temperature
- // because the result is a 16 bit signed integer, it should
- // be stored to an "int16_t" type, which is always 16 bits
- // even when compiled on a 32 bit processor.
- int16_t raw = (data[1] << 8) | data[0];
- if (type_s) {
- raw = raw << 3; // 9 bit resolution default
- if (data[7] == 0x10) {
- // "count remain" gives full 12 bit resolution
- raw = (raw & 0xFFF0) + 12 - data[6];
- }
- } else {
- byte cfg = (data[4] & 0x60);
- // at lower res, the low bits are undefined, so let's zero them
- if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
- else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
- else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
- //// default is 12 bit resolution, 750 ms conversion time
- }
- celsius = (float)raw / 16.0;
- return celsius;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement