Thanks to the interest (and all the help) I have received for this board, I have partnered with SimpleSense to run a GroupGets campaign for this Electron Carrier. This campaign will run until June to see if we can get 50 orders. Thank you for your support!
OverviewI have been building IoT sensors for outdoor use for a few years now. Most of my focus has been on helping local parks better count and report the cars, bikers, joggers and hikers which use their facilities each day. By giving them an accurate and automatic way to measure park utilization, They can save significant labor costs, get a more complete count and facilitate reporting. My hope is that this work will show how important our parks are and help preserve and even expand funding for these vital community resources.
Longer term, I also want to collect environmental and health data with these devices and I realized that a general purpose enhancement to the Particle Electron would be useful in all manner of applications that I - or the community - might dream up. This project, developed in collaboration with the Particle community (see Team link) is open source and available to anyone who can wants to deploy IoT devices where there is no WiFi or utility power.
Here are some images of my devices in use today:
This project takes the Particle Electron - the cellular member of the Particle family - and extends its capabilities for outdoor use. I chose the Particle platform for three main reasons:
- The open nature of the platform and the vibrant user community
- The integrated nature of the platform which includes the device, the cellular service and a platform that allows for remote control, monitoring and upgrades
- The ability of the platform to be extended both in hardware and by easy integration with other on-line services such as Ubidots.
I focused on capabilities which I think are important and broadly applicable:
- Protection against electrostatic and over voltage events. These devices will be used in unprotected environments.
- Enhanced reliability since deployment may be in hard-to-get-to places.
- Local data storage as connectivity is not assured.
- Flexible power options by either utility or Solar energy
I arrived at this final list after extensive consultation with the Particle community through the Particle Forums. I have also built and tested these devices in various locations over the past 6 months. I have received significant help and advice and this document represents my effort to pay back these gifts and pass on the learning I have benefitted from.
Overall hardware design and System DiagramThe major components of the carrier board can be seen in the diagram above. They include:
- Power - The carrier board controls both the external power source as well as the LiPo battery. This enables power to be applied with a simple push button. In addition, the electron can perform a "hard reset" using a pin that will suspend all power for about 100 mSec. You can see these features in action in the circuit simluation video below (link to simulation here). I have also added a 5V boost power converter so there is a 3.3V and a 5V ic2 bus on the carrier.
- External Watchdog - This device provides an independent way to validate proper operation of the Electron and reset it as needed. As these devices are located across the park, making them as reliable as possible is a must. Each time the watchdog resets the Electron, it increments a counter that can be remotely monitored.
- FRAM storage - This give me a place to store "state" variables so the Electron can pick up where it left off if reset. It also provides a way to recover data if connectivity is lost.
- Temperature sensor - This is important as you may want to put over temperature alarms (Electron only good to 80° C) or low temp which should suspend charging the battery.
- Protection - All external power and signal lines are protected from power spikes and static discharge. Again, as these devices are located outdoors, I wanted to give them some protection from the elements.
I wanted the carrier board to be as small as possible so most of the components are on the bottom and the Electron, power connectors, power switch are on the other. I needed a large capacitor as I plan to use Solar power for some of my more report installations so this cap is also on the top. Note: The carrier requires you to solder the LiPo pin onto the Electron - this pin comes unpopulated from Particle.
You can order the OSH Park board using this link. I picked components that are hand solderable (0805 is the smallest surface mount component) but, I recommend using a stainless steel stencil from OSH Stencils and using a reflow oven for best results. You can order the stencil for this board at this link.
I have attached a link to a Github Repository that uses the carrier board as part of a Passive Infrared (PIR) sensor based person counter. In this section, I will explain software concepts so you can integrate it into your code.
- Watchdog Timer - This device will periodically signal the Electron that a response is needed. The Electron then has one period (set by the value of a resistor on the carrier from a few milliseconds to a couple hours) to respond or "pet" the watchdog. If this does not happen in time, the watchdog assumes the Electron is locked up and resets the device. Here is a timing diagram from TI's data sheet.
Here is the minimal code for the watchdog timer.
// Included Libraries
#include "Adafruit_FRAM_I2C.h" // Library for FRAM functions
#include "FRAM-Library-Extensions.h" // Extends the FRAM Library
#include "electrondoc.h" // Documents pinout
// Pin Constants
const int donePin = D6; // Pin the Electron uses to "pet" the watchdog
const int wakeUpPin = A7; // This is the Particle Electron WKP pin
// Program Variables
int resetCount; // Counts the number of pin reset
volatile bool doneEnabled = true; // This enables petting the watchdog
void setup()
{
Serial.begin(9600);
pinMode(donePin,OUTPUT); // Allows us to pet the watchdog
pinMode(wakeUpPin,INPUT_PULLDOWN); // This pin is active HIGH
// The watchdog timer will signal us and we have to respond
attachInterrupt(wakeUpPin, watchdogISR, RISING);
resetCount = FRAMread8(RESETCOUNT); // Retrive system recount data
// Check to see if we are starting from a pin reset
if (System.resetReason() == RESET_REASON_PIN_RESET)
{
resetCount++;
FRAMwrite8(RESETCOUNT,resetCount); // increment likely a watchdog reset
}
Serial.print("Reset count: ");
Serial.println(resetCount);
}
void loop() {
}
void watchdogISR()
{
if (doneEnabled)
{
digitalWrite(donePin, HIGH);
digitalWrite(donePin, LOW);
}
}
When you have a particularly high-risk operation such as publishing data and waiting for a response, you can set doneEnabled = false and only set it back to true once the response is received.
- FRAM - This is the Fujitsu non-volatile and fast memory which can store up to 256k. In my code, I build out a fairly complex memory map of this space where I store system settings, state and data. You don't have to go this far in order to get real value from this storage. Note: The Electron has "EEPROM - like" storage as well so, if you don't need more than a couple kilobytes of storage, you can leave this part off the carrier. I have created a set of functions to make reading and writing 8, 16 and 32 bit numbers easier. Here is some sample code to get you started.
//These defines let me change the memory map and configuration
#define VERSIONNUMBER 7 // change each time the memory map is changed
// First Word - 8 bytes for setting global values
#define RESETCOUNT 0x3 // How often the Electron was reset
//Second Word - for storing current counts
#define CURRENTDAILYCOUNTADDR 0xA // Current Daily Count
#define CURRENTCOUNTSTIME 0xC // Time of last count
// Included Libraries
#include "Adafruit_FRAM_I2C.h" // Library for FRAM functions
#include "FRAM-Library-Extensions.h" // Extends the FRAM Library
#include "electrondoc.h" // Documents pinout
// FRAM and Unix time variables
uint8_t abyte = 255; // 8-bits
uint16_t doublebyte = 65535; // 16-bits
time_t t; // 32 bits time encouded as UNIX time
void setup()
{
Serial.begin(9600);
Wire.begin(); //Create a Wire object
if (fram.begin()) { // FRAM i2c addr in here, e.g. begin(0x51);
Serial.println(F("Found I2C FRAM"));
}
else {
Serial.println(F("No I2C FRAM found ... check your connections"));
}
// Check to see if the memory map in the sketch matches the data on the chip
if (FRAMread8(VERSIONADDR) != VERSIONNUMBER) {
Serial.print(F("FRAM Version Number: "));
Serial.println(FRAMread8(VERSIONADDR));
Serial.read();
Serial.println(F("Memory/Sketch mismatch! Erase FRAM? (Y/N)"));
while (!Serial.available());
switch (Serial.read()) { // Give option to erase and reset memory
case 'Y':
ResetFRAM();
break;
case 'y':
ResetFRAM();
break;
default:
Serial.println(F("Cannot proceed"));
BlinkForever();
}
}
}
void loop()
{
Serial.println("Here we will store and retrieve some values");
// Store the numbers
FRAMwrite8(RESETCOUNT,abyte);
FRAMwrite16(CURRENTDAILYCOUNTADDR,doublebyte);
FRAMwrite32(CURRENTCOUNTSTIME,t); // This stores a time as UNIX time
// Retrieve the numbers:
Serial.print("One byte:"); Serial.println(FRAMread8(RESETCOUNT));
Serial.print("2 bytes:"); Serial.println(FRAMread16(CURRENTDAILYCOUNTADDR));
Serial.print("4 bytes:"); Serial.println(FRAMread32(CURRENTCOUNTSTIME));
delay(2000);
}
void BlinkForever() // When something goes badly wrong...
{
Serial.println(F("Error - Cannot Proceed"));
while(1) {
digitalWrite(blueLED,HIGH);
delay(200);
digitalWrite(blueLED,LOW);
delay(200);
}
}
- Temperature Sensor - The TMP-36 is an analog sensor and the code to convert to temperature is relatively straight forward.
int getTemperature()
{
int reading = analogRead(tmp36Pin); //getting the analog reading
float voltage = reading * 3.3; // converting that reading to voltage
voltage /= 4096.0; // This is specific to the Electron
// converting from 10 mv per degree with 500 mV offset to degrees
// ((voltage - 500mV) times 100) - 5 degree calibration
int temperatureC = int(((voltage - 0.5) * 100));
temperatureF = int((temperatureC * 9.0 / 5.0) + 32.0); // convert Fahrenheit
return temperatureF;
}
Conclusion and Next StepsThese carriers have proved to be very reliable and have survived 6 months so far in the North Carolina Summer. I have started working on a Solar Implementation and have some ideas for future improvement. Please let me know if this is helpful and if you have any comments or suggestions that could help improve the carrier.
I have engaged Macrofab to manufacture assembled modules for me. If you would like an assembled module, send me a DM and I will arrange the details with you.
Thanks, Chip
Comments