Esempio n. 1
0
void doSlowAdc(void) {

	efiAssertVoid(CUSTOM_ERR_6658, getRemainingStack(chThdGetSelfX())> 32, "lwStAdcSlow");

#if EFI_INTERNAL_ADC

	/* Starts an asynchronous ADC conversion operation, the conversion
	 will be executed in parallel to the current PWM cycle and will
	 terminate before the next PWM cycle.*/
	slowAdc.conversionCount++;
	chSysLockFromISR()
	;
	if (ADC_SLOW_DEVICE.state != ADC_READY &&
	ADC_SLOW_DEVICE.state != ADC_COMPLETE &&
	ADC_SLOW_DEVICE.state != ADC_ERROR) {
		// todo: why and when does this happen? firmwareError(OBD_PCM_Processor_Fault, "ADC slow not ready?");
		slowAdc.errorsCount++;
		chSysUnlockFromISR()
		;
		return;
	}
	adcStartConversionI(&ADC_SLOW_DEVICE, &adcgrpcfgSlow, slowAdc.samples, ADC_BUF_DEPTH_SLOW);
	chSysUnlockFromISR()
	;
#endif /* EFI_INTERNAL_ADC */
}
Esempio n. 2
0
static void pwmpcb_fast(PWMDriver *pwmp) {
	efiAssertVoid(CUSTOM_ERR_6659, getRemainingStack(chThdGetSelfX())> 32, "lwStAdcFast");
#if EFI_INTERNAL_ADC
	(void) pwmp;

	/*
	 * Starts an asynchronous ADC conversion operation, the conversion
	 * will be executed in parallel to the current PWM cycle and will
	 * terminate before the next PWM cycle.
	 */
	chSysLockFromISR()
	;
	if (ADC_FAST_DEVICE.state != ADC_READY &&
	ADC_FAST_DEVICE.state != ADC_COMPLETE &&
	ADC_FAST_DEVICE.state != ADC_ERROR) {
		fastAdc.errorsCount++;
		// todo: when? why? firmwareError(OBD_PCM_Processor_Fault, "ADC fast not ready?");
		chSysUnlockFromISR()
		;
		return;
	}
	adcStartConversionI(&ADC_FAST_DEVICE, &adcgrpcfg_fast, fastAdc.samples, ADC_BUF_DEPTH_FAST);
	chSysUnlockFromISR()
	;
	fastAdc.conversionCount++;
#endif /* EFI_INTERNAL_ADC */
}
Esempio n. 3
0
void gadc_lld_timerjobI(GadcTimerJob *pj) {
	acg.channelselects = pj->physdev;
	acg.trigger = ADC_TRIGGER_TIMER;
	acg.frequency = nextfreq;
	nextfreq = 0;						// Next job use the same timer
	adcStartConversionI(&ADCD1, &acg, pj->buffer, pj->todo);
}
Esempio n. 4
0
static void pwmpcb_slow(PWMDriver *pwmp) {
	efiAssertVoid(getRemainingStack(chThdSelf())> 32, "lwStAdcSlow");

#if EFI_INTERNAL_ADC
	(void) pwmp;

	/* Starts an asynchronous ADC conversion operation, the conversion
	 will be executed in parallel to the current PWM cycle and will
	 terminate before the next PWM cycle.*/
	slowAdc.conversionCount++;
	chSysLockFromIsr()
	;
	if (ADC_SLOW_DEVICE.state != ADC_READY &&
	ADC_SLOW_DEVICE.state != ADC_COMPLETE &&
	ADC_SLOW_DEVICE.state != ADC_ERROR) {
		// todo: why and when does this happen? firmwareError("ADC slow not ready?");
		slowAdc.errorsCount++;
		chSysUnlockFromIsr()
		;
		return;
	}
	adcStartConversionI(&ADC_SLOW_DEVICE, &adcgrpcfgSlow, slowAdc.samples, ADC_BUF_DEPTH_SLOW);
	chSysUnlockFromIsr()
	;
#endif
}
Esempio n. 5
0
void gadc_lld_adc_nontimerI(GadcLldNonTimerData *pgntd) {
	/**
	 *  We don't need to calculate num_channels because the AT91SAM7 ADC does this for us.
	 */
	acg.channelselects = pgntd->physdev;
	acg.trigger = ADC_TRIGGER_SOFTWARE;
	adcStartConversionI(&ADCD1, &acg, pgntd->buffer, 1);
}
Esempio n. 6
0
/**
 * @brief   Starts an ADC conversion.
 * @details Starts an asynchronous conversion operation.
 * @note    The buffer is organized as a matrix of M*N elements where M is the
 *          channels number configured into the conversion group and N is the
 *          buffer depth. The samples are sequentially written into the buffer
 *          with no gaps.
 *
 * @param[in] adcp      pointer to the @p ADCDriver object
 * @param[in] grpp      pointer to a @p ADCConversionGroup object
 * @param[out] samples  pointer to the samples buffer
 * @param[in] depth     buffer depth (matrix rows number). The buffer depth
 *                      must be one or an even number.
 *
 * @api
 */
