/* * Called every time new ADC values are available. Note that * the ADC is initialized from mcpwm.c */ void main_dma_adc_handler(void) { ledpwm_update_pwm(); if (sample_at_start && (mc_interface_get_state() == MC_STATE_RUNNING || start_comm != mcpwm_get_comm_step())) { sample_now = 0; sample_ready = 0; sample_at_start = 0; } static int a = 0; if (!sample_ready) { a++; if (a >= sample_int) { a = 0; if (mc_interface_get_state() == MC_STATE_DETECTING) { curr0_samples[sample_now] = (int16_t)mcpwm_detect_currents[mcpwm_get_comm_step() - 1]; curr1_samples[sample_now] = (int16_t)mcpwm_detect_currents_diff[mcpwm_get_comm_step() - 1]; ph1_samples[sample_now] = (int16_t)mcpwm_detect_voltages[0]; ph2_samples[sample_now] = (int16_t)mcpwm_detect_voltages[1]; ph3_samples[sample_now] = (int16_t)mcpwm_detect_voltages[2]; } else { curr0_samples[sample_now] = ADC_curr_norm_value[0]; curr1_samples[sample_now] = ADC_curr_norm_value[1]; ph1_samples[sample_now] = ADC_V_L1 - mcpwm_vzero; ph2_samples[sample_now] = ADC_V_L2 - mcpwm_vzero; ph3_samples[sample_now] = ADC_V_L3 - mcpwm_vzero; } vzero_samples[sample_now] = mcpwm_vzero; curr_fir_samples[sample_now] = (int16_t)(mc_interface_get_tot_current() * 100.0); f_sw_samples[sample_now] = (int16_t)(mc_interface_get_switching_frequency_now() / 10.0); status_samples[sample_now] = mcpwm_get_comm_step() | (mcpwm_read_hall_phase() << 3); sample_now++; if (sample_now == sample_len) { sample_ready = 1; sample_now = 0; chSysLockFromISR(); chEvtSignalI(sample_send_tp, (eventmask_t) 1); chSysUnlockFromISR(); } main_last_adc_duration = mcpwm_get_last_adc_isr_duration(); } } }
void mc_interface_fault_stop(mc_fault_code fault) { if (mc_interface_dccal_done() && m_fault_now == FAULT_CODE_NONE) { // Sent to terminal fault logger so that all faults and their conditions // can be printed for debugging. chSysLock(); volatile int val_samp = TIM8->CCR1; volatile int current_samp = TIM1->CCR4; volatile int tim_top = TIM1->ARR; chSysUnlock(); fault_data fdata; fdata.fault = fault; fdata.current = mc_interface_get_tot_current(); fdata.current_filtered = mc_interface_get_tot_current_filtered(); fdata.voltage = GET_INPUT_VOLTAGE(); fdata.duty = mc_interface_get_duty_cycle_now(); fdata.rpm = mc_interface_get_rpm(); fdata.tacho = mc_interface_get_tachometer_value(false); fdata.cycles_running = m_cycles_running; fdata.tim_val_samp = val_samp; fdata.tim_current_samp = current_samp; fdata.tim_top = tim_top; fdata.comm_step = mcpwm_get_comm_step(); fdata.temperature = NTC_TEMP(ADC_IND_TEMP_MOS1); terminal_add_fault_data(&fdata); } m_ignore_iterations = m_conf.m_fault_stop_time_ms; switch (m_conf.motor_type) { case MOTOR_TYPE_BLDC: case MOTOR_TYPE_DC: mcpwm_stop_pwm(); break; case MOTOR_TYPE_FOC: mcpwm_foc_stop_pwm(); break; default: break; } m_fault_now = fault; }
void mc_interface_mc_timer_isr(void) { ledpwm_update_pwm(); // LED PWM Driver update const float input_voltage = GET_INPUT_VOLTAGE(); // Check for faults that should stop the motor static int wrong_voltage_iterations = 0; if (input_voltage < m_conf.l_min_vin || input_voltage > m_conf.l_max_vin) { wrong_voltage_iterations++; if ((wrong_voltage_iterations >= 8)) { mc_interface_fault_stop(input_voltage < m_conf.l_min_vin ? FAULT_CODE_UNDER_VOLTAGE : FAULT_CODE_OVER_VOLTAGE); } } else { wrong_voltage_iterations = 0; } if (mc_interface_get_state() == MC_STATE_RUNNING) { m_cycles_running++; } else { m_cycles_running = 0; } if (pwn_done_func) { pwn_done_func(); } const float current = mc_interface_get_tot_current_filtered(); const float current_in = mc_interface_get_tot_current_in_filtered(); m_motor_current_sum += current; m_input_current_sum += current_in; m_motor_current_iterations++; m_input_current_iterations++; float abs_current = mc_interface_get_tot_current(); float abs_current_filtered = current; if (m_conf.motor_type == MOTOR_TYPE_FOC) { // TODO: Make this more general abs_current = mcpwm_foc_get_abs_motor_current(); abs_current_filtered = mcpwm_foc_get_abs_motor_current_filtered(); } // Current fault code if (m_conf.l_slow_abs_current) { if (fabsf(abs_current_filtered) > m_conf.l_abs_current_max) { mc_interface_fault_stop(FAULT_CODE_ABS_OVER_CURRENT); } } else { if (fabsf(abs_current) > m_conf.l_abs_current_max) { mc_interface_fault_stop(FAULT_CODE_ABS_OVER_CURRENT); } } // Watt and ah counters const float f_sw = mc_interface_get_switching_frequency_now(); if (fabsf(current) > 1.0) { // Some extra filtering static float curr_diff_sum = 0.0; static float curr_diff_samples = 0; curr_diff_sum += current_in / f_sw; curr_diff_samples += 1.0 / f_sw; if (curr_diff_samples >= 0.01) { if (curr_diff_sum > 0.0) { m_amp_seconds += curr_diff_sum; m_watt_seconds += curr_diff_sum * input_voltage; } else { m_amp_seconds_charged -= curr_diff_sum; m_watt_seconds_charged -= curr_diff_sum * input_voltage; } curr_diff_samples = 0.0; curr_diff_sum = 0.0; } } // Sample collection if (m_sample_at_start && (mc_interface_get_state() == MC_STATE_RUNNING || m_start_comm != mcpwm_get_comm_step())) { m_sample_now = 0; m_sample_ready = 0; m_sample_at_start = 0; } static int a = 0; if (!m_sample_ready) { a++; if (a >= m_sample_int) { a = 0; if (mc_interface_get_state() == MC_STATE_DETECTING) { m_curr0_samples[m_sample_now] = (int16_t)mcpwm_detect_currents[mcpwm_get_comm_step() - 1]; m_curr1_samples[m_sample_now] = (int16_t)mcpwm_detect_currents_diff[mcpwm_get_comm_step() - 1]; m_ph1_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[0]; m_ph2_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[1]; m_ph3_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[2]; } else { m_curr0_samples[m_sample_now] = ADC_curr_norm_value[0]; m_curr1_samples[m_sample_now] = ADC_curr_norm_value[1]; m_ph1_samples[m_sample_now] = ADC_V_L1 - mcpwm_vzero; m_ph2_samples[m_sample_now] = ADC_V_L2 - mcpwm_vzero; m_ph3_samples[m_sample_now] = ADC_V_L3 - mcpwm_vzero; } m_vzero_samples[m_sample_now] = mcpwm_vzero; m_curr_fir_samples[m_sample_now] = (int16_t)(mc_interface_get_tot_current() * 100.0); m_f_sw_samples[m_sample_now] = (int16_t)(mc_interface_get_switching_frequency_now() / 10.0); m_status_samples[m_sample_now] = mcpwm_get_comm_step() | (mcpwm_read_hall_phase() << 3); m_sample_now++; if (m_sample_now == m_sample_len) { m_sample_ready = 1; m_sample_now = 0; chSysLockFromISR(); chEvtSignalI(sample_send_tp, (eventmask_t) 1); chSysUnlockFromISR(); } m_last_adc_duration_sample = mcpwm_get_last_adc_isr_duration(); } } }