//////////////////////////////////////////////
// Fan Speed Controller
//
// Author(s): David Hobday
// Date: 11 December 2006
//
// Target Device: EZ-Controller Turbo (PIC18F2520 with booloader)
//
// Revision History:
// V1.0 11/12/2006 - Initial Release
//
//////////////////////////////////////////////
//
// This code controls the speed of a fan using pulse width modulation,
// ie the fan speed is controlled by varying the duty cycle of voltage
// waveform applied to the fan - all done without using any PWM hardware.
//
// The desired speed is set by typing a 1 to 3 digit number (0 to 255) on the
// keypad and then pressing the '#' key. Pressing the '*' key switches
// between the last two set speeds.
//
// This code uses Novo RTOS as it makes things so much simpler.
// The PWM is implemented in software using Novo RTOS Sys_Sleep functions.
//
// The Keypad matrix is connected to PORTC (see keypad.c for details).
// The pwm output is genrated from pin RB1.
//
// The Novo SysTimerUpdate() function is called in the main yield task, so any
// time values used with waiting functions, such as Sys_Sleep(), represent the
// number of times the run queue is transversed rather than an absolute time.
// We use this technique to get a faster update of the software PWM signal.
// The sleep queue is transversed every 10us on a PIC18 with 40MHz clock.
// That gives a PWM signal period of 255 x 10us = 2.55ms
//
#include <system.h>
#include <novocfg_pic18t3e5ts1.h>
#include <novo.h>
// use this configuration when not targeting EZ-COntroller turbo with bootloader,
// also remember to remove linker option -rb 0x800
// #include "PicConfig.h"
#pragma CLOCK_FREQ 40000000
#include "keypad.h"
#define hTask0 0
#define hTask1 1
unsigned char speed = 50; // set initial speed
// Delays are measured in run execution counts as we update SysTimerUpdate in the main yeild loop
// In this application an update occurs around every 10us
#define DEBOUNCE_DELAY_2500us() Sys_Sleep( 250 )
unsigned char WaitForKey()
{
unsigned char key = 0;
unsigned char i;
// wait for no key press and keypad stable for a number of loops
for( i = 0; i < 10; i++ )
{
if( ScanKeyMatrix() != 0xFF )
i = 0;
DEBOUNCE_DELAY_2500us();
}
// wait for key pressed and stable for a number of loops
while( 1 )
{
for( i = 0; i < 10; i++ )
{
unsigned char k = ScanKeyMatrix();
if( key != k ) // key has changed the same
{
key = k;
i = 0;
}
DEBOUNCE_DELAY_2500us(); // debounce delay
}
if( key != 0xFF ) // a key has been pressed
return key;
}
}
void Task0()
{
ScanKeyMatrixInit();
char key;
unsigned char newSpeed = 0, oldSpeed = 0;
while( 1 )
{
key = WaitForKey();
if( key >= '0' && key <= '9' )
{
newSpeed *= 10;
newSpeed += key - '0';
}
if( key == '#' )
{
oldSpeed = speed;
speed = newSpeed;
newSpeed = 0;
}
if( key == '*' )
{
newSpeed = speed;
speed = oldSpeed;
oldSpeed = newSpeed;
newSpeed = 0;
}
}
}
void Task1()
{
while( 1 )
{
portb.1 = 0;
Sys_Sleep( 255 - speed );
portb.1 = 1;
Sys_Sleep( speed );
}
}
void main()
{
SysInit();
SysCreateTask( hTask0, 2, Task0 );
SysCreateTask( hTask1, 2, Task1 );
SysStartTask( hTask0 );
SysStartTask( hTask1 );
trisb = 0x01;
while( 1 )
{
SysTimerUpdate();
Sys_Yield();
}
}
Copyright © 2006 SourceBoost Technologies