/* * USB rotor card * * Created: 30.05.2022 * Update: 11.06.2022 00:34:00 * Author : R5CA * Support only GS232B 450deg */ #include #include #include #include #include #include #include #include #include #define BAUD 9600 #define MYUBRR F_CPU/16/BAUD-1 volatile uint8_t uartRXBuf[16]; // Буфер для данных принятых по UART volatile uint8_t uartRXBufNum = 0; // Кол-во принятых байт по UART volatile uint8_t uartRXC = 0; // Флаг окончания приема данных по UART #define ROTOR_DDR DDRD #define ROTOR_PORT PORTD #define ROTOR_CW PD5 #define ROTOR_CCW PD6 #define ROTOR_AZ_IN 0 // Канал АЦП измерения азимута #define ROTOR_SPEED_DDR DDRB // DDR регулировки скорости #define ROTOR_SPEED_PORT PORTB // Порт регулировки скорости #define ROTOR_SPEED_PINNUM PB3 // Номер пина регулировки скорости(обязательно OC2A) #define STOP 0 #define SLOW_START 1 #define ROTARY 2 #define SLOW_DOWN 3 #define SLOW_DOWN_AZ 20 // Расстояние начала плавной остановки uint16_t EEMEM EEPcal0 = 0; // EEProm значение калибровки 0 градусов uint16_t EEMEM EEPcal90 = 0; // EEProm значение калибровки 90 градусов uint16_t EEMEM EEPcal180 = 0; // EEProm значение калибровки 180 градусов uint16_t EEMEM EEPcal270 = 0; // EEProm значение калибровки 270 градусов uint16_t EEMEM EEPcal360 = 0; // EEProm значение калибровки 360 градусов uint16_t EEMEM EEPcal450 = 0; // EEProm значение калибровки 450 градусов uint8_t EEMEM EEPspeed = 128; // EEProm скорость вращения uint16_t cal0 = 0; // Значение калибровки 0 градусов uint16_t cal90 = 0; // Значение калибровки 90 градусов uint16_t cal180 = 0; // Значение калибровки 180 градусов uint16_t cal270 = 0; // Значение калибровки 270 градусов uint16_t cal360 = 0; // Значение калибровки 360 градусов uint16_t cal450 = 0; // Значение калибровки 450 градусов uint8_t rot_cw = 0; // Вращение по часовой uint8_t rot_ccw = 0; // Вращение против часовой volatile uint8_t timer = 0; // Переменная таймера задержки плавного старта/остановки volatile uint16_t timer2 = 0; // Переменная таймера void uartbuf_zero(void) // Обнуление буфера UART { for(uint8_t i=0; i<16; i++) // Обнуление буфера UART { uartRXBuf[i] = 0x00; // Обнуление буфера UART } } void usart_init(unsigned int ubrr) // Инициализация USART { UBRR0H = (unsigned char) (ubrr >> 8); // Установка скорости UBRR0L = (unsigned char) ubrr; // Установка скорости UCSR0B = (1<= cal450) // Если считанное значение АЦП больше 450-ой калибровки { return 450; // То возвращаем 450 } else if(az_raw_data > 0 && az_raw_data < 90) // Если приблизительный азимут от 0 до 90 градусов { az_raw_data = lround((adc_val - cal0)*90.0/(cal90-cal0)); // То делаем уточненный расчет по части шкалы в 90 градусов(0-90) с использованием дополнительных калибровок return az_raw_data; // Возвращаем значчение азимута } else if(az_raw_data >= 90 && az_raw_data < 180) // Если приблизительный азимут от 90 до 180 градусов { az_raw_data = lround(90.0+((adc_val - cal90)*90.0/(cal180-cal90))); // То делаем уточненный расчет по части шкалы в 90 градусов(90-180) с использованием дополнительных калибровок return az_raw_data; // Возвращаем значчение азимута } else if(az_raw_data >= 180 && az_raw_data < 270) // Если приблизительный азимут от 180 до 270 градусов { az_raw_data = lround(180.0+((adc_val - cal180)*90.0/(cal270-cal180))); // То делаем уточненный расчет по части шкалы в 90 градусов(180-270) с использованием дополнительных калибровок return az_raw_data; // Возвращаем значчение азимута } else if(az_raw_data >= 270 && az_raw_data < 360) // Если приблизительный азимут от 270 до 360 градусов { az_raw_data = lround(270.0+((adc_val - cal270)*90.0/(cal360-cal270))); // То делаем уточненный расчет по части шкалы в 90 градусов(270-360) с использованием дополнительных калибровок return az_raw_data; // Возвращаем значчение азимута } else if(az_raw_data >= 360 && az_raw_data <= 450) // Если приблизительный азимут от 360 до 450 градусов { az_raw_data = lround(360.0+((adc_val - cal360)*90.0/(cal450-cal360))); // То делаем уточненный расчет по части шкалы в 90 градусов(360-450) с использованием дополнительных калибровок return az_raw_data; // Возвращаем значчение азимута } else { return az_raw_data; } } void set_az(uint16_t az_r, uint16_t az_n) // Расчет кратчайшего пути для поворота антенны { int16_t cw; // Переменная для длины пути по часовой стрелке int16_t ccw; // Переменная для длины пути против часовой стрелки ccw = az_r - az_n; // Расчет пути против часовой стрелки if(ccw < 0) // Расчет пути против часовой стрелки { ccw += 360; // Расчет пути против часовой стрелки } cw = az_n - az_r; // Расчет пути по часовой стрелке if(cw < 0) // Расчет пути по часовой стрелке { cw += 360; // Расчет пути по часовой стрелке } if(cw < ccw) // Если по часовой короче, чем против { if(cw + az_r <= 450) // и получившийся азимут не выходит за возможности редуктора { rot_cw = 1; // То вращаем по часовой стрелке } else // Иначе { rot_ccw = 1; // против часовой стрелки } } else // Если против часовой короче, чем по { if((int16_t)az_r - (int16_t)ccw > 0) // и получившийся азимут не выходит за возможности редуктора { rot_ccw = 1; // То вращаем против часовой } else // Иначе { rot_cw = 1; // По часовой } } } void pwm_init(void) // Инициализация ШИМ { TCCR2A |= (1< 0) { timer2--; } } void timer0_stop(void) // Остановка таймера 0 { TCCR0B &= ~(1< 20) // Текущая скорость меньше максимальной и таймер дотикал до переключения { step_val += 16; // чуть добавляем скорость OCR2A = step_val; // чуть добавляем скорость timer = 0; // обнуляем таймер } if(step_val == speed) // Если достигли максимальной скорости { rot_stat = ROTARY; // Меняем статус } } if((rot_stat == SLOW_START || rot_stat == ROTARY) && ((rot_ccw == 1 && ((raw_az - new_az) < SLOW_DOWN_AZ)) || (rot_cw == 1 && ((new_az - raw_az) < SLOW_DOWN_AZ))) && manual == 0) // Разница между текущим и заданным азимутом меньше, чем задана для плавной остановки { rot_stat = SLOW_DOWN; // Меняем статус } if(rot_stat == SLOW_DOWN) // Плавная остановка { if(step_val > 31 && timer > 15) // Если значение скорости больше минимальной и таймер дотикал до переключения { OCR2A = step_val; // Чуть уменьшаем скорость step_val -= 16; // Чуть уменьшаем скорость timer = 0; // обнуляем таймер } if(step_val <= 31 && need_stop == 1) { ROTOR_PORT &= ~((1<