Code snippets December 28
Following are code snippets and commentary from my programming efforts. Most of the heavy lifting is the very handy orangutan-lib for the atmel atmega168, which you can download here. And much thanks to Tom Benedict, another KAPper, for all his help with this stuff.
Altitude Calculation
alt_data = analog10(3); // 1024
pressure = ((alt_data + 97.28) / 9.216) * 10; // millibars
altitude = 145366.45 * (1 - pow((pressure / 1013.25), 0.190284));
alt_data is the raw 0-1024 bits read off the internal ADC. The pressure calculation is straight out of the pressure sensor’s data sheet, with the units converted to scale per our bit range. The altitude equation took me a bit to track down in this form. It’s based on the ISA atmosphere model, and uses 1013.25 millibar as sea level. If you are operating near sea level, it’s possible for the pressure to vary anywhere from 870 millibar to 1800 millibar (under extreme circumstances). Normal readings, however, can result in a negative number, so realize that the altitude calculation can result in numbers below sea level.
Switch debouncing
I was getting some really terrible inconsistent results from my switches. The culprit? Switch bouncing. In short, when a switch opens or closes, it switches between two states for a little bit before settling into a stable solution. Jack Ganssle wrote a wonderful article based on his empirical studies of 18 different switches over 300 actuations gave some really good parameters to play with. He suggests a polling periodic solution without really sampling. My 1ms timer runs this code:
sh1 = _PINC.B1;
if(sh1==0)
{
if(sh1bounce<20)
{
sh1bounce++;
}
}
else
{
if(sh1bounce>0)
{
sh1bounce–;
}
}
It’s that easy. It reads the state of the pin, if it’s 0 then it increments the counter by 1, if it’s 1 then it decrements the counter by 1. It stops at 20 and 0. Elsewhere, there’s a function that looks at these variables and watches for them to hit an end state (0/20).
What’s really going on here is that if the switch is off, the value just sits at 0. When you actuate the switch, there’s a period where the value is random. As long as it doesn’t sit at any other value for more than 20ms, it should be a clean change. The one catch is that if the bounce values go 0, 1, 0, 1, 2, 3… it could trigger two “offs” in a row, however it doesn’t consider the switch changed until it goes all the way to 20 first.
The other side of this for the shutter– you should know that the shutter switch is a 3-way toggle switch, so that I can have two different shutter modes depending on if I push the switch up or down, is as follows:
if(shuttermode == 0) // If the switch is not already pressed
{
if(sh1bounce == 20) // Switch 1 is pressed
{
shuttermode=1;
uartSendByte('S');
}
else if(sh2bounce == 20) // Switch 2 is pressed
{
shuttermode=1;
uartSendByte('S');
}
else if(sh1bounce == 0 && sh2bounce == 0)
// Sort of a failsafe
{
shuttermode=0;
}
}
else if(shuttermode == 1 && sh1bounce == 0 && sh2bounce == 0)
{
shuttermode = 0;
} // If both switches are off and shuttermode == 1, set back to 0.