/* * 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 && mcpwm_get_state() == MC_STATE_STARTING) { sample_now = 0; sample_ready = 0; was_start_wample = 1; sample_at_start = 0; } static int a = 0; if (!sample_ready) { a++; if (a >= sample_int) { a = 0; 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; ph2_samples[sample_now] = ADC_V_L2; ph3_samples[sample_now] = ADC_V_L3; vzero_samples[sample_now] = ADC_V_ZERO * MCPWM_VZERO_FACT; if (mcpwm_get_state() == MC_STATE_DETECTING && 0) { status_samples[sample_now] = mcpwm_get_detect_top(); } else { uint8_t tmp; if (was_start_wample) { if (mcpwm_get_state() == MC_STATE_STARTING) { tmp = 1; } else if (mcpwm_get_state() == MC_STATE_RUNNING) { tmp = 2; } else { tmp = 3; } } else { tmp = mcpwm_read_hall_phase(); } status_samples[sample_now] = mcpwm_get_comm_step() | (tmp << 3); } curr_fir_samples[sample_now] = (int16_t)(mcpwm_get_tot_current_filtered() * 100); sample_now++; if (sample_now == sample_len) { sample_ready = 1; sample_now = 0; was_start_wample = 0; chSysLockFromIsr(); chEvtSignalI(sample_send_tp, (eventmask_t) 1); chSysUnlockFromIsr(); } main_last_adc_duration = mcpwm_get_last_adc_isr_duration(); } } }
/* * 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(); } } }
static void adc_int_handler(void *p, uint32_t flags) { (void)p; (void)flags; uint32_t t_start = timer_time_now(); // Reset the watchdog timeout_feed_WDT(THREAD_MCPWM); int curr0 = GET_CURRENT1(); int curr1 = GET_CURRENT2(); #ifdef HW_HAS_3_SHUNTS int curr2 = GET_CURRENT3(); #endif m_curr0_sum += curr0; m_curr1_sum += curr1; #ifdef HW_HAS_3_SHUNTS m_curr2_sum += curr2; #endif curr0 -= m_curr0_offset; curr1 -= m_curr1_offset; #ifdef HW_HAS_3_SHUNTS curr2 -= m_curr2_offset; #endif m_curr_samples++; // Update current #ifdef HW_HAS_3_SHUNTS float i1 = -(float)curr2; #else float i1 = -(float)curr1; #endif float i2 = (float)curr0; m_current_now = utils_max_abs(i1, i2) * FAC_CURRENT; UTILS_LP_FAST(m_current_now_filtered, m_current_now, m_conf->gpd_current_filter_const); // Check for most critical faults here, as doing it in mc_interface can be too slow // for high switching frequencies. const float input_voltage = GET_INPUT_VOLTAGE(); 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 (m_conf->l_slow_abs_current) { if (fabsf(m_current_now) > m_conf->l_abs_current_max) { mc_interface_fault_stop(FAULT_CODE_ABS_OVER_CURRENT); } } else { if (fabsf(m_current_now_filtered) > m_conf->l_abs_current_max) { mc_interface_fault_stop(FAULT_CODE_ABS_OVER_CURRENT); } } // Buffer handling static bool buffer_was_empty = true; static int interpol = 0; static float buffer_last = 0.0; static float buffer_next = 0.0; interpol++; if (interpol > m_conf->gpd_buffer_interpol) { interpol = 0; if (m_sample_buffer.read != m_sample_buffer.write) { buffer_last = buffer_next; buffer_next = m_sample_buffer.buffer[m_sample_buffer.read++]; m_sample_buffer.read %= SAMPLE_BUFFER_SIZE; m_output_now = buffer_last; m_is_running = true; buffer_was_empty = false; } else { if (!buffer_was_empty) { stop_pwm_hw(); } buffer_was_empty = true; } } else if (!buffer_was_empty) { m_output_now = utils_map((float)interpol, 0.0, (float)m_conf->gpd_buffer_interpol + 1.0, buffer_last, buffer_next); m_is_running = true; } if (m_is_running) { gpdrive_output_sample(m_output_now); if (m_output_mode == GPD_OUTPUT_MODE_CURRENT) { float v_in = GET_INPUT_VOLTAGE(); float err = m_current_state.current_set - m_current_now_filtered; m_current_state.voltage_now = m_current_state.voltage_int + err * m_conf->gpd_current_kp; m_current_state.voltage_int += err * m_conf->gpd_current_ki * (1.0 / m_fsw_now); utils_truncate_number_abs((float*)&m_current_state.voltage_int, v_in); set_modulation(m_current_state.voltage_now / v_in); } } ledpwm_update_pwm(); m_last_adc_isr_duration = timer_seconds_elapsed_since(t_start); }
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(); } } }