LoRa stand for Long Rang, in this post i will show you what i m up to with LoRa Sensors, Zone Controller and ESP8266 Gateway. PiHome infrastructure i.e. battery powered temperature sensors, zone controller, boiler controller and esp8266 smart home gateway is built with nRF24L01 wireless which operate at 2.4Gh. nRF24L01 is cheap solution but it has range limitation and unable to penetrate through the solid walls and you need repeaters installed around the place to get full coverage. Its best to invest some time to discover alternate to nRF24L01 2.4GHz wireless that could penetrate walls and can work on low power and easy to implement, i think LoRa tick all the boxes. lets get started on this investigation.

LoRa Sensors, Zone Controller and ESP8266 Gateway

LoRa Sensors, Zone Controller and ESP8266 Gateway

LoRa modules comes in three different wireless ISM (Industrial, Scientific, and Medical) frequency bands 433Mhz, 868Mhz 915MHz, These frequency bands were set aside for RF use for purposes other than telecommunications.

First designed pcb for LoRa module which has footprint for RFM69CHW, RFM69CW, RFM69HW and RFM69W with smd antenna for these modules, PCBs in image are for 1-Wire DS18b20 temperature sensors powered by 3xAAA batteries, Smart home gateway and Zone/Boiler controller.All these PCBs have Atmega328 with 8MHz boot-loader with onboard MIC5205-3.3 voltage regulator to step down power for radio and Atmega328.

Sketches

On first attempt i have plan to use default mysensor sketches without any modification to prove no hardware issue/error. once i have successful communication i can customize these sketches to improve things. important to note i m using 433Mhz version of LoRa module.

1-Wire DS18b20 Temperature Sensor

Following sketch for 1-Wire DS18b20 digital temperature sensor powered by 3 x AAA batteries, upon successful connection to gateway led blink once and second time blink for number of attached sensors. LoRa RFM69 module feed from LG33 regulator with 10uF and 100nF cap for smoothing out power to radio.

//  _____    _   _    _                             
// |  __ \  (_) | |  | |                           
// | |__) |  _  | |__| |   ___    _ __ ___     ___ 
// |  ___/  | | |  __  |  / _ \  | |_  \_ \   / _ \ 
// | |      | | | |  | | | (_) | | | | | | | |  __/
// |_|      |_| |_|  |_|  \___/  |_| |_| |_|  \___|
//
//    S M A R T   H E A T I N G   C O N T R O L 
// *****************************************************************
// *       Battery Powered OneWire DS18B20 Temperature Sensor      *
// *           Version 0.01 Build Date 21/12/2019                  *
// *            Last Modification Date 22/12/2019                  *
// *                                          Have Fun - PiHome.eu *
// *****************************************************************

// Enable debug prints to serial monitor
#define MY_DEBUG

//Set MY_SPLASH_SCREEN_DISABLED to disable MySensors splash screen. (This saves 120 bytes of flash)
#define MY_SPLASH_SCREEN_DISABLED

//Define Sketch Name 
#define SKETCH_NAME "Temperature Sensor"
//Define Sketch Version 
#define SKETCH_VERSION "0.01"

// Enable and select radio type attached
#define MY_RADIO_RFM69 // Define for using RFM69 radio
//#define MY_RADIO_RFM95

#define MY_RFM69_FREQUENCY RFM69_433MHZ  // Define for frequency setting. Needed if you're radio module isn't 868Mhz (868Mhz is default in lib)
#define MY_RFM69_NEW_DRIVER
#define MY_IS_RFM69HW  // Mandatory if you radio module is the high power version (RFM69HW and RFM69HCW), Comment it if it's not the case
// #define MY_RFM69_NETWORKID 100  // Default is 100 in lib. Uncomment it and set your preferred network id if needed
// #define RFM69_IRQ_PIN 2  // Default in lib is using D2 for common Atmel 328p (mini pro, nano, uno etc.). Uncomment it and set the pin you're using. Note for Atmel 328p, Mysensors, and regarding Arduino core implementation D2 or D3 are only available. But for advanced mcus like Atmel SAMD (Arduino Zero etc.), Esp8266 you will need to set this define for the corresponding pin used for IRQ
// #define MY_RFM69_IRQ_NUM 4 // Temporary define (will be removed in next radio driver revision). Needed if you want to change the IRQ pin your radio is connected. So, if your radio is connected to D3/INT1, value is 1 (INT1). For others mcu like Atmel SAMD, Esp8266, value is simply the same as your RFM69_IRQ_PIN
// #define MY_RFM69_SPI_CS 15 // If using a different CS pin for the SPI bus. Use MY_RFM69_CS_PIN for the development branch.

//#define MY_RFM69_ATC_MODE_DISABLED
//#define MY_RFM69_TX_POWER_DBM 20

//PiHome - Make Sure you change Node ID, for each temperature sensor. 21 for Ground Floor, 20 for First Floor, 30 for Domastic Hot Water.
#define MY_NODE_ID 30

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

#define ledpin 4 			// LED for one Blink Power On, second blink for temperature sensors after successfull radio contact with gateway and three blinks for low battery 

