An attempt at adding a tow-mode input.
#define NUM_FWD_GEARS 4 //# number of forward speeds
#define BUTTON_READ_INTERVAL 50ul //mS time between up/down button reads
#define NO_PRESS 0x00 //mask bit mask for no buttons pressed
#define BUTTON_UP_PRESSED 0x01 //mask bit mask for up button pressed
#define BUTTON_DOWN_PRESSED 0x02 //mask bit mask for down button pressed
#define TCC_DELAY 1000ul //mS after TCC is enabled, time delay before activation
const byte buttonUP = 2; //pin Push Button for UP shift
const byte buttonDOWN = 4; //pin Push Button for Down shift
const byte switchTOWMODE = 7; //pin Switch for tow/haul mode
const byte solA = 3; //pin Solenoid A output
const byte solB = 5; //pin Solenoid B output
const byte TCC = 6; //pin TCC output
byte
gearSelection,
lastGearSelection,
lastUp,
lastDn,
lastTM;
bool
bTCCStatus;
unsigned long
timeTCCSolenoid;
typedef struct structGearSolenoidProfiles
{
byte solenoid_A;
byte solenoid_B;
bool bTCCGearEnable;
}sGearSolenoidProfiles;
//
// How does Arduino know reverse, park or drive?
//
const sGearSolenoidProfiles GearSolenoidProfiles[NUM_FWD_GEARS] =
{
{
//1st
.solenoid_A = HIGH,
.solenoid_B = LOW,
.bTCCGearEnable = false
},
{
//2nd
.solenoid_A = LOW,
.solenoid_B = LOW,
.bTCCGearEnable = false
},
{
//3rd
.solenoid_A = LOW,
.solenoid_B = HIGH,
.bTCCGearEnable = true
},
{
//4th
.solenoid_A = HIGH,
.solenoid_B = HIGH,
.bTCCGearEnable = true
}
};//GearSolenoidProfiles[]
void setup()
{
pinMode( buttonUP, INPUT_PULLUP );
lastUp = digitalRead( buttonUP ); //set initial button state
pinMode( buttonDOWN, INPUT_PULLUP );
lastDn = digitalRead( buttonDOWN ); //set initial button state
pinMode( switchTOWMODE, INPUT_PULLUP );
pinMode( solA, OUTPUT ); //Solenoid A set as output
pinMode( solB, OUTPUT ); //Solenoid B set as output
pinMode( TCC, OUTPUT ); //TCC set as output
digitalWrite( solA, LOW ); //set intital state as off
digitalWrite( solB, LOW );
digitalWrite( TCC, LOW );
//internal flag for TCC status
bTCCStatus = false;
gearSelection = 0; //start in "1st" gear for this test
lastGearSelection = 0xff; //ensure we change into correct gear first pass by making last != current
}//setup
void loop()
{
Gear_Selection_Control();
Gear_Solenoid_Control();
TCC_Control();
}//loop
void Gear_Selection_Control( void )
{
byte
btnState;
btnState = ReadButtons();
switch( btnState )
{
case NO_PRESS:
//nothing pressed or not read (interval not elapsed); no action
break;
case BUTTON_UP_PRESSED:
if( gearSelection < (NUM_FWD_GEARS-1) )
gearSelection++;
break;
case BUTTON_DOWN_PRESSED:
if( gearSelection > 0 )
gearSelection--;
break;
default:
//only remaining possibility is both pressed; ignore with no action
break;
}//switch
}//void
void Gear_Solenoid_Control( void )
{
if( gearSelection != lastGearSelection )
{
lastGearSelection = gearSelection;
digitalWrite( solA, GearSolenoidProfiles[gearSelection].solenoid_A );
digitalWrite( solB, GearSolenoidProfiles[gearSelection].solenoid_B );
//if
// - the gear just selected enables the TCC, and
// - the last gear did not enable it, and
// - the TCC is not now enaged
// start the TCC delay timer
if( bTCCStatus == false )
{
if( GearSolenoidProfiles[gearSelection].bTCCGearEnable == true &&
GearSolenoidProfiles[lastGearSelection].bTCCGearEnable == false )
{
timeTCCSolenoid = millis();
}//if
}//if
}//if
}//Gear_Control
void TCC_Control( void )
{
unsigned long
tNow;
bool
bTCCEnabled;
tNow = millis();
//TCC enabled if:
// - 4th gear is engaged, OR
// - 3rd gear is engaged and tow-mode not selected, AND
// - TCC delay timer has expired
bTCCEnabled = ( (gearSelection == 3) ||
( (gearSelection == 2 && digitalRead( switchTOWMODE ) == HIGH) ) ) &&
( tNow - timeTCCSolenoid >= TCC_DELAY );
//if conditions passed and TCC is now off, turn on its solenoid
if( bTCCEnabled )
{
if( bTCCStatus == false )
{
//turn on TCC
digitalWrite( TCC, HIGH );
bTCCStatus = true;
}//if
}//if
else
{
if( bTCCStatus == true )
{
//turn off TCC
digitalWrite( TCC, LOW );
bTCCStatus = false;
}//if
}//else
}//TCC_Control
//returns a mask:
//0b00000000 - no buttons pressed
//0b00000001 - up pressed
//0b00000010 - down pressed
//0b00000011 - both pressed
//
byte ReadButtons( void )
{
static unsigned long
timeButton = 0;
unsigned long
tNow;
byte
retval,
nowButton;
retval = NO_PRESS;
tNow = millis();
if( (tNow - timeButton) >= BUTTON_READ_INTERVAL )
{
//set up for next read interval
timeButton = tNow;
//read the button and set the flags
nowButton = digitalRead( buttonUP );
if( nowButton != lastUp )
{
lastUp = nowButton;
if( nowButton == LOW )
retval |= BUTTON_UP_PRESSED;
}//if
nowButton = digitalRead( buttonDOWN );
if( nowButton != lastDn )
{
lastDn = nowButton;
if( nowButton == LOW )
retval |= BUTTON_DOWN_PRESSED;
}//if
}//if
return retval;
}//ReadButtons