ESP32-C3 BLE / WiFi dev board with 0.42-inch OLED notes
I got some ESP32-C3 dev boards with built-in OLED screens for a Halloween costume project, and I've been troubled by the lack of documentation and general information about both the ESP32-C3 platform and the board, so here are some notes for future hackers:
OLED type is SH1106, not SSD1306, as seen in some forum posts and even in the blurry screenshot that accompanies these boards. Specifically, the U8G2 constructor for this board is U8G2_SH1106_72X40_WISE_F_HW_I2C(). With the SSD1306 driver, the screen pixels are shifted to the left and there's a column or two of corrupted data on the right-hand-side of the OLED screen.
Apparently the ESP32-C3 chip cannot measure its supply voltage internally, something that even ATtiny chips can do :(
Proper Arduino configuration is:
(CPU frequency and partition setup are of course configurable).
I'm not sure yet if I2C is actually hardware-offloaded here, but the pins are apparently non-default, with SDA=5, SCL=6. At least the display speed doesn't change at all when changing the I2C frequency. I don't have the equipment to measure this, but so far it looks like I2C clock speed is ignored. Anyway, I can get about 73 FPS, or about 11ms per frame draw on the built-in 72x40 OLED.
But overall, looks like a nice dev board, and it's neat that it's powered by a RISC-V microcontroller. Perfect for hobby projects that don't need many pins.
I’ve been trying to find a cheap-ish boost converter from LiPo voltages to 5V, and since I’m using EasyEDA, it’s natural that I’d look to LCSC for components to use in my design.
Interestingly enough, it appears that there are a lot of small 6-pin ICs from various manufacturers which fit the bill... figuratively and literally, but there’s something strange about them: there are all pin-compatible and have for the most part exactly the same documentation. It’s like someone came up with a design which was copied by many different companies. I’ve read enough about doing business in China that I’m pretty sure that’s by design.
Anyway, so far, I found these parts which for all intents and purposes look like a single re-badged component, or the same design (or two) manufactured by many companies:
Shouding SB6286
Shouding SDB628 (I have no idea how this component differs from the previous one)
Shenzhen-Suosemi-Tech SX1308
XI'AN Aerosemi Tech MT3608
Techcode TD8208 (this one has slightly different spec but is pin-compatible and though the doc is prettier, seems similar to the others)
Feeling Tech FP6291LR-G1 (similar spec to the Techcode one)
Silergy SY7152
... I’m sure there are others.
On the one hand, this looks like a jellybean component which is widely popular and mass-produced on a large scale, so it might make sense that a lot of companies are producing their own variant, but on the other hand - WTF?
The reason why I’ve found this is that I tried to implement one of them (actually the first one on the above list) and it fails in several mysterious ways, so I might have received duds. I’ll try using other pin-compatible ones and see how it goes.
How to start with electronics on a tight budget 2: playing with electricity
If your parents ever said you should not play with electricity, it’s time to disregard their advice. If you’re just starting with electronics, or have some mild and shabby experience from your college years, you will probably want to just get a bunch of components and start playing with them, to learn what they do. During this period, you should be prepared that you’ll burn through a lot of components due to misuse or not reading the manuals. That’s ok, it means you’re learning.
For starts, you should get acquainted with AliExpress and eBay. If you already know eBay, then you’ll feel at home when you realise that AliExpress is the Chinese eBay. Both sites enable stores to register and sell their goods, often extremely cheap. Most of electronics components on AliExpress do not even charge shipping.
This post describes a couple of really essential pieces which you can use to get started, with emphasis on the Arduino ecosystem. Future posts will describe more complex electronics, all the way to manufacturing PCBs.
For starts, you should get something like this:
#1: A five-pack of Arduinos
As it’s normal and expected you’ll burn a few, just get a bunch of Arduinos to work with. They are excellent for learning how microcontrollers work, and are surprisingly resilient. It’s really tough to destroy one - but it happens. So buy 5 of them. Here’s a link on AliExpress. When bought in bulk like on this link, they’ll cost around $2.85 each.
You should also buy a couple of mini USB cables for those, for example here.
#2 Breadboards and wires
Breadboards are things into which you will stick Arduinos and other components. You’ll also need lots of wires to connect things together, and something which resembles a power source. For now, we’ll stick with USB-related stuff.
This package for about $3.70 gets you a breadboard, a power converter for the breadboard, and a bunch of wires, to get you started. This power converter needs a 12V power supply, so get one of those also. By using this, you’ll have access to the most commonly used voltages in hobbyist electronics: 12V, 5V and 3.3V.
How to start with electronics on a tight budget 1: introduction
I’d like to summarise what I’ve been doing the past year or so, what I’ve learned and where I’m going from here. I’ve always been a software guy - even in university I’ve mostly avoided anything to do with hardware, and while I’ve quite the broad experience in software and IT, I’ve had next to no experience in hardware until about two years go. I’ve messed around a bit with Arduino and Raspberry Pis, but those were very simple projects, nothing complicated. I’ve gotten a bit fed up with working with “intangible” software and started seeking what I can do and learn in hardware. I’m writing this to illustrate that, basically, until about a year and a half ago I haven’t soldered anything useful, and that, though I remember some fundamentals from the uni, I never had neither the education, nor the experience nor any interest in electronics. Of course, working with software, sometimes even at a very low-level (I was once a kernel developer for FreeBSD) helped much, but not nearly enough.
This was the first thing I made on a proto-board that worked, and required some design and soldering, and I was very much pleased and proud about it (one of the early blog posts at this blog talks about it - it is a supercapacitor-powered solar sensor):
That was a bit over one year ago.
I’m located in Croatia, a country known for its beautiful coastline and great tourist destinations, but essentially a tar pit for any non-tourism industry, especially for hardware. Things are improving, though, and while there are no schools or workshops where one could learn professional electronics, there are occasional companies which manage to actually produce and sell something - which is a category where I’d like to be in the near future.
Lately, I’ve been involved at a company, a self-funded startup with a couple of friends, which aims to produce some interesting things (but more about that in a future post, mostly because there’s still much work in front of us so I don’t want to oversell it). From the start, the electronics part was supposed to be done by a friend who had the most experience with actual electronics of all of us, but that has fallen through, and so partly from necessity, partly from interest to learn something new, I got to design and sometimes assemble almost all of our electronics, in addition to most of the software parts.
Well, it was a humbling experience, with a very steep, and fast, learning curve, and a trail of non-working boards left-and-right. It would be fair to say that only now, almost a year since I’ve started, my boards have started working well for the most part. I think I’ve designed something like 20-ish boards (for a couple of product lines) in that time, and at least 15 of them had major bugs.
I’ve learned a lot in the process, and one of the best ways to get my thoughts in order is to write them down, so I’m writing :)
In the next couple of posts, I aim to explain how I’ve started, which pitfalls I’ve discovered, and hopefully leave a trail for other enthusiasts to follow.
(Of course, I’m not the only one or first who’s doing something like this, so I invite everyone who’s interested to comment and contribute!)
The trouble with power - or: mixing and matching batteries, devices and solar power
I’m writing this to clear my head on what are the options when dealing with semi-low-power devices, especially solar powered ones. If I’m wrong, I’d very much like to know about it.
From the device sides, there are two main voltages on which things which interest me operate on: 3.3V and 5V. Luckily, with most devices there’s quite a bit of overlap and a pretty wide range. For example, AVR MCUs most often tolerate anything from 1.8V to 5.5V, depending on the frequency they are being driven. Since for low-power devices I’m using the lowest conventionally configurable frequency of 1 MHz, this means that the MCU will happily run on a really wide range of voltages. On the other hand, the ESP8266 chip, by spec, will run only on voltages ranging from 3.0 to 3.6V. The popular ARM chip STM32F103 operates from 2.0 to 3.6V.
There are many hobbyist devices which support a 3V to 5V range, for example the DHT11 and DHT22 temperature and humidity sensors, and many small OLED modules contain a LDO which steps down anything into a 3V-ish range.
So, aiming at about 3.3-ish range for devices usable with AVR, ARM and ESP8266 seems like a good target.
Ok, what about the power supply side?
The power supply side is a mess. Starting with the simplest batteries, non-rechargeable (primary) ones with nominal voltage of 1.5V will just reach 3V when combined in series... nominally. In reality, a single cell’s voltage will range from 1.55 to about 1.25V before they become completely unusable:
This means that the series combination will go from 3.1 V to 2.5 V. Good enough for AVR and ARM, but a bit short for the ESP8266.
Moving to rechargeable (secondary) batteries, the trendy LiPo cells bring their own set of problems. Firstly, their voltage ranges from around 3 V (with obligatory over-discharge protection) to 4.2 V. Which means that for usage with a 3.3 V device, a LDO or, if cheap, one or more diodes are needed.
The number of charge cycles for LiPo is in the range of 300-500, depending on the quality if the batteries.
Then we have the old-ish NiMH batteries which are particularly attractive for solar devices because they support about twice the number of charge cycles of LiPo. They come with their own voltage curves:
As long as NimH cells are not discharged with a high current, their voltages should stay at around 1.1 V - 1.2 V pretty much the whole time.
But to reach the 3.3 V-ish range, three NiMH cells need to be combined in series, giving a nominal voltage of 3.6V, which is on the high end for 3.3 V devices, but bearable, as long as the batteries are not charged to the hilt so we avoid the starting voltage which can go up to 1.5 V per cell.
And at last, there are supercapacitors, which have three annoying properties: one is that their discharge voltage always drops, exponentially:
The second one is that the reasonably priced ones come rated at 2.7 V, which means that a single one is definitely too low voltage for any kind of device, as most of the power of the capacitor is “hidden” behind a voltage too low to power devices. 1.8 V is just 44% of the 2.7 V starting voltage, which means that if connected directly to a load which stops working at 1.8 V, the amount of power received will be just the tip of the triangle in the upper left corner, between the peak and the 66% line. The third annoying property is that the total capacity of capacitors connected in series (which is needed to increase the charging voltage) drops the more capacitors are added:
So for N identical capacitors in series, the total capacity is linearly lesser:
Ctotal = C / N
E.g. two supercapacitors of 100 F rated at 2.7 V connected in series have a resulting voltage of 5.4 V and a resulting capacity of 50 F. Bummer.
With supercapacitors, an essential component is a boost converter which will take any voltage up to e.g. 0.5 V at the lowest range (depending on a specific device) and produce a stable voltage on its output. Except that boost converters also waste power, so they’re not always the right choice. And in some circuits, where a drop in voltage is permissible, it may be beneficial to just leave it dropping.
About solar panels
Small solar panels are made of individual cells which give around 0.5 V each. The total voltage and current rating of the panel depends on the dimensions and how the cells are connected. Usually, they’re just connected in series:
This example has 8 cells which re simply connected in series to give a total of 4V. This is just the nominal open-circuit voltage. In practice, solar cells will perform like current sources and their voltage will drop depending on the current drawn.
Both 3.5 V and 4.5 V solar panels are more expensive and more rare than 4 V panels, so 4 V seems like the value to aim for.
One annoying property of solar cells is that they conduct when there is no sunlight, so a diode is pretty much necessary to keep the battery from discharging through the panel. And this diode has its mandatory voltage drop.
The smallest drop comes from Schottky diodes, which goes up to 0.45 V, but unfortunately it’s current-dependant:
So if there’s no current flowing, the diode’s voltage drop is nearly 0, i.e. it carries over almost the full voltage of the source.
So the question is: how do we fit a solar panel, with voltage increments of 0.5 V, or more likely 1 V for the low-cost mass-produced ones, a diode, and a battery?
If using three NiMH batteries in series, we’re aiming for a solar panel + diode combination of around 3.6 V. Nominally, a Schottky diode would make such a drop on a 4 V solar panel, EXCEPT when the battery is full and nothing is using the power from the solar panel, at which time the Schottky diode, at least in theory, would just pass the whole 4V to both the battery and the device connected to it.
In the above graph, it takes about 1 mA of current to have the voltage drop of the 1N5817 diode (a very common Schottky) to raise to about 0.15V, which means 3.85 V being passed to the device. And I’ve learned to make boards which use much less than 1 mA in standby.
Normal diodes are great in the low current range but their voltage drop gets huge when current raises to mA ranges usable for charging.
I’ll just have to see how it behaves in practice.
I’m discounting LiPo batteries in this scenario because they need both special circuitry to charge, and a voltage regulator to discharge, and both things waste power.
Update: A friend sent a link to LTC4079, an IC which can supposedly charge LiPo batteries and seems reasonably easy to integrate. I hope to test it one day.
Reading voltage and current from MAX471 sensor modules, or any analogue voltage sensor by an AVR microcontroller
MAX471 / MAX472 are great little sensors often found in module boards targeted for Arduino users. These boards are currently very cheap on eBax and AliExpress, and usually look like this:
The only major downside to these sensors is that the ICs are not manufactured anymore. The manufacturer’s data sheet states the product was manufactured using an obsolete process and so isn’t available any more. Which is a bit of a shame because they are excellent in certain circumstances.
The MAX471 chip is an analogue current sensor, which means that it measures current and outputs a voltage level which has a linear correspondence to the measured current. Thus, it can be read by any microcontroller which has an ADC, and that nowadays includes pretty small ones like the ATtiny series. No protocol is necessary to get a reading from the MAX471 / MAX472.
The module integrates more than the MAX471 sensor!
The IC itself needs a couple of registers to configure its range, and the red-coloured sensor module on the above picture also contains a couple more resistors which form a voltage divider, so the module also offers voltage measurement capability.
The module is intended to measure power consumption of devices which use up from about a watt to about 60 watts. I don’t think it’s very precise in the low range. It outputs a voltage level on the Vt pin which is 5x lower then the input voltage, and outputs a voltage level on the At pin which is directly analogous to the current, i.e. for 1A it will output 1V.
By measuring the voltage and current output pins from the module, it’s trivial to calculate the power passing through the device. The device’s limits are about 3A for current and about 25V for the voltage (this one depends on the voltage of the MCU doing the reading of the analogue pin!).
Reading voltage accurately
AVR microcontrollers (and this is also true for most of the other families of microcontrollers) generally measure a voltage level using an ADC (analogue-to-digital) circuit which compares the desired voltage to the MCUs Vcc level, and outputs an integer in the range of 0 to 1023 (because the ADC has 10 bits of accuracy). So for an input voltage of 0 V, the ADC will output 0, and for an input voltage exactly equal to Vcc it will output 1023. To convert this reading into a (floating point) voltage, this equation needs to be used:
Microcontrollers are often used in battery-powered devices, and this means the Vcc will change over time. If the Vcc value were hard-coded in the program (i.e. “5.0”), the voltage calculated in the above equation would soon become severely inaccurate.
Fortunately, the AVR MCUs have an built-in, stable internal voltage reference which can also be used to measure a voltage. The “stable” part means it doesn’t vary with Vcc and even to a large degree with external factors such as temperature. Unfortunately, this reference voltage level is around 1.1 V, which means by default we could only measure voltages on the pin up to this level. Also, the reference voltage is uncalibrated, meaning its value, while stable for a particular IC, varies during the production process, so each chip has a slightly different internal reference voltage level.
Fortunately, again, the AVR’s ADC can be configured to measure the internal voltage reference, comparing it to the external Vcc, and if the Vcc is known, the internal voltage reference can be calibrated. We can attach a voltmeter to the Vcc pin and measure it precisely, then measure the internal voltage reference, and calculate its value from the same equation as above. With a bit of math, by measuring the internal voltage reference, the Vcc can be calculated and calibrated, which is done by the following code:
int readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined (__AVR_ATtiny167__) || defined(__AVR_ATtiny87__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return result - 0; // hard-coded calibration
}
By running a program on the MCU with the above code, which returns an integer number of millivolts, and comparing its result to what an external voltmeter says the Vcc is, we can incorporate this difference as a calibration value in the “return” statement above, so the result of the function is equal to what the external voltmeter reports.
This calibrated Vcc value is needed to measure the output of the MAX471 sensor module:
float Vcc = readVcc() / 1000.0; // Vcc in volts
float Vpin = (analogRead(A0) / 1023.0) * Vcc; // Voltage on the Vt pin
float Vsensor = Vpin * 5; // The sensor divides the voltage by 5
float Asensor = (analogRead(A1) / 1023.0) * Vcc; // Voltage on the At pin
This is enough to accurately measure voltages of up to 25 V (only if the MCU is powered by a 5V-ish power supply, because the input to the ADC must not exceed Vcc!), and currents of up to 3 A on the sensor module.
Supercapacitors mostly come in low voltages, usually 2.7V or 2.5V, which limits what can be done with a single supercap. Here are some notes from my experiences using them to power small electronic devices.
As capacitors are discharged, their voltage falls off exponentially. This produces the interesting property that, if the resistance of the circuit is constant, the more a supercap is discharged, the less current is drawn and the less power the circuit draws.
This means that adding a booster to the supercap to boost and (somewhat) stabilise the voltage to a certain higher level exhausts the capacitor much more quickly than a circuit which is designed to operate on a wide range of voltages would. This booster would draw progressively more current as the capacitor’s voltage falls off, which means the more the capacitor is discharged, the more it is stressed (assuming the output power is the same).
On the other hand, pairing two 2.7 V capacitors in series raises their combined voltage to 5.4 V at its peak, which is much more useful for general electronics. However, the capacity in farads drops off the more capacitors are added:
So, having two capacitors of 100 F rated at 2.7 V in series results in a combined capacitor of 50 F rated at 5.4 V. Not ideal, but survivable. Parallel connections of capacitors keeps the voltage the same and increases the capacity as a sum of individual capacities.
So for most of (my) electronics projects, it’s much more useful to have pairs of supercapacitors and treat them as 5 V power sources, and design circuits which work from 5 V down to 2 V. This also means that the charging circuit to the capacitor(s) usually needs to have a boost/buck DC-DC converter which regulates whetever is on the input side (possibly a solar cell in my projects) to between 5V and 5.4V.
A solar-powered supercapacitor-backed blinking night light
The Sun is shining and I’m again thinking about solar energy. A lot of stuff has happened since my last project of this type - among others, I’ve found EasyEDA for designing circuits and PCBs, which for me has the perfect balance between complexity and features, and also allows direct ordering of PCBs from unnamed factories in China.
So, I’ve designed an actual PCB, through-hole, and had it made. It arrived in about 2 weeks, and as far as I can tell, the quality is very fine. This is my first PCB where I’ve designed the circuit and drawn the board myself, so I’m quite proud to have made it!
Here’s the project link on EasyEDA.
This design is an evolution of my previous designs of low-power solar-charged supercapacitor-backed gadgets. This is the first time I’ve used 2 supercapacitors in series, of 100 F and 2.7 V each, for about 5.4 V tolerance. I’ve read that capacitor (un)balancing can be a problem: where one of the caps in series accumulates more voltage than the other and exceeds its rating, so I’ve experimented with adding Zener diodes to cap the voltage on each of the caps to 2.7 V. This sort of worked but not really. The biggest problem was that the Zener diode voltage-current curve actually has significant multi-mA “leakage” even when it’s not fully conducting in the reverse direction. Since this is supposed to be a low-powered circuit, I just couldn’t afford the 3 mA or so leakage on the Zeners which is practically always happening. Look at the left-hand side of this graph:
So, after some discussion on the AVRfreaks forum, I’ve decided to follow the recommendation to let internal capacitor resistance handle the balancing, i.e. to not do anything special on my side. So far, it seems ok to have the capacitors directly connected in series. The solar cell which powers them maxes out at 5 V.
The MCU here is the miniscule ATtiny13 - it periodically checks if the input voltage on the solar panel is less than 2V, and if it is, blinks. While waiting, it deep-sleeps in the power-down mode. Really simple stuff.
While at it, I’ve measure the reverse feed current of the solar panel. Before doing this I had some vague idea that the solar cell should approximately behave as a diode, but now I’ve confirmed it: apparently, it behaves as a diode where the forward voltage is the “output” voltage of the cell (or the panel). E.g. for a panel of cells rated at 5 V, if an external voltage is supplied to it in the correct (nominal) polarity, it will suddenly start conducting as this voltage approaches 5V. And even before it starts fully conducting, it leaks several mA (the closer to the design voltage, of course, the larger the leakage).
Since I’m storing energy from the solar panel in the supercapacitors, this means that when there’s no sunlight, capacitors will tend to discharge over the solar panel, which is not desirable. To mitigate this in the circuit, a Schottky diode prevents this from happening.
Two 100 F supercapacitors in series make the total capacitance 50 F. With this circuit design, once fully charged, the blinker device can work continuously for about 120 hours, with about a 1/8 duty cycle on the LEDs without any sunlight. I estimate this translates into at least 10 cloudy days. And it’s actually quite quick to charge - several hours of early-morning sunlight is enough.
The reason for using supercapacitors here is endurance - while batteries will last for 2-3 years before the chemistry degrades enough they’re unusable, capacitors will last almost forever.
There are 2 LEDs in parallel, behind a 1 kOhm resistor. I’ve used yellow ones this time. Judging by the U-I curves of variously coloured LEDs, if white LEDs were used, the device could possibly last even longer (as they consume less current for the given voltage) - or would not even light up as the voltage on the supercaps drops. I’ll need to test this some more.
First steps with the RCWL 0516 radar sensor / switch
The RCWL-0516 module can be bought for around $2 at numerous online retailers on eBay and Aliexpress, as well as others. It's intended for lamps and wall lights, where it can turn them on when motion is detected, and turn them off after a short timeout. Short-range (~~5m) radar modules such as this one are an alternative to PIR (passive infra-red) modules. Despite it being a very wide-spread and cheap module, documentation is scarce.
After some experimentation, the module's apparently meant to be connected to 5V on the VIN line, ground to the GND line, and the OUT line will go HIGH when movement is detected in the area of space in front of the module (where the chip is). I got much poorer performance when trying to use it from the back side.
I currently have no idea what the 3V3 pin is. I first thought the module power supply should be 3.3V provided on this line, but when I did that, the module seemed to be overly sensitive or noisy.
In this way, with only the three lines connected, the module seems to be fairly stable and usable. The OUT pin will go high for a couple of seconds when movement is detected, then go low again. The module should be very applicable for motion detection in home automation scenarios.
Towards a MPPT solar charge controller #1: A controllable buck converter
I like to experiment with solar cells and one thing which I quickly found out is that, especially since I’m now in the part of the world where Winter is Coming, I could really use a MPPT charge controller instead of this cheap one.
MPPT stands for Maximum Power Point Tracking, and here the idea is that the controller doesn’t just switch the power from the solar cells to the battery ON or OFF, but it actually does a power conversion, exchanging Volts for Amperes and vice versa in the goal of achieving maximum power output. This maximum point happens on the knee of the I/V graphs for solar cells:
The point here being that, simply sucking the most current from the solar cell with a low-resistance load will not yield the maximum power from it. Another way of looking at is is that, In effect, and through a lot of complications, a MPPT charge controller will dynamically adjust the resistance of the load to match the one expected by the solar cell, as the amount of light changes (and it’s always changing).
The general way to do this is by constructing a “smart” buck converter, which will measure the current and voltage on the solar cell side, then adjust its buck factor, measure again, and if the new result is better than the old one, continue adjusting in the same direction (up or down in terms of voltage); if not, adjust in the opposite direction and measure again. This is also known as a “perturb and observe” algorithm.
We can measure the current and voltage by using some cheap hardware, and calculate the power and the direction of the nudge with a microcontroller (I’m aiming for something in the ATtiny series), so the only other component which is required is a controllable buck converter itself.
If you search for tutorials on building MPPT controllers, you will find a modest number of them, and all of them are building the buck converter from scratch. It’s a simple enough circuit. On the other hand, I’d rather misuse something already existing than produce a modern art-piece of wires on my breadboards, so I was thinking about how to utilise something like this:
This is a cheap and very standard DC-DC buck converter module available at tons of places on the Internet. There are a couple of variations with several different chips. Note the voltage range of this one, approximately 50V max on input and 35V max on the output.
The module has this big blue adjustable resistor / potentiometer, which I’ve measured to go to approx. 6.6 kOhm on the high end. By adjusting this pot, the output goes from approx 2.5V when the resistance is the highest, to whatever my desk power supply can produce on the low end.
So the question becomes: how do I change its resistance? What component do I know, of which I can vary the resistance by using a microcontroller?
After some hours of light thinking, it hit me: a transistor! So, I’ve got a baggie of BS170 MOSFETs, and went to work. Transistors are very non-linear beasts, but at their essence, they are sort of resistance valves which should pretty much be what I need here. Their non-linearity can be fuzzed in software with the PandO algorithm.
EDIT: it gets a bit weird here - I made, measured and wrote all this and didn’t notice I connected the PWM-driven voltage on MOSFET gate and drain, instead of gate and source. So I’m scratching my head on why exactly this works, since from connections, it appears I’m driving the transistor with Vgd instead of Vgs???. And - when I’ve switched the transistor into the right orientation, the MOSFET doesn’t work, in fact, there is no conductance between drain and source. Hmmm, WTF? I’ve tested the transistor, it’s physically in the right orientation. It seems like something in the module itself messes with the voltages.
I didn’t look at the transistor datasheet before I started, and just assumed it will need Vgs around 2V to turn on, so I’ve used a 3.3V Arduino, made a simple sketch which sweeps through PWM factors, and hooked a large-ish capacitor on it (I happened to have a 470uF one on the desk, it’s probably an overkill). The resulting smoothed voltage (+ and -) I’ve connected to the MOSFET gate and drain. I’ve used my tiny oscilloscope to verify the PWM and smoothing work well.
If you look at the pot on the module above, it has 3 pins, two static ones which cover the maximum resistance, and the middle one which varies over this range. I’ve desoldered the pot
I’ve connected the MOSFET source pin to the leftmost pin of the ex-pot (when the module is oriented so that the pot pins are on the bottom), and the MOSFET drain to the middle ex-pot pin (which is also connected to the Arduino “negative” / common). Now, I don’t really know if this messes up the module, or the MCU side of the circuit in some significant way, with regards to the superposition of the 2 power sources (the lab power source on the module, and the Arduino power source are separate). Nothing blew up or melted so I guess I’m good.
And... it works. After some fiddling with the code, to find the range of PWM factors which will usefully energise the gate of the MOSFET (turns out to be between 90 and 190), and adding a 1 kOhm resistor in series with the MOSFET source pin, I’ve managed to control the buck module programatically, from the Arduino, in the range of around 8V - 17V. Which is nice.
Now, what’s the point of this experiment? Besides being geeky-cool, it means I can build a MPPT controller (admittedly for low amperages of around 3A) from parts costing around $4. Note that real MPPT controllers even from China wholesale stores cost more than $50, so there’s money in a bit of invention ;)
Next step is to buy the voltage & current sensor so I can put together the intelligent controller part of the circuit.
EDIT: so about that Vgd vs Vgs thing, it looks like the module also does its own voltage routing, and both Vgd and Vgs are positive (and different), and proportional to the smoothed-out PWM voltage. Vgs goes from 0.2V to around 2.4V, and Vgd is around 0.2V higher (note that I’m driving Vgd, and I have no idea what drives Vgs). This seems to put the MOSFET into a “triode mode,” and I’ve stumbled upon it by pure luck. It also seems to be a mostly-linear-resistance region, which is excellent for my intended purpose or using a MOSFET as a variable resistor. Mystery solved!
Miniature desk (or portable) power supply rig for less than $9
Probably the first things any electronics hobbyist should buy are a multimeter, a soldering iron, and a power supply. And if you have the money and opportunity to buy quality stuff, you should. If you don’t or even if it’s down to lack of desk space, there are both cheap and small options plenty.
While I have a proper power supply, I’ve recently bought a small device which is just cute, tiny and good enough for many purposes, as well as cheap enough to be discardable:
This a very simple buck converter, of a design similar to the cheap general purpose DC-DC modules which can be found in large quantities all over the Internet, with slightly different chips. This particular module can be bought for around $5.5.
Since this is a buck converter (i.e. it drops down DC voltage from a source), it needs an AC-DC adapter in front of it to supply the DC voltage. To do this, I’ve used a very cheap and also ubiquitous AC-DC 12V adapter such as this one:
All in all, the cost of the buck converter and adapter together is below $9. For this money, you get what you paid for:
A very small, very compact, fits-inside-a-cookie-box power supply setup
Adjustable voltage range from 1V to 11V
No current adjustments or protection
About 2.5A - 3A maximum current draw (though not for a long time)
The device can be calibrated if required
With this setup, you can basically adjust the voltage output at around 0.2V precision, at a decent range for working with Arduino and other microcontrollers, and with enough current for hobbyist use.
As a experiment, I’ve hooked up a 12V, 500 mA AC-DC adapter to the module, and measured the short-circuit current at 4V at the output to be around 2.5A. The module did give away some noises which probably indicates it’s not too happy with this situation, but it worked and nothing caught fire, at least for the few seconds I did the experiments.
If you need an adjustable power supply for goofing around, this is a very decent choice.
I’m working on some stuff which will require distance sensing, so I’ve searched around and found that TCRT5000 sensors are very, very cheap. I’ve ordered some to test how they behave in practice.
The image above was what I’ve just found, and the recommended circuit for the sensor differs a bit to what I’ve found before. Luckily, the sensor seems to be Arduino-class resilient to abuse. :) Despite what the diagrams in the picture above show, and what the photo on the left seems to confirm, the package looks pretty much symmetrical to me, with the only visual difference between the two sides being the colour of the diodes. The black one is the receiver (transistor, T), and the bluish one the transmitter (diode, D).
My circuit looked something like this:
I.e. no external resistors (a pullup on the analog input), with an external LED connected to a PWM pin. The code simply turns on the TCR5000 diode, reads the analog input, and dims the external LED with PWM proportionally.
The TCR5000 module, I’ve learned later, is mostly used for “line tracking” in small wheel-mounted robots. There, it’s used simply to detect if the reflection changes, signifying that the course needs to change.
I’ve found that the sensor module is pretty good in detecting IR reflectivity, at around 10-20 cm. So, as an actual distance sensor it’s not very good, as it would basically need to be calibrated to every target surface type. It could be used as a simple on/off detector in simple applications.
Getting started with cheap STM32 ARM development boards
There are a lot of vendors on AliExpress and eBay which sell a particular form of a STM32 development board with an ARM processor, costing around $2. So far, it looks like all of them have distinct yellow connectors, so they look like this:
The silkscreening is somewhat consistently bad, and the boards do look incredibly alike, so it really looks like they are actually manufactured at a single place or at least with an exact single list of components.
At a first look, these seemed to me to be “Maple Mini” boards, for which there is much support on various sites and forums, but no, the boards are actually a variation on the minimum development boards for the STM32F103C8 ARM CPUs. Luckily, once this is known, the rest is easy.
The board itself is quite capable, with a 72 MHz CPU, 64 KiB of flash, 20 KiB of SRAM, 3 USARTs, 2 I2C, 2 SPI, a CAN and an USB2 peripherals. To make use of all this hardware, some advanced software support is needed, specifically something like FreeRTOS.
The boards have support in the Arduino IDE, which can be manually installed by unpacking this GitHub repository in the “hardware” subdirectory of the main Arduino directory. Name it Arduino_STM32.
The actual device cannot be programmed from its USB port (or is complicated enough that most people don’t even bother), so you will need a USB-to-serial converter which supports 3.3 V power and signals. I had almost such a thing, a converter which is advertised as “dual mode” 5 V and 3.3 V. It turns out that this “dual mode” nature of the converter means it outputs 4 V, which is not optimal, though it didn’t fry my board. I’ve connected the USB-to-serial to the board in this way:
serial TX -> pin A10
serial RX -> pin A9
serial 3.3V -> 5 V pin
serial GND -> GND
My intent here was to power the module directly with 3.3V from the USB-to-serial converter and proceed to program it from there. Apparently, it works, though I’m a bit worried about the 4V on the TX/RX pins. The board can also be powered from its built-in USB connector, but a separate USB-to-serial converter is still needed:
(I’ve learned a lot from this blog post).
The development board itself can boot the MCU either in the “upload / command” mode or in the “execute user program” mode. This is determined by the BOOT0 jumper (the one closer to the edge of the board). Only when the BOOT0 jumper is set to 1, and the other jumper to 0, and the RESET button clicked, can the board be programmed or configured (so this jumper position is needed for steps 2 and 3 in the following list).
There was some need for twiddling in the whole process:
The drivers for my particular USB-to-serial converter were apparently provided with my Windows system, but for some reason they didn’t work. I’ve downloaded some new drivers from here and then it worked.
The MCU on the board itself was apparently shipped “locked” for some reason, meaning new programs couldn’t be uploaded to it. To solve this, I had to download the “STM32 Flash Loader Demonstrator” and unlock it. This tool communicates on 115200 bps, 8 bits, Even party, and no Echo.
Once the Arduino IDE is restarted after unpacking the board files, new board choices will become available. Here, the “Generic STM32F103C” board needs to be selected with the “Serial” upload method.
After this is done, everything else goes smoothly, keeping in mind that when the BOOT0 jumper is set to 1, the RESET button need to be clicked before uploading the program from the Arduino IDE. The boot loader will execute the newly uploaded program after the upload completes.
Once the board is to be put to use without programming it, both jumpers can be set to 0, and then the board will execute the user code immediately when powered on or reset.
Which has more energy, one 500 F 2.7 V supercap, or six 120 F supercaps in series at 16.2 V?
I’ve bought a supercapacitor module made of six 120 F supercapacitors of 2.7 V in series, for a total voltage of 16.2 V, and a single bigger supercapacitor rated at 500 F and 2.7 V. My question was: which one stores more energy?
For start, there’s the equation for approximating the energy in capacitors with Ah, which takes into account the usable range of voltages, and goes like this:
Ah = Farads * DeltaVolts / 3600
This equation is sort of both accurate and useless, because the concept of Amp-Hours applies cleanly only to batteries which are approximately a constant-voltage source. In capacitors, it’s a bit iffy because their voltage is constantly dropping.
I’m calculating DeltaVolts as whatever the rated voltage of the capacitors is, minus a 0.5 V since that’s the lowest my boost converter will work with. The 6 120 F capacitors in series will result in a total capacitance of only 20 F, so my results are:
For the module: 20*(16.2-0.5)/3600 = 0.0872 Ah
For the big cap: 500*(2.7-0.5)/3600 = 0.305 Ah
In mAh, those are 87 mAh and 305 mAh. Note that both of these are very small values compared to regular chemical batteries.
Actually, this result surprised me, because I really thought that having 6*120F=720F of capacitance, in any physical configuration, will store more energy than a 500 F capacitor. This needs a more thorough investigation.
The above equation mixes concepts quite a bit, so let’s go directly to Joules. The energy stored in a capacitor is:
E = 0.5 * C * V^2
For the module: E = 0.5 * 20 * 16.2^2 = 2624 J
For the big cap: E = 0.5 * 500 * 2.7^2 = 1822 J
So actually I was right. More energy is stored in 6 * 120 F 2.7 V capacitors in series than in a single 500 F capacitor.
Let’s check how this plays out in practice, though.
I recently got a battery capacity tester, a simple module which discharges a battery (or any kind of source) through a big resistor and measures how much energy flows in the process.
It’s very easy to use: it draws power from the USB port for its MCU and other electronics, it has a configurable lower voltage at which discharging will stop, and it can basically be used to measure any kind of energy transfer, including charging a battery, not only discharging it.
I’ve charged the capacitor module to 15V, as I have only a 15 V power supply, and the big capacitor to 2.7V. In both cases, I’ve set the lower (cutoff) discharge voltage to be 0.5 V.
The module yielded about 58 mAh.
The big cap yielded about 220 mAh.
This is in the ballpark of the initial equation (especially given the relatively imprecise capacity of these eBay caps, and probably some wrong expectations on the part of the measurement device with regards to voltage levels). However, I’m puzzled by the results of the energy equation and I currently don’t know how to reconcile this with the measurements I have.
I also measured one of my small 5.5 V 4 F supercaps, charged to 5.3 V under the same conditions, and the module showed around 3 mAh.
All this is very low, compared to chemical batteries.
I recently got some RTC modules based on the DS1307 chip, which also include some additional features: a 32 Kbit EEPROM and a square-wave generator. These modules are plentiful on eBay and Aliexpress and usually look like this:
They are accessed via I2C, are supported by good Arduino libraries, and offhand seem very convenient. However, their accuracy is so bad that they are practically useless.
A friend I lent a couple of modules complained they drift so much he cannot use them for the intended purpose, so I wanted to confirm this with one of the modules I had. I’ve made a simple Arduino sketch which reads the value off the RTC module and prints it to the serial line, and a program on a Raspberry Pi which reads this value and compares it to the system time. Here, the absolute value of the time is not relevant - the module was initialised with some random time a few hours before, and we’re interested in the difference between the RTC time and the system time (which is updated via NTP and we’ll take as wall-time). Ideally, this difference, whatever it is, should remain constant. That would indicate that the RTC is stable, and once adjusted to the proper time, keeps it accurately.
Here’s a plot of what happened:
The difference between the RTC time and wall-clock time (in seconds) was decreasing practically linearly through something like 20-ish hours it was running, which means the RTC is not stable, but drifts. Its seconds are shorter than "real” seconds.
Googling around, it looks like this is a common problem, and there is at least one forum discussion with relevant explanations and ideas which module to buy for better accuracy.
Some months ago I got a packet of “joule thief” devices from eBay:
I had the idea to use the modules with solar-powered ultracapacitors to light up some LEDs - and I made this review with this purpose in mind. I didn’t have enough equipment to realise that plan at the time so after some initial experiments which apparently showed a much larger power consumption than I expected, I stopped playing with them until some future occasion. Now, I have some time to see what’s really going on with the power consumption here.
The first thing I notice now is that the devices I have are slightly different from the image above: the fairly big inductor on the left is replaced with a much smaller, cube-shaped device which presumably has the same characteristics. I measured it as a 0.68 mH, 22 Ohm inductor.
The devices themselves are not real “traditional” joule thieves but implement some kind of two-transistor oscillation circuit. If you have any more information about how they work, please post a comment!
I’ve hooked the module to my desk power source and set it to 1.5 V, and on the output I’ve connected a white LED with a 1 kOhm resistor in series. This combination draws almost exactly 9 mA from the input side, which is higher than I expected. The thing is, joule thief circuits oscillate and have a fairly short duty cycle (practically pulses), and because of this duty cycle they should draw little current and wear a battery down slowly, over a long period of time. Their output should be in spikes of several volts, enough to light up a LED for a very short time, with enough frequency so it appears constantly lit to our eyes. All this is true for the “traditional” ones like in the link above. This module is a bit different.
With my small oscilloscope, I’ve measured that the spikes from this module, when running on the above LED and resistor, come up to above 10 V, with a frequency of around 66 kHz:
The (approximately constant) current consumption of 9 mV is a bit too much for my purpose to use the modules as basically energy harvesting devices.
For comparison, I’ve also measured the current draw from the same LED and resistor circuit (let’s say this is the load I’m aiming for), powered by the small 3.3V boosters (which output a very level voltage), from the same 1.5 V source, and it’s only 7.5 mA (at the input side). These boosters are rated to turn on at about 0.8 V, but stay on at least until 0.5 V, which are similar characteristics to those claimed for the joule thief modules.
So, given the purpose of driving this particular LED and resistor, these modules do a much worse job than generic Chinese boosters. Don’t buy these particular joule thief devices.
As an evolution of my previous projects, I’ve changed and simplified the design of my supercapacitor-powered 24h sensor with ATtiny85, and made a better-looking circuit on a proto-board instead of using breadboards.
The above picture is from a slightly older iteration, using a 1.5 F 5V supercap, which I’ve since replaced with a 4 F one.
This design has the 2.5 V solar cell feeding a 5 V booster module through a Schottky diode, which then charges the supercap, to which the ATtiny85 is directly connected.
As before, the MCU sleeps for a period of time (currently 20 s) then measures its input voltage, directly powers the 433 MHz module from one of its IO pins (rated up to 40 mA), and sends the measurement to a standalone receiver a couple of meters away. I’ve also added internal MCU temperature measurement, which has proven to be uselessly inaccurate. I’ve tried using a DHT-11 sensor module but something went wrong - possibly because the module is faulty. I’ll investigate it later.
With this setup, when the device in near my window, which gets direct sunlight only until about noon, the whole thing manages to operate for about a day and a half on a single full charge, as shown here:
The MCU voltage graph plotted on the receiver side shows that the voltage never drops below 3 V if the days are sunny enough to have the capacitor fully charged. On the high side, it’s capped to 5V from the boost converter. The values have a bit of a positive DC bias because I didn’t calibrate the chip for the variations in its internal voltage reference.
On the 4th, it was a cloudy and stormy day; so the solar panel couldn’t provide enough power to charge the supercap, so the voltage continued to drop. I’ve programmed a cutoff at 2 V at which the MCU basically only sleeps until it gets enough juice. This is why I say this setup can run about a day and a half with a full charge on the supercap. Of course, it would run for a shorter time (hopefully still more than 24h) with a sensor which draws current for itself.