void adcStartConversion(ADCDriver *adcp,
                        const ADCConversionGroup *grpp,
                        adcsample_t *samples,
                        size_t depth) {

  osalSysLock();
  adcStartConversionI(adcp, grpp, samples, depth);
  osalSysUnlock();
}
Esempio n. 7
0
/*
 * PWM cyclic callback.
 * A new ADC conversion is started.
 */
static void pwmpcb(PWMDriver *pwmp) {

  (void)pwmp;

  /* Starts an asynchronous ADC conversion operation, the conversion
     will be executed in parallel to the current PWM cycle and will
     terminate before the next PWM cycle.*/
  chSysLockFromIsr();
  adcStartConversionI(&ADCD1, &adcgrpcfg, samples, ADC_GRP1_BUF_DEPTH);
  chSysUnlockFromIsr();
}
Esempio n. 8
0
void gadc_lld_adc_timerI(GadcLldTimerData *pgtd) {
	/**
	 *  We don't need to calculate num_channels because the AT91SAM7 ADC does this for us.
	 */
	acg.channelselects = pgtd->physdev;
	acg.trigger = pgtd->now ? (ADC_TRIGGER_TIMER|ADC_TRIGGER_SOFTWARE) : ADC_TRIGGER_TIMER;

	adcStartConversionI(&ADCD1, &acg, pgtd->buffer, pgtd->count);

	/* Next time assume the same (still running) timer */
	acg.frequency = 0;
}
Esempio n. 9
0
/**
 * @brief   Performs an ADC conversion.
 * @details Performs a synchronous conversion operation.
 * @note    The buffer is organized as a matrix of M*N elements where M is the
 *          channels number configured into the conversion group and N is the
 *          buffer depth. The samples are sequentially written into the buffer
 *          with no gaps.
 *
 * @param[in] adcp      pointer to the @p ADCDriver object
 * @param[in] grpp      pointer to a @p ADCConversionGroup object
 * @param[out] samples  pointer to the samples buffer
 * @param[in] depth     buffer depth (matrix rows number). The buffer depth
 *                      must be one or an even number.
 * @return              The operation result.
 * @retval MSG_OK       Conversion finished.
 * @retval MSG_RESET    The conversion has been stopped using
 *                      @p acdStopConversion() or @p acdStopConversionI(),
 *                      the result buffer may contain incorrect data.
 * @retval MSG_TIMEOUT  The conversion has been stopped because an hardware
 *                      error.
 *
 * @api
 */
