user2199899
Published © GPL3+

Simple standalone industrial grade weather station

A stunning result will be achieved - the battery life of the weather station is longer than that of similar industrial products.

AdvancedFull instructions provided355
Simple standalone industrial grade weather station

Things used in this project

Hardware components

ATMEGA328P-PU
×2
Gravity:SHT1x Humidity and Temperature Sensor
DFRobot Gravity:SHT1x Humidity and Temperature Sensor
×1
LCD Nokia 5110
×1
LoRa Module
Wireless-Tag LoRa Module
×2
Battery Holder, AA x 2
Battery Holder, AA x 2
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Breadboard (generic)
Breadboard (generic)
×1
AA Batteries
AA Batteries
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
Solder Flux, Rosin
Solder Flux, Rosin
Mini Side Cutter, 120mm Length with 25mm Jaw Capacity
Mini Side Cutter, 120mm Length with 25mm Jaw Capacity

Story

Read more

Schematics

External sensor

Base

Code

sketch_base

Arduino
/*
 Autonomous Arduino-weather station on two AA batteries
 https://create.arduino.cc/projecthub/user2199899/autonomous-arduino-weather-station-on-two-aa-batteries-65ec38
*/

#include <avr/io.h>
#include <util/delay.h>

#include <SPI.h>
#include <LoRa.h>
#include <LowPower.h>
#include "HTU21D.h"
#include <LCD5110_Graph.h>

#define VccHTU 8  //power supply and pull-up HTU21D (pin 14 AtMega328P, D8)
HTU21D myHTU21D;
float Tin; // room temperature
int Hin;  // вindoor humidity

LCD5110 myNokia(3, 4, 5, 6, 7);
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];

float BatIn = 0; // battery voltage
const int batteryPin = A0; //pin 23 (Atmega328P), to which the battery is connected for voltage measurement
const float typVbg = 1.132; //calibration constant, 1.0 - 1.2

unsigned int sleepCounter;  //sleep timer

int r; //broadcast listening cycle counter
int mlc;  //operating cycle counter without external sensor

String LoRaData, Tout_str, Hout_str, BatIn_str, BatOut_str;

// battery voltage measurement
float readVcc() {
  byte i;
  float result = 0.0;
  float tmp = 0.0;

  for (i = 0; i < 1; i++) {
    // Read 1.1V reference against AVcc
    // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
#else
    // works on an Arduino 168 or 328
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

    _delay_ms(3); // Wait for Vref to settle
    ADCSRA |= _BV(ADSC); // Start conversion
    while (bit_is_set(ADCSRA, ADSC)); // measuring

    uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
    uint8_t high = ADCH; // unlocks both

    tmp = (high << 8) | low;
    tmp = (typVbg * 1023.0) / tmp;
    result = result + tmp;
    _delay_ms(5);
  }
  return result;
}

void Measurement() {
  float Tin0;
  // battery voltage measurement
  BatIn = readVcc();
  // measurement of temperature and humidity in the room
  Hin = myHTU21D.readHumidity();
  float Tin_p = myHTU21D.readTemperature();
  Tin = 0.1 * int(Tin_p * 10 + 0.5);  //rounding to tenths
  }

void draw() {
  myNokia.enableSleep();
  myNokia.clrScr();

  //Tin
  char chr_Tin [5];
  String Tin_str = String(Tin);
  myNokia.setFont(SmallFont);
  myNokia.print("            C", LEFT, 0);
  myNokia.print("In", LEFT, 8);
  myNokia.setFont(MediumNumbers);
  Tin_str.toCharArray(chr_Tin, 5); //number of characters + 1
  myNokia.print(String(chr_Tin), CENTER, 0);

  //Tout
  char chr_Tout [5];
  myNokia.setFont(SmallFont);
  myNokia.print("            C", LEFT, 16);
  myNokia.print("Out", LEFT, 24);
  myNokia.setFont(MediumNumbers);
  Tout_str.toCharArray(chr_Tout, 5);
  myNokia.print(String(chr_Tout), CENTER, 16);

  // Hin, Hout
  char chr_Hout [5];
  Hout_str.toCharArray(chr_Hout, 4);
  myNokia.setFont(MediumNumbers);
  myNokia.print(String(Hout_str), RIGHT, 32);
  myNokia.setFont(SmallFont);
  myNokia.print("    In Out", LEFT, 40);
  myNokia.print("      %", LEFT, 32);
  myNokia.setFont(MediumNumbers);
  myNokia.print(String(Hin), LEFT, 32);
  myNokia.setFont(SmallFont);

  // Battery Level
  if (BatIn < 2.2) {
    myNokia.setFont(SmallFont);
    myNokia.print("Bat", LEFT, 0);
  }

  if (BatOut_str == "BLow") {
    myNokia.setFont(SmallFont);
    myNokia.print("Bat", LEFT, 16);
  }

  myNokia.disableSleep();
  _delay_ms(5);
}

