Hat for Raspberry Pi to monitor environmental conditions (my sandbox for learning modern DevOps tools).

It’s 2024, and technologies from web development have made their way into the embedded world too-things like containerization, automated deployment, and more. This project is a small hat for the Raspberry Pi that gathers measurements for temperature, humidity, and air pressure. I created it as a learning tool to explore these concepts while using Docker, Ansible, and Grafana.

The picture below shows the hat. I thought it was so simple that I wouldn't make any mistakes during assembly, but, as usual, I did. The PCB turned out to be too long and collides with the USB port of the Raspberry Pi. That’s why I had to connect it using jumper wires. It works, but it doesn’t look very cool.

I didn’t choose these sensors for any particular reason—they were just parts I had on hand from the good pre-COVID times when software components and sensors were still cheap :)

The circuit is shown below. It consists of two sensors that communicate via I2C with the Raspberry Pi, along with a small LCD that also uses I2C. The LCD displays the measurement data as well.

Some people say that if your Raspberry Pi starts slowing down, it’s a sign that the SD card is about to fail, so it’s time to back up. I noticed mine was slowing down, checked the kernel logs, and everything looked fine, so I figured I was safe. The next day, the SD card was dead. So yeah, it’s definitely a good idea to back up in such cases.

This happened before I got into Docker and all the containerization stuff, so I was just developing scripts directly on the Raspberry Pi—and I think I lost them. It’s funny how I started this project to learn about containerization as a reliable way to deploy code, and I kicked things off with such a fail!

From the software point of view, the project will consist of three components:

  • Python software for gathering data from the sensors
  • InfluxDB for storing the measurements
  • Grafana for data analysis and presentation

I think each of these components will have its own Docker container. In addition, I’ve already created a Docker container for cross-compilation (since my PC has x86 architecture and the Raspberry Pi uses ARM architecture). It was quite a struggle to get that working. I plan to automate the installation using Ansible.

If you’re interested in the details, the full project is available on GitHub and Hackaday. Feel free to explore, make your own modifications, and maybe even improve on what I’ve done. And if you find it useful, don’t forget to share it!

Hardware Data Logger based on STM32 Nucleo and ESP Module

It's been a while since I last posted here, but here I am with something new. This project started when I was cleaning up the repo for a semiconductor radioactivity detector. For that project, I made a small shield for the STM32 Nucleo that included a button and a display.

It was used to present measurements in real time on the display and send them to a Raspberry Pi for further processing. I thought this could be turned into a separate project and reused, and I'll be presenting the results of that in this post. Here is the link to the GitHub of this new project that I describe in this post.

I started working on a new version and came up with these specs:

  • Keep the STM32 Nucleo as the main microcontroller
  • Add an ESP module for remotely uploading data to a Raspberry Pi or any other device
  • Use a much larger color display
  • Include four buttons for interacting with the device
  • Add 4 BNC connectors for gathering data from other devices
  • Include an SD card slot for local data storage
  • It also has a light sensor to dim the display at night.

The picture below shows the version that includes these specifications. Fun fact is that I traveled with this device in my carry-on luggage and was worried there might be issues at security, since it kind of looks like a movie bomb, but everything went fine.

Based on the that version, I created a dedicated PCB. I thought assembling the PCB would be pretty simple, but unfortunately, I forgot to buy all the components, which made it much harder than I expected. In this version, I used SMD female pins to connect to the Nucleo board. However, since I didn't have them on hand, I used THT pins instead. The footprint was different, and I didn’t solder them well, which put a lot of stress on the Nucleo board when connecting the shield.

It kept breaking repeatedly, and I didn’t expect such a small issue to cause so many problems. The LCD no longer works—probably something broke again—but the rest of the setup is functioning. In this version, the STM and ESP communicate with each other, but only in a limited way.

The device was designed in KiCad, and the circuit is shown below.

The firmware was developed using STM32CubeMX (for peripheral configuration), CMake, and C++17. I didn’t use anything from the standard library or dynamic memory allocation.

I’ve also included several tools for checking code quality: unit tests (Google Test, Google Mock), code coverage, static code analysis (cppcheck), and even dynamic code quality checks (which don’t make much sense in my case since I explicitly avoid using dynamic memory allocation, but I wasn’t thinking about that at the time). There are also Doxygen comments and coverage reports to flag any missing documentation.

