Просмотров: 61532

Энкодер из шагового

Закрыть ... [X]

Данный топик является развернутым ответом на вопрос, поднятый в этой теме: Увеличить разрешение энкодера из HDD. Единственным HDD со съемным двигателем в моем хламе оказался SCSI Seagate емкостью 73GB 2004 года выпуска. Вот такой:

За основу решил взять схему из этой статьи: Валкодер из двигателя. Схема была немного переработана с учетом обработки трех фаз, гистерезис усилителей уменьшен в связи скромным выходным напряжением двигателя. Мой экземпляр даже на высоких оборотах выдавал не более 1 вольта, на оборотах, приближенных к реальности получалось 10-30 мВ (скорее всего связано с его высокооборотистостью). Дополнительное осложнение в моем случае заключалось в том, что у него не было отвода от середины обмоток, я решил сделать искусственный отвод резисторным делителем, правда, было сомнение на этот счет. Окончательный вариант схемы выглядит так:


Оставалось это к чему-нибудь подключить и немножко покодить. Под руку попалась STM8S-Discovery. Для начала я снял таблицу состояний, так выглядят два полных цикла:
Число Ф1 Ф2 Ф3
0x01 0 0 1
0x05 1 0 1
0x04 1 0 0
0x06 1 1 0
0x02 0 1 0
0x03 0 1 1
0x01 0 0 1
0x05 1 0 1
0x04 1 0 0
0x06 1 1 0
0x02 0 1 0
0x03 0 1 1
0x01 0 0 1
Код, обрабатывающий изменение в каждой из фаз выглядит незатейливо:
inline uint8_t GetValue() { return (GpioD::Read() >> 2U) & 0x07; } int main() { SysClock::Select(SysClock::HSE); GpioA::WriteConfig<0xFF, GpioBase::In_Pullup>(); GpioB::WriteConfig<0xFF, GpioBase::In_Pullup>(); GpioC::WriteConfig<0xFF, GpioBase::In_Pullup>(); GpioD::WriteConfig<0xFF, GpioBase::In_Pullup>(); //Encoder connected to PD2, PD3, PD4 GpioD::SetConfig<P2 | P3 | P4, GpioBase::In_float>(); Uart::Init<Uarts::DefaultCfg, 921600UL>(); __enable_interrupt(); uint8_t ch = GetValue(); uint8_t value = 0; int16_t encoder; while (true) { value = GetValue(); if(ch != value) { switch(ch) { case 1:{ if(value == 5) ++encoder; if(value == 3) --encoder; } break; case 5:{ if(value == 4) ++encoder; if(value == 1) --encoder; } break; case 4:{ if(value == 6) ++encoder; if(value == 5) --encoder; } break; case 6:{ if(value == 2) ++encoder; if(value == 4) --encoder; } break; case 2:{ if(value == 3) ++encoder; if(value == 6) --encoder; } break; case 3:{ if(value == 1) ++encoder; if(value == 2) --encoder; } break; default: ; } ch = value; Uart::Puts("\r \r"); Uart::Puts(encoder); // Get state table // Uart::Puts(ch, 16); // Uart::Puts("\t"); // Uart::Puts((ch >> 2U) & 0x01, 2); Uart::Puts("\t"); // Uart::Puts((ch >> 1U) & 0x01, 2); Uart::Puts("\t"); // Uart::Puts(ch & 0x01, 2); Uart::Puts("\r\n"); } } }
Итоговое разрешение такого энкодера — 18 шагов на оборот, чего хватит для большинства применений. Эксперимент считаю успешным. Энкодер в работе:
На этом все, спасибо за внимание.
P.S.: На PCB в аттаче есть перемычка под микросхемой.


Источник: http://we.easyelectronics.ru/Shematech/enkoder-iz-bldc.html

Похожие новости


Для прав своими руками из кожи
Как сделать мостик из веревки
Грядки в саду своими руками фото
Как сделать манжеты на детской куртке
Комод из дерева своими руками чертежи




ШОКИРУЮЩИЕ НОВОСТИ