LoRaBaseBoard - DALLAS Temperatursensor - ARDUINO Programm

Hallo zusammen,
ich bin neu in dem Thema IoT und möchte in diesem Thread meine Bemühungen zur Datenübertragung von DALLAS Temperatur Daten dokumentieren.
In diesem Testprogramm ist eine zusätzliche LED an PIN 9 über ein 220Ohm Widerstand angeschlossen. Zum Testen dient diese LED der Sinalisierung.

Im Wesentlichen handelt es sich um ein Testprogramm von 2018 W.Nijs (ALF4all), welches ich zum Testen angepaßt habe. Die Platine wird ohne externe Watchdogschaltung benutzt. Die CPU legt sich für 8 Sekunden schlafen, wacht auf , schaut ob sie weiterschlafen muss und tut dies ggf.
Nach dem sleep Zyklus wird dann der DALLAS Sensor aus gelesen und die Daten übertragen.

Um zu erkennen, an welcher Programmstelle sich der ARDUINO gerade befindet, wird mit der gelben externen LED geblinkt.

Der node wird im ADP Modus betrieben, ich würde dies gerne mit OTAA ausprobieren und ein serielle EEPROM integrieren.

/* This file has been prepared for Doxygen **************************/

/*! \file Arduino-Pro-Mini_RFM95_abp_DALLAS_powersafe-v2.ino *************
*
* \brief DALLAS 18B20 payload test program for Atmega controllers and the
* Arduino compiler chain with the ONEWIRE library.
*
* The payload for all environment nodes are standardized by:
*  1. node (node identification, 0..255)
*  2. battery (battery voltage [V])
*  3. temperature (environment air temperature [C])
*  4. pressure (environment air pressure [Pa])
*  5. humidity (environment air humidity [%])
*
* Copyright (C) 2018 W.Nijs (ALF4all)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* \author   W.Nijs., modified Frank Ulbrich
* \date     08/11/2018
* \version  0.2 07.9.2019, one wire and external LED
*                           #define BATTERY         A0
*                           no DONE PIN
*********************************************************************/

/* ------------------------------------------------------------------
* Arduino 1.8.3 IDE  
*  Lowpower Library Rocketman
*  LMIC
*  OnwWire
*  DALLASTemperatur
*  
* Arduino 328 / 8MHz Pro Mini
* DALLAS DS18B20 Temperatur Sensor  PIN A2
* Status LED gelb                   PIN 9
* 
---------------------------------------------------------------------*/

/*********************************************************************
* The TTN Payload function is equal for all environment applications
**********************************************************************
function Decoder(bytes, port) {
  var retValue =   { 
    bytes: bytes
  };
  retValue.node = bytes[0];
  retValue.battery = bytes[1] / 10.0;
  retValue.vcc = bytes[2] / 10.0;
  retValue.temperature = (((bytes[3] << 8) | bytes[4]) / 10.0) - 40.0;
  retValue.pressure = ((bytes[5] << 16) | (bytes[6] << 8) | bytes[7]); 
  retValue.humidity = ((bytes[8] << 8) | bytes[9]) / 10.0;
  return retValue; 
}
*********************************************************************/

/*****************************************************************//**
* Include section
*  Add all #includes here.
*********************************************************************/
#include <avr/sleep.h>
#include <avr/wdt.h>
#include "LowPower.h"         //rocketman low-power

#include <Wire.h>
#include <SPI.h>

#include <lmic.h>
#include <hal/hal.h>

#include <OneWire.h>
#include <DallasTemperature.h>

/*****************************************************************//**
* Define section
*  Add all #defines here.
*********************************************************************/
#define ONBOARD_LED     13          // not used, conflict with SCK
//define DONE           17          // switch of node from extern
#define SIG_LED          9          // for test signaling

#define NODE_ID         1           // arduino-v4-fu1
#define PAYLOAD_LENGHT  10          // was 9
#define SEA_LEVEL       100800      // [Pa] 

#define ONE_WIRE_BUS    16          // D16 = ARDUINO A2
#define BATTERY         A0          // analog read

/*****************************************************************//**
* Payload vars and functions for counter, battery and the BME/P-280
*********************************************************************/
float node        = 0;
float battery     = 0;
float vcc         = 0;

OneWire ds18b20(ONE_WIRE_BUS);
DallasTemperature sensors(&ds18b20);

float temperature = 0;
float pressure    = 0;
float humidity    = 0;
float altitude    = 34;                // not used in the payload

unsigned char payload[PAYLOAD_LENGHT]; // Payload


/*****************************************************************//**
* LoRa vars
*********************************************************************/
//int   sleepcycles = 75;  // every sleep cycle takes 8 secs -> 10 min
int   sleepcycles = 38;  // every sleep cycle takes 8 secs =>  5 min
//int   sleepcycles = 8;     // every sleep cycle takes 8 secs => 8x8=64s
bool  joined      = false;
bool  sleeping    = false;

static osjob_t sendjob;

// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
//const unsigned TX_INTERVAL = 60;  // only used with DONE Pin