I used ChatGPT (paid version) for most of this configuration. It’s amazing but can also help you quickly generate garbage. It speeds things up when you're headed in the right direction, but if you're doing something silly, it will just help you do it faster. You can check out how the CMake files are written in this project to get an idea of what I mean.

The current version is not finished, and I think I’ll abandon it in favor of a new version. I plan to drop the Nucleo board and place the STM chip directly on the PCB. This will solve the connector issues and make the device smaller and cheaper.

Another idea I have is to use some slots (similar to the ones used for connecting RAM to a PC motherboard, though I haven’t researched the names or footprints yet). This way, I could have one main PCB with the STM, ESP, display, etc., and use detachable boards for acquisition modules.

This is just the beginning, and there’s plenty of room for improvement. If you're curious to see where it goes, don't forget to watch or star the project on GitHub!

Ionization Chamber

An ionization chamber is a device used to measure radioactivity levels. When air atoms are hit by radioactive particles, an ion pair is produced. Ions have an electric charge, and if they are in an electric field created by positive and negative electrodes, negative ions will move toward the positive electrode, and positive ions will move toward the negative electrode. They will attempt to "meet each other," thereby creating a current. This current can be measured and is proportional to the number of ion pairs. The number of ion pairs is proportional to the radioactivity level.

The architecture of the device is presented below. It consists of an analog part and an STM8 microcontroller, which collects and sends measurements via UART. These measurements are collected on the Raspberry Pi side and processed using Python and R scripts. The results are stored as .csv files (raw data) or .png files (diagrams). While it would be possible to simplify this setup and eliminate the Raspberry Pi, I wanted to enable data collection and flashing of the microcontroller remotely, without needing to be physically near the device.

The outer electrode of the ionization chamber was made from PCB scraps and a copper plate, while the inner electrode was constructed using a few centimeters of non-enameled wire. To avoid electromagnetic interference, the amplifier was placed inside a metal chassis.

High voltage is required to create a sufficient electric field in the chamber. Initially, I was unsure of the exact voltage needed, so I added a simple DC/DC converter to the PCB to generate 400V DC. However, tests showed that 4x12V from batteries is sufficient. As a result, while the DC/DC converter is soldered onto the board (visible on the bottom left side of the picture), it is not in use.

The software was written in C and compiled using SDCC. A strange limitation of SDCC is that even if functions are unused, they are still compiled and included in the final binary. Since I am using StdPeriph as a HAL, there were many unused functions that occupied space. To work around this, I added #ifdef 0 ... #endif around each unused function, then attempted to compile and uncommented the functions that were actually needed.

The diagram below shows the results obtained from the device. As can be seen, the device is quite sensitive, capturing even small variations in the measurements.

For more details on the project, feel free to check out the full source code and documentation on GitHub. You can also follow the project's development and updates on Hackaday.

Camera nuclear-radiation sensor: part I

In previous posts I've described a radioactivity detector based on a photodiodes. Image sensors in cameras use photoelements too, so I think that they could be also used to detect radioactivity. At this moment i didn't success in this , nevertheless I will describe here my attempts.

I'm using RaspbberyPI, to get data from the sensor, camera is some low-budget/quality clone designed for RaspberryPI. I have removed optics, and covered whole camera in black tape to block any light coming to the sensor. It's visible on the picture below.

To handle the camera on the software side, I'm using Python script (with PiCamera library). In infinitive loop it takes a photo and calculate sum of pixels value and then sums values of each RGB channel. This value with timestamp is put to CSV file that is later parsed to diagrams using R script.

Without any sample, internal noise of the sensor (and maybe background radiation) should give after some time (e.g. after a couple of hours) a Gaussian curve on the histogram. After putting measured sample to the sensor and waiting similar period, a new Gaussian curve would appear, so that the histogram would have to visible peaks. That was my assumption, hit would prove that the sensor works, however as visible below it doesn't - there is only one peek.

I will try to better isolate the sensor also from electromagnetic noise or maybe buy a new camera (less noisy). Other than that I don't have ideas to make it works.

Weird arrays in C

