To summarise this project, let’s make a list of features, as I did with my previous projects:
High-accuracy CO2, temperature, and relative humidity sensors
High-resolution, low-power 3.7″ E-Paper display
Built-in clock and calendar
Configuration and charging over USB
Two user buttons and status LED for easy interaction and self-calibration
Configurable timed standby mode
Very long battery runtime between charges (up to multiple weeks)
In short, I achieved or exceeded all of the goals I set for this project – it was a complete success. And in addition to that, it taught me a lot about low-power designs, EPD technology, sensor technology, and building smaller devices.
I’ve been using the CO2 station ever since, having a dedicated spot for it under one of my monitors, so that it’s always in view. I especially love how it ended up being a “set and forget” device most of the time – all it needs is an occasional charge and clock adjustment (about once every 3-4 weeks, with my settings and 8 hours of standby per day), as well as a quick calibration in outside air once every 3 weeks.
What doesn’t feel great is having to continuously increase the calibration reference value over time, as the atmosphere’s CO2 concentration rises…
So in conclusion, I am extremely happy with this project. This was the first time I completed a project and didn’t have the feeling that it was lacking something (compared to my initial imagination of it). Even multiple years later, at the time of writing, I feel like there aren’t too many things I’d change if I were to design another CO2 Station now.
As mentioned, I designed the enclosure for this project to be CNC machined out of plywood – I won’t show the process of that here, since it’s essentially the same as I showed for the BlockBox v2. After some basic post-processing, I was left with six beautiful enclosure walls – only blemished by some delamination of the plywood near the top and bottom side countersinks, but that’s easy to fix with some small wooden chips (or just ignore where it’s not visible).
Five of the walls (all except the back) were glued together using wood glue, forming a strong box, which fit the electronics assembly very nicely. Some matching screw holes in the side walls hold the PCB in place using its soldered screw terminals. For an easy USB connection, a USB Micro-B jack was glued into the the side and wired to the board, and the SCD30 module was installed on a long pin header.
The back side of the enclosure received four small wooden blocks with threaded inserts, allowing it to be screwed in securely, while still being easily removable.
And with that, the CO2 Station was fully assembled, and looking great, in my opinion!
As usual, the build of this project started with the electronics. The PCBs arrived looking quite good, and you can clearly see that the board design was based around the EPD, with how much space is dedicated to it in the front.
I started by soldering the boost-passthrough voltage converter components, testing them in isolation to make sure the converter works, before assembling the rest of the power supply section and testing it as a whole.
Once I confirmed that the power supply seemed to work fine, there was no reason to subdivide the rest of the circuit into more small sections, as I didn’t really have a way to test them individually anyway – so I soldered all remaining components into place. The EPD was still not attached to the board at this point, for easier testing, and the SCD30 module would be mounted on the 7-pin header in the bottom left later.
The screw terminals for mounting the board are also not soldered yet in this image.
At this point, I could power the board up and start working on the firmware for the controller. Most of the smaller features, like the real-time clock and USB serial communication, were easily handled using Microchip’s official driver libraries. They also provided an EEPROM emulation library, which allowed me to efficiently use some of the controller’s built-in flash memory to store persistent values even if the device lost power, for example, setting values and the time and date. Communicating with the SCD30 module was also not a problem, as the I2C protocol is supported by the controller’s hardware, and the module-specific data transfer protocol was very simple and easy to use.
Driving the EPD was a different story: On one hand, the display and its driver are designed to be powered down between screen updates, to save power, as EPDs don’t require any power to keep their existing image. To update the image, it was necessary to follow a very specific sequence of power-up, sending data, starting the update, waiting for it to finish, before powering it down again – with certain timing requirements specified by the manufacturer.
With some trial and error, I was able to get the display to update, but it behaved quite weird, taking much longer for the update than it should. However, thanks to some very helpful tips from the Pervasive Displays support team, I finally got it to work as expected and display a test image.
Next, I created some very simple bitmap font files, mostly containing numbers and a few special characters for displaying all the required information. I wrote a small program in C# that allowed me to convert these fonts into C header files, containing the corresponding pixel data in array form, for easy inclusion into the firmware.
An example bitmap font file.
Adding a function to process this raw font data and send it to the display, I could now print numbers to the EPD.
With that, the display logic was almost done – I just created a static base design, positioned various number printouts to display all of the relevant information, created a battery charge level icon, and finished it off with a dynamic “status bar” at the bottom, displaying a message for the user if necessary.
After that, only a few pieces of logic were left – like debouncing and handling user button inputs, and giving status indications using the red/green LED at the front. I assigned the two buttons to be “power/standby” and “measure/calibrate”: The former would switch in/out of “standby” mode on a short press (sensor disabled, low power consumption), and completely switch the system off (blank display) on a long press, while the latter would perform an immediate update of the EPD using the latest sensor data on a short press, and initiate the SCD30’s self-calibration procedure on a long press.
The status LED would glow red while charging, turn green once charging is finished, blink red when the battery is low, and blink green when sensor calibration is recommended.
The remaining settings would be configured over the USB serial interface – date/time, calibration values, measurement and display update intervals, etc. The device could also be configured to automatically go into standby mode between certain times – for example, to reduce power consumption at night, when the sensor is not needed.
Finally, after attaching the EPD to the circuit board using double-sided tape, the functional part of the project was complete.
The first design requirement I chose, using a true CO2 sensor, seemed like a good place to start. After a quick search, I found the Sensirion SCD30 module, which seemed like a perfect centrepiece for the CO2 Station design. It’s based on a high-performance infrared CO2 sensor and includes temperature and relative humidity sensors, all in a single device, with an easy-to-use serial interface (I2C).
The next big question was the choice of display. I really wanted a high-quality display that could show the measurement values in a large font, looking as visually appealing as possible. The typical choice for that would be a backlit LCD screen – but here, its high power consumption would make the “long battery runtime” requirement impossible. Reflective segmented LCD displays, like in digital watches, are perfect for low-power use cases, but they’re not very accessible for single-piece projects like mine.
Therefore, I decided to try out a new technology – an “E-ink” or “E-Paper” Display (EPD), as commonly seen in E-Book readers. My search led me to a Pervasive Displays 3.7″ display panel1, which I decided to use for this project, with its form factor and size being great for what I wanted here. Also, it offered an integrated display controller, which was very helpful – worrying about the intricacies of driving an EPD manually would not have been fun.
The EPD needed a corresponding connector for its FFC (flat flexible cable), as well as some support components – essentially an entire external boost converter, controlled by the EPD.
With that, I had the central components of the design. Next, I chose a low-power central system controller (PIC24F GU series), which would communicate with the sensor and EPD, allow user interaction through buttons and a signal LED, time periodic updates using its integrated real-time clock, and offer a USB interface for configuration.
For powering the device, I decided on a single Li-Ion 18650 cell in a holder. It could be charged from USB using a battery charging controller (DIO5508), and would power the system through a voltage converter (boost-passthrough converter followed by a linear voltage regulator), to ensure the system voltage would always be at 3.3V, regardless of the battery’s state-of-charge. For this design, the Texas Instruments WEBENCH Power Designer was very useful, as in past projects. For additional protection of the battery against deep discharging, I also added a MAX6775 battery monitor, to shut down the system if the battery voltage drops too low.
Designing the PCB was a little different this time, compared to my previous projects – I decided that the best way to mount the display would be on the PCB itself, so the majority of the front side area was reserved for that. All other components, aside from the user buttons and signal LED, had to go on the back side. Additionally, I needed some way to mount the PCB assembly in a enclosure later, so I added some right-angle screw terminals in the corners.
Shown here from the back side, looking “through” the board.
Now, the only missing part of the design was the enclosure. Using Fusion 360, I quickly designed a small wooden box for it (out of 5mm plywood). I could have designed it to be built by hand, it wouldn’t have been too much work – but after the BlockBox v2’s success with CNC machining, I decided I might as well do more of that – it’s fun and produces really good-looking results.
With everything designed and planned out, it was time to order the parts, and build this thing!
The exact EPD model I used is no longer available at the time of writing, but equivalent and improved successors exist. ↩︎
Living at home with my parents during the COVID-19 pandemic, there was one thing that started annoying me after a while. I’d be sitting in my room happily, then my mum comes in, and the first thing she says is “the air in here is awful, open the window”. But… the air feels fine to me, it’s nice and warm, and it’s cold outside… but there’s no point in arguing, I have no way to prove that.
After a while, that annoyance turned into a project idea: What if I build a device to objectively measure the air quality in my room? That way, I would always know when I really need to open a window, and at the same time, have a convincing argument against any potential nagging. 😉
Of course, as with any project, I wanted to get more out of it than just the finished item – I wanted to learn lots of new things while building it. After some research into existing solutions, I came up with the following project goals:
Use an actual CO2 sensor (no “CO2-equivalent” estimations)
Measure temperature too, optionally humidity
Display the measurement values in a clear and visually pleasing way
After the completion of the BlockBox v1, I really thought for a while that I’d be done with this idea. And it only took a few months for me to prove myself wrong, with the BlockBox v2 project.
But this time it felt different – I really was done, at least for now. The BlockBox v2 has its flaws, there are certainly ways to improve it further, but overall… I’m just really happy with it, and very proud of the results of my work – especially if I look at both speakers next to each other.
Let’s look at the features of the final product:
Two-way cross-over speaker system with digital audio path
100W 10″ low-frequency driver
50W hi-fi tweeter
-3dB bass roll-off frequency around 38Hz
Theoretical maximum sound pressure level around 110-113dB (@ 1m)
Bluetooth audio playback (SBC or AAC), effective range ~10-15m
Touchscreen interface with lots of audio settings and playback control
EQ-optimised sound profile (to the best of my abilities)
(Roughly) music-synchronised LEDs
166Wh battery (in practice, lasts for more than 10 hours of continuous playback)
Battery protection and fast charging
2x External USB (5V 1.5A) for phone charging
Optional analog AUX input (not implemented due to lack of practical need)
Looking back at this huge project of building two speakers, I can only say one thing: It was absolutely worth it.
Now, are the speakers by themselves worth it? No, not really. Because I had to buy everything in single-piece quantities, restrict myself quite heavily in terms of what I could work with using the tools I had, and over-engineered many things “just to be safe”, they ended up being wayyyy too expensive to compete with commercially available speakers, at around 1500€ (for both combined) – and that’s if I ignore the cost of the months of work that went into them.
But the main value of this project, for me, was not in the speakers themselves, but the incredible amount of learning and experience that I gained throughout this project, including audio engineering, mechanical design, CAD and manufacturing, electronics design and soldering of course, and microcontroller firmware development.
This is where my speaker-building journey would end for now, but I had a feeling I would be back to it sooner rather than later, in another project.
The digital audio processor included in the BlockBox v2 design (part of the audio PWM modulator) has multiple configurable digital filter stages, specifically, biquadratic filters (“biquads”). These allow the implementation of practically any second-degree infinite-impulse-response (IIR) filter, defined by five filter parameters each.
The baseline for these filters was, of course, the cross-over between the two speaker drivers (low-pass for the bass driver, high-pass for the tweeter, both with the same cut-off frequency). Due to the drivers’ respective effective frequency ranges, I opted for a cross-over frequency of 2000Hz.
Aside from that, the remaining filters were available to fix any frequency response inconsistencies, acting as an equaliser. Therefore, I needed to measure the frequency response of the speaker without any filtering – ideally, this would be done in an acoustic chamber using a calibrated measurement microphone, but I did the best I could: Measuring the response in my room, using RoomEQWizard and the best microphone I had available (a Zoom handheld recorder), opting for measurement methods that try to eliminate most environmental reflection effects (gated and near-field measurements).
Example combined measurement for the low-frequency driver (near-field + gated)
To configure the audio processor filters, I wrote a small piece of helper software that I called SpeakerEQDesigner, which allowed me to visualise the effects of various filter configurations and export the resulting filter coefficients in the fixed-point number format required by the audio processor.
I ended up creating two filter profiles – one that targets maximum flatness of the frequency response (“Hi-fi” profile), and one that sacrifices a little bit of flatness for a higher maximum loudness (“Power” profile).
With these, I should theoretically have achieved very good speaker response characteristics – though I probably didn’t get anything quite as good as the software predicts, because my measurement equipment was quite rudimentary.
Just like before, the build process started with the electronics. So it was time to order new circuit boards and components.
Building the electronics for this second speaker followed the exact same procedure as I described for the BlockBox v1, so I won’t repeat it here. In the end, I had another nice circuit board that looks just slightly different from the first version (shown without the amplifier heat sink here).
Then, it was time for firmware development. This would be a much bigger task than it was for the BlockBox v1, again, because I had to implement a central system controller, as well as touch display communication. I was able to find a community-made library/driver for the FT81X graphics processor in the display module, which certainly made the job easier, though I had to make quite a few modifications to make it work on the PIC32MZ microcontroller. Aside from that, I implemented my own serial communication drivers for controlling the digital audio processor, Bluetooth module, LEDs, and other peripherals, as well as some central system management logic connecting them together, and of course a user interface for the touchscreen. The firmware source code is available in the same GitHub repository as the electronics design files, though I cannot guarantee anything about its correctness, completeness, and especially code quality (I was quite careless sometimes back then).
Clearly, still some bugs to iron out…
When it came to building the enclosure, however, I knew that my methods from the BlockBox v1 would not be viable any more. Making smaller and simpler shapes using my hand saws may have been possible (even if tedious), but the more complex and much bigger pieces needed for this project would just be too much to ask for. Especially considering the idea I had for LED-lit logos on the sides, which require quite significant precision. The translucent parts for the LEDs, as well as some black decoration and cover plates, were laser cut out of acrylic plastic, which I was able to order relatively inexpensively.
As for the main enclosure walls, I decided to use CNC milling – thankfully, though a personal connection to a machine shop at my university, I was able to do so for free, as long as I brought the materials and my own CNC programs. Materials were easy, I just ordered some plain 12mm plywood panels, already cut to the sizes I needed, and got a small piece of aluminium plate stock for the connector panel. The CNC programs were more complicated – Fusion 360 has some great tools for CNC programming based on my CAD design, but as I’d never done anything like that before, it took me a while to research, understand, and learn the basics of machining and CNC programming. In the end, it was time for some machining.
This could be milled much faster with a higher tool RPM, but this machine can’t do more, as it was mostly designed for hard materials. Anyway, I was not in a rush.
With that, I had some rough-looking side panels, which would need quite a bit of post-processing to remove extra tabs and pieces, sand down sharp/rough edges, file away unwanted internal corner radii, and so on.
After post-processing, they looked much better, and also fit the acrylic pieces nicely.
Now it was time to assemble the speaker. I built the main wooden box by screwing the walls together using metal corner pieces, then hand-cut some extra plates with LED strips to go behind the acrylic inserts, installed the drivers, port resonator, display, circuit board, connector plate, battery, and some plastic wool for acoustic damping inside the enclosure.
With everything connected and closed up, the BlockBox v2 was complete.
When I started designing the BlockBox v2, not much time had passed since the completion of the BlockBox v1, so my level of knowledge and experience was similar. I had noticed some mistakes in the original design that I would correct, but decided to leave most of the circuit design untouched, wherever I couldn’t see anything immediately wrong with it.
The first major difference I had to address was the addition of the touchscreen display for user interaction. I looked around at different display options, eventually picking a good and affordable 3.5″ module by Newhaven Display, which offered a sunlight-readable display, resistive touch, and a built-in graphics chip, which would make using the display much easier than if I had to render every part of the user interface in my own firmware.
Still, even with built-in graphics, I would need a much more powerful microcontroller, as it needed to handle the display commands, as well as act as the central system controller – for the BlockBox v1, I offloaded that responsibility to the Bluetooth module, but with the touchscreen, that was no longer a viable option. Also, making my own central system controller would give me much more fine-grained control over everything going on, which was obviously desirable. With these considerations, I decided to use a microcontroller from the Microchip PIC32MZ EF family – it’s likely that I could have picked something lower-cost, but for a prototype project like this, it made the most sense to go with something really powerful, just in case I could use the extra performance.
Another thing that was causing me trouble in the first version was the analog audio signal path. I realised that I was simply not experienced enough with analog circuit design to achieve a high-quality signal in such a way, so I decided to switch to a fully digital audio path for the BlockBox v2. This would also allow me to feed digital audio data to the system controller, for better music-synchronised LED lighting. The first problem with this plan was the Bluetooth module I had used for the first version – it only had an analog audio output. Therefore, I chose its slightly more advanced successor for this design, the Microchip BM83, which also features a digital audio output.
Aside from that, this meant replacing my analog pre-amp and filter stage with a digital signal processor (DSP), and the amplifier with a digital one. Thankfully, Texas Instruments had a great solution for me, which would work as a relatively simple drop-in replacement for my existing circuit: The TAS5548 modulator with integrated DSP, as well as the TAS5634 PWM-input audio amplifier. This amplifier’s pinout and interface was nearly identical to the one I used for the BlockBox v1, allowing me to reuse most of the output stage design – just making sure to use bigger and better inductors, as well as film capacitors for low-distortion filtering this time.
The rest of the circuit remained nearly unchanged. The battery management circuit seemed to work great in the first speaker, so I reused it exactly as it was, along with the choice of battery cells themselves and their 4s4p configuration. As for the voltage converters, I only made a few small modifications – adding a trimmer potentiometer to the power amplifier supply, to be able to lower its voltage for driver safety and efficiency, as well as making the 3.3V supply based on a switching converter as well (instead of just a linear regulator), since the new controller and display needed more power. Unfortunately, I still hadn’t understood the importance of power supply noise reduction in audio circuits, meaning the new power supply design would also be quite noisy – but I didn’t know that at the time. Also, just as with the BlockBox v1, I was still limited in my component choices by the abilities of a simple soldering iron.
I created the modified PCB design based on these changes, deciding to keep the board dimensions and layout the same as in v1, just in case I ever wanted to replace the v1 electronics with the new version as well.
As with the first version, the full schematics and PCB design files (for Autodesk EAGLE) are available on GitHub here. While this design is certainly better than the BlockBox v1, it is still not good overall, and not recommended for direct reuse. After all, it was still designed with some beginner mistakes and flaws.
Since the main source of my “disappointment” with the first BlockBox was the lacking low bass frequency range, that exact point became the springboard for the design of the second version.
Knowing that I wanted a lot more bass, I started looking into better speaker drivers for it. I found quite a few options that would offer a complete bass extension down to ~20-30Hz, but nearly all of them meant sacrificing quite a bit of efficiency. That would mean either increasing the maximum power, which is difficult on battery-powered systems and makes the circuit design harder, or making the speaker quieter. But come on, there’s no way I would allow the second version to be quieter than the first version – that would just make it feel inferior from the start.
So high efficiency remained a very important consideration in my driver selection, and eventually I found a new low-frequency driver that looked great for my needs: The Beyma 10BR60V2. Since it had a lower effective frequency range than the BlockBox v1 driver, I also needed a new tweeter with the ability to pick up higher midrange frequencies. I ended up choosing the Monacor DT-28N, which was also just a higher-quality driver compared to the ones I used for the first version.
There was, however, a very significant difference from the BlockBox v1, with this driver choice: Size. While the first speaker used a 6.5″ driver that could achieve good performance with an 8-9 litre enclosure, this new low-range driver was quite a lot larger at 10″, and according to SpeakerBoxLite, its optimal enclosure volume was somewhere around 61 litres. Yikes.
This prompted me to take a step back and think about it for a moment. Would such a huge speaker even make sense for what I wanted? It’d certainly be much more difficult to carry around. However, I realised that with the right form factor, it may be possible to attach some straps to the speaker and carry it around like a giant backpack itself. The idea was certainly cool enough to make me want to try, so I continued with this choice of drivers.
The enclosure size I ended up deciding on was 55 x 40 x 35 cm, with a 10 cm vent port (Monacor BR-100HP), and walls made of 12mm plywood:
According to the SpeakerBoxLite calculations, with this design, I should be able to achieve a -3dB bass roll-off frequency of 38Hz – certainly a lot better than the first version. It wouldn’t be quite as “precise”, with a slight over-emphasis around 57Hz (+3dB), but I was willing to accept that, especially since audio pre-processing could fix that if it annoyed me later.
Based on this, I once again created a CAD design in Fusion 360, allowing myself to be a bit more ambitious with the features this time. The BlockBox v2 would have some protective rubber corners, hooks for backpack straps, much better LED lighting (including lit logos on the sides), a nice aluminium connector panel on the side, and even a touchscreen display for user interaction (instead of the basic buttons of the first version).
Of course, the electronics would need some changes to go along with these new features, as well as some upgrades to address some of the shortcomings I noticed with the first version. So, naturally, that was the next step of the design.
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.