msg_t adcConvert(ADCDriver *adcp,
                 const ADCConversionGroup *grpp,
                 adcsample_t *samples,
                 size_t depth) {
  msg_t msg;

  osalSysLock();
  osalDbgAssert(adcp->thread == NULL, "already waiting");
  adcStartConversionI(adcp, grpp, samples, depth);
  msg = osalThreadSuspendS(&adcp->thread);
  osalSysUnlock();
  return msg;
}
Esempio n. 10
0
static void pwmpcb_fast(PWMDriver *pwmp) {
#ifdef EFI_INTERNAL_ADC
	(void) pwmp;

	/* Starts an asynchronous ADC conversion operation, the conversion
	 will be executed in parallel to the current PWM cycle and will
	 terminate before the next PWM cycle.*/chSysLockFromIsr()
	;
	adcStartConversionI(&ADC_FAST, &adcgrpcfg_fast, samples_fast, ADC_GRP1_BUF_DEPTH_FAST);
	chSysUnlockFromIsr()
	;
#endif
}
Esempio n. 11
0
/**
 * @brief   Performs an ADC conversion.
 * @details Performs a synchronous conversion operation.
 * @note    The buffer is organized as a matrix of M*N elements where M is the
 *          channels number configured into the conversion group and N is the
 *          buffer depth. The samples are sequentially written into the buffer
 *          with no gaps.
 *
 * @param[in] adcp      pointer to the @p ADCDriver object
 * @param[in] grpp      pointer to a @p ADCConversionGroup object
 * @param[out] samples  pointer to the samples buffer
 * @param[in] depth     buffer depth (matrix rows number). The buffer depth
 *                      must be one or an even number.
 * @return              The operation result.
 * @retval RDY_OK       Conversion finished.
 * @retval RDY_RESET    The conversion has been stopped using
 *                      @p acdStopConversion() or @p acdStopConversionI(),
 *                      the result buffer may contain incorrect data.
 * @retval RDY_TIMEOUT  The conversion has been stopped because an hardware
 *                      error.
 *
 * @api
 */
msg_t adcConvert(ADCDriver *adcp,
                 const ADCConversionGroup *grpp,
                 adcsample_t *samples,
                 size_t depth) {
  msg_t msg;

  chSysLock();
  chDbgAssert(adcp->thread == NULL, "adcConvert(), #1", "already waiting");
  adcStartConversionI(adcp, grpp, samples, depth);
  adcp->thread = chThdSelf();
  chSchGoSleepS(THD_STATE_SUSPENDED);
  msg = chThdSelf()->p_u.rdymsg;
  chSysUnlock();
  return msg;
}
Esempio n. 12
0
void gadc_lld_nontimerjobI(GadcNonTimerJob *pj) {
	acg.channelselects = pj->physdev;
	acg.trigger = ADC_TRIGGER_SOFTWARE;
	adcStartConversionI(&ADCD1, &acg, pj->buffer, 1);
}
Esempio n. 13
0
/*
 * Analog I/O thread
 */
