Jul 182011
 
More Air for Dell 3700

I bought a nice Dell Vostro 3700 some time ago. While generally I am still happy, it clearly has a temperature problem: When you keep all cores busy and they run at their maximum frequency, it gets so hot, it shuts down due to overheating.

This is usually not a problem as most tasks are not using all cores all the time, but when you do a large compile, and for the sake of efficiency try to do a “make -j”, make starts as many compiles concurrently as possible. If those take long time to compile, all cores are busy for an extended period of time.

A not-so-great fix is to simply not keep more than 1 core busy for extended periods of time. Or lower the maximum clock frequency to 1.197 GHz down from 1.596 GHz, so even 4 busy cores will not overheat the CPU. You can find the list of usable frequencies via a simple

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies

and to set the max and min frequency:

for i in /sys/devices/system/cpu/cpu[0-9]* ; do
  echo $highest  >$i/cpufreq/scaling_max_freq
  echo $lowest  >$i/cpufreq/scaling_min_freq
done

but of course this is not more than a workaround and not a fix.

The root cause is (beside the CPU creating too much heat) is the insufficient cooling system. The airflow is…poor. It’s not a problem of dust collecting anywhere (visible): I opened the back of the notebook and it’s clean. If there is dust, it is hiding really well.  The air vents on the back of the notebook are small. The fan is too weak. In the end, the airflow should be higher.

So one of those notebook coolers might be what I can get, but the results seem to vary if you read the reviews on (e.g.) Amazon. It cools notebooks down some few (about 5) degrees is the most common reply.

Paying 1000-8000 Yen for that little cooling…I felt I can do better myself.

Typical design look like this. It is essentially a USB powered fan and some plastic/aluminium. Either the notebook is lifted considerable or if not, then the spinning fan has a hard time to get air flowing since it’s then too close to the table.

Another problem is the limited power the fan can use: 5V @ 500mA max. That is not a lot, even if the fan is quite efficient.

But when I saw this it looked much better as it can freely pull air and push under the notebook. Except for two flaws: too small fans (read: either poor air flow or noisy) and air is pushed below the notebook, creating a considerable air flow left and right below the notebook. Right side is where my mouse is. I don’t need air flow there. But the idea was good, so I started to build a prototype.

It starts with a PWM controlled fan I bought some time ago. 12cm large to generate a generous air flow. PWM controlled to keep it quiet when not needed. To control it, you need a (approx.) 25 kHz positive PWM signal (TTL compatible). My Arduino can do that. All I needed now is a duct to push air below the notebook.

For a prototype I used the white cardboard from empty milk boxes. Very durable, quite stiff, easy to cut and we have a lot of them. Other people already found out it’s very useful and I myself used itbefore for an air duct to remove a useless 3cm fan in a small power supply unit.

Took 1h in total to build. Works quite well.

The fan is controlled manually via an Arduino with a small modification to make the PWM run at 32kHz as 500Hz, the default, makes a sound in the fan. 16kHz makes a higher and weaker sound. 32hKz makes no audible sound. The needed code is found on the Arduino Playground. The rest is trivial. Took about 2h to program.

Update: Since I wrote this entry, I build a wooden housing using 2mm MDF  board. Looks much better. I can highly recommend MDF: easy to saw and glue.

Jul 172011
 
Rotary Encoder Decoded

Potentiometers are the easiest way to get an analog value into the Arduino. Nice for e.g. volume control or setting the speed of a fan or the brightness of a lamp.

A more digital way is to use rotary encoder instead which return pulses or even absolute positions. I found one here and it works as expected. Without using interrupts I was able to decode it just fine, but this really should be done via interrupts, but I never used interrupts before, so I checked via Google and found this. Works well and does not need a polling loop. The rotary encoder even looks identical to the one I bought.

For reference here the short test program:

/**
 * A simple incremental Rotary Encoder decoder example
 * andrew@rocketnumbernine.com
 * http://www.rocketnumbernine.com/2010/03/06/decoding-a-rotary-encoder/
 * use freely
*/

#include <util/delay.h>

volatile uint8_t pinValues[2] = {0,0};
volatile int position = 0;

const int APin=2;
const int BPin=3;

void setup()
{
  Serial.begin(38400);
  pinMode(APin, INPUT); // 2 Encoder pins as inputs
  pinMode(BPin, INPUT);
  digitalWrite(APin, HIGH); // use internal pull-ups
  digitalWrite(BPin, HIGH);

  // enable interrupts on those two pins:
  // Depends on APin=2 and BPin=3
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
}

ISR(PCINT2_vect)
{
  _delay_ms(1);
  int pin0 = digitalRead(APin);
  int pin1 = digitalRead(BPin);
  if (pin0 != pinValues[0]) {
    rotary_encoder_change(0, pin0);
  } else if (pin1 != pinValues[1]) {
    rotary_encoder_change(1, pin1);
  }
} 

void rotary_encoder_change(uint8_t changedPin, uint8_t value)
{
  pinValues[changedPin] = value;
  position += ((pinValues[0] == pinValues[1]) ^ changedPin) ? 1 : -1;
}

void loop()
{
  Serial.println(position);
  delay(200);
}

Small addition: Arduino Playground has some more info.

Jul 162011
 
Arduino and Temperature

I got some sensors from my favorite local electronics shop and one of them was a temperature sensor. Analog output, so I can use it for an XBee too.

I connected it to my FunnelIO board I bought some time ago, and about 10min later I had the room temperature printed on my screen. I really like Arduino boards:  while the CPU is very limited (1 KByte RAM, 14 kByte FLASH for user program), it gets simple things like this quickly done.

Here the loop of the test program:

  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.print("A0=");
  Serial.print(sensorValue);
  Serial.print(" = ");
  //temperature=((sensorValue*3300.0/1024.0)-600.0)/10.0;
  //Serial.print(temperature);
  temperature=(sensorValue*322)-60000;
  Serial.print(temperature/1000);
  Serial.println(" Celsius");

The LM61 outputs 600mV at 0°C and 10mV for each degree more (or less) from -25°C up to +85°C.