Summary
The Particle Electron provides the capability of publishing data to “the cloud” at regular intervals via a 3G cellular connection. Sensors to capture weather data these days are very affordable, and data rates for the Electron are cheap (base rate of $2.99 for the first MB per month and $0.99 per MB thereafter). This gives me the opportunity to build and deploy a weather station that will provide real-time data collected from a remote location. Commercial weather stations with similar functionality are currently retailing for ~$1,000+ and require you to pay ~$200+ annually for their service plan. Real-time access to weather data at my field sites allows me to perform analyses that require time-critical weather data (e.g., crop growth and nutrient cycling simulation models) without having to travel to the site to physically retrieve the data. As an agricultural researcher and farm manager, real-time weather data collected from my field sites allows me to do a better job managing those sites.
Take a look at the data being collected and published every 30 minutes to ThingSpeak from my station in Waseca, MN! If it's winter, this station is probably indoors and will not be publishing data, but past data can be viewed by clicking the link.

And here’s the weather data being published to Weather Underground from the station at my parent’s dairy farm in Greenwood, WI. If it's winter, this station is probably indoors and will not be publishing data, but past data can be viewed by clicking the link.
Here I go through the steps I took to set up the Particle Electron and build my weather stations. I hope this is helpful, and if you build one for yourself, I’d love to hear from you!
A special thanks to Haodong Liang as much of the sensor-related code was adapted from his hackster.io project!
Parts list
Listed prices are what I paid and are only estimates
Required ($262.11)
- Particle Electron - $69.00
- Tipping bucket rain gauge - $29.95
- Anemometer (Wind speed sensor) - 44.95
- Digital Temperature & Humidity Sensor -$9.95
- Photoresistor (I had one available, so I just included it in my project) - < $1.00
- Solar Radiation Shield -$9.99
- I noticed the price increased to $17.81 about a week after purchasing
- This is certainly oversized for our sensor, but was the cheapest I found. The fins do snap off from the bottom and will reduce the size.
- Boost Voltage Converter (to 12V) - $5.95
- If upgrading to a 12V battery, the boost voltage converter isn’t necessary as you can connect directly to the 12V battery)
- Tripod - $71.63
- 7" Spike Nails - $3.39
- 8-pin IP68 Multipole Plug Socket - $4.75
- PVC fittings for mounting sensors off the ground - $11.55
- Drain Strainer (to be used as a platform for tipping bucket) - $ 3.99
- 1" PVC Union - $3.98
- 3/4" x 5’ PVC - $1.28
- 3/4" PVC Elbow - $0.28 x 2 = $0.56
- 3/4" PVC Tee - $0.32
- 3/4" PVC Cap - $0.34 x 2 = $0.68
- 1" x 3/4" Spigot x Slip PVC Bushing (not pictured) - $0.74

Soil Moisture Upgrade ($115.95)
- Watermark Soil Moisture Tension Sensor - $43.00
- Watermark Voltage Adapter 200SS-VA - $58.00
- ADS1115 16-bit Converter - $14.95
12V Battery Upgrade ($82.47)
- Larger battery (12V) - $36.99
- Battery box - $11.99
- Solar Panel - $21.55
- Charge Controller - $9.99
- JST Jumper 2 Wire Assembly (optional; provides “unplugging” flexibility for switching between 12V and 3.7V battery)- $0.95
Consumable Parts and Electronics
- Double Sided Protoboard - 1X
- 10K Ohm Resistors - 2X
- 200 Ohm Resistor - 1X
- Wire, solder, shrink tubing, battery terminals (for the 12V battery upgrade), soldering iron, PVC cement, plumbing goop, hardware and tools for mounting sensors and solar panel, etc.
Electron Setup
1. Be sure your Particle Electron is activated
This requires the SIM card that shipped with your Electron, as well as a valid credit card for billing.
2. Update Particle System Firmware (may not apply)
You may have to update the Particle System Firmware if it’s your first time using the Electron and you haven’t done so already.
When clicking the compile and download icon, I received a notification saying “This project is only compatible with Particle system firmware v0.5.3 or later…” and that I will need to update my firmware. I first tried to update firmware via their “preferred” method (i.e., using Firmware Manager), but the GUI just froze on me, even after a couple restarts (I am using a Windows 10 machine). In the interest of minimizing data consumption, I definitely did not want to update wirelessly, so here I describe what I had to do update via Particle-cli:


