LoraWAN Weather Station

The MiSol weather station is a DIY weather station. It is a white-labelled unit from the OEM manufacturer Fine Offset and is supplied with a RS485 connection for data transmission but no radio link. This project uses LoRaWAN as the radio link, and the The Things Network to collect the data.

Weather station



  • Mi.Sol headless weather station
  • RS485 - UART XY-017 TTL converter, for initial testing of RS485 protocol on a Linux box
  • Pycom LoPy with PySense base, or expansion board
  • LiPo battery
  • Weatherproof case
  • Antenna


  • config.json.template rename this file to config.json and replace the placeholder fields with your application and device keys from TTN.
  • uses ctypes to map the incoming comms protocol from the TTL USB converter on the serial port. Used for initial development.
  • is the structure of the raw Fine Offset message used in
  • sends the raw 17 byte data via LoRa and TTN, and takes the data from a TTN MQTT message and displays using the Curses library.
  • is the final LoRa accumulation and transmitter, using the protocol mapping developed in It sends specific fields rather than the whole data string.
  • is the structure of the raw Fine Offset message, but using the uctypes MicroPython library. It is used in

Weather Station

The MiSol weather station is supplied with a waterproof connector and extension lead which uses the RS485 protocol to transmit data. Even though this is an older serial protocol it is still useful in low-data-rate applications and those needing longer connection leads.

LoRa transmitter

I used a Pycom LoPy v1.0 for the transmitter, but will move to the LoPy4 as they are simpler to set low-power and sleep. I housed it in a waterproof case (the IP56 one from Pycom) and used an appropriate external antenna.

RS485 data

RS485 is a multi-drop serial protocol used for inexpensive networks. It uses a differential balanced line over twisted pair wires. I chose to use a RS485-UART converter (the XY017) during early testing as I was more familiar with programming for UART communications.

General observations

The raw RS485 bytes are sent from the weather station as a set of 17 binary characters. These are transmitted on the RS485 data wire every 16 seconds. I take these and transmit them immediately since they are already encoded. Given time I may further encode the measurements into a smaller number of bytes. LoRaWAN has a duty cycle which means the shorter the transmission time, the less likely you will exceed either the 1% allocated in the ISM band in the EU or the fair-use policy of 30 seconds per day on the TTN network for a single node.

Accumulate and average

The measurements provided by the weather station have different characteristics. Some can be averaged, others have peak and accumulated values. I expect that given the strictures of the LoRa duty cycle (and the TTN fair use policy) that there will be x 'reports' during the day, likely around 500 but depending on the transmission length.

Always send latest value

  • BAT is the battery state so just the last value can be transmitted
  • TMP should not vary rapidly, so just the last value is sent.
  • HM should also not vary rapidly, so only the last value is sent.
  • LIGHT/UVI should only vary slowly, so just transmitting the last value.


  • DIR can be averaged over the measuring interval. Min and max do not apply.
  • WIND speed seems to be an instant measure so need to be averaged
  • GUST just send the max number for the last interval.
  • RAIN seems to already accumulate! I do not know how this gets reset nor over what period it accumulates.


  • FC & SC are not needed, LoRaWAN uses either OTAA or ABP authentication.
  • CRC is not needed as LoRa is uses adaptive bit rates, and a forward error correction code. LoRaWAN is also encrypted.
  • CHECKSUM not needed, for the same reasons as CRC.


The data contains measurements which include temperature, humidity, UV, rainfall and others.

Name Type Bits Description Notes
FC c_uint8 8 Family code x'24'
SC c_uint8 8 Security code x'B3'
DIR c_uint8 8 Wind direction
DIR8 c_uint8 1 High-order bit of wind direction In next nibble to DIR
FIX c_uint8 2 Spare Spare bits
WSP8 c_uint8 1 High order bit of wind speed Goes with WIND below
BAT c_uint8 1 Battery 1=low
TMP c_uint16 11 Temperature
HM c_uint8 8 Humidity
WIND c_uint8 8 Wind speed
GUST c_uint8 8 Gust speed
RAIN c_uint16 16 Rainfall
UVI c_uint16 16 UV
LIGHT c_uint32 24 Light
CRC c_uint8 8 Cyclic Redundancy Check ignored
CHECKSUM c_int8 8 Checksum ignored

To be done


  • determine how rain measure gets accumulated and reset


  • Use IRQ interupt from the UART to wake from sleep, when that is available in the Pycom version of the MicroPython code
  • use the PySense base instead of expansion board and collect other data such as pressure from the on-board sensors