This code is basically a copypaste from the code posted by @thebang2. I only changed NODENAME and node_id
#include <SPI.h>
#include <Wire.h>
#include <RadioLib.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include "I2C_AHT10.h"
//#include <LoRa.h>
#include <ArduinoJson.h>
//#define NODENAME "LORA_KUSLAPUU_1"
String node_id = String("ID") + "010204";
//Set sleep time, when value is 1 almost sleep 20s,when value is 450, almost 1 hour.
//#define SLEEP_CYCLE 450
#define SLEEP_CYCLE 38 //5 Minuten
//Lora set
//Set Lora frequency
// #define FREQUENCY 434.0
#define FREQUENCY 868.0
//#define FREQUENCY 915.0
#define BANDWIDTH 125.0
#define SPREADING_FACTOR 9
#define CODING_RATE 7
#define OUTPUT_POWER 10
#define PREAMBLE_LEN 8
#define GAIN 0
//328p
#define DIO0 2
#define DIO1 6
#define LORA_RST 4
#define LORA_CS 10
#define SPI_MOSI 11
#define SPI_MISO 12
#define SPI_SCK 13
//pin set
#define VOLTAGE_PIN A3
#define PWM_OUT_PIN 9
#define SENSOR_POWER_PIN 5
#define ADC_PIN A2
#define DEBUG_OUT_ENABLE 1
SX1276 radio = new Module(LORA_CS, DIO0, LORA_RST, DIO1);
AHT10 humiditySensor;
String jsonoutput = ""; // string for json transfer
bool readSensorStatus = false;
int sensorValue = 0; // variable to store the value coming from the sensor
int batValue = 0; // the voltage of battery
int count = 0;
int ADC_O_1; // ADC Output First 8 bits
int ADC_O_2; // ADC Output Next 2 bits
int16_t packetnum = 0; // packet counter, we increment per xmission
float temperature = 0.0;
float humidity = 0.0;
bool AHT_init()
{
bool ret = false;
Wire.begin();
if (humiditySensor.begin() == false)
{
#if DEBUG_OUT_ENABLE
Serial.println("AHT10 not detected. Please check wiring. Freezing.");
#endif
}
if (humiditySensor.available() == true)
{
temperature = humiditySensor.getTemperature();
humidity = humiditySensor.getHumidity();
ret = true;
}
if (isnan(humidity) || isnan(temperature))
{
#if DEBUG_OUT_ENABLE
Serial.println(F("Failed to read from AHT sensor!"));
#endif
}
return ret;
}
void Lora_init()
{
int state = radio.begin(FREQUENCY, BANDWIDTH, SPREADING_FACTOR, CODING_RATE, SX127X_SYNC_WORD, OUTPUT_POWER, PREAMBLE_LEN, GAIN);
Serial.println(state);
if (state == ERR_NONE)
{
#if DEBUG_OUT_ENABLE
Serial.println(F("success!"));
#endif
}
else
{
#if DEBUG_OUT_ENABLE
Serial.print(F("failed, code "));
Serial.println(state);
#endif
// while (true)
// ;
}
}
void setup()
{
#if DEBUG_OUT_ENABLE
Serial.begin(115200);
Serial.println("Soil start.");
Serial.print(FREQUENCY);
Serial.println(" Mhz");
#endif
delay(100);
// set up Timer 1
pinMode(PWM_OUT_PIN, OUTPUT);
TCCR1A = bit(COM1A0); // toggle OC1A on Compare Match
TCCR1B = bit(WGM12) | bit(CS10); // CTC, scale to clock
OCR1A = 1;
pinMode(LORA_RST, OUTPUT);
digitalWrite(LORA_RST, HIGH);
delay(100);
pinMode(SENSOR_POWER_PIN, OUTPUT);
digitalWrite(SENSOR_POWER_PIN, HIGH); //Sensor power on
delay(100);
Lora_init();
Wire.begin();
if (humiditySensor.begin() == false)
{
#if DEBUG_OUT_ENABLE
Serial.println("AHT10 not detected. Please check wiring. Freezing.");
#endif
}
#if DEBUG_OUT_ENABLE
else
Serial.println("AHT10 acknowledged.");
#endif
do_some_work();
//setup over
#if DEBUG_OUT_ENABLE
Serial.println("[Set]Sleep Mode Set");
#endif
low_power_set();
}
void loop()
{
wdt_disable();
if (count > SLEEP_CYCLE) //(7+1) x 8S 450
{
#if DEBUG_OUT_ENABLE
//code start
Serial.println("Code start>>");
#endif
do_some_work();
all_pins_low();
#if DEBUG_OUT_ENABLE
//code end
Serial.println("Code end<<");
#endif
//count init
count = 0;
}
low_power_set();
}
ISR(WDT_vect)
{
#if DEBUG_OUT_ENABLE
Serial.print("[Watch dog]");
Serial.println(count);
#endif
delay(100);
count++;
//wdt_reset();
wdt_disable(); // disable watchdog
}
//Set low power mode and into sleep
void low_power_set()
{
all_pins_low();
delay(10);
// disable ADC
ADCSRA = 0;
sleep_enable();
watchdog_init();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
delay(10);
noInterrupts();
sleep_enable();
// turn off brown-out enable in software
MCUCR = bit(BODS) | bit(BODSE);
MCUCR = bit(BODS);
interrupts();
sleep_cpu();
sleep_disable();
}
//Enable watch dog
void watchdog_init()
{
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset
WDTCSR = bit(WDCE) | bit(WDE);
WDTCSR = bit(WDIE) | bit(WDP3) | bit(WDP0); // set WDIE, and 8 seconds delay
wdt_reset(); // pat the dog
}
void do_some_work()
{
digitalWrite(SENSOR_POWER_PIN, HIGH); // Sensor/RF95 power on
digitalWrite(LORA_RST, HIGH);
delay(5);
pinMode(PWM_OUT_PIN, OUTPUT); //digitalWrite(PWM_OUT_PIN, LOW);
TCCR1A = bit(COM1A0); // toggle OC1A on Compare Match
TCCR1B = bit(WGM12) | bit(CS10); // CTC, scale to clock
OCR1A = 1; // compare A register value (5000 * clock speed / 1024).When OCR1A == 1, PWM is 2MHz
Lora_init();
delay(50);
//ADC2 AVCC as reference voltage
ADMUX = _BV(REFS0) | _BV(MUX1);
//ADC2 internal 1.1V as ADC reference voltage
//ADMUX = _BV(REFS1) |_BV(REFS0) | _BV(MUX1);
// 8 分频
ADCSRA = _BV(ADEN) | _BV(ADPS1) | _BV(ADPS0);
delay(50);
for (int i = 0; i < 3; i++)
{
//start ADC conversion
ADCSRA |= (1 << ADSC);
delay(10);
if ((ADCSRA & 0x40) == 0)
{
ADC_O_1 = ADCL;
ADC_O_2 = ADCH;
sensorValue = (ADC_O_2 << 8) + ADC_O_1;
ADCSRA |= 0x40;
//Mod for value from in 0 to 100
// 1000 = Air dry, 500 ultrawet
sensorValue = (sensorValue - 500) / 5;
// End
#if DEBUG_OUT_ENABLE
Serial.print("ADC:");
Serial.println(sensorValue);
#endif
if (readSensorStatus == false)
readSensorStatus = AHT_init();
}
ADCSRA |= (1 << ADIF); //reset as required
delay(50);
}
//ADC3 internal 1.1V as ADC reference voltage
ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX1) | _BV(MUX0);
delay(50);
for (int i = 0; i < 3; i++)
{
//start ADC conversion
ADCSRA |= (1 << ADSC);
delay(10);
if ((ADCSRA & 0x40) == 0)
{
ADC_O_1 = ADCL;
ADC_O_2 = ADCH;
batValue = (ADC_O_2 << 8) + ADC_O_1;
ADCSRA |= 0x40;
#if DEBUG_OUT_ENABLE
Serial.print("BAT:");
Serial.println(batValue);
float bat = (float)batValue * 3.3;
bat = bat / 1024.0;
Serial.print(bat);
Serial.println("V");
#endif
}
ADCSRA |= (1 << ADIF); //reset as required
delay(50);
}
send_lora();
delay(1000);
radio.sleep();
packetnum++;
readSensorStatus = false;
digitalWrite(SENSOR_POWER_PIN, LOW); // Sensor/RF95 power off
delay(100);
}
void all_pins_low()
{
pinMode(PWM_OUT_PIN, INPUT);
pinMode(A4, INPUT_PULLUP);
pinMode(A5, INPUT_PULLUP);
delay(50);
}
void send_lora()
{
// Create json object for transfer
DynamicJsonDocument root(256);
root["node_id"] = node_id;
root["hum"] = (String)humidity;
root["temp"] = (String)temperature;
root["adc"] = (String)sensorValue;
root["bat"] = (String)batValue;
serializeJson(root, jsonoutput);
#if DEBUG_OUT_ENABLE
serializeJson(root, Serial);
#endif
radio.transmit(jsonoutput);
jsonoutput = "";
}
I2C_AHT10.cpp
/****************************************************************
***************************************************************/
#include "I2C_AHT10.h"
/*--------------------------- Device Status ------------------------------*/
bool AHT10::begin(TwoWire &wirePort)
{
_i2cPort = &wirePort; //Grab the port the user wants to communicate on
_deviceAddress = AHT10_DEFAULT_ADDRESS; //We had hoped the AHT10 would support two addresses but it doesn't seem to
if (isConnected() == false)
return false;
//Wait 40 ms after power-on before reading temp or humidity. Datasheet pg 8
delay(40);
//Check if the calibrated bit is set. If not, init the sensor.
if (isCalibrated() == false)
{
//Send 0xBE0800
initialize();
//Immediately trigger a measurement. Send 0xAC3300
triggerMeasurement();
delay(75); //Wait for measurement to complete
uint8_t counter = 0;
while (isBusy())
{
delay(1);
if (counter++ > 100)
return (false); //Give up after 100ms
}
//This calibration sequence is not completely proven. It's not clear how and when the cal bit clears
//This seems to work but it's not easily testable
if (isCalibrated() == false)
{
return (false);
}
}
//Check that the cal bit has been set
if (isCalibrated() == false)
return false;
//Mark all datums as fresh (not read before)
sensorQueried.temperature = true;
sensorQueried.humidity = true;
return true;
}
//Ping the AHT10's I2C address
//If we get a response, we are correctly communicating with the AHT10
bool AHT10::isConnected()
{
_i2cPort->beginTransmission(_deviceAddress);
if (_i2cPort->endTransmission() == 0)
return true;
//If IC failed to respond, give it 20ms more for Power On Startup
//Datasheet pg 7
delay(20);
_i2cPort->beginTransmission(_deviceAddress);
if (_i2cPort->endTransmission() == 0)
return true;
return false;
}
/*------------------------ Measurement Helpers ---------------------------*/
uint8_t AHT10::getStatus()
{
_i2cPort->requestFrom(_deviceAddress, (uint8_t)1);
if (_i2cPort->available())
return (_i2cPort->read());
return (0);
}
//Returns the state of the cal bit in the status byte
bool AHT10::isCalibrated()
{
return (getStatus() & (1 << 3));
}
//Returns the state of the busy bit in the status byte
bool AHT10::isBusy()
{
return (getStatus() & (1 << 7));
}
bool AHT10::initialize()
{
_i2cPort->beginTransmission(_deviceAddress);
_i2cPort->write(sfe_aht10_reg_initialize);
_i2cPort->write(0x80);
_i2cPort->write(0x00);
if (_i2cPort->endTransmission() == 0)
return true;
return false;
}
bool AHT10::triggerMeasurement()
{
_i2cPort->beginTransmission(_deviceAddress);
_i2cPort->write(sfe_aht10_reg_measure);
_i2cPort->write(0x33);
_i2cPort->write(0x00);
if (_i2cPort->endTransmission() == 0)
return true;
return false;
}
//Loads the
void AHT10::readData()
{
//Clear previous data
sensorData.temperature = 0;
sensorData.humidity = 0;
if (_i2cPort->requestFrom(_deviceAddress, (uint8_t)6) > 0)
{
uint8_t state = _i2cPort->read();
uint32_t incoming = 0;
incoming |= (uint32_t)_i2cPort->read() << (8 * 2);
incoming |= (uint32_t)_i2cPort->read() << (8 * 1);
uint8_t midByte = _i2cPort->read();
incoming |= midByte;
sensorData.humidity = incoming >> 4;
sensorData.temperature = (uint32_t)midByte << (8 * 2);
sensorData.temperature |= (uint32_t)_i2cPort->read() << (8 * 1);
sensorData.temperature |= (uint32_t)_i2cPort->read() << (8 * 0);
//Need to get rid of data in bits > 20
sensorData.temperature = sensorData.temperature & ~(0xFFF00000);
//Mark data as fresh
sensorQueried.temperature = false;
sensorQueried.humidity = false;
}
}
//Triggers a measurement if one has not been previously started, then returns false
//If measurement has been started, checks to see if complete.
//If not complete, returns false
//If complete, readData(), mark measurement as not started, return true
bool AHT10::available()
{
if (measurementStarted == false)
{
triggerMeasurement();
measurementStarted = true;
return (false);
}
if (isBusy() == true)
{
return (false);
}
readData();
measurementStarted = false;
return (true);
}
bool AHT10::softReset()
{
_i2cPort->beginTransmission(_deviceAddress);
_i2cPort->write(sfe_aht10_reg_reset);
if (_i2cPort->endTransmission() == 0)
return true;
return false;
}
/*------------------------- Make Measurements ----------------------------*/
float AHT10::getTemperature()
{
if (sensorQueried.temperature == true)
{
//We've got old data so trigger new measurement
triggerMeasurement();
delay(75); //Wait for measurement to complete
uint8_t counter = 0;
while (isBusy())
{
delay(1);
if (counter++ > 100)
return (false); //Give up after 100ms
}
readData();
}
//From datasheet pg 8
float tempCelsius = ((float)sensorData.temperature / 1048576) * 200 - 50;
//Mark data as old
sensorQueried.temperature = true;
return tempCelsius;
}
float AHT10::getHumidity()
{
if (sensorQueried.humidity == true)
{
//We've got old data so trigger new measurement
triggerMeasurement();
delay(75); //Wait for measurement to complete
uint8_t counter = 0;
while (isBusy())
{
delay(1);
if (counter++ > 100)
return (false); //Give up after 100ms
}
readData();
}
//From datasheet pg 8
float relHumidity = ((float)sensorData.humidity / 1048576) * 100;
//Mark data as old
sensorQueried.humidity = true;
return relHumidity;
}
I2C_AHT10.h
/****************************************************************
*
******************************************************************/
#ifndef __I2C_AHT10_H__
#define __I2C_AHT10_H__
#include <Arduino.h>
#include <Wire.h>
#define AHT10_DEFAULT_ADDRESS 0x38
enum registers
{
sfe_aht10_reg_reset = 0xBA,
sfe_aht10_reg_initialize = 0xBE,
sfe_aht10_reg_measure = 0xAC,
};
class AHT10
{
private:
TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
uint8_t _deviceAddress;
bool measurementStarted = false;
struct
{
uint32_t humidity;
uint32_t temperature;
} sensorData;
struct
{
uint8_t temperature : 1;
uint8_t humidity : 1;
} sensorQueried;
public:
//Device status
bool begin(TwoWire &wirePort = Wire); //Sets the address of the device and opens the I2C bus
bool isConnected(); //Checks if the AHT10 is connected to the I2C bus
bool available(); //Returns true if new data is available
//Measurement helper functions
uint8_t getStatus(); //Returns the status byte
bool isCalibrated(); //Returns true if the cal bit is set, false otherwise
bool isBusy(); //Returns true if the busy bit is set, false otherwise
bool initialize(); //Initialize for taking measurement
bool triggerMeasurement(); //Trigger the AHT10 to take a measurement
void readData(); //Read and parse the 6 bytes of data into raw humidity and temp
bool softReset(); //Restart the sensor system without turning power off and on
//Make measurements
float getTemperature(); //Goes through the measurement sequence and returns temperature in degrees celcius
float getHumidity(); //Goes through the measurement sequence and returns humidity in % RH
};
#endif