msg_t thdAnalogIO(void *arg) 
{
  (void)arg;
  uint32_t timeStamp=0;
  float i2cAdcPos[I2C_MAX_CHANNELS]; // 5 servos + resistive foam in the clamp
  float i2cAdcCurrent[I2C_MAX_CHANNELS]; // 5 servo consumption
  bool_t i2cOk = TRUE;
  uint32_t lowPassIteration=0;

   /*
   * initialize the Analog IO (5 pins)
   */
  initAnalogIO ();
  chRegSetThreadName("thdAnalogIO");

  /* init i2c part */
  
  if  (initI2cDriver (&i2c2) != TRUE) {
    DebugTrace ("I2C (i2c2) init FAILED");
    syslog (LOG_FATAL, "I2C (i2c2) FAIL");
    i2cOk = FALSE;
  }
  
  while (!chThdShouldTerminate()) {
    chSysLock ();
    adcStopConversionI (&ADCD3);
    adcStartConversionI (&ADCD3, &adcgrpcfg3, samples3, ADC_BUF_DEPTH);
    chSysUnlock ();
    
    
    if (i2cOk && ( isActive(Analog_inCurrent) || isActive(Analog_inServiPos))) {
      static float medianFilterBuffer[ADC_MEDIAN_SIZE] [SERVO_COUNT+1] [MEDIAN_SIZE] =  {{{0.0f}}};
      // POSITION
      if (i2cGetADC_ADS7828_Val (i2c2.driver, I2C_ADC_SERVOPOS_ADR_OFFSET, 0b01011111, i2cAdcPos)) {
	DebugTrace ("i2cGetADC_ADS7828_Val error for position sensor");
	syslog (LOG_ERROR, "ADS7828 POS FAIL");
      } else {
	// first of all, the median filter
	static bool firstTime=TRUE;
	if (firstTime) {
	  firstTime = FALSE;
	  for (uint32_t i=0; i<SERVO_COUNT+1; i++) {
	    i2cAvPos[i] = i2cAdcPos[i];
	  }  
	} else {
	  for (uint32_t i=0; i<SERVO_COUNT+1; i++) {
	    // shift array and discard oldest value
	    memmove (&medianFilterBuffer[ADC_SERVO_POS][i][0],
		     &medianFilterBuffer[ADC_SERVO_POS][i][1],
		     sizeof(float) * MEDIAN_SIZE-1);

	    // copy new incomming value
	    medianFilterBuffer[ADC_SERVO_POS][i][MEDIAN_SIZE-1] = i2cAdcPos[i];

	    // copy to sort buffer
	    memcpy (&medianFilterBuffer[ADC_VALUE_SORT][i][0],
		     &medianFilterBuffer[ADC_SERVO_POS][i][0],
		     sizeof(float) * MEDIAN_SIZE);
	     
	    // sort the array
	    qsort (&medianFilterBuffer[ADC_VALUE_SORT][i][0], MEDIAN_SIZE, sizeof(float), 
		   &qsortCompareFloatCb);

	    // eliminate lowest and highest values
	    const float medianMean = (medianFilterBuffer[ADC_VALUE_SORT][i][1] + 
	      medianFilterBuffer[ADC_VALUE_SORT][i][2] + medianFilterBuffer[ADC_VALUE_SORT][i][3])/3.f;
	    
	    // then low pass filter
	    lowPassIteration++;
	    i2cAvPos[i] =  (( i2cAvPos[i]*(float)LOW_PASS_N) + medianMean)/ (float) (LOW_PASS_N+1);
	  }  
	}
      }
      
      // CURRENT
      if (i2cGetADC_ADS7828_Val (i2c2.driver, I2C_ADC_CURRENT_ADR_OFFSET, 0b00111111, i2cAdcCurrent)) {
	DebugTrace ("i2cGetADC_ADS7828_Val error for current sensor");
	syslog (LOG_ERROR, "ADS7828 CURRENT FAIL");
      } else {
	//for (uint32_t j=0; j<SERVO_COUNT+1; j++) {
	  //DebugTrace ("RC[%d]=%d", j, (int) (i2cAdcCurrent[j]*4096.0f));
	//}  

	static bool firstTime=TRUE;
	if (firstTime) {
	  firstTime = FALSE;
	  for (uint32_t i=0; i<SERVO_COUNT+1; i++) {
	    i2cAvCurrent[i] = i2cAdcCurrent[i];
	  }  
	} else {
	  for (uint32_t i=0; i<SERVO_COUNT+1; i++) {
	    i2cAvCurrent[i] =  ((i2cAvCurrent[i]*(float)LOW_PASS_N) + 
				i2cAdcCurrent[i])/ (float) (LOW_PASS_N+1);
	  }  
	}
      }
     
    }

    // check on power supply voltage
    if (lowPassIteration >= 100) { // wait for filter to stabilize
      if (analogGet5VoltPowerVoltage() < MIN_5VOLTS_POWER_SUPPLY_VOLTAGE) {
	if (isServoEngaged (SERVO_ALL_SERVOS)) {
	  // have to test validity of analogGet5VoltPowerVoltage() before using it
	  //	  servoDisengage (SERVO_ALL_SERVOS);
#pragma message \
  "enable  servoDisengage (SERVO_ALL_SERVOS) in " __FILE__	\
  " after testing validity of analogGet5VoltPowerVoltage()"
	  syslog (LOG_ERROR, "Surcharge Alim");
 	  syslog (LOG_ERROR, "Servos ** OFF **");	  
	  syslog (LOG_INFO, "rearmer : Bouton VERT");
	}
      }
    }
      //   check on  current intensity
    for (uint32_t i=0; i<SERVO_COUNT; i++) {
      if (i2cAvCurrent[i] >  max_current_intensity_use[i]) {
	if (isServoEngaged (i)) {
	  servoDisengage (i);
	  syslog (LOG_ERROR, "Surcharge Servo %d", i);
 	  syslog (LOG_ERROR, "Servos %d** OFF **", i);
	  syslog (LOG_INFO, "rearmer : Bouton VERT");
	}
      }
    }
  
    if (isActive(Analog_inCommand)) {
      if ((chTimeNow() - timeStamp) >= TIME_STEP) {
	timeStamp = chTimeNow();
	for (uint32_t i=0; i<SERVO_COUNT ; i++) {
	  const float adcV = analogGetCmd(i);
	  servoSetPos (i, adcV); 
	  /*   if (chTimeNow() > 5000) */
	  /*     chprintf (chp, "Apos=%.4f\r\n", adcV); */
	} 
      }
    } else {
      chThdSleepMilliseconds(1);
    }
  }
  
  closeAnalogIO();
  i2cStop (i2c2.driver);
  return 0;
}
Esempio n. 14
0
void sonarStart(){
	sonar_en = TRUE;
	adcStartConversionI(&ADCD1, &adcgrpcfg2, sampels, ADC_BUFFER_DEPTH);
}
Esempio n. 15
0
/*
 * GMD control thread, times are in microseconds.
 */
