Recently I’ve been streaming in the Software and Game Development category on Twitch. I’m currently focusing on developing an Embedded System.

My schedule is currently Tuesdays and Thursdays, 2-6pm Eastern time. Tune in. You could be the One average viewer!

What are we building?

The project itself is what I’m calling a “Compost Monitor,” which is intended to help me better track the health of the compost in my compost bin. There are two major parts to the project: one is the probe hardware itself which collects temperature, humidity, and moisture, and then a data-collection server on the home network that also exposes a web front-end for viewing and analyzing the data. It’s basically a weather station for inside my compost bin.

Block diagram of ESP32 with SHT3X probe and moisture sensor connected, communicating with phoenix server on raspberry pi over WiFi

Learning React Phoenix

First, being the part I was least looking forward to, I spent some time trying to dive into React because the conventional wisdom seems to be “Just use React.” But I kind of hated the experience of just going through tutorials. So at some point I said “screw it” and decided to give Phoenix a try instead. I had heard about Phoenix a while ago, and I very much enjoyed the time I spent doing Advent of Code with Elixir, so I figured this might be more up my alley.

After a couple of days going through tutorials, I understood Phoenix enough to build out a simple project with some fake measurement data and a very simplistic interface for displaying graphs of the data using Chart.JS.

Screenshot of the phoenix web page showing dummy data in a chart

Thus far my opinion of Phoenix is that it’s a lot like Rails without some of its annoyances. The tutorials I was using were also quite good at not making anything seem like magic; they explain very explicitly what you are doing and in many cases even teach you how to do it manually before showing you how to use the generators.

The Embedded System So Far

With this done, I could now get to the part I actually want to work on: the probe. I decided to use an ESP32-S3, party because they are inexpensive, but mostly because it has built-in WiFi. This will allow me to use HTTP to upload data from the probe to the data-collection server with just an IP address or hostname. No hubs or Bluetooth pairing to deal with.

Blinky (The Hello World of Embedded)

Using the ESP-IDF, I implemented a very simple blinky program, teaching my theoretical viewers about the circuitry needed and demonstrating the code for it.

Simple circuit connecting Vcc at 3.3V to GPIO7 via resistor R


gpio_num_t gpio_num = GPIO_NUM_7;
gpio_config_t pin_config = {
  .pin_bit_mask = 1ULL << GPIO_NUM_7,
  .mode = GPIO_MODE_OUTPUT,
};

esp_err_t err = gpio_config(&pin_config);

uint32_t gpio_lvl = 0;
gpio_set_level(gpio_num, gpio_lvl);
gpio_lvl = !gpio_lvl;

for (;;) {
  gpio_set_level(gpio_num, gpio_lvl);
  gpio_lvl = !gpio_lvl;

  vTaskDelay(1000 / portTICK_PERIOD_MS);
}

I pulled the LED out from a set that specifies its forward voltage at 1.8-2.2V and made the assumption that it requires 20mA. Given that, we can calculate the value of R using Ohm’s Law. Since supply voltage is 3.3V and we require the forward voltage to be at most 2.2V, the voltage across the resistor must be 3.3V - 2.2V = 1.1V.

V = IR
1.1V = 20mA R
R = 1.1V / 20mA
R = 55Ω

The closest standard value is 56Ω, but this assumed the maximum forward voltage. It’s more likely to be in the middle of the range, so a larger transistor will leave less voltage for the LED. The next standard value of 68Ω will get us closer to the middle of that range.

First Steps into I2C

The following stream, I wrote some code to read data from an SHT3x temperature and humidity sensor using I2C. All pretty straightforward.

Stay Tuned

The plan for the next stream is Analog-to-Digital conversion for a moisture sensor. Here is a link to the Amazon product page that I used to purchase it https://www.amazon.com/dp/B07SYBSHGX (not an affiliate link or anything like that). Very basically, I will be reading the ADC output periodically.

I think we also need to do a voltage divider. The ESP32 can do 0-1V for the analog input. It has its own built-in attenuation for analog inputs, but even that only allows measurements up to 2.5V, not the maximum 3.3V from the moisture sensor.

One thing I’ll need to keep in mind that there needs to be some kind calibration to give the ADC readings meaningful values. It’s easy enough to calibrate between “dry” and “100% moist”, but we also want to know what the ideal reading is and come up with an ideal range. There’s some real science to do here; but for now we’ll just calibrate the range.

Come check it out!