void drawStart() {
  myNokia.enableSleep();
  myNokia.clrScr();

  //Tin
  char chr_Tin [5];
  String Tin_str = String(Tin);
  myNokia.setFont(SmallFont);
  myNokia.print("            C", LEFT, 0);
  myNokia.print("In", LEFT, 8);
  myNokia.setFont(MediumNumbers);
  Tin_str.toCharArray(chr_Tin, 5); // number of characters + 1
  myNokia.print(String(chr_Tin), CENTER, 0);

  // Battery Level
  if (BatIn < 2.2)
  {
    myNokia.setFont(SmallFont);
    myNokia.print("Bat!", RIGHT, 28);
  }

  //Hin
  myNokia.setFont(SmallFont);
  myNokia.print("         %", LEFT, 18);
  myNokia.print("In", LEFT, 28);
  myNokia.setFont(MediumNumbers);
  myNokia.print(String(Hin), CENTER, 18);

  //No signal!
  myNokia.setFont(SmallFont);
  myNokia.print("Out - - -", CENTER, 40);

  myNokia.update();

  myNokia.disableSleep();
  _delay_ms(5);
}

void setup() {
  Serial.begin(9600);

  pinMode(VccHTU, OUTPUT);
  digitalWrite(VccHTU, 1);
  Serial.println("Power ON!");
  analogReference(DEFAULT);

  // инициализация дисплея
  myNokia.InitLCD();

  myNokia.setFont(SmallFont);
  myNokia.clrScr();
  myNokia.print(">>>>>", CENTER, 20);
  myNokia.update();
  _delay_ms(1000);
  myNokia.setFont(SmallFont);
  myNokia.clrScr();
  myNokia.print("))-->", CENTER, 20);
  myNokia.update();

  if (!LoRa.begin(433E6)) {
    Serial.println("Loading LoRa receiver failed!");
    while (1);

    myNokia.setFont(SmallFont);
    myNokia.clrScr();
    myNokia.print(" ->  ->", CENTER, 20);
    myNokia.update();
  }

  // Диапазон для синхрослова – между "0-0xFF".
  LoRa.setSyncWord(0xF3);
  Serial.println("Broadcast listening. Waiting for a packet from an external sensor...");

  myHTU21D.begin();
  Measurement();
  drawStart();
  digitalWrite(VccHTU, 0);
  _delay_ms(1000);

  myNokia.clrScr();
  myNokia.print("Waiting", CENTER, 10);
  myNokia.print("Message from", CENTER, 22);
  myNokia.print("OUTSIDE", CENTER, 34);
  myNokia.update();
}

void loop() {
  r++;
  digitalWrite(VccHTU, 1);
  if (r < 600)  // 8 MHz;
  {
    mlc = 0;
     // Listening to the broadcast, receiving, decoding. If a signal from an external sensor is received,
     // then measurements in the room, displaying data on the screen and sleeping.
    {
      int packetSize = LoRa.parsePacket();
      if (packetSize) {
        while (LoRa.available()) {
          LoRaData = LoRa.readString();
        }
        int pos1 = LoRaData.indexOf('#');
        int pos2 = LoRaData.indexOf('$');
        Tout_str = LoRaData.substring(0, pos1);
        Hout_str = LoRaData.substring(pos1 + 1, pos2);
        BatOut_str = LoRaData.substring(pos2 + 1, LoRaData.length());

        if ((LoRaData).substring(pos1, pos1 + 1) == "#") {
          Serial.println("Принято, декодировано! r = " +  String(r));
          r = 0;
          Measurement();
          draw();
          digitalWrite(VccHTU, 0);
          // sleepCounter = 49; 16 MHz
          // sleepCounter = 48; 8 MHz
          for (sleepCounter = 48; sleepCounter > 0; sleepCounter--)
          {
            digitalWrite(VccHTU, 1);
            LoRa.sleep ();
            LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
          }
        }
      }
    }
  } else {
    r = 600;
    if (mlc < 250) // 4 hours, operating time without external sensor
    {
      Serial.println("Operation without external sensor.");
      LoRa.sleep ();
      Measurement();
      drawStart();
      digitalWrite(VccHTU, 0);

      for (sleepCounter = 6; sleepCounter > 0; sleepCounter--)
      {
        digitalWrite(VccHTU, 1);
        LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
      }
      mlc++;
    } else {
      r = 0;
      mlc = 0;
    }
  }
  _delay_ms(110); 
}

