You’d think it would be trivial to convert an image to RGB 565 format (16 bits per pixel, using 5 bits for red, 6 for green (since our eyes are more sensitive to it) and 5 for blue). This format was popular years ago, and is making a come back in the mobile arena where most video hardware supports only 16 bpp. In fact, the OpenGL ES standard only allows 16 bpp.

Yet none of the popular image editing software presents you a way to do this.

The ffmpeg utility will do this, fortunately. It can be invoked as such:

ffmpeg -vcodec png -i source.png -vcodec png -pix_fmt rgb565 destination_565.png

Season to taste.

To see a list of “pix_fmt’s” that are supported:

ffmpeg -pix_fmts


This how to will explain how to derive a list of vertices that will be useful in rendering a sphere in 3 dimensions. If you’re only interested in a code example, you’ll find a functional class toward the bottom; however, I will first attempt to explain the concepts.

Sampling Points

Lets start with a definition of a sphere (I assume you know what a sphere is, but a precise definition will provide some insight on where we might find our vertices.) Wolfram defines a sphere as:

…the set of all points in three-dimensional Euclidean space R^3 that are located at a distance R (the “radius“) from a given point (the “center“).

Our clue lies in the beginning of the definition, “…the set of all points…” What this means is that any equation we may use for a sphere will be useful to find points in this set. In other words, any one solution to this equation will yield precisely one point on the sphere. Essentially, we want to sample points along our sphere. The usual equation for a sphere, again borrowed from Wolfram:
x^2 + y^2 + z^2 = R^2
This equation, however, is not entirely useful to us yet. In order to find a single point, we need to know several variables. For example, we know that a unit sphere (a sphere with R=1) will touch the point at  (0, 0, 1), so if we were to use our known values for x and y and R here, we could solve for z:
0^2 + 0^2 + z^2 = 1^2
z^2 = 1
z = sqrt( 1 )
z = +/- 1

Again, this isn’t entirely useful to us because we can only find a useful triplet (x, y, z) by knowing two of its values, which we only knew beforehand because it was convenient. We could find some useful points by looking at the range for x: [-R, R], y: [-R,R], etc. By taking various pairs in these ranges, we could find our vertices by solving for z, but once we define x, our range for y changes, and vice-versa. This is the right concept, but lets look at at another way to define a sphere, which might be more conducive to sampling points in the manner we need.

Spherical Coordinate System

You’ve probably studied an alternative system for describing locations on a sphere in geography related to our Earth. To describe points on our globe, we talk about two variables: latitude and longitude. Distinct values for both of these describes exactly one point on the planet. Latitude describes a horizontal ring around our globe, while Longitude describes a vertical ring around the globe (actually, a semicircle). Where these two intersect, we have our unique location. We often call this coordinate system a geographic coordinate system.

This is actually a special case of a spherical coordinate system. In a spherical coordinate system, we can describe any point as we did above, with one additional value: radius. In our geographic coordinate system, we have a fixed and known radius (6,378.1 kilometers, says Google), so we take it for granted. In a spherical coordinate system, this additional value allows us to describe any point in 3 dimensions. The longitude is usually called θ (theta), and the latitude φ (phi).

The spherical coordinate system essentially uses two angles and a radius to describe points. You can read more about spherical coordinate systems on Wikipedia and Wolfram. As earlier, we can define any point with a triplet (θ, φ, r), now a couple bonuses: we know one of our values (r), and we don’t have the range dependency problems for the other two as we encountered earlier.

Our range for θ is [0, 2Π] and our range for φ is [0, Π], and these ranges do not depend on each other. So we can take any value in one, and any value in the other, and given our radius, we have a point on our sphere. If we sample these values at even intervals, we will have vertices that will make a consistent looking sphere. The smaller the interval we use, the more vertices we will come up with, and the more detailed our sphere will be. Obviously, this will be more work for our rendering engine, so there is an important trade-off there.

We have one last challenge: our rendering engine probably doesn’t like spherical coordinates, so we need to convert back to cartesian coordinates. Fortunately, this is a trivial matter of trigonometry, and we can use sine and cosine for our conversions as follows:
x = r cos θ sin φ
y = r sin θ sin φ
z = r cos φ


Now we have a convenient way to sample points on our sphere and convert them to the coordinate system we need. All we need to do this is a few variables to describe (1) our radius, (2) how many values in the range for θ we want to sample, and (3) how many values in the range for φ we want to sample.  In the code below, we call these numStacks and numSlices. Given these, a couple for-loops is all we need.

Before I get to the example code, let me briefly explain one more thing. In OpenGL, it is possible (and preferred) to reuse vertices. If a vertex is shared between two or more polygons, you can define the vertex once and refer to it by its index as often as needed. For example, if you have triangles ABC and BCD, you can first define an array of your vertices (ABCD), then define your triangles by the indices of your vertices. So our triangles above would be 0,1,2 and 2,3,4. This should explain part of the code below related to indices, except they are designed to use triangle strips. I won’t bother explaining those, as Google will be able to tell you all about them.

