Writing /var/lib/dokuwiki/data/meta/teaching/ie0624/proyectos/control_motores_sincronicos/codigo.meta failed
teaching:ie0624:proyectos:control_motores_sincronicos:codigo
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
teaching:ie0624:proyectos:control_motores_sincronicos:codigo [2018/12/17 03:08] – micros | teaching:ie0624:proyectos:control_motores_sincronicos:codigo [2022/09/20 00:08] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Código Fuente Utilizado para la Implementación del Sistema de Control ===== | + | ====== Código Fuente Utilizado para la Implementación del Sistema de Control ====== |
+ | |||
+ | ==== Diagrama de Flujo==== | ||
+ | * A continuación se muestra el código fuente utilizado para la implementación de Sistema de Control, incluyendo la comunicación a través de USART, y las señales enviadas al puente H para el control de potencia. | ||
+ | Para una mejor comprensión de la lógica general, ver el [[teaching: | ||
+ | |||
+ | <code C> | ||
+ | |||
+ | /* | ||
+ | * Copyright (C) 2018 ARCOS-Lab Universidad de Costa Rica | ||
+ | * | ||
+ | * This program is free software: you can redistribute it and/or modify | ||
+ | * it under the terms of the GNU General Public License as published by | ||
+ | * the Free Software Foundation, either version 3 of the License, or | ||
+ | * (at your option) any later version. | ||
+ | * | ||
+ | * This program is distributed in the hope that it will be useful, | ||
+ | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
+ | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
+ | * GNU General Public License for more details. | ||
+ | * | ||
+ | * You should have received a copy of the GNU General Public License | ||
+ | * along with this program. | ||
+ | */ | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include " | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | // | ||
+ | #define SYSFREQ | ||
+ | #define PWMFREQ | ||
+ | #define PWMFREQ_F | ||
+ | #define PRESCALE | ||
+ | #define PWM_PERIOD_ARR | ||
+ | |||
+ | #define LBLUE GPIOE, GPIO8 | ||
+ | #define LRED GPIOE, GPIO9 | ||
+ | #define LORANGE GPIOE, GPIO10 | ||
+ | #define LGREEN GPIOE, GPIO11 | ||
+ | #define LBLUE2 GPIOE, GPIO12 | ||
+ | #define LRED2 GPIOE, GPIO13 | ||
+ | #define LORANGE2 GPIOE, GPIO14 | ||
+ | #define LGREEN2 GPIOE, GPIO15 | ||
+ | |||
+ | #define LD4 GPIOE, GPIO8 | ||
+ | #define LD3 GPIOE, GPIO9 | ||
+ | #define LD5 GPIOE, GPIO10 | ||
+ | #define LD7 GPIOE, GPIO11 | ||
+ | #define LD9 GPIOE, GPIO12 | ||
+ | #define LD10 GPIOE, GPIO13 | ||
+ | #define LD8 GPIOE, GPIO14 | ||
+ | #define LD6 GPIOE, GPIO15 | ||
+ | |||
+ | |||
+ | void leds_init(void) { | ||
+ | rcc_peripheral_enable_clock(& | ||
+ | gpio_mode_setup(GPIOE, | ||
+ | } | ||
+ | |||
+ | void system_init(void) { | ||
+ | rcc_clock_setup_hsi(& | ||
+ | |||
+ | leds_init(); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | |||
+ | void tim_init(void) | ||
+ | { | ||
+ | /* Enable TIM1 clock. and Port E clock (for outputs) */ | ||
+ | rcc_periph_clock_enable(RCC_TIM1); | ||
+ | rcc_periph_clock_enable(RCC_GPIOE); | ||
+ | |||
+ | //Set TIM1 channel (and complementary) output to alternate function push-pull' | ||
+ | //f4 TIM1=> GIO9: CH1, GPIO11: CH2, GPIO13: CH3 | ||
+ | //f4 TIM1=> GIO8: CH1N, GPIO10: CH2N, GPIO12: CH3N | ||
+ | gpio_mode_setup(GPIOE, | ||
+ | gpio_set_af(GPIOE, | ||
+ | |||
+ | /* Reset TIM1 pepheral. */ | ||
+ | rcc_periph_reset_pulse(RST_TIM1); | ||
+ | |||
+ | /* Timer global mode: | ||
+ | * - No divider | ||
+ | * - Alignment edge | ||
+ | * - Direction up | ||
+ | */ | ||
+ | timer_set_mode(TIM1, | ||
+ | | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | | ||
+ | |||
+ | timer_set_prescaler(TIM1, | ||
+ | timer_set_repetition_counter(TIM1, | ||
+ | timer_enable_preload(TIM1); | ||
+ | timer_continuous_mode(TIM1); | ||
+ | |||
+ | /* Period (32kHz). */ | ||
+ | timer_set_period(TIM1, | ||
+ | |||
+ | /* Configure break and deadtime. */ | ||
+ | timer_set_enabled_off_state_in_idle_mode(TIM1); | ||
+ | timer_set_enabled_off_state_in_run_mode(TIM1); | ||
+ | timer_disable_break(TIM1); | ||
+ | timer_set_break_polarity_high(TIM1); | ||
+ | timer_disable_break_automatic_output(TIM1); | ||
+ | timer_set_break_lock(TIM1, | ||
+ | |||
+ | /* Disable outputs. */ | ||
+ | timer_disable_oc_output(TIM1, | ||
+ | timer_disable_oc_output(TIM1, | ||
+ | timer_disable_oc_output(TIM1, | ||
+ | timer_disable_oc_output(TIM1, | ||
+ | timer_disable_oc_output(TIM1, | ||
+ | timer_disable_oc_output(TIM1, | ||
+ | |||
+ | /* -- OC1 and OC1N configuration -- */ | ||
+ | /* Configure global mode of line 1. */ | ||
+ | timer_enable_oc_preload(TIM1, | ||
+ | timer_set_oc_mode(TIM1, | ||
+ | /* Configure OC1. */ | ||
+ | timer_set_oc_polarity_high(TIM1, | ||
+ | timer_set_oc_idle_state_unset(TIM1, | ||
+ | /* Configure OC1N. */ | ||
+ | timer_set_oc_polarity_high(TIM1, | ||
+ | timer_set_oc_idle_state_unset(TIM1, | ||
+ | |||
+ | |||
+ | //####### | ||
+ | /* Set the capture compare value for OC1. */ | ||
+ | //######### | ||
+ | |||
+ | |||
+ | |||
+ | /* ARR reload enable. */ | ||
+ | timer_enable_preload(TIM1); | ||
+ | |||
+ | /* | ||
+ | * Enable preload of complementary channel configurations and | ||
+ | * update on COM event. | ||
+ | */ | ||
+ | timer_disable_preload_complementry_enable_bits(TIM1); | ||
+ | |||
+ | /* Enable outputs in the break subsystem. */ | ||
+ | timer_enable_break_main_output(TIM1); | ||
+ | |||
+ | /* Generate update event to reload all registers before starting*/ | ||
+ | timer_generate_event(TIM1, | ||
+ | |||
+ | timer_set_oc_mode(TIM1, | ||
+ | timer_enable_oc_output(TIM1, | ||
+ | timer_disable_oc_output (TIM1, TIM_OC1N); | ||
+ | |||
+ | /* Counter enable. */ | ||
+ | timer_enable_counter(TIM1); | ||
+ | |||
+ | //enable capture compare interrupt | ||
+ | timer_enable_update_event(TIM1); | ||
+ | |||
+ | timer_enable_irq(TIM1, | ||
+ | nvic_enable_irq(NVIC_TIM1_UP_TIM16_IRQ); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | //ADC ######################################################################################## | ||
+ | |||
+ | static void adc_setup(void) | ||
+ | { | ||
+ | //ADC | ||
+ | rcc_periph_clock_enable(RCC_ADC12); | ||
+ | rcc_periph_clock_enable(RCC_GPIOA); | ||
+ | //ADC | ||
+ | gpio_mode_setup(GPIOA, | ||
+ | gpio_mode_setup(GPIOA, | ||
+ | adc_power_off(ADC1); | ||
+ | adc_set_clk_prescale(ADC1, | ||
+ | adc_set_single_conversion_mode(ADC1); | ||
+ | adc_disable_external_trigger_regular(ADC1); | ||
+ | adc_set_right_aligned(ADC1); | ||
+ | /* We want to read the temperature sensor, so we have to enable it. */ | ||
+ | adc_enable_temperature_sensor(); | ||
+ | adc_set_sample_time_on_all_channels(ADC1, | ||
+ | uint8_t channel_array[] = { 2 }; /* ADC1_IN2 (PA1) */ | ||
+ | adc_set_regular_sequence(ADC1, | ||
+ | adc_set_resolution(ADC1, | ||
+ | adc_power_on(ADC1); | ||
+ | |||
+ | /* Wait for ADC starting up. */ | ||
+ | int i; | ||
+ | for (i = 0; i < 800000; i++) | ||
+ | __asm__(" | ||
+ | } | ||
+ | |||
+ | void tim1_up_tim16_isr(void) { //Timer overflow interrupt, PWM frecuency | ||
+ | // Clear the update interrupt flag | ||
+ | timer_clear_flag(TIM1, | ||
+ | gpio_toggle(GPIOE, | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | |||
+ | static void usart_setup(void) | ||
+ | { | ||
+ | /* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */ | ||
+ | rcc_periph_clock_enable(RCC_USART2); | ||
+ | rcc_periph_clock_enable(RCC_GPIOA); | ||
+ | |||
+ | /* Setup GPIO pin GPIO_USART2_TX/ | ||
+ | gpio_mode_setup(GPIOA, | ||
+ | gpio_set_af(GPIOA, | ||
+ | |||
+ | /* Setup UART parameters. */ | ||
+ | usart_set_baudrate(USART2, | ||
+ | usart_set_databits(USART2, | ||
+ | usart_set_stopbits(USART2, | ||
+ | usart_set_mode(USART2, | ||
+ | usart_set_parity(USART2, | ||
+ | usart_set_flow_control(USART2, | ||
+ | |||
+ | /* Finally enable the USART. */ | ||
+ | usart_enable(USART2); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | //print numbers func. with USART | ||
+ | |||
+ | static void my_usart_print_int(uint32_t usart, int16_t value)// | ||
+ | { | ||
+ | int8_t i; | ||
+ | int8_t nr_digits = 0; | ||
+ | char buffer[25]; | ||
+ | |||
+ | if (value < 0){ | ||
+ | value = value*(-1); | ||
+ | } | ||
+ | if (value == 0) { | ||
+ | usart_send_blocking(usart, | ||
+ | } | ||
+ | |||
+ | while (value > 0) { | ||
+ | buffer[nr_digits++] = " | ||
+ | value /= 10; | ||
+ | } | ||
+ | |||
+ | for (i = nr_digits-1; | ||
+ | usart_send_blocking(usart, | ||
+ | } | ||
+ | |||
+ | usart_send_blocking(usart, | ||
+ | usart_send_blocking(usart, | ||
+ | } | ||
+ | |||
+ | //funcion para esperar tiempos | ||
+ | static void delay(int t){ | ||
+ | for(int i= 0; i< | ||
+ | __asm__(" | ||
+ | } | ||
+ | |||
+ | //funcion que recibe un valor entre -99% y 99% para el valor de referencia | ||
+ | static valor_de_referencia(){ | ||
+ | uint16_t ret=0; | ||
+ | int16_t in_data[4]={0}; | ||
+ | uint8_t i=0; | ||
+ | int new_data=0; | ||
+ | |||
+ | while(i< | ||
+ | |||
+ | switch (new_data){ | ||
+ | case 0: //Si la primera tecla no es - o +, no avanza | ||
+ | in_data[0]=usart_recv_blocking(USART2); | ||
+ | if(in_data[0]== 0x2B || in_data[0]== 0x2D){ | ||
+ | usart_send_blocking(USART2, | ||
+ | i++; | ||
+ | new_data=1; | ||
+ | } | ||
+ | break; | ||
+ | case 1: //Si la segunda tecla no es un numero no avanza | ||
+ | in_data[1]=usart_recv_blocking(USART2); | ||
+ | if(in_data[1]> | ||
+ | usart_send_blocking(USART2, | ||
+ | i++; | ||
+ | new_data=2; | ||
+ | } | ||
+ | break; | ||
+ | case 2://Si la tercer tecla no es un numero no avanza | ||
+ | |||
+ | in_data[2]=usart_recv_blocking(USART2); | ||
+ | if(in_data[2]> | ||
+ | usart_send_blocking(USART2, | ||
+ | i++; | ||
+ | new_data=3; | ||
+ | } | ||
+ | break; | ||
+ | case 3: //Si la cuarta tecla no es un enter no finaliza | ||
+ | in_data[3]=usart_recv_blocking(USART2); | ||
+ | if(in_data[3]==0x0D){ | ||
+ | i++; | ||
+ | } | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | if(in_data[0]==0x2B){ret=100; | ||
+ | ret=ret+(in_data[1]-48)*10+(in_data[2]-48); | ||
+ | |||
+ | //regresa el valor convertido a un int, si es mayor a 100 es positivo, y si es menor a 100 es negativo. +50 = 150; -50 = 050 | ||
+ | return ret; | ||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | double duty; | ||
+ | double kp=0.3; | ||
+ | double Ti=40; | ||
+ | double rango=4096; | ||
+ | double e; | ||
+ | double I=0.0; | ||
+ | double Inew=0.0; | ||
+ | double Iant=0.0; | ||
+ | double control; | ||
+ | double vel; | ||
+ | double P; | ||
+ | int16_t temp; | ||
+ | bool sentido; | ||
+ | int16_t ref;//% del valor deseado, | ||
+ | int cambio_sentido; | ||
+ | |||
+ | system_init(); | ||
+ | tim_init(); | ||
+ | adc_setup(); | ||
+ | usart_setup(); | ||
+ | |||
+ | |||
+ | ref=valor_de_referencia(); | ||
+ | if(ref> | ||
+ | sentido=true;// | ||
+ | ref=ref-100;// | ||
+ | } else { | ||
+ | sentido=false;// | ||
+ | ref=ref*(-1); | ||
+ | } | ||
+ | cambio_sentido=ref; | ||
+ | |||
+ | while (1){ | ||
+ | |||
+ | // | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | if(sentido==true){ | ||
+ | usart_send_blocking(USART2, | ||
+ | } else { | ||
+ | usart_send_blocking(USART2, | ||
+ | } | ||
+ | my_usart_print_int(USART2, | ||
+ | |||
+ | |||
+ | // | ||
+ | // | ||
+ | adc_start_conversion_regular(ADC1); | ||
+ | while (!(adc_eoc(ADC1))); | ||
+ | temp=adc_read_regular(ADC1); | ||
+ | |||
+ | if (gpio_get(GPIOA, | ||
+ | ref=valor_de_referencia(); | ||
+ | if(ref> | ||
+ | sentido=true;// | ||
+ | ref=ref-100; | ||
+ | } else { | ||
+ | sentido=false;// | ||
+ | ref=ref*(-1); | ||
+ | } | ||
+ | |||
+ | if (cambio_sentido*ref< | ||
+ | gpio_clear(GPIOE, | ||
+ | gpio_clear(GPIOE, | ||
+ | delay(5000); | ||
+ | } | ||
+ | cambio_sentido=ref; | ||
+ | } | ||
+ | |||
+ | // | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | my_usart_print_int(USART2, | ||
+ | |||
+ | //Control PI | ||
+ | //Calculo de error normalizado | ||
+ | e=((double)ref/ | ||
+ | |||
+ | usart_send_blocking(USART2, | ||
+ | if (e>0){ | ||
+ | usart_send_blocking(USART2, | ||
+ | } else { | ||
+ | usart_send_blocking(USART2, | ||
+ | } | ||
+ | my_usart_print_int(USART2, | ||
+ | //Control proporcional | ||
+ | P = e*kp; | ||
+ | usart_send_blocking(USART2, | ||
+ | my_usart_print_int(USART2, | ||
+ | |||
+ | //Anti windup | ||
+ | if (control > 1.0){ | ||
+ | control=1.0; | ||
+ | I=Iant; | ||
+ | } | ||
+ | if (control < -1.0){ | ||
+ | control=-1.0; | ||
+ | I=Iant; | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | } else { | ||
+ | duty=control*(-1); | ||
+ | } | ||
+ | |||
+ | // Control Integral | ||
+ | usart_send_blocking(USART2, | ||
+ | my_usart_print_int(USART2, | ||
+ | |||
+ | //Senal de control PI | ||
+ | control = P + I; | ||
+ | usart_send_blocking(USART2, | ||
+ | if (control> | ||
+ | usart_send_blocking(USART2, | ||
+ | } else { | ||
+ | usart_send_blocking(USART2, | ||
+ | } | ||
+ | my_usart_print_int(USART2, | ||
+ | |||
+ | |||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | |||
+ | // | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | if ((control)< | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | // | ||
+ | Iant = I; | ||
+ | Inew = I + (kp/ | ||
+ | | ||
+ | |||
+ | | ||
+ | // | ||
+ | |||
+ | |||
+ | //Se imprime el valor de la velocidad | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | usart_send_blocking(USART2, | ||
+ | my_usart_print_int(USART2, | ||
+ | |||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | * **NOTA:** El código fuente utilizado para la implementación del sistema de control, está diseñado para una alimentación de '' | ||
+ | |||
+ | <code C> | ||
+ | // | ||
+ | e=((double)ref/ | ||
+ | </ | ||
+ | |||
+ | y cambiar el valor '' | ||
[[teaching: | [[teaching: |
teaching/ie0624/proyectos/control_motores_sincronicos/codigo.1545016108.txt.gz · Last modified: 2022/09/20 00:08 (external edit)