// Define sensor node childs
#define CHILD_ID_BATT 1
#define CHILD_ID_TEMP 0

#define COMPARE_TEMP 10 // Send temperature only if changed? 1 = Yes 0 = No, > 1 - force send if it value not sent that number of times and value is valid (keep lower than notice interval)
#define COMPARE_BVOLT 1 // Send battery voltage only if changed? 1 = Yes 0 = No, > 1 - force send if it value not sent that number of times
#define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected 

#define MAX_ATTACHED_DS18B20 1
unsigned long SLEEP_TIME = 56000; // Sleep time between reads (in milliseconds)

int batteryNotSentCount=0;
int temperatureNotSentCount[MAX_ATTACHED_DS18B20];

// Battery related init
int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
float oldBatteryV = 0;
MyMessage msgBatt(CHILD_ID_BATT, V_VOLTAGE);

// Dallas Temperature related init
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
float lastTemperature[MAX_ATTACHED_DS18B20];
int numSensors=0;
bool receivedConfig = false;
bool metric = true;
// Initialize temperature message
MyMessage msg(CHILD_ID_TEMP, V_TEMP);

void before(){
  // Startup up the OneWire library
  sensors.begin();
}

void setup(){

	//This is LED pin set to output and turn it on for short while 
	pinMode(ledpin, OUTPUT);
	digitalWrite(ledpin, HIGH);
	delay(60);
	digitalWrite(ledpin, LOW);

	// requestTemperatures() will not block current thread
  sensors.setWaitForConversion(false);
  // needed for battery soc
  // use the 1.1 V internal reference
  #if defined(__AVR_ATmega2560__)
      analogReference(INTERNAL1V1);
  #else
      analogReference(INTERNAL);
  #endif
}

void presentation() {
	// Send the sketch version information to the gateway and Controller
	sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
	// Fetch the number of attached temperature sensors  
	numSensors = sensors.getDeviceCount();
	//Blink LED as number of sensors attached
	blink_led(numSensors, ledpin);
	
	//check if attached sensors number is grater then 0 if no then put led on solid
	#if numSensors > 0
		digitalWrite(ledpin, HIGH);
	#else 
		digitalWrite(ledpin, LOW);
	#endif
	
	
  // Present all sensors to controller
  for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
     present(i, S_TEMP);
  }
}

void loop(){
	
	int battSensorValue = analogRead(BATTERY_SENSE_PIN);
	float batteryV  = battSensorValue * 0.011828;    //R1 1M, R2 100K divider across battery and using internal ADC ref of 1.1v
	int batteryPcnt = ((batteryV - 2.5) / (4.5 - 2.5) * 100); // for 3 x AAA Battery Powered
		
	#ifdef MY_DEBUG
		Serial.print("Pin Reading: ");
		Serial.println(battSensorValue);
		Serial.print("Battery Voltage: ");
		Serial.print(batteryV);
		Serial.println(" v");
		//Print Battery Percentage
		Serial.print("Battery percent: ");
		Serial.print(batteryPcnt);
		Serial.println(" %");
	#endif
	
	#if COMPARE_BVOLT == 1
		if (oldBatteryV != batteryV) {
			send(msgBatt.set(batteryV, 2));
			sendBatteryLevel(batteryPcnt);
			oldBatteryV = batteryV;
		}
	#elif COMPARE_BVOLT == 0
		send(msgBatt.set(batteryV, 2));
		sendBatteryLevel(batteryPcnt);
	#else
    if (oldBatteryV != batteryV || batteryNotSentCount>=COMPARE_BVOLT) {
      send(msgBatt.set(batteryV, 2));
      sendBatteryLevel(batteryPcnt);
      oldBatteryV = batteryV;
      batteryNotSentCount=0;
    }
    else{
      batteryNotSentCount++;
    }
	#endif

	// Fetch temperatures from Dallas sensors
	sensors.requestTemperatures();
	// query conversion time and sleep until conversion completed
	int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
	//sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
	sleep(conversionTime);
  // Read temperatures and send them to controller 
	for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
		// Fetch and round temperature to one decimal
		float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;

		// Only send data if temperature has changed and no error
		#if COMPARE_TEMP == 1
			if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
				// Send in the new temperature
				send(msg.setSensor(i).set(temperature,1));
				// Save new temperatures for next compare
				lastTemperature[i]=temperature;       
			}
		#elif COMPARE_TEMP == 0
			if (temperature != -127.00 && temperature != 85.00) {
			// Send in the new temperature
				send(msg.setSensor(i).set(temperature,1));
			}
		#else
		if ((lastTemperature[i] != temperature || temperatureNotSentCount[i]>=COMPARE_TEMP) && temperature != -127.00 && temperature != 85.00) {
			// Send in the new temperature
			send(msg.setSensor(i).set(temperature,1));
			// Save new temperatures for next compare
			lastTemperature[i]=temperature; 
			//Reset values not sent count
			temperatureNotSentCount[i]=0;      
		}else{
			lastTemperature[i]=temperature; 
			temperatureNotSentCount[i]++;
		}
		#endif
	}
	
	//Condition to check battery levell is lower then minimum then blink led 3 times
	if (batteryV < 2.0) { //for 3 x AAA Battery Powered Sensor 
		blink_led(3, ledpin);
	}
	//go to sleep for while
	sleep(SLEEP_TIME);
}

