KeHoSoftware
Published © GPL3+

M5Stack COM. LoRaWAN Using Arduino IDE

M5Stack recently released an updated LoRaWAN module. This tutorial teaches you how to connect it to The Things Network using Arduino IDE.

AdvancedFull instructions provided3 hours1,497
M5Stack COM. LoRaWAN Using Arduino IDE

Things used in this project

Hardware components

M5GO IoT Starter Kit
M5Stack M5GO IoT Starter Kit
×1
M5Stack COM.LoRaWAN Module 868MHz (ASR6501)
×1
ENV II Unit with Temperature Humidity Pressure Sensor(SHT30+BMP280)
M5Stack ENV II Unit with Temperature Humidity Pressure Sensor(SHT30+BMP280)
×1
PIR Sensor Human Body Infrared PIR Motion Sensor (AS312)
M5Stack PIR Sensor Human Body Infrared PIR Motion Sensor (AS312)
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

M5Stack Core TTN SensorNode MOV Video

M5Stack Core with TTN connection and how to mount sensors with LEGO

Code

M5Stack_CORE_TTN_SensorNode_V1_03.ino

Arduino
main source code
/****************************************************************************
**                                                                         **
** Name:        M5_Stack_CORE_TTN_SensorNode.ino                           **
** Author:      Achim Kern                                                 **
** Interpreter: Arduino IDE 1.8.13                                         **
** Licence:     Freeware                                                   **
** Function:    Main Program                                               **
**                                                                         **
** Notes:       based on idea from SEEED STUDIO and LCARS SmartHome        **
**                                                                         **
** History:                                                                **
**                                                                         **
** 1.00        - 24.01.2021 - initial release                              **
**                          - TTN joined                                   **
** 1.01        - 25.01.2021 - ENVII unit implemented                       **                
**                          - NeoPixel implemented                         **
**                          - battery level implemented                    **                          
**                          - TTN payload defined                          **                          
**                          - PIR Motion sensor - display on/off           **                          
**                          - sensor data on screen display                **
** 1.02        - 26.01.2020 - show jpg pictures on booting                 **                          
** 1.03        - 27.01.2021 - TTN access codes                             **
**                                                                         **
*****************************************************************************

/*
 * Application and Version
 */
   const char* application  = "M5STACK_CORE_TTN_SensorNode";
   const char* aktu_version = "1.03";

/*
 * M5 STACK TFT Display
 * 
 */
   // we need these libraries, defines, variables
   #include <M5Stack.h>
   // we use special fonts
   #include "Free_Fonts.h"
   // tft backlight - on/off button 1 - on/off after 1 minute
   bool tft_backlight = true; 
   // screen off counter 
   int tft_counter=0;
   // pictures on the sd card
   String iot_picture="";

/*
 * M5 STACK RGB NeoPixels
 * 
 */
   // we need these libraries, defines, variables   
   #include <Adafruit_NeoPixel.h>
   #define M5STACK_FIRE_NEO_NUM_LEDS 10
   #define M5STACK_FIRE_NEO_DATA_PIN 15
   Adafruit_NeoPixel pixels = Adafruit_NeoPixel(M5STACK_FIRE_NEO_NUM_LEDS, M5STACK_FIRE_NEO_DATA_PIN, NEO_GRB + NEO_KHZ800);   

 /*
 * ENVII M5Stack Unit I2C Pressure & Temperature & Humidity Sensor
 * ---------------------------------------------------------------
 * ENV II is an environment sensor which can sense temperature, humidity and atmospheric pressure. 
 * It is built with SHT30 and BMP280 sensors and is programmed over I2C. 
 * SHT30 is a digital temperature and humidity sensor with high precision and low power consumption. 
 * BMP280 is an absolute barometric pressure sensor which is especially designed for mobile applications. 
 * It offers the highest flexibility to optimize the device regarding power consumption, resolution and filter performance.
 * 
 */
   // Enable/disable sensor measurements if you want to
   #define ENABLE_SENSOR_ENVII
   // Sensors enabled, but not found in the hardware will be ignored
   #ifdef ENABLE_SENSOR_ENVII
     #include <M5Stack.h>
     #include <Wire.h>
     #include "Adafruit_Sensor.h"
     #include <Adafruit_BMP280.h>
     #include "SHT3X.h"
     SHT3X sht30;
     Adafruit_BMP280 bme;
     float env2_tmp = 0.0;
     float env2_hum = 0.0;
     float env2_pressure = 0.0;
     /*-----------------------------------------*/
     /* Function void sensor_env2()             */
     /*                                         */
     /* TASK    : read out env2 sensor data     */
     /* UPDATE  : 04.11.2020                    */
     /*-----------------------------------------*/   
     void sensor_env2(void)
     {
       // read the sensor
       env2_pressure = bme.readPressure();
       env2_pressure = env2_pressure/100;
       if(sht30.get()==0)
       {
         env2_tmp = sht30.cTemp-1;
         env2_hum = sht30.humidity+5;
       }   
     }     
   #endif

/*
 * GROVE UNIT PIR Motion Sensor
 * ----------------------------
 * This sensor allows you to sense motion, usually human movement in its range. Simply connect it and program it, 
 * when anyone moves in its detecting range, the sensor will output HIGH on its SIG pin.
 *
 */
   // Enable/disable sensor measurements if you want to
   #define ENABLE_SENSOR_PIR_MOTION
   // Sensors enabled, but not found in the hardware will be ignored
   #ifdef ENABLE_SENSOR_PIR_MOTION
     #define PIR_MOTION_SENSOR 36 
     bool MOTION=false;
   #endif

/*
 * connected sensor data place holders
 */
   // m5stack-core-01
   #define M5STACK 0
   int m5stack_temp  = 0;
   int m5stack_humi  = 0;
   int m5stack_press = 0;
   int m5stack_bat   = 0;

/*   
 * TTN OTAA access data 
 * we must use this in the setup() 
 */
  // DevEui=XXXXXXXXXXXXXXXX(For OTAA Mode)
  // DevEui="XXXXXXXXXXXXXXXX";
   
  // AppEui=XXXXXXXXXXXXXXXX(For OTAA Mode)
  // always the same if equal devices
  // AppEui = "XXXXXXXXXXXXXXXX";
   
  // AppKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(For OTAA Mode)
  // AppKey="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; 
   
   // ttn counter send frequence - used in loop()
   int TTNCounter=0;
      
