Skip to content

⚙ Configuration

Because I work mainly out of a Chromebook and Rasperry Pis, this project is using the arduino-cli command line utility with Linux rather than the Arduino IDE.

Initialize the config
arduino-cli config init
Add the ESP32 package library
arduino-cli config add board_manager.additional_urls
Check that the update addition was successful.
cat ~/.arduino15/arduino-cli.yaml


This is assuming that arduino-cli was installed in the home directory (~/.arduino15)

Update the core index
arduino-cli core update-index
Install the ESP32 core
arduino-cli core install esp32:esp32
Search for the featheresp32 board
arduino-cli board search featheresp32
Typical Output
Board Name              FQBN                     Platform ID
Adafruit ESP32 Feather  esp32:esp32:featheresp32 esp32:esp32

Take note of the output under FQBN because that is what will need to be passed as the board (-b) parameter with the arduino-cli command. In this example, the board to be used will be esp32:esp32:featheresp32.A

Install the required libraries
arduino-cli lib install ThingSpeak "Adafruit SH110X" "Adafruit INA260 Library" Timezone ESP-Google-Sheet-Client
Tested Library Versions
Name                    Version
Adafruit_SH110X         2.1.6A
Adafruit_INA260_Library 1.5.0
ESP-Google-Sheet-Client 1.0.0
ThingSpeak              2.0.1
Timezone                1.2.4

Create a channel on ThingSpeak and take note of the Channel ID, channel Write API Key, and User API Key.

Create secret.h and update variables in config.h.

arduino-cli compile -b esp32:esp32:featheresp32 .


The dot at the end of the command tells arduino-cli to use the sketch in the current directory. The name of the sketch may also be used.

Typical Output
WARNING: library Timezone claims to run on avr architecture(s) and may be incompatible with your current board which runs on esp32 architecture(s).
Sketch uses 742601 bytes (56%) of program storage space. Maximum is 1310720 bytes.
Global variables use 40648 bytes (12%) of dynamic memory, leaving 287032 bytes for local variables. Maximum is 327680 bytes.

Be sure to compile your code before uploading it if changes have been made to the sketch!