/*****************************************************************//**
* RFM95 pin mapping section
*  Mapping for the ALF4all iot-lora-v4 PCB
*********************************************************************/
const lmic_pinmap lmic_pins = {
  .nss = 6,
  .rxtx = LMIC_UNUSED_PIN,
  .rst = 5,
  .dio = {2, 3, 4},
};


/********************************************************************
* TTN keys and addresses ADP                node : arduino-v4-fu1
*********************************************************************/
// LoRaWAN NwkSKey, network session key
// Copy from TTN Console MSB first!
static const PROGMEM u1_t NWKSKEY[16] = { 0x76, 0x77, 0x16, 0x03, 0x80, 0x19, 0xEB, 0x88, 0x8A, 0x9B, 0xF2, 0x00, 0x00 0x00, 0x00, 0x00 };

// LoRaWAN AppSKey, application session key
// Copy from TTN Console MSB first!
static const u1_t PROGMEM APPSKEY[16] = { 0x8E, 0x03, 0x4A, 0xAA, 0x93, 0x5B, 0x49, 0xB9, 0x49, 0x81, 0x9B,  0x00, 0x00 0x00, 0x00, 0x00 };

// LoRaWAN end-device address (DevAddr)
static const u4_t DEVADDR = { 0x20000000 }; // <-- Change this address for every node!
// 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) { }


/*****************************************************************//**
* readBattery() ... in the moment no read on A0 pin, static
*********************************************************************/
float readBattery(void) {
  float result = 3.0;

  return (result);      // Return battery voltage in V
};

///*****************************************************************//**
//* readBattery()
//*********************************************************************/
//float readBattery(void) {
//  float sensor = 0;
//  float result = 0;
//
//  sensor = analogRead(BATTERY);
//
//  // 2M, 470K divider across battery and using the internal ADC ref
//  // of 1.1V.
//  // The sense point is bypassed with 100 nF to reduce noise at that
//  // point.
//  // Vmax = ((2e6+470e3)/470e3)*1.1V = 5,78V
//  // Resolution = 5,78/1023 = 5.65mV/bit
//  // Voltage divider current = 3V/2.47M = 1.22uA
//  result  = sensor * 0.00565;
//
//  return result;      // Return battery voltage in V
//};


/*****************************************************************//**
* readVcc()
*********************************************************************/
float readVcc(void) {
  float result = 0;

  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2);                         // Wait for Vref to settle

  ADCSRA |= _BV(ADSC);              // Start conversion
  while (bit_is_set(ADCSRA,ADSC));  // Wait conversion is ready
 
  uint8_t low  = ADCL; // Read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both
  result = (float)((high<<8) | low);
 
  result = 1125300L/result;  // Calculate battery voltage in mV
  return (result/1000);      // Return battery voltage in V
};


/*****************************************************************//**
* getParameters()
*********************************************************************/
void getParameters(void) {
  node        = NODE_ID;
  battery     = readBattery();                    // [V   0.1]
  vcc         = readVcc();                        // [V   0.1]
  sensors.requestTemperatures();  
  temperature = sensors.getTempCByIndex(0);       // [C    0.1]
};


/*****************************************************************//**
* payloadEncode()
* the payload format is equal for all environment applications
*********************************************************************/
void payloadEncode(void) {
  int i = 0;

  // Payload encode algorithm
  // nod [0..255]
  // bat [0.0..5.5V] => bat = bat * 10; => [0..55]
  // tmp [-40..85C] => tmp = tmp + 40; => [0..125] => tmp = tmp * 10; => [0..1250]
  // prs [30000..110000Pa] 
  // hum [0.0..100.0% RH] => hum = hum * 10 => [0..1000]

  unsigned int  nod = (unsigned char)(node); 
  unsigned char bat = (unsigned char)(battery * 10);
  unsigned char vcc = (unsigned char)(vcc * 10);
  unsigned int  tmp = (unsigned int)((temperature + 40.0) * 10.0); 
  unsigned long prs = (unsigned long)(pressure);
  unsigned int  hum = (unsigned int)(humidity * 10);

  payload[i++] = nod;       // nod => 1 byte
  payload[i++] = bat;       // bat => 1 byte
  payload[i++] = vcc;       // vcc => 1 byte
  payload[i++] = tmp >> 8;  // tmp => 2 bytes
  payload[i++] = tmp;
  payload[i++] = prs >> 16; // prs => 3 bytes
  payload[i++] = prs >> 8;
  payload[i++] = prs;
  payload[i++] = hum >> 8;  // hum => 2 bytes
  payload[i++] = hum;
};


/*****************************************************************//**
* parameter_print()
* Only for debugging
*********************************************************************/
void parameterPrint(void) {
  Serial.print("Node id     = ");
  Serial.println(node, 0);

  Serial.print("Battery     = ");
  Serial.print(battery, 1);
  Serial.println(" V");

  Serial.print("Vcc         = ");
  Serial.print(vcc, 1);
  Serial.println(" V");

  Serial.print("Temperature = ");
  Serial.print(temperature, 1);
  Serial.println(" *C");

  Serial.print("Pressure    = ");
  Serial.print((pressure), 0);
  Serial.println(" Pa");

  Serial.print("Humidity    = ");
  Serial.print(humidity, 1);
  Serial.println(" %");

  Serial.print("Altitude    = ");
  Serial.print(altitude, 2);
  Serial.println(" m");
};