/*
 * Generally, you should use "unsigned long" for variables that hold time
 * The value will quickly become too large for an int to store
 */
   // this timer is used to update tft display and mqtt data send frequence
   unsigned long previousMillis = 0;
   // every 10 minutes
   // unsigned long interval = 600000;  
   // every 3 minutes
   // unsigned long interval = 180000;
   // every 30 seconds
   unsigned long interval = 30000;   
   unsigned long counter  = 0;

/*-------------------------------------------------------------------------------*/
/* Function void ATCommand(char cmd[],char date[], uint32_t timeout = 50)        */
/*                                                                               */
/* TASK    : send AT commands to the M5Stack COM.LoRaWAN Module                  */
/* UPDATE  : 24.01.2021                                                          */
/*-------------------------------------------------------------------------------*/
void ATCommand(char cmd[],char date[], uint32_t timeout = 50)
{
  char buf[256] = {0};
  if(date == NULL)
  {
    sprintf(buf,"AT+%s",cmd);
  }
  else 
  {
    sprintf(buf,"AT+%s=%s",cmd,date); 
  }
  Serial2.write(buf);
  delay(200);
  ReceiveAT(timeout);
}

/*-------------------------------------------------------------------------------*/
/* Function bool ReceiveAT(uint32_t timeout)                                     */
/*                                                                               */
/* TASK    : receive AT msg's from the M5Stack COM.LoRaWAN Module                */
/* UPDATE  : 24.01.2021                                                          */
/*-------------------------------------------------------------------------------*/
bool ReceiveAT(uint32_t timeout)
{
  uint32_t nowtime = millis();
  while(millis() - nowtime < timeout){
    if (Serial2.available() !=0) {
      String str = Serial2.readString();
      if (str.indexOf("+OK") != -1 || str.indexOf("+ERROR") != -1) {
        Serial.println(str);
        return true;
      }else {
        Serial.println("[!] Syntax Error");
        break;
      }
    }
  }
  Serial.println("[!] Timeout");
  return false;
}