Upload the sketch to the Feather
arduino-cli upload -p /dev/ttyUSB0 -b esp32:esp32:featheresp32 .
Typical Output v3.1
Serial port /dev/ttyUSB0
Chip is ESP32-D0WD-V3 (revision 3)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 7c:87:ce:f0:88:0c
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Configuring flash size...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00001000 to 0x00005fff...
Flash will be erased from 0x00010000 to 0x000c6fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Compressed 8192 bytes to 47...
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 635.7 kbit/s)...
Hash of data verified.
Compressed 17104 bytes to 11804...
Wrote 17104 bytes (11804 compressed) at 0x00001000 in 0.4 seconds (effective 313.6 kbit/s)...
Hash of data verified.
Compressed 748480 bytes to 477080...
Wrote 748480 bytes (477080 compressed) at 0x00010000 in 8.3 seconds (effective 722.5 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 128...
Wrote 3072 bytes (128 compressed) at 0x00008000 in 0.1 seconds (effective 439.5 kbit/s)...
Hash of data verified.

Hard resetting via RTS pin...
Monitor serial connection using GNU Screen
screen /dev/ttyUSB0 115200


Make sure the baud rate matches the BAUDE_RATE in the config.h!

The recharge mode is the default mode during boot.

The A button on the OLED may be held down during boot to choose the discharge mode which will keep the OLED on and display the battery measurements.

Mode: recharge
Hostname: Feather
 Percentage: 90%
 Voltage: 4.04 V
 Current: 700 mA
 Power: 2.6 W
 Number: 1642208
 Status: success
Sleep time: 15m
Mode: discharge
 Percentage: 90%
 Voltage: 4.04 V
 Current: 700 mA
 Power: 2.6 W

Kill the monitoring screen by pressing Ctrl + a k y

🔑 Secrets

secrets.h is a file used to store secrets such as API tokens and wifi credentials that aren't updated in GitHub. The file is ignored in .gitignore.

#define SECRET_SSID "MySSID"                   // replace MySSID with your WiFi network name
#define SECRET_PASS "MyPassword"               // replace MyPassword with your WiFi password

#define SECRET_CH_ID 0000000                   // replace 0000000 with your channel number
#define SECRET_WRITE_APIKEY "XYZ"              // replace XYZ with your channel write API Key

#define SECRET_HOSTNAME "Feather"

#define SECRET_USER_APIKEY "ABC"               // replace ABC with ThingSpeak User API Key

#define PROJECT_ID "esp-signer-xxxxxx"         // taken from "project_id" key in the Google Cloud Platform JSON file.
#define CLIENT_EMAIL "[email protected]" // taken from "client_email" key in the Google Cloud Platform JSON file.
#define SPREADSHEET_ID "ABCDEFG"               // Google Sheet ID.
#define PRIVATE_KEY "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n" // taken from "private_key" key in the Google Cloud Platform JSON file.
Secrets can be used in sketches
#include "secrets.h"

The nomenclature used in this project is different than what arduino-cli specifies (arduino_secrets.h) because this project does not use an Arduino.

secrets task

Task may also be used to generate secrets.h.

PROJECT_ID=esp-signer-xxxxxx \
CLIENT_EMAIL="[email protected]" \
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n"

Overwrite Sketch Header

Instead of using the secrets.h file, the include may be commented out at the top of the sketch and the variable values may be manually written in the header of solar-battery-charger.ino


This method is not recommended if the sketch is going to be uploaded to a repository!

Clear Channel

The channel may be cleared if the created_at date of the last data point is older than the current date. The dates take into account the current timezone which may be set with timeZone. To turn on the clear channel option, set doClear to true.


Instead of specifying -b and -p for every command, a sketch.json may be stored in the sketch directory that sets the defaults for that sketch.

The sketch.json file may be generated by using the arduino-cli board attach command.

arduino-cli board attach -b esp32:esp32:featheresp32 .
arduino-cli board attach -p /dev/ttyUSB0 .

Attaching the board didn't work for me because arduino-cli didn't recognize the Feather attached to my port for some reason and so I had to manually add the port.


The port needs to start with the protocol, e.g. serial://.

The documentation doesn't show what a typical sketch.json looks like so here is one:

  "cpu": {
    "fqbn": "es32:esp32:featheresp32",
    "port": "serial:///dev/ttyUSB0"

💬 ThingSpeak

The results are exported to a ThingSpeak public channel which can be seen here.

The channel Write API Key (SECRET_WRITE_APIKEY) can be found in the API Keys tab on the channel page.

The Channel ID (SECRET_CH_ID) can be found on at the top of the channel page.

📡 Fields

On the Channel Settings tab of the channel, create 3 fields for the battery percentage, level, and voltage.

📈 Visualizations & Widgets

Add whichever visualizations and widgets you'd like.

📟 Notification from IFTTT

Notifications from IFTTT can be setup by connecting ThingSpeak to IFTTT. See these instructions.

📄 Google Sheets

The sketch can also upload data to a Google Sheet using the ESP-Google-Sheet-Client library. Checkout the documentation for how to setup the library.

Create a new sheet.

Share the sheet with the client email from the Google Cloud Platform json file.

Fill out the header of the sheet.

Get the spreadsheet ID from the URL in between the /d/ and /edit#gid=0<SPREADSHEET_ID>/edit#gid=0

Fill out the variables in the secrets.h file.

Set doSheets in the config.h file to true to enable the uploading of values to Sheets.


If the Google Sheet is created in a normal Google account, you'll need to share the Sheet with the email address specified in CLIENT_EMAIL in order to write to it using the Google Cloud Platform.

Battery Percentage

See the calibration page on how to calibrate the system.

🤖 Task

go-task may be used to automate some of the commands.

Update the parameters in task.env.


Variables are duplicated both in task.env and sketch.json because I couldn't get go-task to not have errors when trying to parse sketch.json when it didn't exist.

Bootstrap the entire environment (not including the installation of arduino-cli)
task bootstrap


This will overwrite your entire arduino-cli config file!

Compile, upload, and monitor the sketch.
task compile-upload
Get a list of all of the commands.
Back to top