/*****************************************************************//**
* payload_print()
* Only for debugging
*********************************************************************/
void payloadPrint(void) {
  int i = 0;
  
  Serial.print("Payload     = ");

  for (i = 0; i < PAYLOAD_LENGHT; i++ ) {
    if (payload[i] < 16)
      Serial.print("0");
    Serial.print(payload[i], HEX);
    Serial.print(" ");
  };
  Serial.println("");
};


/*****************************************************************//**
* onEvent()
*  Event handler
*********************************************************************/
void onEvent (ev_t ev) {
  int i,j;

  Serial.print(os_getTime());
  Serial.print(": ");
  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;
    case EV_TXCOMPLETE:
      sleeping = true;
      if (LMIC.dataLen) {
        // data received in rx slot after tx
        // if any data received, the LED will blink
        // this number of times, with a maximum of 10
        Serial.print(F("Data Received: "));
        Serial.println(LMIC.frame[LMIC.dataBeg],HEX);
        i = (LMIC.frame[LMIC.dataBeg]);
        // i (0..255) can be used as data for any other application
        // like controlling a relay, showing a display message etc.
        if (i>10){
          i=10;     // maximum number of BLINKs
        };
        for(j=0;j<i;j++) {
          digitalWrite(SIG_LED,HIGH);
          delay(500);
          digitalWrite(SIG_LED,LOW);
          delay(500);
        };
      };

      // FUlb 2x Blinken TX ready
      for(int jj=0;jj<2;jj++) {
          digitalWrite(SIG_LED,LOW);
          delay(200);
          digitalWrite(SIG_LED,HIGH);
          delay(200);
          digitalWrite(SIG_LED,LOW);       
        };      
      Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
      delay(50);  // delay to complete Serial Output before Sleeping
      // Schedule next transmission
      // next transmission will take place after next wake-up cycle in main loop
      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;
  };
};


/*****************************************************************//**
* sendMessage()
* 
*********************************************************************/
void sendMessage(osjob_t* j) {
  getParameters();
  parameterPrint(); // Optional, only for debugging
  payloadEncode();
  payloadPrint();   // Optional, only for debugging
  
  // First 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, (uint8_t*)payload, PAYLOAD_LENGHT, 0);
    Serial.println(F("Sending: "));
  };
};


/*****************************************************************//**
* Setup function
*  The setup function runs once when you press reset or power the 
*  board.
*********************************************************************/
void setup() {
  Serial.begin(115200);
  Serial.println(F("=================="));
  Serial.println(F("- TTN 18B20 ABP  -"));
  Serial.println(F("- ALF4all  FUlb  -"));
  Serial.println(F("- ..powersafe_v2 -"));
  Serial.println(F("=================="));
  pinMode(SIG_LED, OUTPUT);   // init ONBOARD_LED as an output.
  digitalWrite(SIG_LED, LOW); // init ONBOARD_LED as LOW

  //pinMode(DONE, OUTPUT);          // init DONE pin as an output.
  //digitalWrite(DONE, LOW);        // init DONE as LOW
  
  // FUlb , blinking 3x
  for(int j=0;j<3;j++) {
          digitalWrite(SIG_LED,HIGH);
          delay(500);
          digitalWrite(SIG_LED,LOW);
          delay(500);
        };
  
  sensors.begin();                // Dallas Sensor

  // 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

  #if defined(CFG_eu868)
    // 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.
    // NA-US channels 0-71 are configured automatically
    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.
  #elif defined(CFG_us915)
    // NA-US channels 0-71 are configured automatically
    // but only one group of 8 should (a subband) should be active
    // TTN recommends the second sub band, 1 in a zero based count.
    // https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json
    LMIC_selectSubBand(1);
  #endif

  // Disable link check validation
  LMIC_setLinkCheckMode(0);

  // TTN uses SF9 for its RX2 window.
  LMIC.dn2Dr = DR_SF9;

  // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library)
  LMIC_setDrTxpow(DR_SF7,14);

  Serial.println(F("Starting loop..."));
  Serial.println();
};


/*****************************************************************//**
* Loop function
*  The loop function runs over and over again forever.
*********************************************************************/

void loop() {

  sendMessage(&sendjob);            // Transmit sensor values
  Serial.println(F("loop, LED on"));
    digitalWrite(SIG_LED,HIGH);     // Set SIG_LED HIGH to on
                                    // indicate start of transmission
  // Shut down alternative
  /* not used
  digitalWrite(DONE, HIGH);         // Set DONE HIGH to shut down power
  */
  //delay(5000);                    // wait 5 seconds (for debugging)
  
  // Sleeping alternative
  while(sleeping == false) {
    //Serial.println(F("loop, runloop"));
    os_runloop_once();
  };
  sleeping = false;
  for (int i=0;i<sleepcycles;i++) {
    Serial.print(F("sleeping: "));
    Serial.println(i);
    delay(50);
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); // sleeps 8s
  };
};
1 Like