int main() {
  init();
  setup();

  for (;;) {
    loop();
  }
}

sketch_out-sensor

Arduino
/*
 Autonomous Arduino-weather station on two AA batteries
 https://create.arduino.cc/projecthub/user2199899/autonomous-arduino-weather-station-on-two-aa-batteries-65ec38
*/

#include <avr/io.h>
#include <util/delay.h>

#include <SPI.h>
#include <LoRa.h>
#include <LowPower.h>
#include <Wire.h>
#include <avr/power.h>
#include "HTU21D.h"

#define VccHTU 8  //power and pull HTU21D (pin 14 AtMega328P, D8)
HTU21D myHTU21D;
float Tout; // temperature
int Hout;  //  humidity

unsigned int sleepCounter, sleepCounter0; // counter that sets the sleep time
int pct;  // counter of the number of packets before going to sleep
String messageOut; // LoRa message
float BatOut; // battery voltage
const int batteryPin = A0; // pin 23 (Atmega328P), to which the battery is connected for voltage measurement
const float typVbg = 1.132; // calibration constant, 1.0 - 1.2

int counter = 0;
// battery voltage measurement
float readVcc() {
  byte i;
  float result = 0.0;
  float tmp = 0.0;

  for (i = 0; i < 1; i++) {
    // Read 1.1V reference against AVcc
    // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
#else
    // works on an Arduino 168 or 328
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

    _delay_ms(3); // Wait for Vref to settle
    ADCSRA |= _BV(ADSC); // Start conversion
    while (bit_is_set(ADCSRA, ADSC)); // measuring

    uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
    uint8_t high = ADCH; // unlocks both

    tmp = (high << 8) | low;
    tmp = (typVbg * 1023.0) / tmp;
    result = result + tmp;
    _delay_ms(5);
  }
  return result;
}

void Measurement () {
 // measurement of temperature and humidity
  Hout = myHTU21D.readHumidity();

  float Tout_p = myHTU21D.readTemperature();
  Tout = 0.1 * int(Tout_p * 10 + 0.5);  //rounding to tenths

  // измерение напряжения батареек
  BatOut = 0.1 * int(readVcc() * 10 + 0.5);
  if (BatOut < 2.2) {
    BatOut = 0.0;
  } else {
    BatOut = 2.2;
  }
}

void SendMessage () {
  // send data (temperature, humidity, battery status)
  if (BatOut > 2.1) {
    messageOut = String(Tout) + "#" + String(Hout) + "$" + String("BGood");
  }
  else {
    messageOut = String(Tout) + "#" + String(Hout) + "$" + String("BLow");
  }

  LoRa.beginPacket();
  LoRa.print(messageOut);
  LoRa.endPacket();
}

void setup() {
  Serial.begin(9600);
  Serial.println("Power ON");
  analogReference(DEFAULT);

  pinMode(VccHTU, OUTPUT);
  digitalWrite(VccHTU, 1);
  _delay_ms(200);
  myHTU21D.begin();

  int counter = 0;
  while (!LoRa.begin(433E6) && counter < 10) {
    Serial.println("Could not find LoRa transmitter!");
    counter++;
    _delay_ms(500);
  }
  LoRa.setTxPower(4); // transmitter power, 2...20 dB
  LoRa.setSyncWord(0xF3);
}

void loop() {
  digitalWrite(VccHTU, 1);
  if (pct < 3)
  { // measurements, sending packets
    Serial.println(messageOut);
    Measurement ();
    SendMessage ();
  } else {// measurements, sending a packet and a long sleep
    Serial.println(messageOut);
    Serial.println("sleep ...");
    Measurement ();
    SendMessage ();
    for (sleepCounter = 6; sleepCounter > 0; sleepCounter--)
    {
      digitalWrite(VccHTU, 0);
      digitalWrite(VccHTU, 1);
      LoRa.sleep ();
      LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
    }
    pct = 0;
  }
  pct++;
  if (pct >= 3) pct = 3; // counter overflow protection
}

int main() {
  init();
  setup();

  for (;;) {
    loop();
  }
}

Credits

user2199899

user2199899

0 projects • 3 followers

Comments