⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 control.c

📁 熟悉verilog,帮助初学者尽快掌握verilog
💻 C
📖 第 1 页 / 共 3 页
字号:
   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 + -