So here’s the code, this first one I’ve defined in sphere.h:

class SphereMesh {
        SphereMesh( const float radius, const unsigned int numStacks, const unsigned int numSlices );
        float const getRadius() const { return _radius; };
        unsigned int const getNumStacks() const { return _numStacks; }
        unsigned int const getNumSlices() const { return _numSlices; };
        const float* const getVertices() const { return _vertices; };
        unsigned int const getNumVertices() const { return _numVertices; };
        const unsigned short* const getIndices() const { return _indices; };
        unsigned int const getNumIndices() const { return _numIndices; };
        // given
        const float _radius;
        const unsigned int _numStacks;
        const unsigned int _numSlices;
        // computed
        unsigned int _numVertices;
        unsigned int _numIndices;
        float* _vertices;
        unsigned short* _indices;

And sphere.cpp:

SphereMesh::SphereMesh( const float radius, const unsigned int numStacks, const unsigned int numSlices ) :
        _radius(radius), _numStacks(numStacks), _numSlices(numSlices) {
    _numVertices = (numStacks + 1) * numSlices;
    _vertices = new float[ _numVertices * 3 ];
    _numIndices = numStacks * (numSlices + 1) * 2;
    _indices = new unsigned short[ _numIndices ];
    // build vertices. loop around each stack to get all the vertices on it.
    int vertexIndex = 0;
    for ( unsigned int stackNum=0; stackNum<=_numStacks; ++stackNum ) {
        for ( unsigned int sliceNum=0; sliceNum<_numSlices; ++sliceNum ) {
            float theta = stackNum * (PI / numStacks);
            float phi = sliceNum * 2 * (PI / numSlices);
            float sinTheta = sin(theta);
            float sinPhi = sin(phi);
            float cosTheta = cos(theta);
            float cosPhi = cos(phi);
            _vertices[ vertexIndex ] =      _radius * cosPhi * sinTheta;
            _vertices[ vertexIndex+1 ] =    _radius * sinPhi * sinTheta;
            _vertices[ vertexIndex+2 ] =    _radius * cosTheta;
    // build indcies. for each stack, loop around and build a triangle strip.
    int indexIndex = 0;
    for ( unsigned int stackNum=0; stackNum<_numStacks; ++stackNum ) {
        for ( unsigned int sliceNum=0; sliceNum<=_numSlices; ++sliceNum ) { // less than or equal, as opposed to above
            _indices[ indexIndex ] = (stackNum * numSlices) + (sliceNum % _numSlices);
            _indices[ indexIndex+1 ] = ( (stackNum + 1) * numSlices ) + (sliceNum % numSlices);
SphereMesh::~SphereMesh() {
    delete [] _vertices;
    delete [] _indices;

I hope this has been helpful. Don’t hesitate to ask questions.


Design and Concept



Let me start by putting in to words the goal I was seeking. I wanted a way to control fermentation temperature and timing of my beer with a high level of precision and to be able to extract data along the way that might help me make better beer. Perhaps a bulleted list of requirements would be more clear:

  • Precise control over temperature
  • Programmable phases or durations of fermentation with defined temperatures and periods of time
  • Collection of temperature samples at regular intervals for graphing
  • Multiple beers at different temperatures simultaneously
  • Ample capacity
  • 100% automation


I wanted to support multiple fermentations which would occur independently at different temperatures, so immediately I knew that I would need to build something in the style of a cabinet with well insulated separation. The automation would require that I have some equipment to do my bidding, so I would need a chamber for that as well.

Fermentation Chambers

In order to maintain separate temperatures, I needed some electronics. If I didn’t mind manually adjusting the temperature at the right times, I could have gotten away with one of the many commercial temperature controllers that exist. But I wanted to automate that process, and those could have bumped the cost of the project quite a bit. So I decided to get a programmable microcontroller that could help change the temperature exactly the way I wanted it to. I quickly came across the Arduino, which looked like something I could learn to use quickly.

The fermentation process needed to be completely automated, so I needed a source of “cold” in order to remove heat from the system. The only option that really left me was a refrigerator. Some similar projects I had seen drilled a hole in a fridge (or freezer) in order to pump coolant from a chamber to a refrigerated reservoir. I decided instead to remove the cooling system from an small fridge I had been hanging on to, and incorporate that into one of the chambers mentioned previously.

Recommissioned refrigerator compressor

This would allow me to keep something cold, but I needed to keep multiple fermenting beers happy. I needed to “distribute” the cold to each in a manner that would allow me to keep very precise and steady temperatures. This problem has been solved well by others, such as Jason Smith, so I decided to borrow his knowledge and use pumps, fans, and radiators.

So here’s how the system would work. The cooling system from the old fridge keeps a large reservoir of water (mixed with a small amount of glycol to inhibit freezing.) cold. Ultimately, I decided that this reservoir should be as large as I could fit in the chamber I had to work with, which is about 13 US Gallons. For each chamber, I included a pump in the coolant attached to a tube which runs to the chamber. On the other end, inside the chamber, the tube attaches to a radiator, which is coupled with a fan. From there, a tube brings the water back to the reservoir. This allows me to pump cold water from the reservoir to the chamber and then pull the air in the chamber over the cold radiator to bring the chamber temperature down.

Radiator-fan assembly

Radiator-fan assembly


Click to enlarge

The electronics control when this occurs. Each chamber has thermometers that can sample the temperature of its air and also the temperature of the beer as it ferments. When the fermentation temperature becomes too high, the corresponding pump and fan turn on briefly, causing the temperature of the air to drop. This happens very frequently, and the result is that the fermentation temperature settles somewhere very close to its target. Meanwhile, another thermometer samples the temperature of the coolant in the reservoir, and the cooling system is turned on and off as necessary to keep the coolant cold enough to suit its purpose. I will elaborate on the electronic components later.

Architectural Concerns

The architecture of the chamber was fairly straightforward: I needed several chambers each large enough to handle my 10-15 gallon batches and an extra chamber to hold the coolant reservoir, the coolant system, and my electronic components. I did need to make some decisions to meet a few challenges, though.

Each chamber needed to be insulated from its neighbors adequately such that it wouldn’t influence the temperature of other chambers drastically. Initially,  I decided to use boards of insulation that could be easily cut to shape and layered between chambers. However, I double-guessed myself and decided I could use space more efficiently (my calculations involving R-values said so!), while saving time and money, by using an expanding foam product instead. As I will explain later, this was a bad decision and a waste of time and money.

I also had competing concerns with the doors. I wanted to make sure that my doors were air tight, but were also easy to open and close. As I opted to include 3 fermentation chambers and a fourth chamber for my other equipment, I had to keep things compact as best I could and did not have space for large hinges or latches, etc. I decided that the insulation on the door, since it was to be about 1.5 inches thick, would provide a fit tight enough that the doors would remain in place. This was almost adequate, but eventually I decided to use some bolts to keep the doors on very tightly, as I will explain later.


The electronics involved in this project were not very complex, but I didn’t have very much experience here so I had to climb a learning curve before I could make informed decisions and a working product. As mentioned above, the heart of the electronics is an Arduino microcontroller. It connects primarily to two different devices: temperature probes and relays.

The temperature probes were one of the more exciting parts of the project. Cheap, small, and inexpensive, they allowed me to exceed my goals related to temperature in a manner that brings to mind the word “overkill.” The Dallas One-Wire temperature probes, which are available at virtually any electronics vendor, provide temperature readings accurate to +/- 0.5°C with extreme precision. They derive their power from the bus over which they communicate, meaning that fewer wires are necessary, and they can be chained together. The Arduino has a very useful One-Wire library available, so implementation was actually pretty trivial. The One-Wire bus is an interesting study, and if you are so inclined, I would recommend a study of it.

The relays were also very easy to utilize (a relay essentially allows you to open and close one circuit by opening and closing a second circuit). Controlling them via the Arduino is ultimately one very simple line of code at this point, so turning on and off the pumps, the fans, and the refrigeration system is trivial.

Software Architecture

With the cooling capability and the electronics to control it, I now needed to design the software that would allow me to control the temperatures in a meaningful manner. I’m pleased with the way I approached this.

Since the Arduino is written in a C-like language with a very limited binary size (something like 14k, most of which was consumed the minute I imported the One-Wire and TCP libraries), it was clear that it’s job needed to be minimal. On the other hand, I have at least one machine in the house that I always keep running with more than adequate storage capacity. By contrast, it could manage virtually anything job I threw at it.

I decided, then, to define the Arduino’s responsibilities as anything that another more powerful machine could not do:

  • Sample a temperature from a probe
  • Turn a switch on or off

I will get more in to depth in regard to the software architecture and the decisions I made later on.


I’ve been asked more than once about the cost of this project, so I’ll try to recount the ballpark numbers. Altogether, the project cost me a little over $1000 (I assume the fridge to be “free”). The majority of that was in construction materials, tubing, etc. The electronics accounted for about $400 of that. I had some considerable waste, as I will explain later, so others could easily build something like this with a smaller budget. Also, it may be perfectly acceptable to use only one pump instead of three.

In a later article, I will attempt to list the items I purchased (a “bill of materials”).

See the Fermentation Controller index page for more information on my project.