/** * \internal * \brief Common function to test frequency computation from QDEC * * \param test Current test case * \param res QDec resolution for this test * \param delay Delay between each quadrature steps * \param freq_unit QDec frequency unit used for this test * \param freq Expected frequency for this test */ static void run_qdec_freq_mode(const struct test_case *test, uint16_t res, uint8_t delay, uint16_t freq_unit, uint16_t freq) { qdec_config_t config; uint32_t freq_computed; /* Set to 0 the pins */ generator_qenc_reset(); /* QDec configuration */ qdec_get_config_defaults(&config); qdec_config_phase_pins(&config, CONF_QDEC_PORT, CONF_QDEC_PINS_BASE, false, 1); qdec_config_tc(&config, CONF_QDEC_TC); qdec_config_enable_freq(&config, freq_unit); qdec_config_freq_tc(&config, CONF_QDEC_FREQ_TC); qdec_config_revolution(&config, res); /* QDec enable */ qdec_enabled(&config); /* Reenable dir out on pins */ generator_qenc_reset(); /* Launch test */ generator_qenc(QENC_STEP_1); main_delay_ms(delay); generator_qenc(QENC_STEP_2); main_delay_ms(delay); generator_qenc(QENC_STEP_3); main_delay_ms(delay); generator_qenc(QENC_STEP_4); main_delay_ms(delay); generator_qenc(QENC_STEP_1); main_delay_ms(delay); generator_qenc(QENC_STEP_2); main_delay_ms(delay); generator_qenc(QENC_STEP_3); freq_computed = qdec_get_frequency(&config); /* 5% tolerance on Frequency */ if (freq_unit == 1) { test_assert_true(test, (freq_computed >= (freq - ((freq * 5) / 100))) && (freq_computed <= (freq + ((freq * 5) / 100))), "QDec frequency failure: expected %umHz, catched %umHz\r\n", freq, freq_computed); } else { test_assert_true(test, (freq_computed >= (freq - ((freq * 5) / 100))) && (freq_computed <= (freq + ((freq * 5) / 100))), "QDec frequency failure: expected %uHz, catched %uHz\r\n", freq, freq_computed); } }
/** * \internal * \brief Test QDEC in index mode on step QENC_STEP_4 * * \param test Current test case. */ static void run_qdec_index4_mode( const struct test_case *test) { qdec_config_t config; struct qenc_step seq[] = { {QENC_STEP_1, 0}, {QENC_STEP_2, 1}, {QENC_STEP_3, 2}, {QENC_STEP_4, 3}, {QENC_STEP_1, 4}, {QENC_STEP_2, 5}, {QENC_STEP_3 | QENC_INDEX_PIN, 6}, {QENC_STEP_4 | QENC_INDEX_PIN, 0}, {QENC_STEP_1 | QENC_INDEX_PIN, 1}, {QENC_STEP_2 | QENC_INDEX_PIN, 2}, {QENC_STEP_3, 3}, {QENC_STEP_4, 4}, {QENC_STEP_1, 5}, {QENC_STEP_2, 6}, {QENC_STEP_3 | QENC_INDEX_PIN, 7}, {QENC_STEP_4 | QENC_INDEX_PIN, 0}, {QENC_STEP_1 | QENC_INDEX_PIN, 1}, {QENC_STEP_2 | QENC_INDEX_PIN, 2}, }; /* Set to 0 the pins */ generator_qenc_reset(); /* QDec configuration */ qdec_get_config_defaults(&config); qdec_config_phase_pins(&config, CONF_QDEC_PORT, CONF_QDEC_PINS_BASE, false, 1); qdec_config_tc(&config, CONF_QDEC_TC); qdec_config_enable_index_pin(&config, false, QDEC_STATE_NO_PH0_PH90); qdec_config_revolution(&config, 8); /* QDec enable */ qdec_enabled(&config); /* Reenable dir out on pins */ generator_qenc_reset(); /* Launch test */ generator_qenc_seq(test, &config, seq, sizeof(seq) / sizeof(seq[0])); }
void app_sampling_init(void) { /* QDec configuration */ qdec_get_config_defaults(&qdec_config); qdec_config_phase_pins(&qdec_config, &PORTA, 6, false, 500); qdec_config_enable_rotary(&qdec_config); qdec_config_tc(&qdec_config, &TCC5); qdec_config_revolution(&qdec_config, 40); qdec_enabled(&qdec_config); /* ! ADC module configuration */ struct adc_config adc_conf; /* Configure the ADC module: * - signed, 12-bit results * - VCC reference * - 200 kHz maximum clock rate * - manual conversion triggering * - callback function */ adc_read_configuration(&LIGHT_SENSOR_ADC_MODULE, &adc_conf); adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_VCC); adc_set_clock_rate(&adc_conf, 200000); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&LIGHT_SENSOR_ADC_MODULE, &adc_conf); adc_set_callback(&LIGHT_SENSOR_ADC_MODULE, &app_sampling_handler); adc_enable(&LIGHT_SENSOR_ADC_MODULE); /* Configure ADC A channel 0 for light and NTC sensors. * - differantial measurement (V- linked on internal GND) * - gain x0.5 * - interrupt flag set on completed conversion * - interrupts enabled */ adcch_read_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0, &adcch_conf); adcch_set_input(&adcch_conf, LIGHT_SENSOR_ADC_INPUT, ADCCH_NEG_INTERNAL_GND, 0); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0, &adcch_conf); fifo_init(&app_sampling_fifo_desc, app_sampling_fifo_buffer, APP_SAMPLING_FIFO_SIZE); rtc_set_callback(&app_sampling_start); /* Display background */ gfx_mono_draw_line(DISPLAY_SAMPLING_TEXT_POS_X - 3, 0, DISPLAY_SAMPLING_TEXT_POS_X - 3, 32, GFX_PIXEL_SET); app_sampling_display_rate(); gfx_mono_draw_string(DISPLAY_LIGHT_TEXT, DISPLAY_LIGHT_TEXT_POS_X, DISPLAY_LIGHT_TEXT_POS_Y, &sysfont); gfx_mono_draw_filled_rect( DISPLAY_LIGHT_PROBAR_START_POS_X, DISPLAY_LIGHT_PROBAR_START_POS_Y, DISPLAY_LIGHT_PROBAR_START_SIZE_X, DISPLAY_LIGHT_PROBAR_START_SIZE_Y, GFX_PIXEL_SET); gfx_mono_draw_filled_rect( DISPLAY_LIGHT_PROBAR_STOP_POS_X, DISPLAY_LIGHT_PROBAR_STOP_POS_Y, DISPLAY_LIGHT_PROBAR_STOP_SIZE_X, DISPLAY_LIGHT_PROBAR_STOP_SIZE_Y, GFX_PIXEL_SET); /* Start a RTC alarm immediatly */ rtc_set_alarm_relative(0); }
/** * \brief Main application routine * - Configure system clock * - Call QDec driver API to configure it and enable it * - Call generator of quadrature encoder * - Get position, direction and frequency and display its */ int main( void ) { const usart_serial_options_t usart_serial_options = { .baudrate = CONF_TEST_BAUDRATE, .charlength = CONF_TEST_CHARLENGTH, .paritytype = CONF_TEST_PARITY, .stopbits = CONF_TEST_STOPBITS, }; qdec_config_t config; uint16_t qdec_position, qdec_position_prev = 0; uint32_t generator_qenc_freq = 2000 / QUADRATURE_RESOLUTION; bool generator_qenc_dir = true; /* Usual initializations */ board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); stdio_serial_init(CONF_TEST_USART, &usart_serial_options); printf("\x0C\n\r-- QDec Example --\n\r"); printf("-- Compiled: %s %s --\n\r\n\r", __DATE__, __TIME__); /* QDec configuration * Here, we use the default hardware ressources * proposed by default configuration. */ qdec_get_config_defaults(&config); qdec_config_phase_pins(&config, CONF_QDEC_PORT, CONF_QDEC_PINS_BASE, false, 1); qdec_config_tc(&config, CONF_QDEC_TC); qdec_config_enable_freq(&config, 1); qdec_config_freq_tc(&config, CONF_QDEC_FREQ_TC); qdec_config_revolution(&config, QUADRATURE_RESOLUTION); /* QDec enable */ qdec_enabled(&config); /* Generate quadrature encoder signals */ generator_qenc_enable(CONF_QDEC_PORT, CONF_QDEC_PINS_BASE, CONF_GENERATOR_QENC_TC, QUADRATURE_RESOLUTION, generator_qenc_freq, generator_qenc_dir); while (1) { /* read position */ qdec_position = qdec_get_position(&config); if (qdec_position_prev != qdec_position) { /* New position then display it */ qdec_position_prev = qdec_position; printf("%02u", qdec_position); /* display direction */ if (qdec_get_direction(&config)) { printf(" ++"); } else { printf(" --"); } /* Display frequency */ printf(" %5umHz\r\n", qdec_get_frequency(&config)); } /* Manage Quadrature encoder generator through UART */ if (usart_rx_is_complete(CONF_TEST_USART)) { char key = getchar(); if (key == 'd') { generator_qenc_dir = !generator_qenc_dir; generator_qenc_set_direction(generator_qenc_dir); } if (key == '-') { if (generator_qenc_freq > QUADRATURE_GENERATOR_FREQ_STEP) { generator_qenc_freq -= QUADRATURE_GENERATOR_FREQ_STEP; generator_qenc_set_freq(generator_qenc_freq); } } if (key == '+') { generator_qenc_freq += QUADRATURE_GENERATOR_FREQ_STEP; generator_qenc_set_freq(generator_qenc_freq); } } } }