Category Archives: General

Posts that do not fall into any specific category may be listed here.

Arduino-based fan tachometer using IR, with video, code and schematics

In 2009 I uploaded a video to YouTube showing an Arduino measuring the rotational speed of a basic computer fan. It was one of a number of YouTube videos I did as I was studying for a Masters in Computer Science. This particular module was an embedded systems programming course, with a bit of electronics thrown in. Here’s the video:

I was recently asked if the schematics were available for this video. Unfortunately I was unable to locate the schematics as shown in the video, however I do have the source code. This is a simple Arduino Sketch that uses an open source ‘Timer’ library. You can download the fan-rpm-sketch source code. When reading this source code please keeping in mind that there are three processes going on:

a) setup/loop Sketch methods – responsible for attaching interrupts, configuring the Timer, and writing the RPM count out to the serial port

b) IR ISR – this interrupt routine is configured to be triggered by the falling edge of the IR input – i.e. whenever the leading (or falling, I forget which)  fan blade <em>edge</em> passes the sensor

c) A Timer routine that is attached to a high speed timer and called every second to calculate the RPM value extrapolated from the number of fins seen that second.

I also have schematics and documentation for the newer application – a Temperature Controlled Fan:

The difference between the two is the addition of two modules to the layout – the thermistor temperature sensor, and the opto-isolated pulse-width-modulated speed controller. On the software side, we now use FreeRTOS on Arduino.

To edit the schematic, you may download the free Schematic Capture package, Bsch3V.

As a guideline to the above, this block diagram shows the main parts of the design:

Block diagram for the fan controller circuit

Parts List

a)    Thermistor – taken from a Lithium ion battery pack, not even sure the specs on it !
b)    IR LED and IR phototransistor – Radioshack 276-0142
c)    Fan – standard 80mm 12V two-lead (no tach) computer fan
d)    7.5V power – 1A AC-DC adapter used for Arduino and Fan power instead of a battery pack
e)    CNY 75B opto-coupler

Except for a few edits, the text that follows was mostly written in 2009.

Hardware Discussion

The use of an opto-coupler is separates the low voltage Arduino digital IO from the slightly higher voltage used to power the Arduino board and the Fan. Potentially any voltage is supported up to the limits of the CNY 75B part.

Thermistor
Use of this component required a low current limiting resistor to generate an acceptable voltage drop over the thermistor, so a 4.7k was chosen.

IR LED and Transistor
The IR transistor from radio shack required a large bias resistance to place it in ‘switching’ mode rather than amplification mode. A 100K ohm resistor was chosen. An approximate 100 ohm current limiting resistance for the IR LED was provided through two 47ohm resistors in serial.

Fan and Power choice
Using the 12V fan in conjunction with a 7.5V power source is not optimal but it works. The current required to feed the base of the NPN transistor is obviously changed by the lowered voltage, so the resistances used needed to be different. A 4.7k ohm resistor was placed in parallel with a 10k ohm resistor which appears to provide a faster response from the fan ( I assume due to lowered switch time of the NPN transistor ).

Software

System Software Block Diagram
Free RTOS software block diagram for a fan controller Design Discussion

The system software is built upon FreeRTOS but is wrapped in a C++ layer. All tasks inherit from a task class that provides wrappers around functions applicable to tasks,  including creation, stack and priority configuration, and the ability to invoke a derived (virtual) method that is the actual task code provided by the implementor of the derived class.

In addition to tasks, there is one other class to wrap the configuration of timer 2 as a PWM output. The combination of timer 2 and output compare B means that we are driving pin 3 as the PWM output.

The C++ layer follows the arduino sketch model in three regards:
a)    The use of a setup and loop function for task code
b)    The provision of implicitly available functions – basically anything wrapped by the task base class
c)    The code is built entirely within the sketch tool

However, it needed to implement a global override of the new operator to call pvPortMalloc – the FreeRTOS implementation. In addition I had to place dummy overrides for pure virtual and guard C++ runtime implementation functions.

The original setup method is used to both initialize all tasks in the system – configure the hardware to some base state, and then invoke the FreeRTOS Scheduler. If something goes wrong, it falls through to the original arduino sketch loop method, which is implemented to provide a distinct LED pattern so that this error condition can be seen.

