ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 ноября
266831 Топик полностью
Cepгeй Бopщ (12.08.2011 11:38 - 12:25, просмотров: 78) ответил ut1wpr на Сергей, вы совершенно правы. Эдак я действительно его раскручу. До меня только сейчас дошло, что это не трехфазный мотор, нужно для ротора создать определенную энергетику полей, а это уже амплитудные составляющие, а не фазовые. А можно кусочком
Примерно так: Синус табличный, 8-битные знаковые целые, используется еще и для формирования трех фаз 400Гц, поэтому количество точек кратно трем: class sinus { public: typedef int8_t result_t; typedef uint16_t phase_t; // [0.. 2 * M_PI) - phase typedef uint16_t index_t; // [0.. PERIOD / 128 * 2) - table index static phase_t const PERIOD = 170 * 3 * 128U; // 170 = 510 / 3 static result_t value(phase_t phase); static index_t index(phase_t phase); static result_t value_by_index (phase_t phase); private: static result_t PROGMEM const Envelope[PERIOD / 128 * 2]; }; #if defined(__AVR__) INLINE sinus::result_t sinus::value(phase_t phase) { return pgm_read_byte(&Envelope[index(phase)]); } INLINE sinus::result_t sinus::value_by_index(index_t index) { return pgm_read_byte(&Envelope[index]); } #else INLINE sinus::result_t sinus::value(phase_t phase) { return Envelope[index(phase)]; } INLINE sinus::result_t sinus::value_by_index(index_t index) { return Envelope[index]; } #endif INLINE sinus::index_t sinus::index(phase_t phase) { return phase >> 7; }Массив огибающей содержит две копии синуса чтобы не думать о выходе индекса за пределы массива при вычислении сдвинутого по фазе синуса. Вычисление амплитуд: inline void synchro_driver::set_angle(angle_t angle) { sinus::index_t Angle_idx = sinus::index(angle); Amplitude[PHASE_A] = sinus::value_by_index(Angle_idx + sinus::index(sinus::PERIOD / 3 * 0)); Amplitude[PHASE_B] = sinus::value_by_index(Angle_idx + sinus::index(sinus::PERIOD / 3 * 1)); Amplitude[PHASE_C] = sinus::value_by_index(Angle_idx + sinus::index(sinus::PERIOD / 3 * 2)); } Вычисление значений ШИМ: inline void synchro_driver::drive(sinus::result_t excitation_sample) { Output[PHASE_A] = 0x80 - uint16_t(excitation_sample * Amplitude[PHASE_A]) / 128; Output[PHASE_B] = 0x80 - uint16_t(excitation_sample * Amplitude[PHASE_B]) / 128; Output[PHASE_C] = 0x80 - uint16_t(excitation_sample * Amplitude[PHASE_C]) / 128; } inline output_t synchro_driver::output(output_no_t output_no) { return Output[output_no]; } вычисление фазы и огибающей для обмотки возбуждения: inline void excitation::drive() { phase_t Phase_tmp = Phase; if(Phase_tmp < STEP) Phase_tmp += PERIOD; Phase_tmp -= STEP; Phase = Phase_tmp; } inline sinus::result_t excitation::sample() { return sinus::value(Phase); } Собственно обработчик прерывания: ISR(TIMER0_OVF_vect) { PHASE_A_OCR = Needle[0].output(synchro_driver::PHASE_A); PHASE_B_OCR = Needle[0].output(synchro_driver::PHASE_B); PHASE_C_OCR = Needle[0].output(synchro_driver::PHASE_C); Excitation.drive(); sinus::result_t Exc_sample = Excitation.sample(); PHASE_E_OCR = 0x80 + Exc_sample; PHASE_F_OCR = 0x80 - Exc_sample; // Bridge connection Needle[0].drive(Exc_sample); } Выходы ШИМ раскачиваются L293D или полумостами IR2104+IR7103, их питание 24-30в. На авиационных указателях получаю точность установки стрелки порядка градуса. Будут вопросы - стучитась в почту (указана в профиле).