code:
#define MAX_INTERVAL 500 // max time a LED can be off while blinking, in ms
#define STABILITY_THRESHOLD 50 // time the input state must be stable before movement starts, in ms
#define DO_NOTHING 0x00
#define MOVE_UP 0x01
#define MOVE_DOWN 0x02
#define MOVE_FAST 0x04
#define MOVE_UPFAST (MOVE_UP | MOVE_FAST)
#define MOVE_DOWNFAST (MOVE_DOWN | MOVE_FAST)
// what to do for each combination of inputs; any combination of 2 or more active inputs means
// do nothing, only the combinations with exactly one active input, except the middle (neatral) input
// result in movement. These are positions 0x01 (1) for up fast, 0x02 (2) for up slow, 0x04 (4) for neutral,
// 0x08 (8) for down slow, 0x10 (16) for down fast. Note the array index starts at 0
const unsigned char Actions[ 32 ] =
{ DO_NOTHING, MOVE_UPFAST, MOVE_UP, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 0..7
MOVE_DOWN, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 8..15
MOVE_DOWNFAST, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, // 16..23
DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING, DO_NOTHING }; // 24..31
unsigned short InputCounters[ 5 ] = { 0, 0, 0, 0, 0 };
unsigned char ReadInputs, FilteredInputs, PreviousInputs = 0;
unsigned long StabilityCount = 0;
void setup()
{
pinMode( 0, INPUT ); // input top LED
pinMode( 1, INPUT );
pinMode( 2, INPUT );
pinMode( 3, INPUT );
pinMode( 4, INPUT ); // input bottom LED
pinMode( 5, OUTPUT ); // move UP output
pinMode( 6, OUTPUT ); // move DOWN output
pinMode( 7, OUTPUT ); // move FAST output
}
void loop()
{
unsigned char Index;
FilteredInputs = 0;
ReadInputs = digitalRead( 0 ) | ( digitalRead( 1 ) << 1 ) | ( digitalRead( 2 ) << 2 ) | ( digitalRead( 3 ) << 3 ) | ( digitalRead( 4 ) << 4 );
// this loop monitors each input for recent activity; when an input is active, the timer for that inputs
// is set to MAX_INTERVAL, and starts counting down from there; when it reaches 0, the input is considered
// inactive. MAX_INTERVAL should be set slightly longer than the maximum time the LED for an input can be off
// when blinking
for( Index = 0; Index < 5; Index++ )
{
if( ReadInputs & ( 1 << Index ) )
InputCounters[ Index ] = MAX_INTERVAL;
if( InputCounters[ Index ] )
{
InputCounters[ Index ]--;
FilteredInputs |= 1 << Index;
}
}
// now check if the input state has been stable for a number of successive cycles, to prevent movement
// when 2 LEDs are blinking, since one can always be detected slightly earlier or later than the other
// If current and previous input states are different, reset stability counter
if( PreviousInputs != FilteredInputs )
StabilityCount = 0;
// now store the current input state for the next cycle
PreviousInputs = FilteredInputs;
// if stability counter has not yet reached the threshold, increment it, and force the input state to 0
// to prevent any movement
if( StabilityCount < STABILITY_THRESHOLD )
{
StabilityCount++;
FilteredInputs = 0;
}
// lookup what to do for this state and write to outputs
digitalWrite( 5, Actions[ FilteredInputs ] & MOVE_UP );
digitalWrite( 6, Actions[ FilteredInputs ] & MOVE_DOWN );
digitalWrite( 7, Actions[ FilteredInputs ] & MOVE_FAST );
delay(1); // actual loop interval will be slightly longer, because it also takes some time to execute
}
Niet getest, bij gebrek aan hardware. Misschien dat ik het later nog in een simulatie omgeving ga testen.