Recently I've saw quite strange way to create an array in C. I will describe it bellow - looks quite interesting!

Let's assume we have an array given bellow:

int myArray[4];
We could rework it, so that each element is declared separately:
    int myArray0;
    int myArray1;
    int myArray2;
    int myArray3;

Now we can obtain pointer to first element and last element, and iterate through elements in between it as with regular array. We exploit that compiler will probably put those variables in the same order in the same place in memory.

A full example is given below:

#include <stdio.h>

void processElement(int e)
{
    printf("processing element in array, it has value %d\n", e);
}

int main()
{
    int myArray0 = 0;
    int myArray1 = 1;
    int myArray2 = 2;
    int myArray3 = 3;

    // dummy way to force compiler not to optimalize-out our array members
    printf("%d\n%d\n%d\n%d\n", &myArray0, &myArray1, &myArray2, &myArray3);

    int *start = &myArray0;
    int *stop = &myArray3;

    if(start > stop)
    {
        start = &myArray3;
        stop = &myArray0;
    }

    for(int* it= start; it <= stop; *it++)
    {
       processElement(*it);
    }
}

:)

Semiconductor nuclear-radiation sensor: part III

In this post I will present a new hardware version of my sensor, older versions are described in part I and part II. In comparison to the previous one, sensitivity is roughly x10 more sensitive.

In previous version, tin foil window for photodiodes was very close to the BNC sockets and because enclosure was small, it was hard to place a sample close enough. Not it's better, however, if I would choosing again, I would use metal enclosure similar to those used in PC oscilloscopes and put BNCs on front panel, power socket on rear panel and tin foil window on top. This would allow me to easier access for debugging- now I have to desolder sockets to get to photodiodes or to bottom side of PCB (fortunately this side is empty).

Bellow you can see the diagram (click on it to enlarge), what has changed in comparison to previous version:

  • One additional photodiode (previous version has only two of them) to increase sensitivity, also the window in enclosure is much bigger
  • x10 bigger resistance of the feedback loop resistor in first stage amplifier, I tried bigger, but then osculations started
  • Bias for photodiodes using 12V batteries, I could increase it, but didn't have enough space in this enclosure
  • Buffer op-amp at the analog output
  • Digital output.

Additional changes not shown on diagram:

  • U1 is OPA657U
  • U2 is OPA656U
  • R4 is 1G
  • As close as possible to input power socket are placed in paraller 1n/16V and 100n/16V, without them the device started to oscillate randomly.
  • A Schottky diode is connected in series after mentioned above extra capacitors to reduce risk of damaging the device when power supply is connected incorrectly. I don't know if it will help enough but I have already broke one PCB of this device this way, so now it's there.

Digital output is 12V in high state, 0V in low state, this is not very useful for 3V3 logic microcontroller that I'm using for data acquisition, so I made a simple converter using additional PCB.

Here it is visible soldered. I like in those SMA Female sockets that they can be soldered to the edge of the PCB (as visible below) and this is still quite mechanically stable, but doesn't require to drill holes as in regular mounting way.

All materials (including software part presented in previous post) for this hardware revision can be downloaded from project's repository.

Semiconductor nuclear-radiation sensor: part II

There are many ways to measure radioactivity level, semiconductor detectors sense interactions between ionizing radiation and p-n junction. Because in hobbyist area most popular are Geiger-Muller based detectors (in short: not a semiconductor but lamp based devices), I think it's a cool idea to take a look at this approach.

In this post I will present such home-made sensor and a set of software to parse collected results.

Picture below presents circuit of the sensor that I made, it consist of a photodiode that acts as a sensor, transimpedance amplifier and "regular" amplifier. I've selected op-amps that has little input noise.

Changes that I made during testing the device, that are not presented on the diagram:

  • D1 is BPW34
  • U1 is OPA657U
  • U2 is OPA656U
  • 2p capacitor is connected in parallel with R6
  • 820k resistor is connected between U2 out and BNC socket.

Below is visible sensor in enclosure and without it. Because the device is sensitive for background EMI and light noise, a metal housing is needed. To increase exposure of the sensor to the radiation, where it is, in the housing, a hole is made and just a tiny adhesive metal tape is covering it.