After implementing the C++ layer, however, it became readily apparent that something was wrong, as the stability of the software was variable depending on the order in which tasks were created, whether they were created in FreeRTOS.  What is provided is a working version, but only after much trial and error. Changes to stack sizes, queue sizes, serial debug messages, adding of tasks, or changing the order of tasks and hardware initialization is not recommended! I suspect but cannot be sure that the combination of heap, stack, and static allocations conflict in some non-trivial way. (edit: based on later experiences, I have to see it is actually quite trivial. If you run out of stack of heap memory, you’ll have trouble. If the stack expands onto the heap, you’ll have trouble. Also, you don’t have much to start with, and working in C++ you can easily be fooled that you don’t have to worry about this. You do.)

Were I to implement this project again, I would either go with Eclipse or WinAVR as the build tool and eliminate the use of Arduino functions like the serial engine, or I would strip the C++ layer out to minimize overhead on the Arduino.

RPM Counter

Internally the software is using an interrupt triggered by the IR phototransistor on digital pin 2 to monitor the fan RPM count. A task converts the count to an RPM measure and writes it to the serial every second. A semaphore is used to  synchronize the interrupt ISR with the RPM task.

Originally I tried to go with a counting semaphore, but the FreeRTOS download I am using complained that it does not exist. I did not want to resort to a mutex semaphore on an integer so instead I went with a recursive semaphore. The recursive semaphore allowed itself to be taken as many times as the interrupt is fired, so the task keeps taking the semaphore until it blocks. It waits a maximum of 1 second updated each time the semaphore is taken, so the task is able to block and yet still sum up the counts at the end of each second.

Analog / Thermal / Sense task

This variously named task reads the analog reading on analog port 0 which is hooked up to the thermistor. This value is scaled, inverted, and biased back from a 0-1023 range, of which 900+ is ice and 673 is room temperature back to a zero to 255 value that can be used to set the PWM duty period.

timer2pwm object

This singleton object is used to manage the timer2 output compare B configuration which drives the PWM period on digital pin 3, which drives the fan. Use of timer 2 does not conflict with analog readings or with the FreeRTOS timer tick interrupt.

Serial  task/class

The serial task exposes functions that are intended to be called from other tasks. They place values onto internally managed FreeRTOS queues which are processed once a second by the serial task code. This centralizes access to the serial bus.

Download the source code: arduino-fan-temperature-controller-freertos

Update; added source code for a Sketch version using TimerOne:
RpmSensorUsingTimerOne

Reimagining xeyes for HTML5

Many of you will know of xeyes, a cute little app that has been around for decades. The eyes follow you as you move your mouse around the screen.

. I don’t know why I thought about it ( I have been setting up unix servers lately ), but I was inspired to do some HTML5 work with the recent release of Firefox 4 and their Web O’ Wonder.

So what’s my favorite HTML5 feature? SVG? Oh sure, everyone loves SVG – can’t over-estimate the effect the resurgence of SVG in HTML5 is going to have. See my TopCoder Map for an example of SVG awesomeness.

But no that’s not my favorite, because it’s not neat enough, the spec is huge, and there are interactions that mean it won’t safe to use in a browser for many years to come. That’s not the reason for this post, so I won’t go into detail.

Canvas is great, we can draw. But we could do that before, albeit server side. Also, I think I dislike the 2d context API.

Truly, I don’t have a favorite feature – the ones I like the best are the smaller APIs that slot neatly into the spec and are well defined. Which brings me to the point of this post:

The Device Orientation API (link to spec)

This magical API works only on mobile devices, I’m using an iPod Touch. It’s incredibly easy to use. Call this from onLoad, or just inline it:

function rotate(oe) {
// your code here
}

function init()
{
window.addEventListener("deviceorientation", rotate,false);
}

To understand the oe event parameter, read the spec. It is tiny, so don’t be afraid! There are 3 orientation attributes, alpha, beta and gamma. Each is a rotation around an axis referenced to a frame where the device is lying flat. Alpha goes between 0 and 360, beta goes between -180 and 180 (degrees), and gamma goes between -90 and 90 degrees.
Zero’s across the board imply the device matches the reference frame, which means it is lying flat on a table in front of you.

There is no guaranteed rate at which the rotate event is called, so you’ll see I use a separate render function called at regular intervals.

Using this API, I decided to implement a mobile version of xeyes – only the eyes follow you, reacting to the angle of the screen so that they are always looking at you!

If you’ve read this far, feel free to see the live version here: Eyes for HTML5.

Here are the steps I took:

1) Draw a face on a Canvas on page load
2) On each render:
a) Clear the eye sockets
b) Add pupils at a set distance based on beta and gamma angles.

Drawing a face


