Solar Powered Low Cost LoRa Node with Integrated Battery Holder

I wish to share my designs for a multipurpose LoRa microcontroller board based on the Atmel 328P microcontroller with an RFM95W LoRa module attached and LiPo Battery holder mounted on the reverse side of the board. Details of the design including PCB and BOM are available here.

The version 2, design details available here, adds onboard solar power LiPo charger for the integrated 18650 LiPo battery, using the CN3065. The idea is to provide a Low Cost LoRa module that makes all digital and analog inputs of the Atmel 328P available. This node can be used for prototyping. The board runs on 3.3V and the regulator on board is the MCP1700T-3302E/TT. No power LED is provided to reduce power consumption but an LED is connected to D7 via a 1K resistor.

If you plan to implement this project, remember to flash a bootloader unto the controller. Usually, I do this after the controller has been soldered on the board but before the LoRa module is welded on. This allows you to use the pads where the LoRa module should be to connect to the SPI bus of the controller for flashing.

Below are pictures of the finished version 1. Version 2 boards are currently in production.







Feedback and suggestions for improvement are welcome.


Good Work.

I do this after the controller has been soldered on the board but before the LoRa module is welded on.

Is it possible to flash the bootloader aftersoldering the RFM95 ?

In my experience, I doesn’t work. The SPI bus doesn’t respond correctly with more than one device on it.

It’s possible, but you need to PullUP SS!


Cool. Thanks for this info.

Here are some pictures of the Version 2 board, which includes connection for a 6V solar panel and solar charging for a LiPo battery using the CN3065. All unused analog and digital pins are exposed and there are connectors for 3.3V and GND on board. This allows connection of multiple sensors directly to the board. The LoRa module used if the RFM95W.

When encased, we will be using multiple nodes like this to monitor motion and environmental conditions in different locations within a city. I hope people will come up with other more creative applications.

Here are some photos…




Hi @aizukanne

I find very interesting your design. I may order some pcb’s myself. Have you tried them?
It could be very interesting any comment based on experience. Any bug until now? What about battery duration? It would be great if you provide some example code.

Thank you very much for sharing! :clap: :clap:

Hi xz81,

Yes I have tried them. No bugs noticed. The battery duration depends largely on application. Perhaps, if there was a standard application to be used to measure battery life that would help.
The voltage regulator on board the MCP1700T has Extremely Low Operating Current for Longer Battery Life (1.6 uA typical). I have been running the modules with a 1.25W solar panel attached so I have never had the batteries run out. I have an OTAA node which hasn’t been in the sun for a few weeks but is still running on a 5000mAH (18WH) 26650 LiPo. Battery is currently at 3.2V.

From my experience, battery life depends on your sketch. Reducing blink time for LEDs, increasing update interval etc, all help to increase battery life.

The code is the basic LMIC sketch in ADB or OTAA with the following pin Mapping

   // Pin mapping
    const lmic_pinmap lmic_pins = {
    .nss = 6,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 5,
    .dio = {2, 3, LMIC_UNUSED_PIN},

Here is a picture of one of the nodes


Hope that helps.

Thank you very much for the info.

this project fits into our current project plan for a dynamo based cargobikometer (kilometer counter) for a prototyp for our free cargobikes of The counter uses the dynamo frequency for calculating the distance.

With an extra solarmodule attached on the cargobike, the battery will be charged, if the cargobike is not moving and charged by the dynamo.


Hi @fLottes-Adlershof,

Sounds interesting. Will you be transmitting the readings over LoRa?
I will like know how it works out. The schematics and gerber are free to use and modify.

Good luck

Yes, that is the plan, transmitting the collected data via LoRaWAN to our own intenet server.

can you explain a bit more about that ‘sensor’ part… interesting


the signal from the hub dynamo are converted by a trigger into a rectangle signal. Then I measure the period of the signal with the pulseIn() function at pin 25 of my ESP32 device.

int getFrequency() {
  float freq = 0;
  // use pulseIn function
  // disable interrupt during measure
  // measure HIGH and LOW
  if ( debug == 1 ) {
    Serial.println("DEBUG: call pulseIn functions on measurePin:" + String(measurePin) );
  Htime = pulseIn(measurePin, HIGH, PULSE_TIMEOUT);   //read high time
  Ltime = pulseIn(measurePin, LOW,  PULSE_TIMEOUT);    //read low time
  if ( debug == 1 ) {
    Serial.println("DEBUG: after pulseIn functions" );
    Serial.println("DEBUG: Htime: " + String(Htime) );
    Serial.println("DEBUG: Ltime: " + String(Ltime) );
  //enable interrupts again

  Ttime = Htime + Ltime;
  if ( Ttime > 0 ) {
    if ( debug == 1 ) {
      Serial.println("DEBUG: Ttime = " + String(Ttime) );
    freq = 1000000 / Ttime; //getting frequency with Ttime is in micro seconds
  // display frequency

  if ( debug2 == 1 ) {
    return (freq_fixed);
  } else {
    return (freq);

Then the distance will be calculated:

void getDistance() {
  // speed in m/s wheel_size in mm
  current_speed = ( frequency / dynamo_pulse ) * wheel_size / 1000.0 ;

  // distance in m/s
  distance_during_measurement = current_speed * _MEASURE_INTERVAL;

  // calculate the current speed in km/h
  current_speed *= 3.6;

  // count the total distance in m of the current day
  distance_daily += distance_during_measurement;
  distance_daily_km = distance_daily / 1000.0 ;

  // count the total distance in m
  distance_total += distance_during_measurement;
  distance_total_km = distance_total / 1000.0 ;

  // convert distance_total_km  into integer with round function
  //distance_total_lora = round(distance_total_km);

  if ( debug == 1 )
    Serial.print("DEBUG: measurement_interval in seconds = ");
    Serial.print("DEBUG: current_speed in km/h = ");
    Serial.print("DEBUG: distance_during_measurement in m = ");
    Serial.print("DEBUG: distance_daily in m = ");
    Serial.print("DEBUG: distance_total in m = ");
    Serial.print("DEBUG: distance_total_lora in km = ");

But currently I have a problem, if I activate the LMIC functions in my code. With LMIC enabled the pulseIn() function returns always zero.

This is the main part with no activated LoRa functions.

void setup()
  pinMode(measurePin, INPUT);

  // initialize OLED display

  // initialize LoRa


void loop() {
  uint32_t currentSeconds;

  currentSeconds = (uint32_t) millis() / 1000;
  if ( debug == 2 ) {
    Serial.print("DEBUG: currentSeconds: ");
    Serial.print("DEBUG: measuretime: ");
    Serial.print("DEBUG: _MEASURE_INTERVAL: ");

  if ((currentSeconds - measuretime) >= _MEASURE_INTERVAL) {  // Wake up every xx seconds

    // get the dynamo frequency
    frequency = getFrequency();
    if ( debug == 1 ) {
      Serial.print("DEBUG: Frequency: ");

    measuretime = currentSeconds;


Do you have any idea, why the pulseIn function returns always zero, if LMIC is active?

Next time please take the time to format your message yourself.

Hi, good work. Can we use RFM95W module for commercial projects ?

Perhaps not directly related to this thread, but yes of course you can use the RFM95W for commercial projects, assuming you carry out the approriate testing and get certification for the end device.

1 Like

thank you so much for the information, I been dealing with this issue for a week trying to find a way to burn boot loader via ICSP while the lora module is soldered on

I’m Moses, Please how can i purchase this end node for a project in Nigeria.