Привет читателям и писателям Датагор.ру! Попала мне в руки такая вот красивая новогодняя игрушка. Внутри три светодиода, над ними вращается прозрачный шар из пластика. Конструкция формирует линзы, которые проецируют красоту во все стороны. Шар медленно крутится, разноцветные узоры бегают по стенам и потолку.
Всё бы ничего, но вот моторчик почти сразу начал достаточно громко и противно шуметь щётками. Такой маленький, и такая зараза! Мне ничего не оставалось, как решить проблему самым радикальным образом: избавиться от щеток совсем. С моим гигантским запасом шаговых двигателей сделать это казалось не сложно ?
Содержание статьи / Table Of Contents
↑ Схема первая
Выбираю подходящий шаговик под 5V питание, собираю простейшую схему на тиньке Attiny2313A и ULN2003:Рис.2 Схема первого макета
Код пишем в Mikropascal. Программа просто переключает выходы поочередно в нужном для шаговика порядке, таким образом моторчик работает в режиме полушага.
program stepper;
Var
counter: byte;
Const
states: array [0..7] of byte = (%00010000,
%01010000,
%01000000,
%01100000,
%00100000,
%10100000,
%10000000,
%10010000);
begin
//config
DDRB:=%11110000;
{ Main program }
While true do
begin
inc (counter);
if (counter>7) then counter:=0;
portB:= states[counter];
delay_ms (50);
end;
end.
↑ Первый запуск с шаром, первые проблемы
Собираем макет, напыживаем шар на вал и испытываем.Вот те раз! Шаговик в полном соответствии со своей шаговой природой … шагает! Крутится тоесть, но рывками, неравномерно. Да ещё издает характерные стучащие звуки, подпрыгивая на столе. Гораздо тише, чем было, но всё же… К сожалению видео слабо передало эффект.
Ок, звуки можно побороть, прикрепив мотор через пористую резину, но что делать с неравномерным вращением? Ведь и бегающие проекции точно так же дергаются, не очень-то это красиво.
↑ Решение
Решение пришло само собой, когда я вспомнил о своей предыдущей статье про шаговики: «Как покрутить шаговый двигатель с помощью аудиоусилителя».Смысл такой: если крутить моторчик двумя синусоидами, он вращается гораздо равномернее, и практически бесшумно!
В чистом виде такое решение едва ли будет применимо, но вот сделать синусоиду ШИМом можно, и для этого даже не понадобится более мощный микроконтроллер. У Attiny2313A есть четыре канала ШИМ, что как раз нам подходит.
Как мы помним, шаговый двигатель имеет сдвоенные обмотки. В паре две полуобмотки намотаны в разные стороны, благодаря чему одна электрическая полярность дает два возможных направления магнитного поля. Задача сформулирована: одну полуволну синусоиды надо выдать в одну полуобмотку, вторую полуволну — в парную ей полуобмотку. Для двух оставшихся полуобмоток делается то же самое, но со сдвигом фазы на 90 градусов.
↑ Расчёт синуса
Я не стал заморачиваться с вычислением значений синуса в микроконтроллере и просто подготовил их заранее в Excel.Поскольку используется восьмибитный ШИМ, для каждого шага значение синуса (оно не может быть больше единицы) нужно умножить на 255, чтобы получить итоговые значения от 0 до 255
Получился такой ряд цифр:
↑ Новый код
В программе просто сваливаем их в массив, и потом обращаемся по номеру элемента массива — к первому, ко второму, к третьему и т. д. Цифры поочередно поступают в регистры сравнения таймеров, задавая желаемую скважность на выходе.Получился такой код:
program stepper;
Var
counter: byte;
counter_shift: byte;
Const
sinus: array [0..179] of byte = (0,9,18,27,35,44,53,62,70,79,87,96,104,112,120,128,
135,143,150,157,164,171,177,183,190,195,201,206,211,
216,221,225,229,233,236,240,243,245,247,249,251,253,
254,254,255,255,255,254,254,253,251,249,247,245,243,
240,236,233,229,225,221,216,211,206,201,195,190,183,
177,171,164,157,150,143,135,128,120,112,104,96,87,79,
70,62,53,44,35,27,18,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
begin
//конфиг портов
DDRB:=%00011100;
DDRD:=%00100000;
//конфиг таймерa 0
//TCCR0A:=%10100011; //оба выхода включены, выбран быстрый ШИМ
//TCCR0B:=%00000010; //делитель 8
TCCR0A:=%10100011; //оба выхода включены, выбран медленный ШИМ
TCCR0B:=%00000001; //делитель 1
//конфиг таймерa 1
//TCCR1A:=%10100001; //оба выхода включены, выбран быстрый ШИМ 8 бит
//TCCR1B:=%00001010; //делитель 8
TCCR1A:=%10100001; //оба выхода включены, выбран медленный ШИМ 8 бит
TCCR1B:=%00000001; //делитель 1
counter:=0;
counter_shift:=45;
{ Main program }
While true do
begin
inc (counter);
if (counter>179) then begin counter:=0; counter_shift:=45 end;
inc (counter_shift);
if (counter_shift>179) then counter_shift:=0;
OCR0A:= sinus[counter];
OCR0B:= sinus[179-counter];
OCR1AL:= sinus[counter_shift];
OCR1BL:= sinus[179-counter_shift];
delay_us (1000);
end;
end.
↑ Схема вторая
Макет придется немного поправить. Когда мы просто выводили нули и единицы, можно было использовать любые GPIO ноги, но аппаратный ШИМ привязан к конкретным четырем ногам:Собираем, запускаем… О чудо, работает, даже как бы и неплохо, но тоненько свистит в такт шагам.
Уменьшаем предделитель таймера с 8 до 1, но сам таймер переставляем режим фазо-корректного ШИМ, он в два раза медленнее «быстрого» ШИМ. Итоговая частота получилась около 16 кГц, что уже не слышно.
Включаем… Писк пропал! Тишина просто пугающая! Крутится плавно!
Осталось всё собрать, чтобы выглядело не хуже, чем было.
↑ Итоги тестирования, правки, выводы
Тестовая эксплуатация показала, что нужна некоторая доработка. Маленькая китайская платка 5В питания от пульсирующей нагрузки сходила с ума, пришлось сгладить потребление с помощью четырех конденсаторов по 1500 μF 6.3V из материнок.Что ещё хуже, плавное вращение оказалось неустойчивым. Может несколько минут крутиться плавно, потом, начинает дергаться, потом опять вращаться плавно… Кроме того, были проблемы с запуском. При старте раскачка начиналась обязательно, и её приходилось успокаивать пальцем.
Для начала я решил приделать плавный старт, хотя это и было неудобно, ведь оба таймера заняты ШИМом. Это не помогло, всё стало хуже. Очевидно, что дело не в программе, а в физических основах работы устройства.
Проанализируем:
1) Каждое устойчивое положение мотора не фиксируется жестко, оно обладает определенной упругостью.
2) Шар это достаточно массивный кусок пластика, обладающий моментом инерции
3) Упругость и масса образуют колебательную систему!
4) Мы сами её раскачиваем пинками (хотя и сглаженными) через повторяющиеся промежутки времени!
В итоге оказалось достаточно в приведенном выше коде изменить период следования тактов.
Вместо delay_us (1000); делаем delay_us (1150);
Резонанс сбивается, и всё начинает работать как запланировано. Старт тоже становится уверенным, и любая внесенная извне раскачка моментально угасает.
Хочу заметить, что если вы решите сделать что-то подобное, эти конкретные цифры периода, вероятно, не подойдут под ваш моторчик и под ваш вращающийся объект. Их придётся подбирать самому.
Теперь всё прекрасно работает, всем спасибо за внимание!
↑ Файлы
🎁stepper.7z 63.43 Kb ⇣ 9 В архиве проект в Proteus 8, проект-исходник в mikroPascal, готовый stepper.hex, файл синус.xlsx.↑ Фьюзы
Воспользуемся онлайн калькулятором фьюзов. Выбираем нашу тиньку. Больше ничего не трогаем, снимаем только галку на Divide clock by 8 internally; [CKDIV8=0]. Жмем внизу «apply feature settings».Нужные фьюзы программа выдаст ниже в виде галок и в виде 16-ричных значений. В нашем случае поменяется только одна галка — CKDIV.
↑ Дополнение о моторах
Родной мотор во точно такой:Редуктора не слышно, он демпферной смазкой залит по уши. А вот сам моторчик противно скрежещет.
Если не торопиться, на его место можно воткнуть такой:
Он тоже шаговый, но с редуктором, поэтому ему все эти приколы с резонансами пофиг. Наверняка очень тихий.
Камрад, рассмотри датагорские рекомендации
🌼 Полезные и проверенные железяки, можно брать
Опробовано в лаборатории редакции или читателями.