If you have not done so already, install particle-cli according to these instructions.
Note 1: “particle-cli” is Particle’s Command Line Interface that provides a robust set of tools to configure and set up your Electron.
Note 2: You must be sure node.js is installed to be able to successfully use particle-cli.
With the Particle Electron connected to the computer via USB, login to the Particle by typing particle login
in your Terminal or Command Prompt (green box in image below), then update your Particle by typing particle update
(blue box).

Return to the online Particle Build Web IDE and compile and download firmware (click the little cloud icon shown above) - it should proceed without the error message now.
Wiring Diagram
1. Connect your sensors to the Electron according to the following:
-
DHT Tempurature/humidity sensor --> D5
-
Photoresistor --> A1
-
Reed switch (rain pin) --> D2
-
Anemometer --> A2
-
ADS1115 16-bit converter --> SCL to D1; SDA to D0; note also that ADDR on ADS1115 should be connected to ground
-
Watermark signal wire --> ADS1115 A3 pin
Protoboard wiring diagram for connecting the temperature/humidity sensor, photoresistor, reed switch (tipping bucket rain gauge), Watermark (soil moisture), and anemometer.
I definitely recommend connecting everything via a breadboard before soldering anything to be sure the sensors and software are behaving as expected.
Note 1: This wiring diagram was created with fritzing; the .fzz file can be downloaded from Github and loaded into Fritzing for more detail; the Fritzing software also implements interactive tooltips that show the pin ID when hovering with your mouse.
Note 2: If you are using a three-pin temperature/humidity and/or a three-pin photoresistor sensor, the 10K Ohm pullup resistor may already be attached to the sensor itself. If so, the pullup resistor between 3V3 and signal on the protoboard is not necessary. Refer to this tutorial for details regarding the different sensor styles.
Note 3: Double check the input pins and be sure they coincide with the pins declared in the code.
There are photos showing my protoboard wiring and sensors in the Mounting the Hardware section. Check them out to see how I did it.
Understanding the Code
Particle uses an online IDE for modifying and compiling Particle code before it can be uploaded to the Electron. My code, electron-weather.ino, can be downloaded or copied from Github so you can follow along.
I’m not going to discuss every bit of the code in the electron-weater.ino file, but here I will generally explain what is being done when the Electron is connected to sensors and is in an active state (measuring and publishing data).
1. Libraries
- Adafruit_ADS1X15.h
- To be able to interpret the ADS1115 16-bit Converter and measure soil matric tension
- stdint.h
- To get a 16-bit data type so we can measure the full dynamic range of ADS1115 output
- Adafruit_DHT.h
- To measure temperature and humidity
- SdFat.h
- To write data to a micro SD card (this code has not yet been validated)
2. Time
Among the first several lines of code, you’ll find the variables sensorCapturePeriod
and publishPeriod
. The values of these variables should be changed depending on your preference for how often you’d like the sensors to capture data (multiple captures per publish period are averaged over the entire publish period), and how often you’d like to publish the data to the cloud. The code below will capture sensor data every 5 seconds and publish data every 30 minutes.
// Time
// ---
// Set time zone and daylight savings information and initiate
// intervals to determine when to capture sensor readings and
// publish data.
float offsetDST = Time.; // Get current DST offset; default is +1.0
// I read that Particle does not automatically detect DST, so
// it must be manually delclared; however, whenever publishing
// time, Unix UTC is expected, so I don't want to globally
// adjust the Time variable.. If I did, then the Unix timestamp
// may be altered (not 100% sure about this..?). My goal in
// declaring time zone is to know when to reset daily rain.
// Time.beginDST(); // Because DST is not automatically detected by Particle, it must be manually declared
// Time.endDST(); // Comment out beginDST() or endDST() depending on if DST is in effect
unsigned int isDST = 1; // Change to 0 if not observing daylight savings time
int gmt_timeZone = -6; // Change to appropriate time zone for your device
unsigned int sensorCapturePeriod = (5); // units are seconds
unsigned int publishPeriod = (60 * 30); // units are seconds
unsigned int sensorCount = 1; // this provides 32 bits of dynamic range
unsigned int publishCount = 1;
time_t initialTime;
time_t endOfDay;
time_t scheduledSensor;
time_t scheduledPublish;
Because I’m a scientist and I like consistency, I added functionality in the void setup()
function to begin the effective “active time” (this is kept track of in the code via the initialTime
variable) of the Electron either at the top or bottom of the hour. That is, after flashing your code, the Electron will begin taking sensor measurements when Time.minute() == 0
or when Time.minute() == 30
. This will effectively result in consistent times for both the sensor readings and the publish events. Using a publishPeriod = (30*60)
as in the above code, data will consistently be published every 30 minutes at the top and bottom of every hour. Because the code also keeps sensorCount
and publishCount
variables, we are able to schedule future sensor readings and publish events based on our initialTime
. This is noteworthy because it results in future sensor reading times to be independent of the time that passes when sensors are capturing measurements. Sure, it is perhaps less than a millisecond to have a sensor take a measurement, but if we’re taking thousands of measurements every day, this adds up over a period of weeks or months (and will inevitably result in inconsistencies in the time that data are captured and recorded from day to day). You don’t care about such consistency? Feel free to comment out the initalTime
lines and add a single line of code to set the inital time --> initialTime = Time.now();
Example: if I flash code to my Electron at 09:07:00, the initialTime
variable will be adjusted to represent 09:30:00. The sensors will begin capturing data after the 09:30:00 time (how long after depends on when the sensorCapturePeriod
was set), and the first publishing event will occur at 10:00:00 (assuming the publishPeriod
is kept at 30 minutes). The following code publishes the initial system time, time in which data will first begin being collected, time zone that is set, whether or not daylight savings time is being observed, and UTC time corresponding to the end of the day. When it comes time to upload code to the Electron, be sure these variables are correctly set for your locale.
void
According the Particle Docs, the Electron will establish a “handshake” with the Particle server:
- whenever the device comes online and
- once per week
Therefore, the Electron’s system time will be updated only after successfully establishing this “handshake” (once per week), and the system time may deviate from actual time by several seconds between handshakes.
3. Publishing data
The app has three methods of publishing data:
- via particle.io logs
- via ThingSpeak
- via Weather Underground
Publishing to a web server (e.g., ThingSpeak, Weather Underground, etc.) requires you to set up a user account and use a webhook to send data from the Electron to the external web server. Please refer to the Publish data to a Webserver section below for steps on how to set up a webhook between your Electron and the web server. For now, I will just demonstrate how to publish to the particle.io logs.
Publishing to particle.io logs is good for testing as it is much simpler (less code to change), but publishing to ThingSpeak (or any other web server) is recommended when you’re sure your device is working as expected and is being deployed remotely (my weather station is at a field site over 80 miles away). To save on my data use, I usually comment out one of the publish methods in the “Publish” section of the void loop()
(the example below has the publishToThingSpeak()
function commented out and will only publish to ThingSpeak).
// Publish
if (Time. >= scheduledPublish)
I do not have a wind vane to measure the wind direction for my prototype, but the code regarding the wind vane should collect wind direction measurements. You’ll have to uncomment the wind_direction
variable and add it to the appropriate publishing function (e.g., publishToParticle()
) for the wind direction measurement data to publish.
Create the App/Firmware
The Particle Build Web IDE is a web interface for modifying the code to be uploaded to your Electron. I recommend spending some time becoming familiar with its layout and the different features available.
Perform the following steps in the Web IDE to create and compile the app to a local directory:
- Create a new app by adding a name and description (description is optional)
- Import code by copying/pasting contents of electron-weather.ino (available on GitHub)
- Include the following libraries by clicking the ribbon icon on the left sidebar, searching for the library, and clicking the “Include in Project” button. Or, follow these links (I hope the links don’t die anytime soon):
- Verify your code by clicking the checkmark icon
- Modify your code to suit your needs (e.g., comment out sensor variables that you do not have connected, adjust sensor pins if necessary, etc.)
Note: I try to make a habit to Verify my code after nearly every change I make to be sure there aren’t any syntax errors. I don’t find the Particle Build Web IDE to be particularly useful for debugging and spotting syntax errors. Much time can be saved by Verifying your code often.
- Compile and download a binary version of your app by clicking the cloud icon with a downward pointing arrow
Upload the App and Publish Data
Perform the following steps to upload the app and publish your data:
-
Flash the compiled app from your local machine to the Electron by navigating to the directory to which the compiled binary version of you app was saved (.bin file). Then, with the Particle Electron connected to the computer via USB, flash the firmware from your local machine to the Particle Electron. In the Terminal or Command Prompt, type:
particle serial flash <firmware.bin>
Note that the Electron must be in “listening mode” (hold the MODE button on the Particle Electron for ~3 seconds until the LED is blinking blue)

