Luis Ortiz
Published © CC BY-NC-SA

IoT Energy Harvester Using Cayenne

The IoT Solar Harvester simplifies a problem: harvests ambient energy to power an IoT sensor and stores excess energy for later use.

AdvancedFull instructions provided4 hours4,196
IoT Energy Harvester Using Cayenne

Things used in this project

Hardware components

SparkFun ESP8266 Thing - Dev Board
SparkFun ESP8266 Thing - Dev Board
Linear Technology LTC3106
5V/500mAh 2.5W Solar Panel
N-Channel mosfet
I had the NTR4003N (SOT-23) on hand and worked nicely
Panasonic 1F 5.5V Super-capacitor
Other types of super-capacitors or rechargeable batteries may be used
Various Capacitors, Resistors and other components
Detailed list in the "LTC3106 Custom PCB detailed BOM" section
Jumper wires (generic)
Jumper wires (generic)

Software apps and online services

myDevices Cayenne
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)


Read more

Custom parts and enclosures

IoT Energy Harvester enclosure

Will keep the main components nicely organized


IoT Energy Harvester main Schematic

Schematic showing how all modules of the IoT Energy Harvester are connected

LTC3106 Energy Harvester schematic

Custom PCB for the LTC3106 (QFN-20) with programmable features

LTC3106 IoT Energy Harvester PCB settings

How to program the custom PCB for the LTC3106 IoT Energy Harvester


Code for the Sparkun ESP8266 Thing - Dev Board

Will push the sensors data to the Cayenne Dashboard and will manage the deep sleep cycles (when active).
// Code for the IoT Energy Harvester
// Luis Ortiz -
// October 4, 2017
// This sketch will publish analog sensor readings, uptime and DeepSleep status (Enabled/Disabled) to the Cayenne dashboard
// When deep sleep is enabled, set a jumper on the SLEEP-EN of the Sparkfun ESP8266 - Dev Board
// To upload the sketch. Jumper must be removed from the SLEEP-EN.

#define CAYENNE_PRINT Serial       // Comment this out to disable prints and save space
#define SLEEP_ENABLE_PIN 4         // Pin to manually Enable/Disable Deep Sleep.
#include <CayenneMQTTESP8266.h>


// WiFi network info.
char ssid[] = "ssid";
char wifiPassword[] = "wifiPassword";

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "Cayenne-username";
char password[] = "Cayenne-password";
char clientID[] = "Cayenne-clientID";

unsigned long lastMillis = 0;

// To enable deep sleep: SLEEP_ENABLE_PIN is high or left disconnected -INPUT_PULLUP-. Jumper is required on SLEEP-EN
// To disable deep sleep: connect SLEEP_ENABLE_PIN to GND. Jumper is not required on SLEEP-EN.
const int sleepTimeS = 60;    //Publish interval or sleep time in seconds. See comments above

byte sleepEnabled;

void setup() {

  digitalWrite(BUILTIN_LED, HIGH);            //Led Off

  //Add static IP to reduce the WiFi startup time -reduces WiFi startup time, lowering power consumption-
  Cayenne.begin(username, password, clientID, ssid, wifiPassword);

void loop() {

  sleepEnabled = digitalRead(SLEEP_ENABLE_PIN);
  if (sleepEnabled == LOW) {
    if (millis() - lastMillis > 10000) {
      lastMillis = millis();

      //Write data to Cayenne here.
  } else {
    Serial.print("[LuisLab] deepSleep: "); Serial.print(sleepTimeS); Serial.println(" seconds.");
    ESP.deepSleep(sleepTimeS * 1000000, WAKE_RF_DEFAULT);

unsigned int Ch4Value;

void cayenneSendData () {
  Ch4Value = analogRead(A0);

  Cayenne.virtualWrite(0, sleepEnabled, "digital_sensor", "d");         //Sends sleepEnable status to button on Dashboard
  Cayenne.virtualWrite(1, round(lastMillis / 1000), "counter", "null"); //Sends the current uptime in milliseconds.
  Cayenne.virtualWrite(4, Ch4Value);
  if (sleepEnabled == LOW) {
    digitalWrite(BUILTIN_LED, LOW);     //Led will be On when Deep Sleep disabled
    Serial.println("[LuisLab] Ch0: Deep Sleep disabled");
  Serial.print("[LuisLab] Ch4: "); Serial.println(Ch4Value);

//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
  CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s",, getValue.getId(), getValue.asString());
  //Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");


Luis Ortiz

Luis Ortiz

1 project • 29 followers
Systems Engineer by day, avid tinkerer at night. I spend free time in DIY projects involving electronics, 3-D Printing and automation.