📄 control.c
字号:
else printf ("0");
if (input(RETRACTED)) printf ("1");
else printf ("0");
if (input(CYCLE_SW)) printf ("1");
else printf ("0");
if (InitialRetractsEnabled()) printf ("1");
else printf ("0");
if (MultiCyclesEnabled()) printf ("1");
else printf ("0");
if (SelfTestRequested()) printf ("1");
else printf ("0");
printf ("\r");
/* Check for Self Test signal. */
if (SelfTestRequested ()) {
printf ("Self Test.\r");
SelfTest (); /* This function never returns..... */
}
/* Check the multicycles strapping option (done via A/D channel #1) */
if (MultiCyclesEnabled()) byMaxCycles = MAX_PENDING_CYCLES;
else byMaxCycles = 1;
printf ("Max Cycles: %u\r", byMaxCycles);
/* Enable Timer Interrupt */
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_4);
/* Enable Interrupts */
enable_interrupts (INT_TIMER1);
enable_interrupts (GLOBAL);
/* Blink some lights.. */
LampTest ();
/*** Get an initial battery voltage sample */
GetBatteryVoltage();
printf ("Initial A/D: %4lX\r", nBatteryVoltage);
nBatteryVoltage_last1 = nBatteryVoltage;
nBatteryVoltage_last2 = nBatteryVoltage;
nBatteryVoltage_last3 = nBatteryVoltage;
/************* Main Loop **************/
/* Set a timer for when our initial charger rule applies. Once this
time expires, the rule can't fire */
byTicks_Initial_Charge = TICKS_INITIAL_CHARGE;
for (;;) {
/******************************************************/
/* */
/* SAMPLE Battery Voltage with A/D */
/* */
/******************************************************/
/*** Get a raw battery voltage sample out of the A/D chip. */
GetBatteryVoltage();
/* Average last 4 samples */
nAvgBatteryVoltage = nBatteryVoltage +
nBatteryVoltage_last1 +
nBatteryVoltage_last2 +
nBatteryVoltage_last3;
/* Must divide by the 4 samples, which is just a right shift of 2 */
nAvgBatteryVoltage = nAvgBatteryVoltage >> 2;
/* Shift samples down the sample chain */
nBatteryVoltage_last3 = nBatteryVoltage_last2;
nBatteryVoltage_last2 = nBatteryVoltage_last1;
nBatteryVoltage_last1 = nBatteryVoltage;
/* TEST: Print out A/D values on the RS232 port. */
if (byTicks_Display == 0) {
printf ("A/D: %4lXh (avg), %4lXh (inst)\r", nAvgBatteryVoltage, nBatteryVoltage);
byTicks_Display = 4; /* Only update output once a second */
}
/******************************************************/
/* */
/* UPDATE The CHARGING SYSTEM */
/* */
/******************************************************/
if (bCharging && (nAvgBatteryVoltage > CHARGE_MAX) && (byTicks_Charger_Hysterysis == 0)) {
/* Shut down charger */
bCharging = FALSE;
/* Set hysterysis ticker so we don't consider a change for 1 second */
byTicks_Charger_Hysterysis = TICKS_CHARGER_HYST;
}
else if (!bCharging && (nAvgBatteryVoltage < CHARGE_MIN) && (byTicks_Charger_Hysterysis == 0)) {
/* Start charger up */
bCharging = TRUE;
/* Set hysterysis ticker so we don't consider a change for 1 second */
byTicks_Charger_Hysterysis = TICKS_CHARGER_HYST;
}
/* New Rule: Charge if below CHARGE_MAX and Motor is on */
else if (bMotorOn && (nAvgBatteryVoltage < CHARGE_MAX) && (byTicks_Charger_Hysterysis == 0)) {
/* Start charger up */
bCharging = TRUE;
/* Set hysterysis ticker so we don't consider a change for 1 second */
byTicks_Charger_Hysterysis = TICKS_CHARGER_HYST;
}
/* Try the initial charging rule */
if (byTicks_Initial_Charge != 0) {
if (!bEverCharged && (nAvgBatteryVoltage < CHARGE_MAX)) {
bCharging = TRUE;
}
}
/******************************************************/
/* */
/* CYCLE SWITCH State Machine */
/* */
/******************************************************/
switch (byCycleSwitchState) {
case STATE_CYCLE_SWITCH_IDLE:
if (input(CYCLE_SW) == 0 && !bTimeoutOccured) {
/* Switch was pressed! */
/* Set switch ticks for debounce */
byTicks_CycleSwitch = TICKS_CYCLESWITCH;
bySample_CycleSwitch = 0;
byCycleSwitchState = STATE_CYCLE_SWITCH_SAMPLE;
}
break;
case STATE_CYCLE_SWITCH_SAMPLE:
// The counter, nSample_CycleSwitch, counts how many times
// in a row we sample the switch pressed. We demand a certain
// number of agreeing samples before we declare the switch
// truly pressed. This will help reduse false cycles from noise.
//
//
if (byTicks_CycleSwitch == 0) {
// timeout.. must have been noise..
byCycleSwitchState = STATE_CYCLE_SWITCH_IDLE;
}
else if (bySample_CycleSwitch == CYCLE_SWITCH_REQUIRED_SAMPLES) {
// OK. We got this far, so take the action
if (byPendingCycles < byMaxCycles) {
byPendingCycles++;
}
byCycleSwitchState = STATE_CYCLE_SWITCH_WAIT_RELEASE;
}
else if (input(CYCLE_SW) != 0) {
// Whoa!! not low. Still unstable. Reset counter.
bySample_CycleSwitch = 0;
}
else if (input(CYCLE_SW) == 0) {
// Here is a valid low sample. Increment counter.
bySample_CycleSwitch++;
}
break;
case STATE_CYCLE_SWITCH_WAIT_RELEASE:
if (byTicks_CycleSwitch == 0) {
if (input(CYCLE_SW) == 1) {
byCycleSwitchState = STATE_CYCLE_SWITCH_IDLE;
}
byTicks_CycleSwitch = TICKS_CYCLESWITCH;
}
break;
default:
byCycleSwitchState = STATE_CYCLE_SWITCH_IDLE;
break;
}
/******************************************************/
/* */
/* Motor/RAM Cycle State Machine */
/* */
/******************************************************/
switch (byCycleState) {
case STATE_CYCLE_INITIAL:
// See if the option is enabled. If not, simply skip to IDLE state
if (!InitialRetractsEnabled()) {
byCycleState = STATE_CYCLE_IDLE;
break;
}
/**** Initially, we demand that ram be completely retracted. ****/
if (SenseRetracted()) {
// Already retracted.. Cool..
byCycleState = STATE_CYCLE_IDLE;
break;
}
/* Not retracted! */
printf ("Initially unretracted...\r");
Reverse();
printf ("RV..\r");
byCycleState = STATE_CYCLE_INITIAL_WAITJUICE;
break;
case STATE_CYCLE_INITIAL_WAITJUICE:
if (bEnoughMotorJuice) {
// We have enough juice to start. We need to take a short cut
// into the normal sequencing.
printf ("Motor..\r");
bMotorPaused = FALSE;
StartMotor();
nTicks_Reverse = TICKS_REVERSE;
byCycleState = STATE_CYCLE_REVERSE2;
}
break;
case STATE_CYCLE_IDLE:
if (byPendingCycles != 0 && !bTimeoutOccured) {
/* There's at least one cycle queued, so let's start. */
Forward();
printf ("FW..\r");
/* First, wait till enough juice */
byCycleState = STATE_CYCLE_CHECKJUICE;
/* Also, add in a little delay just to let things settle */
byTicks_Delay = 1;
}
break;
case STATE_CYCLE_CHECKJUICE:
if (bEnoughMotorJuice && (byTicks_Delay == 0)) {
/* Enough juice is available, so, let'd start going forward.
Set a timer ticker also. */
StartMotor();
printf ("Motor..\r");
nTicks_Forward = TICKS_FORWARD;
byCycleState = STATE_CYCLE_FORWARD;
}
else {
if (!bCharging && (nAvgBatteryVoltage < CHARGE_MAX)) {
bCharging = TRUE;
}
printf ("Wait juice..\r");
byCycleState = STATE_CYCLE_WAITJUICE;
}
break;
case STATE_CYCLE_WAITJUICE:
if (bEnoughMotorJuice) {
printf ("Got juice..\r");
byCycleState = STATE_CYCLE_CHECKJUICE;
}
break;
case STATE_CYCLE_FORWARD:
/* Handle Pause case first thing.. */
if (bMotorPaused) {
if (!bBatteryProtect && (byTicks_Delay == 0)) {
/* Battery voltage OK again. Restart, and restore ticks */
printf ("Resume..\r");
bMotorPaused = FALSE;
nTicks_Forward = nTicks_Paused;
StartMotor();
}
}
/* Check for timeout or extended sensor */
else {
if ((nTicks_Forward == 0) || SenseExtended()) {
printf ("RV..\r");
Reverse();
nTicks_Reverse = TICKS_REVERSE;
byTicks_Delay = TICKS_IGNORE_SENSORS;
byCycleState = STATE_CYCLE_REVERSE1;
/* If a timout ever occurs, light the service soon light! */
if (nTicks_Forward == 0) {
printf ("Timeout!\r");
bTimeoutOccured = TRUE;
byPendingCycles = 0; // Clear out all pending cycles
byCycleState = STATE_CYCLE_IDLE;
StopMotor();
}
}
else if (bBatteryProtect) {
/* Battery voltage extremely low! Pause motor till enough juice
is present. Save our tick counter, too. */
printf ("Pause..\r");
StopMotor();
bMotorPaused = TRUE;
nTicks_Paused = nTicks_Forward;
/* Also add a hysterysis factor to avoid chatter */
byTicks_Delay = 8;
}
}
break;
case STATE_CYCLE_REVERSE1:
/* Initially after reversing, ignore sensors for a little bit */
if (byTicks_Delay == 0) {
/* OK, that was long enough.. Go to primary reverse state. */
byCycleState = STATE_CYCLE_REVERSE2;
}
break;
case STATE_CYCLE_REVERSE2:
/* Handle Pause first thing.. */
if (bMotorPaused) {
if (!bBatteryProtect && (byTicks_Delay == 0)) {
/* Voltage is OK again. Restart, and restore ticks */
printf ("Resume..\r");
bMotorPaused = FALSE;
nTicks_Reverse = nTicks_Paused;
StartMotor();
}
}
/* Check for timeout or retracted sensor */
else {
if ((nTicks_Reverse == 0) || SenseRetracted() || SenseExtended()) {
StopMotor();
if (byPendingCycles != 0)
byPendingCycles--;
byCycleState = STATE_CYCLE_DONE;
/* A slight delay is required after motor is
shut down and when direction solenoid is de-energized. */
byTicks_Delay = TICKS_CYCLE_DONEDELAY;
/* If a timout ever occurs, light the service soon light! */
if (nTicks_Reverse == 0) {
printf ("Timeout!\r");
bTimeoutOccured = TRUE;
byPendingCycles = 0; // Clear out all pending cycles
byCycleState = STATE_CYCLE_IDLE;
StopMotor();
}
}
else if (bBatteryProtect) {
/* Battery voltage extremely low! Pause motor till enough juice
is present. Save our tick counter, too. */
printf ("Pause..\r");
StopMotor();
bMotorPaused = TRUE;
nTicks_Paused = nTicks_Reverse;
/* Also add a hysterysis factor to avoid chatter */
byTicks_Delay = 8;
}
}
break;
case STATE_CYCLE_DONE:
/* Wait till the final delay is done between motor start and direction. */
if (byTicks_Delay == 0) {
printf ("Done Cycle..\r");
byCycleState = STATE_CYCLE_IDLE;
}
break;
}
/*****************************************************/
/* */
/* UPDATE Various Flags */
/* */
/*****************************************************/
/*** Set flag whether we have starting power available or nor. ****/
// Also, put some hysterysis in here..
//
if (!bEnoughMotorJuice && (nAvgBatteryVoltage > (SPA_VOLTAGE))) {
bEnoughMotorJuice = TRUE;
}
else if (bEnoughMotorJuice && (nAvgBatteryVoltage < (SPA_VOLTAGE - SPA_HYSTERYSIS))) {
bEnoughMotorJuice = FALSE;
}
/* Check if battery voltage is less than the BATTERY_PROTECT */
if (nAvgBatteryVoltage < BATTERY_PROTECT) {
bBatteryProtect = TRUE;
}
else {
bBatteryProtect = FALSE;
bBatteryEverOK = TRUE; // Set flag that battery has been OK at some point.
}
/* The service soon light comes on if ever a timeout occurs
or if ever the battery protect threshhold was passed (once battery
ever achieved a decent level). This state (and LED) once set stays
on forever (until reset). */
if ((bBatteryProtect && bBatteryEverOK) || bTimeoutOccured)
bServiceSoon = TRUE;
/*****************************************************/
/* */
/* UPDATE LEDs and Relay I/O */
/* */
/*****************************************************/
/* Update Cycle LEDs */
switch (byPendingCycles) {
case 0:
output_low (CYCLE1_LED);
output_low (CYCLE2_LED);
output_low (CYCLE3_LED);
break;
case 1:
output_high (CYCLE1_LED);
output_low (CYCLE2_LED);
output_low (CYCLE3_LED);
break;
case 2:
output_high (CYCLE1_LED);
output_high (CYCLE2_LED);
output_low (CYCLE3_LED);
break;
case 3:
output_high (CYCLE1_LED);
output_high (CYCLE2_LED);
output_high (CYCLE3_LED);
break;
}
/* Update the SPA LED */
if (bEnoughMotorJuice) {
output_high (SPA_LED);
}
else {
output_low (SPA_LED);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -