Ejemplo n.º 1
0
static void configure(void)
{
    _params.timing_advance_deg64        = config_get("motor_timing_advance_deg") * 64 / 60;
    _params.motor_bemf_window_len_denom = config_get("motor_bemf_window_len_denom");
    _params.bemf_valid_range_pct128     = config_get("motor_bemf_valid_range_pct") * 128 / 100;
    _params.zc_failures_max  = config_get("motor_zc_failures_to_stop");
    _params.zc_detects_min   = config_get("motor_zc_detects_to_start");
    _params.comm_period_max  = config_get("motor_comm_period_max_usec") * HNSEC_PER_USEC;
    _params.comm_blank_hnsec = config_get("motor_comm_blank_usec") * HNSEC_PER_USEC;

    _params.spinup_timeout              = config_get("motor_spinup_timeout_ms") * HNSEC_PER_MSEC;
    _params.spinup_start_comm_period    = config_get("motor_spinup_start_comm_period_usec") * HNSEC_PER_USEC;
    _params.spinup_end_comm_period      = config_get("motor_spinup_end_comm_period_usec") * HNSEC_PER_USEC;
    _params.spinup_num_good_comms       = config_get("motor_spinup_num_good_comms");
    _params.spinup_duty_cycle_increment = config_get("motor_spinup_duty_cycle_inc");

    /*
     * Validation
     */
    if (_params.comm_period_max > motor_timer_get_max_delay_hnsec()) {
        _params.comm_period_max = motor_timer_get_max_delay_hnsec();
    }

    if (_params.spinup_end_comm_period > _params.comm_period_max) {
        _params.spinup_end_comm_period = _params.comm_period_max;
    }

    _params.adc_sampling_period = motor_adc_sampling_period_hnsec();

    lowsyslog("Motor: RTCTL config: Max comm period: %u usec, BEMF window denom: %i\n",
              (unsigned)(_params.comm_period_max / HNSEC_PER_USEC),
              _params.motor_bemf_window_len_denom);
}
Ejemplo n.º 2
0
static int init_constants(unsigned frequency)
{
	assert_always(_pwm_top == 0);   // Make sure it was not initialized already

	/*
	 * PWM top, derived from frequency
	 */
	if (frequency < MOTOR_PWM_MIN_FREQUENCY || frequency > MOTOR_PWM_MAX_FREQUENCY) {
		return -1;
	}

	const int pwm_steps = PWM_TIMER_FREQUENCY / frequency;
	if ((pwm_steps < 2) || (pwm_steps > 65536)) {
		assert(0);
		return -1;
	}

	_pwm_top = pwm_steps - 1;
	_pwm_half_top = pwm_steps / 2;

	const int effective_steps = pwm_steps / 2;
	const float true_frequency = PWM_TIMER_FREQUENCY / (float)pwm_steps;
	const unsigned adc_period_usec = motor_adc_sampling_period_hnsec() / HNSEC_PER_USEC;
	lowsyslog("Motor: PWM freq: %f; Effective steps: %i; ADC period: %u usec\n",
		true_frequency, effective_steps, adc_period_usec);

	/*
	 * PWM min - Limited by MOTOR_ADC_SAMPLE_WINDOW_NANOSEC
	 */
	const float pwm_clock_period = 1.f / PWM_TIMER_FREQUENCY;
	const float pwm_adc_window_len = (MOTOR_ADC_SAMPLE_WINDOW_NANOSEC / 1e9f) * 2;
	const float pwm_adc_window_ticks_float = pwm_adc_window_len / pwm_clock_period;
	assert(pwm_adc_window_ticks_float >= 0);

	uint16_t pwm_half_adc_window_ticks = (uint16_t)pwm_adc_window_ticks_float;
	if (pwm_half_adc_window_ticks > _pwm_half_top) {
		pwm_half_adc_window_ticks = _pwm_half_top;
	}

	_pwm_min = pwm_half_adc_window_ticks;
	assert(_pwm_min <= _pwm_half_top);

	/*
	 * ADC synchronization.
	 * ADC shall be triggered in the middle of a PWM cycle in order to catch the moment when the instant
	 * winding current matches with average winding current - this helps to eliminate the current ripple
	 * caused by the PWM switching. Thus we trigger ADC at the point ((pwm_value / 2) - adc_advance).
	 * Refer to "Synchronizing the On-Chip Analog-to-Digital Converter on 56F80x Devices" for some explanation.
	 */
	const float adc_trigger_advance = MOTOR_ADC_SYNC_ADVANCE_NANOSEC / 1e9f;
	const float adc_trigger_advance_ticks_float = adc_trigger_advance / pwm_clock_period;
	assert(adc_trigger_advance_ticks_float >= 0);
	assert(adc_trigger_advance_ticks_float < (_pwm_top * 0.4f));
	_adc_advance_ticks = (uint16_t)adc_trigger_advance_ticks_float;

	lowsyslog("Motor: PWM range [%u; %u], ADC advance ticks %u\n",
		(unsigned)_pwm_min, (unsigned)_pwm_top, (unsigned)_adc_advance_ticks);
	return 0;
}
Ejemplo n.º 3
0
uint32_t motor_rtctl_get_min_comm_period_hnsec(void)
{
    // Ensure some number of ADC samples per comm period
    uint32_t retval = motor_adc_sampling_period_hnsec() * 5;
    if (retval < ABS_MIN_COMM_PERIOD_USEC * HNSEC_PER_USEC) {
        retval = ABS_MIN_COMM_PERIOD_USEC * HNSEC_PER_USEC;
    }
    return retval;
}