static void motordrive(GPTDriver *gptp) {

	(void) gptp;

	U32DelayCount = 0;

	chSysLockFromIsr();

	// Read Input ADC's
	adcStartConversionI(&ADCD3, &adcgrp2cfg, InputSamples, ADC_GRP2_BUF_DEPTH);
	// Read Feedback ADC's
	adcStartConversionI(&ADCD1, &adcgrp1cfg5, vertFeedbackSample, ADC_GRP1_BUF_DEPTH);
	adcStartConversionI(&ADCD2, &adcgrp1cfg4, latFeedbackSample, ADC_GRP1_BUF_DEPTH);

	chSysUnlockFromIsr();

//TODO undo the constant enable
	// Read input switch positions
//	U8EnableDriveSwitch = 1;
	U8EnableDriveSwitch = palReadPad(GPIOD, GPIOD_PIN8); // PD8
//	U8PosnVelModeSwitch = 1; // PD9
	U8PosnVelModeSwitch = palReadPad(GPIOD, GPIOD_PIN9); // PD9

	// Handle ENABLE on GMD and LEDs on GFE
	if(U8EnableDriveSwitch > 0 && U8ShellEnable > 0) {
		// Turn ON enable
		palSetPad(GPIOD, GPIOD_PIN10);
		palSetPad(GPIOD, GPIOD_PIN6);
//		// Turn Green LED on, Red LED off
//		palSetPad(GPIOD, GPIOD_PIN0);
//		palClearPad(GPIOD, GPIOD_PIN1);

		// Interlock drives on mode change
		if(U8ShellMode == 2) {
			if(U8PosnVelModeSwitch != U8PrevPosnVelModeSwitchState) {
				vertAxisStruct.U8DriveIsInterlocked = 1;
				latAxisStruct.U8DriveIsInterlocked = 1;
			}
		}
		else {
			if(U8ShellMode != U8PrevPosnVelModeSwitchState) {
				vertAxisStruct.U8DriveIsInterlocked = 1;
				latAxisStruct.U8DriveIsInterlocked = 1;
			}
		}
	}
	else {
		// Otherwise enable is OFF
		palClearPad(GPIOD, GPIOD_PIN10);
		palClearPad(GPIOD, GPIOD_PIN6);
//		// Turn Green LED off, Red LED on
//		palClearPad(GPIOD, GPIOG_PIN0);
//		palSetPad(GPIOD, GPIOD_PIN1);

		// Lock out drives
		vertAxisStruct.U8DriveIsInterlocked = 1;
		latAxisStruct.U8DriveIsInterlocked = 1;
	}

	// Interlock drives on mode change
	if(U8ShellMode == 2) {
		U8PrevPosnVelModeSwitchState = U8PosnVelModeSwitch;
	}
	else {
		U8PrevPosnVelModeSwitchState = U8ShellMode;
	}

//	U8PrevPosnVelModeSwitchState = U8PosnVelModeSwitch;

	processLeds();

	// Handle HW Watchdog on GMD
	if(u8WatchDogCycleCount > 7){
		u8WatchDogCycleCount = 0;
		palTogglePad(GPIOD, GPIOD_PIN11);
		palTogglePad(GPIOD, GPIOD_PIN5);
	}
	else
		u8WatchDogCycleCount++;

	return;
}