Note 1: I saw several websites (including the Particle Docs page) stating that I should use the following command for flashing my firmware, but I did not have success (maybe it may have worked for an older version of Particle products…?):
particle flash -serial <firmware.bin>
Note 2: I could choose to flash my app wirelessly, but I don’t like to if I can use another method as it is data-intensive.
- View the data being published by your Particle Electron! If the Electron was set up correctly and the compiled app was flashed to the Electron, you should be able to view a live stream of your data from your token web URL (if you are logged in to particle.io, data will be published at your Electron’s logs page).
Publish Data to a Web Server
Being able to view the published data from particle.io is nice to be able to see that the microcontroller is actually measuring and publishing data, but we are limited in what we can do with the data. Webhooks are a way to send data collected from our Particle Electron to other apps and services connected to the internet. Basically, webhooks allow us to get our data where we need it. Because the Electron is a “cellular-only” device, we must use webhooks as an internet aggregator to save our data.
Here I explain how to use a webhook to listen for specific events published by my Electron, in which case I trigger a web request to the token web URL that temporarily displays data from my Electron (the token web URL is shown at the top of the particle.io logs page). I used a webhook to allow ThingSpeak and/or Weather Underground to listen to publish events from my Particle Electron. ThingSpeak is an open IoT platform that offers free data storage of time-stamped data and allows users to easily view, analyze, and export their data. A ThingSpeak channel can be public or private. Weather Underground is a weather platform that allows users to register their personal weather station (PWS) and publish data real-time for the public to access via the web. Both ThingSpeak and Weather Underground have mobile apps to view data from a smartphone or tablet:
- ThingSpeak
- ThingView for Android
- iOS - none
- Weather Underground
Both platforms have advantages and disadvantages, so I’d just suggest trying them both to see which fits better for you. I like how Weather Underground incorporates the entire forecast and allows you to easily check the weather from other stations in the area, but I think ThingSpeak has a much more straightforward approach to downloading your data. I’m sure there are dozens of other platforms you could try out to view your data as well (e.g., Google Sheets).