/*-------------------------------------------------------------------------------*/
/* Function void rgb_neopixel(String color)                                      */
/*                                                                               */
/* TASK    : show rgb neopixels (co2 ampel)                                      */
/* UPDATE  : 07.10.2020                                                          */
/*-------------------------------------------------------------------------------*/
void rgb_neopixel(int r,int g,int b)  
{
  // right side
  if (tft_backlight == true)
  {
    pixels.setPixelColor(0, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    pixels.setPixelColor(1, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    pixels.setPixelColor(2, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    pixels.setPixelColor(3, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    pixels.setPixelColor(4, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    // left side
    pixels.setPixelColor(5, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    pixels.setPixelColor(6, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    pixels.setPixelColor(7, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    pixels.setPixelColor(8, pixels.Color(r,g,b));
    pixels.show(); delay(200);
    pixels.setPixelColor(9, pixels.Color(r,g,b));
    pixels.show(); delay(200);
  }  
}

/*-------------------------------------------------------------------------------*/
/* Function void rgb_neopixel_on(String color)                                   */
/*                                                                               */
/* TASK    : show rgb neopixels immediately                                      */
/* UPDATE  : 07.10.2020                                                          */
/*-------------------------------------------------------------------------------*/
void rgb_neopixel_on(int r,int g,int b)  
{
  // right side
  pixels.setPixelColor(0, pixels.Color(r,g,b));
  pixels.setPixelColor(1, pixels.Color(r,g,b));
  pixels.setPixelColor(2, pixels.Color(r,g,b));
  pixels.setPixelColor(3, pixels.Color(r,g,b));
  pixels.setPixelColor(4, pixels.Color(r,g,b));
  // left side
  pixels.setPixelColor(5, pixels.Color(r,g,b));
  pixels.setPixelColor(6, pixels.Color(r,g,b));
  pixels.setPixelColor(7, pixels.Color(r,g,b));
  pixels.setPixelColor(8, pixels.Color(r,g,b));
  pixels.setPixelColor(9, pixels.Color(r,g,b));
  pixels.show(); 
}

/*-------------------------------------------------------------------------------*/
/* Function void rgb_neopixel_off()                                              */
/*                                                                               */
/* TASK    : rgb neopixels off                                                   */
/* UPDATE  : 18.11.2020                                                          */
/*-------------------------------------------------------------------------------*/
void rgb_neopixel_off()  
{
  // right side
  pixels.setPixelColor(0, pixels.Color(0,0,0));
  pixels.setPixelColor(1, pixels.Color(0,0,0));
  pixels.setPixelColor(2, pixels.Color(0,0,0));
  pixels.setPixelColor(3, pixels.Color(0,0,0));
  pixels.setPixelColor(4, pixels.Color(0,0,0));
  // left side
  pixels.setPixelColor(5, pixels.Color(0,0,0));
  pixels.setPixelColor(6, pixels.Color(0,0,0));
  pixels.setPixelColor(7, pixels.Color(0,0,0));
  pixels.setPixelColor(8, pixels.Color(0,0,0));
  pixels.setPixelColor(9, pixels.Color(0,0,0));
  pixels.show(); 
}

/*-------------------------------------------------------------------------------*/
/* Function void array_to_string(byte array[], unsigned int len, char buffer[])  */
/*                                                                               */
/* TASK    : build string out of payload data                                    */
/* UPDATE  : 24.01.2021                                                          */
/*-------------------------------------------------------------------------------*/
void array_to_string(byte array[], unsigned int len, char buffer[])
{
  for (unsigned int i = 0; i < len; i++)
  {
    byte nib1 = (array[i] >> 4) & 0x0F;
    byte nib2 = (array[i] >> 0) & 0x0F;
    buffer[i*2+0] = nib1  < 0xA ? '0' + nib1  : 'A' + nib1  - 0xA;
    buffer[i*2+1] = nib2  < 0xA ? '0' + nib2  : 'A' + nib2  - 0xA;
  }
  buffer[len*2] = '\0';
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_room_screen(String room_name, long int room_bg)     */
/*                                                                               */
/* TASK    : show tft display room screen                                        */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_room_screen(String room_name, long int room_bg) 
{
  M5.Lcd.fillScreen(TFT_WHITE);
  M5.Lcd.fillRect(0,0,320,50,room_bg);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.setTextColor(TFT_WHITE);
  M5.Lcd.setCursor((320 - M5.Lcd.textWidth(room_name)) / 2, 32);
  M5.Lcd.print(room_name); 
  // drawing verticle line
  M5.Lcd.drawFastVLine(150,50,190,TFT_DARKGREEN);
  // drawing horizontal line
  M5.Lcd.drawFastHLine(0,140,320,TFT_DARKGREEN);
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_status_bar(String room_name, long int room_bg)      */
/*                                                                               */
/* TASK    : show tft display status bar                                         */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_status_bar(String room_name, long int room_bg) 
{
  M5.Lcd.fillRect(0,0,320,50,room_bg);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.setTextColor(TFT_WHITE);
  M5.Lcd.setCursor((320 - M5.Lcd.textWidth(room_name)) / 2, 32);
  M5.Lcd.print(room_name); 
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_sensor_temperature(void)                            */
/*                                                                               */
/* TASK    : show tft display sensor temperature                                 */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_sensor_temperature(int temperature) 
{
  // setting the temperature
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB9);
  M5.Lcd.drawString("Temperature",15,65);
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.drawNumber(temperature,50,95);
  M5.Lcd.setFreeFont(FMB12);
  M5.Lcd.drawString("C",100,95);  
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_update_temperature(void)                            */
/*                                                                               */
/* TASK    : show tft display update temperature                                 */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_update_temperature(int temperature) 
{
  // setting the temperature
  M5.Lcd.fillRect(50,95,50,30,WHITE);
  M5.Lcd.setTextColor(BLACK);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.drawNumber(temperature,50,95);
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_sensor_humidity(int humidity)                       */
/*                                                                               */
/* TASK    : show tft display sensor humidity                                    */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_sensor_humidity(int humidity) 
{
  // setting the humidity
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB9);
  M5.Lcd.drawString("Humidity",30,160);
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.drawNumber(humidity,50,190);
  M5.Lcd.setFreeFont(FMB12);
  M5.Lcd.drawString("%",100,190);
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_update_humidity(void)                               */
/*                                                                               */
/* TASK    : show tft display update humidity                                    */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_update_humidity(int humidity) 
{
  // setting the humidity
  M5.Lcd.fillRect(50,190,50,30,TFT_WHITE);
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.drawNumber(humidity,50,190);
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_sensor_pressure(int pressure)                       */
/*                                                                               */
/* TASK    : show tft display sensor pressure                                    */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_sensor_pressure(int pressure) 
{
  // setting the pressure
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB9);
  M5.Lcd.drawString("Pressure",190,65);
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.drawNumber(pressure,160,95);
  M5.Lcd.setFreeFont(FMB12);
  M5.Lcd.drawString("mBar",250,95);
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_update_pressure(void)                               */
/*                                                                               */
/* TASK    : show tft display update pressure                                    */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_update_pressure(int pressure) 
{
  // setting the pressure
  M5.Lcd.fillRect(160,95,85,30,TFT_WHITE);
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.drawNumber(pressure,160,95);
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_sensor_battery(int battery)                         */
/*                                                                               */
/* TASK    : show tft display sensor battery                                     */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_sensor_battery(int battery) 
{ 
  // setting the battery power
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB9);
  M5.Lcd.drawString("Battery",200,160);
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.drawNumber(battery,200,190);
  M5.Lcd.setFreeFont(FMB12);
  M5.Lcd.drawString("%",280,190);
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_update_battery(int battery)                         */
/*                                                                               */
/* TASK    : show tft display update heating                                     */
/* UPDATE  : 22.09.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_update_battery(int battery) 
{
  // setting the battery
  M5.Lcd.fillRect(160,190,105,30,TFT_WHITE);
  M5.Lcd.setTextColor(TFT_BLACK);
  M5.Lcd.setFreeFont(FMB18);
  M5.Lcd.drawNumber(battery,200,190);
}

/*-------------------------------------------------------------------------------*/
/* Function void tft_display_m5stack(void)                                       */
/*                                                                               */
/* TASK    : show tft display m5stack (this m5stack)                             */
/* UPDATE  : 10.12.2020                                                          */
/*-------------------------------------------------------------------------------*/
void tft_display_m5stack(void) 
{
  // display room screen
  tft_display_room_screen("M5STACK-CORE-2",BLUE); 
  // display temperature sensor
  tft_display_sensor_temperature(m5stack_temp);
  // display humidity sensor
  tft_display_sensor_humidity(m5stack_humi); 
  // display pressure sensor
  tft_display_sensor_pressure(m5stack_press); 
  // display battery sensor
  tft_display_sensor_battery(m5stack_bat);
}

/*-------------------------------------------------------------------------------*/
/* Function void send_to_TTN(void)                                               */
/*                                                                               */
/* TASK    : send sensor data to TTN                                             */
/* UPDATE  : 25.01.2021                                                          */
/*-------------------------------------------------------------------------------*/
void send_to_TTN(void) 
{  
  // show picture
  iot_picture="/ttn.jpg";
  M5.Lcd.drawJpgFile(SD, iot_picture.c_str());
  
  // neopixels red
  rgb_neopixel(255,0,0);

  // activate communication
  Serial.println("LoraSet=?");  
  ATCommand("LoraSet", "?");
  delay(500);
  
  Serial.println(F(" "));
  Serial.print(F(application)); Serial.print(F(" Version ")); Serial.println(F(aktu_version));
  Serial.println(F(" "));

  // check if we can access battery functions
  if(!M5.Power.canControl())
  {
    Serial.println(F("[!] No communication with IP5306 chip"));
  }

  // actual battery level
  uint8_t bat = M5.Power.getBatteryLevel();
  Serial.print(F("[?] M5STACK BATTERY LEVEL --> "));
  Serial.print(bat);
  Serial.println(F(" %"));
  m5stack_bat=bat;
  int32_t battery_int = bat * 100; 
    
  #ifdef ENABLE_SENSOR_ENVII     
    sensor_env2();
    m5stack_temp=env2_tmp;
    m5stack_humi=env2_hum;
    m5stack_press=env2_pressure;
    Serial.print(F("[?] M5STACK Unit ENVII --> "));
    Serial.print("ENVII-P:"); Serial.print(env2_pressure); 
    Serial.print("  ENVII-T:"); Serial.print(env2_tmp);  
    Serial.print("  ENVII-H:"); Serial.println(env2_hum);                 
  #endif

  // now we create the payload and send it to the TTN
  int32_t temp_int      = env2_tmp * 100;
  int32_t pressure_int  = env2_pressure * 100;
  int32_t hum_int       = env2_hum * 100;

  byte payload[12];
  payload[0] = temp_int;
  payload[1] = temp_int >> 8;
  payload[2] = temp_int >> 16;

  payload[3] = hum_int;
  payload[4] = hum_int >> 8;
  payload[5] = hum_int >> 16;

  payload[6] = pressure_int;
  payload[7] = pressure_int >> 8;
  payload[8] = pressure_int >> 16;
    
  payload[9]  = battery_int;
  payload[10] = battery_int >> 8;
  payload[11] = battery_int >> 16;

  Serial.print(F("[x] actual TTN payload --> "));
  char str[32] = "";
  array_to_string(payload, 12, str);
  Serial.println(str);

  // now send all to TTN
  ATCommand("SendHex", str); 
  // neopixels now off
  rgb_neopixel_off();
  // display sensor data
  tft_display_m5stack();       
}

/*-------------------------------------------------------------------------------*/
/* Function void setup()                                                         */
/*                                                                               */
/* TASK    : setup all needed requirements                                       */
/* UPDATE  : 24.01.2021                                                          */
/*-------------------------------------------------------------------------------*/
void setup() 
{
  // initialize the M5Stack object
  M5.begin();

  /*
    Power chip connected to gpio21, gpio22, I2C device
    Set battery charging voltage and current
    If used battery, please call this function in your project
  */
  M5.Power.begin();

  // open serial monitor
  Serial.begin(115200);
  
  // activate the NeoPixels
  pixels.begin();
  rgb_neopixel(0,0,0);

  // boot application
  delay(3000);
  Serial.println(F(" "));
  Serial.println(F(" "));
  Serial.println(F("Starting..."));
  Serial.print(F(application)); Serial.print(F(" Version ")); Serial.println(F(aktu_version));
  Serial.println(F("connected via TTN Stuttgart"));
  Serial.println(F(" ")); 

  M5.Lcd.fillScreen(TFT_RED);
  M5.Lcd.setFreeFont(FMB12);
  M5.Lcd.setTextColor(TFT_WHITE);
  M5.Lcd.setCursor((320 - M5.Lcd.textWidth("M5Stack CORE")) / 2, 100);
  M5.Lcd.print("M5Stack CORE");
  M5.Lcd.setCursor((320 - M5.Lcd.textWidth("TTN SensorNode")) / 2, 120);
  M5.Lcd.print("TTN SensorNode");
  M5.Lcd.setCursor((320 - M5.Lcd.textWidth("Version x.xx")) / 2, 140);
  M5.Lcd.print("Version ");
  M5.Lcd.print(aktu_version);
  delay(6000);

  // SD card
  M5.Lcd.fillScreen(TFT_NAVY);
  M5.Lcd.setFreeFont(FMB12);
  M5.Lcd.setTextColor(TFT_YELLOW);
  M5.Lcd.setCursor((320 - M5.Lcd.textWidth("SD card initialize..")) / 2, 120);
  M5.Lcd.print("SD card initialize..");
  delay(2000);
  // check if we have a sd card inserted
  if (!SD.begin()) 
  {
    Serial.println("[!] SD Card failed, or not present");
    while (1);
  }
  Serial.println("[x] SD Card initialized.");

  // Lcd display 
  M5.Lcd.setBrightness(255); 

  // show iot picture
  iot_picture="/iot.jpg";
  M5.Lcd.drawJpgFile(SD, iot_picture.c_str());
  delay(2000);

  // activate the FIRE NeoPixels blue
  rgb_neopixel(0,0,255);

  // actual battery level
  uint8_t bat = M5.Power.getBatteryLevel();
  Serial.print(F("[?] M5STACK BATTERY LEVEL --> "));
  Serial.print(bat);
  Serial.println(F(" %"));
  m5stack_bat=bat;  

  #ifdef ENABLE_SENSOR_ENVII
    // show picture
    iot_picture="/unit_env2.jpg";
    M5.Lcd.drawJpgFile(SD, iot_picture.c_str());
    delay(2000);  
    Wire.begin();
    while (!bme.begin(0x76))
    {
      Serial.println(F("[!] Could not find a valid BMP280 sensor, check wiring!"));
    }
    Serial.println(F("[x] GROVE ENVII Sensor detected"));
    // read the env2 sensor */
    sensor_env2();
    m5stack_temp=env2_tmp;
    m5stack_humi=env2_hum;
    m5stack_press=env2_pressure;
    Serial.print(F("[?] M5STACK UNIT ENVII --> "));
    Serial.print("ENVII-P:"); Serial.print(env2_pressure); 
    Serial.print("  ENVII-T:"); Serial.print(env2_tmp);  
    Serial.print("  ENVII-H:"); Serial.println(env2_hum);  
  #endif

  #ifdef ENABLE_SENSOR_PIR_MOTION
    // show picture
    iot_picture="/unit_pir.jpg";
    M5.Lcd.drawJpgFile(SD, iot_picture.c_str());
    delay(2000);   
    pinMode(PIR_MOTION_SENSOR, INPUT);
    Serial.println(F("[x] GROVE PIR Motion Sensor detected"));
  #endif   
    
  // now connect to the M%Stack COM.LoRaWAN module
  // TX 0/3/17
  // RX 5/15/16
  // Before you connect the module to your M5Stack device, make sure you set the TXD/RXD dip switches correctly. 
  // If you use the grey or basic and have nothing else connected, the default UART pin configuration 16/17 is fine. 
  // For the Fire you should use 13/5, as all other settings can interfere with internals of the Fire.
  //   
  // Serial2.begin(115200, SERIAL_8N1, 15, 13);
  Serial2.begin(115200, SERIAL_8N1, 16, 17);
  // show picture
  iot_picture="/comx_lorawan.jpg";
  M5.Lcd.drawJpgFile(SD, iot_picture.c_str());

  // we have to get and set some parameters 
  // first order does not work - waking module 
  ATCommand("LORAWAN", "?");
  delay(500);

  // setting LoRaWan Mode
  ATCommand("LORAWAN", "1");
  delay(500);

  // DevEui=XXXXXXXXXXXXXXXX(For OTAA Mode)
  // DevEui="XXXXXXXXXXXXXXXX";
   
  // AppEui=XXXXXXXXXXXXXXXX(For OTAA Mode)
  // always the same if equal devices
  // AppEui = "XXXXXXXXXXXXXXXX";
   
  // AppKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(For OTAA Mode)
  // AppKey="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  

  // your TTN access data
  ATCommand("DevEui", "XXXXXXXXXXXXXXXX");
  delay(500);
  ATCommand("AppEui", "XXXXXXXXXXXXXXXX");
  delay(500);
  ATCommand("AppKey", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
  delay(500);

  // we join the TTN network
  ATCommand("Join", "1");
  
  // show picture
  iot_picture="/ttn.jpg";
  M5.Lcd.drawJpgFile(SD, iot_picture.c_str());
  delay(2000);   
 
  // neopixels now off
  rgb_neopixel_off();

  // display sensor data
  tft_display_m5stack();   
}

/*-------------------------------------------------------------------------------*/
/* Function void loop()                                                          */
/*                                                                               */
/* TASK    : this runs forever                                                   */
/* UPDATE  : 24.01.2021                                                          */
/*-------------------------------------------------------------------------------*/
void loop()
{ 
  // check if some one has pressed a button
  if (M5.BtnA.wasPressed()) 
  {
    Serial.println("[x] Button A was pressed - Display ON/OFF");
    tft_backlight = !tft_backlight;   
    // Turning off the LCD backlight
    if (tft_backlight == false) { rgb_neopixel_off(); M5.Lcd.sleep();  M5.Lcd.setBrightness(0); }
    // Turning on the LCD backlight
    if (tft_backlight == true)  { M5.Lcd.wakeup(); M5.Lcd.setBrightness(255); }
    delay(200);
  }

  // check if some one has pressed a button
  if (M5.BtnB.wasPressed()) 
  {
    Serial.println("[x] Button B was pressed."); 
    delay(200);  
  }

  // check if some one has pressed a button
  if (M5.BtnC.wasPressed()) 
  {
    Serial.println("[x] Button C was pressed - Send to TTN");
    send_to_TTN();   
    delay(200);   
  }

  /*
   * If we have an enabled PIR Motion Sensor we will send immediately
   * a message to the LoRaWan Gateway if we have detected an intruder
   */ 
  #ifdef ENABLE_SENSOR_PIR_MOTION
    // read the motion sensor
    // only if display is dark
    if (tft_backlight == false)
    {
      int sensorValue = digitalRead(PIR_MOTION_SENSOR);
      // if the sensor value is HIGH we have an intruder ?
      if(sensorValue == HIGH)       
      { 
        if (MOTION == false)
        {
          // digitalWrite(LED, HIGH);
          MOTION=true;
          Serial.println("[x] PIR MOTION detected ..."); 
          // M5.Speaker.tone(661, 20);
          tft_backlight = true;  
          if (tft_backlight == true)  { tft_counter=0; M5.Lcd.wakeup(); M5.Lcd.setBrightness(255); }        
        }     
      }
      // if the sensor value is HIGH we have an intruder ?
      if(sensorValue == LOW)       
      { 
        // digitalWrite(LED, LOW);
        MOTION=false;   
      }
    }     
  #endif
  
  /* 
   * It is checked whether the time for the transmission interval has already expired
   * If the time difference between the last save and the current time is greater
   * as the interval, the following function is executed.
  */
  if (millis() - previousMillis > interval)
  {
    // correct timer
    previousMillis = millis();

    
    // shall we now publish (10 minutes)
    TTNCounter++;
    if (TTNCounter==20)
    {
      send_to_TTN();
      TTNCounter=0; 
    }
    
    // tft got to sleep after 1 minute
    tft_counter++;
    if (tft_counter==3) 
    {
      if (tft_backlight == true) { tft_backlight=false; }   
      // Turning off the LCD backlight
      if (tft_backlight == false) 
      {
        rgb_neopixel_off(); 
        M5.Lcd.sleep();  M5.Lcd.setBrightness(0);
        Serial.println(F("[x] sleeping mode ... "));
      }
      tft_counter=0;     
    }   
  }

  delay(100);  
  M5.update();
}

Free_Fonts.h

Arduino
Free Fonts
// Attach this header file to your sketch to use the GFX Free Fonts. You can write
// sketches without it, but it makes referencing them easier.

// This calls up ALL the fonts but they only get loaded if you actually
// use them in your sketch.
//
// No changes are needed to this header file unless new fonts are added to the
// library "Fonts/GFXFF" folder.
//
// To save a lot of typing long names, each font can easily be referenced in the
// sketch in three ways, either with:
//
//    1. Font file name with the & in front such as &FreeSansBoldOblique24pt7b
//       an example being:
//
//       tft.setFreeFont(&FreeSansBoldOblique24pt7b);
//
//    2. FF# where # is a number determined by looking at the list below
//       an example being:
//
//       tft.setFreeFont(FF32);
//
//    3. An abbreviation of the file name. Look at the list below to see
//       the abbreviations used, for example:
//
//       tft.setFreeFont(FSSBO24)
//
//       Where the letters mean:
//       F = Free font
//       M = Mono
//      SS = Sans Serif (double S to distinguish is form serif fonts)
//       S = Serif
//       B = Bold
//       O = Oblique (letter O not zero)
//       I = Italic
//       # =  point size, either 9, 12, 18 or 24
//
//  Setting the font to NULL will select the GLCD font:
//
//      tft.setFreeFont(NULL); // Set font to GLCD

#define LOAD_GFXFF

#ifdef LOAD_GFXFF // Only include the fonts if LOAD_GFXFF is defined in User_Setup.h

    // Use these when printing or drawing text in GLCD and high rendering speed fonts
    #define GFXFF 1
    #define GLCD  0
    #define FONT2 2
    #define FONT4 4
    #define FONT6 6
    #define FONT7 7
    #define FONT8 8

    // Use the following when calling setFont()
    //
    // Reserved for GLCD font  // FF0
    //

    #define TT1 &TomThumb

    #define FM9 &FreeMono9pt7b
    #define FM12 &FreeMono12pt7b
    #define FM18 &FreeMono18pt7b
    #define FM24 &FreeMono24pt7b

    #define FMB9 &FreeMonoBold9pt7b
    #define FMB12 &FreeMonoBold12pt7b
    #define FMB18 &FreeMonoBold18pt7b
    #define FMB24 &FreeMonoBold24pt7b

    #define FMO9 &FreeMonoOblique9pt7b
    #define FMO12 &FreeMonoOblique12pt7b
    #define FMO18 &FreeMonoOblique18pt7b
    #define FMO24 &FreeMonoOblique24pt7b

    #define FMBO9 &FreeMonoBoldOblique9pt7b
    #define FMBO12 &FreeMonoBoldOblique12pt7b
    #define FMBO18 &FreeMonoBoldOblique18pt7b
    #define FMBO24 &FreeMonoBoldOblique24pt7b

    #define FSS9 &FreeSans9pt7b
    #define FSS12 &FreeSans12pt7b
    #define FSS18 &FreeSans18pt7b
    #define FSS24 &FreeSans24pt7b

    #define FSSB9 &FreeSansBold9pt7b
    #define FSSB12 &FreeSansBold12pt7b
    #define FSSB18 &FreeSansBold18pt7b
    #define FSSB24 &FreeSansBold24pt7b

    #define FSSO9 &FreeSansOblique9pt7b
    #define FSSO12 &FreeSansOblique12pt7b
    #define FSSO18 &FreeSansOblique18pt7b
    #define FSSO24 &FreeSansOblique24pt7b

    #define FSSBO9 &FreeSansBoldOblique9pt7b
    #define FSSBO12 &FreeSansBoldOblique12pt7b
    #define FSSBO18 &FreeSansBoldOblique18pt7b
    #define FSSBO24 &FreeSansBoldOblique24pt7b

    #define FS9 &FreeSerif9pt7b
    #define FS12 &FreeSerif12pt7b
    #define FS18 &FreeSerif18pt7b
    #define FS24 &FreeSerif24pt7b

    #define FSI9 &FreeSerifItalic9pt7b
    #define FSI12 &FreeSerifItalic12pt7b
    #define FSI19 &FreeSerifItalic18pt7b
    #define FSI24 &FreeSerifItalic24pt7b

    #define FSB9 &FreeSerifBold9pt7b
    #define FSB12 &FreeSerifBold12pt7b
    #define FSB18 &FreeSerifBold18pt7b
    #define FSB24 &FreeSerifBold24pt7b

    #define FSBI9 &FreeSerifBoldItalic9pt7b
    #define FSBI12 &FreeSerifBoldItalic12pt7b
    #define FSBI18 &FreeSerifBoldItalic18pt7b
    #define FSBI24 &FreeSerifBoldItalic24pt7b

    #define FF0 NULL //ff0 reserved for GLCD
    #define FF1 &FreeMono9pt7b
    #define FF2 &FreeMono12pt7b
    #define FF3 &FreeMono18pt7b
    #define FF4 &FreeMono24pt7b

    #define FF5 &FreeMonoBold9pt7b
    #define FF6 &FreeMonoBold12pt7b
    #define FF7 &FreeMonoBold18pt7b
    #define FF8 &FreeMonoBold24pt7b

    #define FF9 &FreeMonoOblique9pt7b
    #define FF10 &FreeMonoOblique12pt7b
    #define FF11 &FreeMonoOblique18pt7b
    #define FF12 &FreeMonoOblique24pt7b

    #define FF13 &FreeMonoBoldOblique9pt7b
    #define FF14 &FreeMonoBoldOblique12pt7b
    #define FF15 &FreeMonoBoldOblique18pt7b
    #define FF16 &FreeMonoBoldOblique24pt7b

    #define FF17 &FreeSans9pt7b
    #define FF18 &FreeSans12pt7b
    #define FF19 &FreeSans18pt7b
    #define FF20 &FreeSans24pt7b

    #define FF21 &FreeSansBold9pt7b
    #define FF22 &FreeSansBold12pt7b
    #define FF23 &FreeSansBold18pt7b
    #define FF24 &FreeSansBold24pt7b

    #define FF25 &FreeSansOblique9pt7b
    #define FF26 &FreeSansOblique12pt7b
    #define FF27 &FreeSansOblique18pt7b
    #define FF28 &FreeSansOblique24pt7b

    #define FF29 &FreeSansBoldOblique9pt7b
    #define FF30 &FreeSansBoldOblique12pt7b
    #define FF31 &FreeSansBoldOblique18pt7b
    #define FF32 &FreeSansBoldOblique24pt7b

    #define FF33 &FreeSerif9pt7b
    #define FF34 &FreeSerif12pt7b
    #define FF35 &FreeSerif18pt7b
    #define FF36 &FreeSerif24pt7b

    #define FF37 &FreeSerifItalic9pt7b
    #define FF38 &FreeSerifItalic12pt7b
    #define FF39 &FreeSerifItalic18pt7b
    #define FF40 &FreeSerifItalic24pt7b

    #define FF41 &FreeSerifBold9pt7b
    #define FF42 &FreeSerifBold12pt7b
    #define FF43 &FreeSerifBold18pt7b
    #define FF44 &FreeSerifBold24pt7b

    #define FF45 &FreeSerifBoldItalic9pt7b
    #define FF46 &FreeSerifBoldItalic12pt7b
    #define FF47 &FreeSerifBoldItalic18pt7b
    #define FF48 &FreeSerifBoldItalic24pt7b

    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    // Now we define "s"tring versions for easy printing of the font name so:
    //   tft.println(sFF5);
    // will print
    //   Mono bold 9
    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    #define sFF0 "GLCD"
    #define sTT1 "Tom Thumb"
    #define sFF1 "Mono 9"
    #define sFF2 "Mono 12"
    #define sFF3 "Mono 18"
    #define sFF4 "Mono 24"

    #define sFF5 "Mono bold 9"
    #define sFF6 "Mono bold 12"
    #define sFF7 "Mono bold 18"
    #define sFF8 "Mono bold 24"

    #define sFF9 "Mono oblique 9"
    #define sFF10 "Mono oblique 12"
    #define sFF11 "Mono oblique 18"
    #define sFF12 "Mono oblique 24"

    #define sFF13 "Mono bold oblique 9"
    #define sFF14 "Mono bold oblique 12"
    #define sFF15 "Mono bold oblique 18"
    #define sFF16 "Mono bold oblique 24" // Full text line is too big for 480 pixel wide screen

    #define sFF17 "Sans 9"
    #define sFF18 "Sans 12"
    #define sFF19 "Sans 18"
    #define sFF20 "Sans 24"

    #define sFF21 "Sans bold 9"
    #define sFF22 "Sans bold 12"
    #define sFF23 "Sans bold 18"
    #define sFF24 "Sans bold 24"

    #define sFF25 "Sans oblique 9"
    #define sFF26 "Sans oblique 12"
    #define sFF27 "Sans oblique 18"
    #define sFF28 "Sans oblique 24"

    #define sFF29 "Sans bold oblique 9"
    #define sFF30 "Sans bold oblique 12"
    #define sFF31 "Sans bold oblique 18"
    #define sFF32 "Sans bold oblique 24"

    #define sFF33 "Serif 9"
    #define sFF34 "Serif 12"
    #define sFF35 "Serif 18"
    #define sFF36 "Serif 24"

    #define sFF37 "Serif italic 9"
    #define sFF38 "Serif italic 12"
    #define sFF39 "Serif italic 18"
    #define sFF40 "Serif italic 24"

    #define sFF41 "Serif bold 9"
    #define sFF42 "Serif bold 12"
    #define sFF43 "Serif bold 18"
    #define sFF44 "Serif bold 24"

    #define sFF45 "Serif bold italic 9"
    #define sFF46 "Serif bold italic 12"
    #define sFF47 "Serif bold italic 18"
    #define sFF48 "Serif bold italic 24"

#else // LOAD_GFXFF not defined so setup defaults to prevent error messages

    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    // Free fonts are not loaded in User_Setup.h so we must define all as font 1
    // to prevent compile error messages
    // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    #define GFXFF 1
    #define GLCD  1
    #define FONT2 2
    #define FONT4 4
    #define FONT6 6
    #define FONT7 7
    #define FONT8 8

    #define FF0 1
    #define FF1 1
    #define FF2 1
    #define FF3 1
    #define FF4 1
    #define FF5 1
    #define FF6 1
    #define FF7 1
    #define FF8 1
    #define FF9 1
    #define FF10 1
    #define FF11 1
    #define FF12 1
    #define FF13 1
    #define FF14 1
    #define FF15 1
    #define FF16 1
    #define FF17 1
    #define FF18 1
    #define FF19 1
    #define FF20 1
    #define FF21 1
    #define FF22 1
    #define FF23 1
    #define FF24 1
    #define FF25 1
    #define FF26 1
    #define FF27 1
    #define FF28 1
    #define FF29 1
    #define FF30 1
    #define FF31 1
    #define FF32 1
    #define FF33 1
    #define FF34 1
    #define FF35 1
    #define FF36 1
    #define FF37 1
    #define FF38 1
    #define FF39 1
    #define FF40 1
    #define FF41 1
    #define FF42 1
    #define FF43 1
    #define FF44 1
    #define FF45 1
    #define FF46 1
    #define FF47 1
    #define FF48 1

    #define FM9  1
    #define FM12 1
    #define FM18 1
    #define FM24 1

    #define FMB9  1
    #define FMB12 1
    #define FMB18 1
    #define FMB24 1

    #define FMO9  1
    #define FMO12 1
    #define FMO18 1
    #define FMO24 1

    #define FMBO9  1
    #define FMBO12 1
    #define FMBO18 1
    #define FMBO24 1

    #define FSS9  1
    #define FSS12 1
    #define FSS18 1
    #define FSS24 1

    #define FSSB9  1
    #define FSSB12 1
    #define FSSB18 1
    #define FSSB24 1

    #define FSSO9  1
    #define FSSO12 1
    #define FSSO18 1
    #define FSSO24 1

    #define FSSBO9  1
    #define FSSBO12 1
    #define FSSBO18 1
    #define FSSBO24 1

    #define FS9  1
    #define FS12 1
    #define FS18 1
    #define FS24 1

    #define FSI9  1
    #define FSI12 1
    #define FSI19 1
    #define FSI24 1

    #define FSB9  1
    #define FSB12 1
    #define FSB18 1
    #define FSB24 1

    #define FSBI9  1
    #define FSBI12 1
    #define FSBI18 1
    #define FSBI24 1

#endif // LOAD_GFXFF

SHT3X.cpp

Arduino
sensor unit ENVII
#include "SHT3X.h"

/* Motor()

*/
SHT3X::SHT3X(uint8_t address)
{
  Wire.begin();
  _address=address;
}



byte SHT3X::get()
{
  unsigned int data[6];

  // Start I2C Transmission
  Wire.beginTransmission(_address);
  // Send measurement command
  Wire.write(0x2C);
  Wire.write(0x06);
  // Stop I2C transmission
  if (Wire.endTransmission()!=0) 
    return 1;  

  delay(500);

  // Request 6 bytes of data
  Wire.requestFrom(_address, 6);

  // Read 6 bytes of data
  // cTemp msb, cTemp lsb, cTemp crc, humidity msb, humidity lsb, humidity crc
  for (int i=0;i<6;i++) {
    data[i]=Wire.read();
  };
  
  delay(50);
  
  if (Wire.available()!=0) 
    return 2;

  // Convert the data
  cTemp = ((((data[0] * 256.0) + data[1]) * 175) / 65535.0) - 45;
  fTemp = (cTemp * 1.8) + 32;
  humidity = ((((data[3] * 256.0) + data[4]) * 100) / 65535.0);

  return 0;
}

SHT3X.h

Arduino
header sensor unit ENVII
#ifndef __SHT3X_H
#define __SHT3X_H


#if ARDUINO >= 100
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#include "Wire.h"

class SHT3X{
public:
  SHT3X(uint8_t address=0x44);
  byte get(void);
  float cTemp=0;
  float fTemp=0;
  float humidity=0;

private:
  uint8_t _address;

};


#endif

Adafruit_Sensor.h

Arduino
Adafruit Sensors
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software< /span>
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and
 * extended sensor support to include color, voltage and current */
 
#ifndef _ADAFRUIT_SENSOR_H
#define _ADAFRUIT_SENSOR_H

#ifndef ARDUINO
 #include <stdint.h>
#elif ARDUINO >= 100
 #include "Arduino.h"
 #include "Print.h"
#else
 #include "WProgram.h"
#endif

/* Intentionally modeled after sensors.h in the Android API:
 * https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */

/* Constants */
#define SENSORS_GRAVITY_EARTH             (9.80665F)              /**< Earth's gravity in m/s^2 */
#define SENSORS_GRAVITY_MOON              (1.6F)                  /**< The moon's gravity in m/s^2 */
#define SENSORS_GRAVITY_SUN               (275.0F)                /**< The sun's gravity in m/s^2 */
#define SENSORS_GRAVITY_STANDARD          (SENSORS_GRAVITY_EARTH)
#define SENSORS_MAGFIELD_EARTH_MAX        (60.0F)                 /**< Maximum magnetic field on Earth's surface */
#define SENSORS_MAGFIELD_EARTH_MIN        (30.0F)                 /**< Minimum magnetic field on Earth's surface */
#define SENSORS_PRESSURE_SEALEVELHPA      (1013.25F)              /**< Average sea level pressure is 1013.25 hPa */
#define SENSORS_DPS_TO_RADS               (0.017453293F)          /**< Degrees/s to rad/s multiplier */
#define SENSORS_GAUSS_TO_MICROTESLA       (100)                   /**< Gauss to micro-Tesla multiplier */

/** Sensor types */
typedef enum
{
  SENSOR_TYPE_ACCELEROMETER         = (1),   /**< Gravity + linear acceleration */
  SENSOR_TYPE_MAGNETIC_FIELD        = (2),
  SENSOR_TYPE_ORIENTATION           = (3),
  SENSOR_TYPE_GYROSCOPE             = (4),
  SENSOR_TYPE_LIGHT                 = (5),
  SENSOR_TYPE_PRESSURE              = (6),
  SENSOR_TYPE_PROXIMITY             = (8),
  SENSOR_TYPE_GRAVITY               = (9),
  SENSOR_TYPE_LINEAR_ACCELERATION   = (10),  /**< Acceleration not including gravity */
  SENSOR_TYPE_ROTATION_VECTOR       = (11),
  SENSOR_TYPE_RELATIVE_HUMIDITY     = (12),
  SENSOR_TYPE_AMBIENT_TEMPERATURE   = (13),
  SENSOR_TYPE_VOLTAGE               = (15),
  SENSOR_TYPE_CURRENT               = (16),
  SENSOR_TYPE_COLOR                 = (17)
} sensors_type_t;

/** struct sensors_vec_s is used to return a vector in a common format. */
typedef struct {
    union {
        float v[3];
        struct {
            float x;
            float y;
            float z;
        };
        /* Orientation sensors */
        struct {
            float roll;    /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90<=roll<=90 */
            float pitch;   /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180<=pitch<=180) */
            float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359 */
        };
    };
    int8_t status;
    uint8_t reserved[3];
} sensors_vec_t;

/** struct sensors_color_s is used to return color data in a common format. */
typedef struct {
    union {
        float c[3];
        /* RGB color space */
        struct {
            float r;       /**< Red component */
            float g;       /**< Green component */
            float b;       /**< Blue component */
        };
    };
    uint32_t rgba;         /**< 24-bit RGBA value */
} sensors_color_t;

/* Sensor event (36 bytes) */
/** struct sensor_event_s is used to provide a single sensor event in a common format. */
typedef struct
{
    int32_t version;                          /**< must be sizeof(struct sensors_event_t) */
    int32_t sensor_id;                        /**< unique sensor identifier */
    int32_t type;                             /**< sensor type */
    int32_t reserved0;                        /**< reserved */
    int32_t timestamp;                        /**< time is in milliseconds */
    union
    {
        float           data[4];
        sensors_vec_t   acceleration;         /**< acceleration values are in meter per second per second (m/s^2) */
        sensors_vec_t   magnetic;             /**< magnetic vector values are in micro-Tesla (uT) */
        sensors_vec_t   orientation;          /**< orientation values are in degrees */
        sensors_vec_t   gyro;                 /**< gyroscope values are in rad/s */
        float           temperature;          /**< temperature is in degrees centigrade (Celsius) */
        float           distance;             /**< distance in centimeters */
        float           light;                /**< light in SI lux units */
        float           pressure;             /**< pressure in hectopascal (hPa) */
        float           relative_humidity;    /**< relative humidity in percent */
        float           current;              /**< current in milliamps (mA) */
        float           voltage;              /**< voltage in volts (V) */
        sensors_color_t color;                /**< color in RGB component values */
    };
} sensors_event_t;

/* Sensor details (40 bytes) */
/** struct sensor_s is used to describe basic information about a specific sensor. */
typedef struct
{
    char     name[12];                        /**< sensor name */
    int32_t  version;                         /**< version of the hardware + driver */
    int32_t  sensor_id;                       /**< unique sensor identifier */
    int32_t  type;                            /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */
    float    max_value;                       /**< maximum value of this sensor's value in SI units */
    float    min_value;                       /**< minimum value of this sensor's value in SI units */
    float    resolution;                      /**< smallest difference between two values reported by this sensor */
    int32_t  min_delay;                       /**< min delay in microseconds between events. zero = not a constant rate */
} sensor_t;

class Adafruit_Sensor {
 public:
  // Constructor(s)
  Adafruit_Sensor() {}
  virtual ~Adafruit_Sensor() {}

  // These must be defined by the subclass
  virtual void enableAutoRange(bool enabled) { (void)enabled; /* suppress unused warning */ };
  virtual bool getEvent(sensors_event_t*) = 0;
  virtual void getSensor(sensor_t*) = 0;
  
 private:
  bool _autoRange;
};

#endif

sd.zip

Arduino
jpg pictures sd card
No preview (download only).

Credits

KeHoSoftware

KeHoSoftware

5 projects • 2 followers

Comments

Add projectSign up / Login