//Blink LED function, pass ping number and number of blinks usage: blink_led(variable or number of time blink, ledpin);
void blink_led(int count, int pin){
	for(int i=0;i<count;i++){
		digitalWrite(pin, HIGH);
		delay(700);
		digitalWrite(pin, LOW);
		delay(700);
	}
}

ESP8266 Smart Home Gateway

ESP module used for this test  have micro usb and onboard 3.3v voltage regulator. ESP powered from 5v power supple through micro USB and RFM69 module powered through AMS1117-3.3v regulator with 10uF and 100nF cap for smoothing out power to radio.

//  _____    _   _    _                             
// |  __ \  (_) | |  | |                           
// | |__) |  _  | |__| |   ___    _ __ ___     ___ 
// |  ___/  | | |  __  |  / _ \  | |_  \_ \   / _ \ 
// | |      | | | |  | | | (_) | | | | | | | |  __/
// |_|      |_| |_|  |_|  \___/  |_| |_| |_|  \___|
//
//    S M A R T   H E A T I N G   C O N T R O L 
// *****************************************************************
// *       Battery Powered OneWire DS18B20 Temperature Sensor      *
// *           Version 0.01 Build Date 20/12/2019                  *
// *            Last Modification Date 21/12/2019                  *
// *                                          Have Fun - PiHome.eu *
// *****************************************************************

// Enable debug prints to serial monitor
#define MY_DEBUG

// Use a bit lower baudrate for serial prints on ESP8266 than default in MyConfig.h
#define MY_BAUD_RATE 9600

// Enables and select radio type (if attached)
//#define MY_RADIO_RF24
//#define MY_RADIO_RFM69
//#define MY_RADIO_RFM95

#define MY_GATEWAY_ESP8266

#define MY_WIFI_SSID "MySSID"
#define MY_WIFI_PASSWORD "MyVerySecretPassword"


// Enables and select radio type (if attached)
#ifdef ESP8266
// For RFM69
#define MY_RADIO_RFM69
#define MY_RFM69_NEW_DRIVER
#define MY_RFM69_FREQUENCY RFM69_433MHZ // (868Mhz is default in lib) For other frequency, add this define to your sketch and set it to your preferred value in RFM69_433MHZ, RFM69_868MHZ or RFM69_915MHZ
#define MY_IS_RFM69HW // Omit if your RFM is not "H" - Mandatory if you radio module is the high power version (RFM69HW and RFM69HCW), Comment it if it's not the case
#define MY_RFM69_NETWORKID 100  // Default is 100 in lib. Uncomment it and set your preferred network id if needed

#define MY_RFM69_IRQ_PIN D1
#define MY_RFM69_IRQ_NUM MY_RFM69_IRQ_PIN
#define MY_RFM69_CS_PIN D8 // NSS. Use MY_RFM69_SPI_CS for older versions (before 2.2.0)

// For RFM95
//#define MY_RADIO_RFM95
//#define MY_RFM95_IRQ_PIN D1
//#define MY_RFM95_IRQ_NUM MY_RFM95_IRQ_PIN
//#define MY_RFM95_CS_PIN D8
#endif
// Enable UDP communication
//#define MY_USE_UDP  // If using UDP you need to set MY_CONTROLLER_IP_ADDRESS below

// Set the hostname for the WiFi Client. This is the hostname
// it will pass to the DHCP server if not static.
//#define MY_HOSTNAME "sensor-gateway"

// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP)
//#define MY_IP_ADDRESS 192,168,178,87

// If using static ip you can define Gateway and Subnet address as well
//#define MY_IP_GATEWAY_ADDRESS 192,168,178,1
//#define MY_IP_SUBNET_ADDRESS 255,255,255,0

// The port to keep open on node server mode
#define MY_PORT 5003

// How many clients should be able to connect to this gateway (default 1)
#define MY_GATEWAY_MAX_CLIENTS 2

// Flash leds on rx/tx/err
// Led pins used if blinking feature is enabled above
#define MY_DEFAULT_ERR_LED_PIN 16  // Error led pin
#define MY_DEFAULT_RX_LED_PIN  16  // Receive led pin
#define MY_DEFAULT_TX_LED_PIN  16  // the PCB, on board LED
#define MY_WITH_LEDS_BLINKING_INVERSE

#if defined(MY_USE_UDP)
#include <WiFiUdp.h>
#endif

#include <ESP8266WiFi.h>
#include <MySensors.h>

void setup()
{
	// Setup locally attached sensors
}

void presentation()
{
	// Present locally attached sensors here
}

void loop()
{
	// Send locally attached sensors data here
}

For your knowledge for LoRa on WiKi page, nRF24L01 temperature sensors powered by 18650 battery link