Publishing Data to ThingSpeak
You will need:
- a valid ThingSpeak Channel Number
- a valid ThingSpeak Write API Key
- to know the number of fields being used on your ThingSpeak channel (i.e., the number of variables/sensor measurements being output)
Refer to the Particle Docs page to:
- Set up and configure your ThingSpeak account.
- Create a channel with the appropriate number of fields - I used all eight to record temperature, humidity, light, soil moisture tension, daily rainfall, wind speed, wind gust, and battery voltage).
- Make note of the Channel ID and Write API Key (and be sure to keep the Channel ID and Write API key a secret!)
- Set up and activate Webhooks to your Particle account.
- Create the webhook integration
Note: for my weather station, I send data via the webhook using the .json file format, so the following is a bit different from what’s published on the Particle Docs page.
To create the JSON webhook via the Particle CLI, perform the following steps:
- Create a JSON file with a Webhook option. To do so, make a copy of the following code and save it appropriately (I saved my JSON as webhook_thingspeak.json):
Note: The webhook request (“requestType”) is a POST, which is a method of sending data to another web server. In this case, we are using ThingSpeak, but it could be another server (like Google Sheets).
- Open the Terminal or Command Prompt and login to the Particle CLI (optional).
- Navigate to the directory to which the JSON file resides, then run the following command to create the webhook for your account (replacing the angle brackets with your .json filename):
particle webhook create <webhook_thingspeak.json>
- If successful, you will get a success message returned on your Terminal or Command Prompt, and you will be able to see the webhook on the Particle Console webpage:

You will have to modify some parts of the code before successfully publishing to ThingSpeak.
- Change your
thingspeakChannelNumber
and the writeapi_key
(these variables are towards the top of the electron-weather.ino file) to reflect those shown on your ThingSpeak Channel.
- Remember to keep these secret, especially the write API key!
// Publish
unsigned long thingspeakChannelNumber = 123456;
//char thingSpeakWriteAPIKey[] = "0GNFLHX4317NSAH4";
String api_key = "ABC1DEF2GHI3JKL4"; // ThingSpeak Write API Key.
String field1 = "";
String field2 = ""; // i.e. field2 is null
String field3 = "";
String field4 = "";
String field5 = "";
String field6 = "";
String field7 = "";
String field8 = "";
String status = "";
- Modify the number of fields (i.e.,
field1
,field2
, etc. shown above) to reflect the number of fields that are enabled on your ThingSpeak Channel (screenshot shown below).

- Modify the number of fields and adjust the variables containing the data accordingly for each field in the
publishToThingSpeak()
function:
void
- Near the end of the electron-weather.ino file, there is a
createThinkSpeakjson()
function. If not using all eight fields, you will have to adjust the number of fields:
void
- Compile and download, then flash the app to your Electron. If your code was set up correctly, timestamped data will begin logging to your ThingSpeak account. I notice that it takes 3-5 seconds from the time it should publish until the time it actually gets published (publishing will occur at the top and bottom of every hour after data initially begin being collected). This discrepancy is expected as it takes some time to send data over the 3G network.
Publishing Data to Weather Underground
You will need:
- a valid Weather Underground Station ID
- a valid Weather Underground Password
Steps:
- Set up a Weather Underground account and add a new personal weather station. Check out the Support page if you are having any issues with this.
- Once your PWS is registered, you will see your Station ID and Station Key (be sure to keep these a secret!).
- Set up the appropriate webhooks. If you have not done so, please read through the Publishing Data to ThingSpeak sub-section above to get an overview of how webhooks are used. Much of the information covered in the ThingSpeak section also applies when publishing to Weather Underground.
To save a bit on my data usage, I created two separate Weather Underground webhooks - webhook_wunderground_norain.json
for when it hasn’t yet rained on a particular day and webhook_wunderground_rain.json
for when it has rained. The difference between the two is simply whether or not rainfall rate and daily rainfall are being published. If daily rainfall is zero, then I don’t publish the rainfall data. If you’d prefer, you could choose to always publish rainfall data and only use the one webhook.
Similar to creating the ThingSpeak webhook, you’ll have to opent the command prompt, navigate to the directory to which the JSON file resides, then run the following command to create the Weather Underground webhook (replacing the angle brackets with your .json filename(s)):
particle webhook create <webhook_wunderground_rain.json>
particle webhook create <webhook_wunderground_norain.json>
If you’d like to modify the data being published, be sure to modify both the webhook .json as well as your Particle code.
Note: Refer to the Particle Guide for tips on how to reduce data use.
Mounting the Hardware
I’m not sure if it was the best idea, but in the interest of keeping external parts to a minimum, I decided to put the Electron inside the tipping bucket enclosure. Because of this, in my prototype version, I struggled with running the wires from the Electron to the sensors outside the tipping bucket, and it also made some aspects of soldering challenging.
The second time around, I drilled the hole for the 8-pin IP68 Multipole Plug Socket higher on the external tipping bucket funnel. By drilling that hole above the electronics enclosure, the 8-pin IP68 plug socket does not hit against the electronics enclosure on the inside. You’ll just have to be careful not to drill the actual funnel when drilling this hole! For the hole in the internal electronics enclosure, I would drill as high as possible to make it easier to shimmy the Electron into the enclosure and reduce the likelihood that the wires will rub against the external funnel (the wires will also be closer to where your fingers can reach them, so this is a plus as well). I would also advise to make the hole in the internal electronics enclosure as small as possible while still being able to fit all the wires through because with a larger hole, there is a greater likelihood of moisture finding its way into the electronics enclosure.
Please scroll through the photos below to see the steps I took to build the platform and mount the hardware.