function preload() {
var context = viewer.getContext("2d");
drawFace(context);
context.restore();
}
function drawFace(context) {

context.clearRect(0,0,300,300);

context.save();

context.beginPath();
context.strokeStyle='black';
context.arc(75,75,25,0,Math.PI*2);
context.stroke();
context.closePath();

context.beginPath();
context.arc(175,75,25,0,Math.PI*2);
context.stroke();
context.closePath();

context.beginPath();
context.moveTo(125,100);
context.lineTo(125,150);
context.stroke();
context.closePath();

context.beginPath();
context.arc(125,150,75,Math.PI/4,Math.PI/2 + Math.PI/4);
context.stroke();
context.closePath();
}

Clearing and Rendering the eyes

The trick to this part is simpy that I use the eye drawing code from above to set a clipping region, which I then clear, and then draw the eyes in. This clipping means my eyes stay in their sockets!

function newEyes(context, gamma, beta)
{
context.save();
context.beginPath();
context.arc(175,75,23,0,Math.PI*2);
context.clip();
context.fillStyle = 'white';
context.fill();
context.closePath();

context.beginPath();
context.arc(175-gamma/5,75-beta/5,15,0,Math.PI*2);
context.fillStyle = 'black';
context.fill();
context.closePath();
context.restore();

context.save();
context.beginPath();
context.arc(75,75,23,0,Math.PI*2);
context.clip();
context.fillStyle = 'white';
context.fill();
context.closePath();

context.beginPath();
context.arc(75-gamma/5,75-beta/5,15,0,Math.PI*2);
context.fillStyle = 'black';
context.fill();
context.closePath();
context.restore();

}

The orientation and render handers

Since we don’t know when or if we will get an orientation event, we keep it separate to our render routine. This is just good practice in general. The render routine runs often to keep the animation smooth. The orientation handler can do processing only when needed. Of course, it’s not doing anything other than storing a variable here.


var lastOrientation = null;
var nextOrientation = null;

function renderer() {
if(nextOrientation == null) return;

if(lastOrientation != null &&(nextOrientation.gamma == lastOrientation.gamma)) return;

var context = viewer.getContext("2d");
newEyes(context,nextOrientation.gamma,nextOrientation.beta);
context.restore();
}

// event handler
function rotate(oe) {
lastOrientation = nextOrientation;
nextOrientation = oe;
}

setInterval(renderer,100);

That’s it, feel free to download and use the code. You’ll find it here: eyes.

Comments and ideas for uses of the orientation and motion APIs are welcome. I have some, but perhaps for another post.

Happy coding!

Peter

Old computer upgrade tales

1) Back in the days of the 80486 (1995) where I lived in Coventry, England; there was an a con going on where computers were being sold as containing 2nd level cache memory, but in fact to save money, the cache memory was dummy. This was possible because the cache memory just sat on top of the memory bus and responded more quickly than main memory. The upgrade path was obvious to me: unsolder the bad cache memory directly from the board, and replace it with good cache memory DIP chips and sockets that I would buy for the purpose. Sure enough, the first unsoldered chip I smashed apart was a block of solid plastic – no silicon!
Well, unfortunately my soldering skills were not up to the task, and after all was said and done, it wouldn’t boot any more. Happy ending: I gave it to my dad who managed to fix it back up by replacing a bad power transistor that happened to be close to where I had been soldering.

2) A little later on I had an Athlon on MSI m/b machine I had decided to flash the BIOS to a newer version. Something went wrong and I was left with a bricked machine. Now, I actually had two machines at that time, and I’ve always been a fan of MSI motherboards so I happened to have two almost identical boxes. Inspiration struck and I booted up the working machine to DOS. Then, *while it was running*, I opened the case up and popped the BIOS chip out, replacing it with the bad one. This worked because the BIOS had been shadowed to main memory and didn’t care that it had just been gutted! I flashed the bad chip from DOS, popped it back out and returned it to the bad machine,…and crossed my fingers…
:) Worked like a charm.

Optimizing Richfaces AJAX a4j update1

This is one of those things you have to laugh or cry about.

The primary reason that I have found that our consolidated AJAX page is slow, and that no amount of HTTP traffic optimization is going to fix, is that two of our composited components had implemented getters by way of a database query.

This is absolute bad practice – JSF does not guarantee that your getters will be called just once, so even in a Web 1.0 application you may be making redundant database queries.

In an AJAX application this problem is exacerbated – doubtless none of those queries are necessary on the AJAX request.

In our application each of those queries ate up about 100ms, multiplied about 3 times each because they were embedded in getters. Obviously this soon becomes a noticeable delay ruins the feel of the application.

Simply caching the query in the bean removes this problem, but in a Seam component you have several more options to refine this approach.

Since our beans were EVENT scoped, we specifically outjected PAGE scoped variables to host the cache.