Translate

понедельник, 16 апреля 2018 г.

Измерение скорости вращение двигателя жёсткого диска на Ардуино

Feci quod potui, faciant meliora potentes. (Латинская пословица)


Я обещал продолжить копать свой двигатель, и я-таки продолжил. Ну и натерпелся я с ним. Сказать по правде, он мне уже порядком поднадоел, в первую очередь из-за косяков с макетной платой, на которой, как выяснилось, ничего более-менее сложное лучше не собирать. Это потому что контакты здесь хлипкие, и когда начинает отходить один из нескольких десятков проводов, то найти его очень проблематично. В общем, очень капризная конструкция получилась. Ну, сделал и сделал. Сделал, что смог, кто может, пусть делает лучше. ☺ Надо рассказать, что получилось.

Когда разумный предел числа проводов на макетке пройден

Принцип работы.


Основу я оставил старую, так что начало проекта можно посмотреть вот здесь:

А вот что добавил. Во-первых нужен датчик для измерения скорости. Датчик я собрал сам из двух диодов. Взял обычный белый светодиод и фотодиод. Сначала думал сделать проще: наклеил на вращающуюся часть своего двигателя кусок чёрной изоленты и направил оба диода в одну точку. Двигатель серебристый, свет отражается - падает от светодиода на фотодиод - его сопротивление тоже падает, а когда мимо них проносится изолента - сопротивление возрастает. Но как-то не понравился мне этот способ, отражённый свет не открывал фотодиод полностью, и я решил сделать диск с прорезью.
Такой вот суперколхозный сенсор. 
Осциллограмма сигнала с фотодиода
А вот уже после добавления транзистора что вышло.
Главное взять что-то твёрдое и не просвечивающее, у меня это кусок коробки из-под конфет. Диоды я примотал так, чтобы они смотрели друг на друга и между ними вращался диск. Получилась исключительно колхозная конструкция, но она работает. В момент пролёта вырезанного края между диодами напряжение на фотодиоде проседает. Проверить это лучше всего сначала мультиметром, а потом осциллографом. Без своего нового карманного осциллографа я не представляю, как бы всё это настроил. О нём я планирую отдельный пост. Как вы можете видеть на первой осциллограмме, с фотодиода мы получаем пилу с амплитудой примерно 2,5 вольта. В общем, сигнал близок к синусу, и его амплитуды у меня было не достаточно, чтобы срабатывали прерывания. Я решил это дело исправить и добавил транзистор, чтобы усилить сигнал. Поставил транзистор С945, он нормально подходит под параметры схемы. Получилось уже что-то более похожее на прямоугольный импульс, а главное - амплитуда возросла до нужных 5 вольт. Хотя тоже не очень, ещё и побочные какие-то шумы возникли. Их я решил отфильтровать ёмкостями. Поставил два конденсатора: по делителю напряжения датчика и по коллектору транзистора. Стало значительно ровнее, шум частично ушёл. Вот такой сигнал уже можно принимать. На второй осциллограмме видно, что осциллограф пишет частоту 43 герца, это слишком много для реального количества оборотов в секунду. Дело в том, что промежуточные пики тоже подсчитываются. Емкостями удалось почти избавиться от них, хотя на стадии разгона они не ушли.
Вот так получилось после добавления фильтрующих конденсаторов.
Другое дело, побочку совсем не вылечил, но считает уже нормально.
Но здесь возникли новые проблемы. двигатель (или алгоритм у меня такой) оказался очень капризный - чуть что, и останавливается - сбивается ШИМ. Я подключил для вывода числа оборотов свой LCD дисплей. Как его подключать можно посмотреть в предыдущем посте:

Так вот, даже обращение к дисплею начинало сбивать ШИМ. Особенно капризен двигатель оказался во время разгона. В результате я решил убрать подсчёт числа оборотов при разгоне вообще. Максимальную скорость тоже пришлось сократить с 1350 миллисекунд между импульсами до 1500, иначе двигатель срывался. Получившаяся скорость составила примерно 1400 оборотов в минуту. И я хотел, конечно, тоже вывести такую строчку на дисплей, что мол столько-то "O6OPOTOB/C", но лишняя строчка кода сбивала модуляцию ещё сильнее, так что я отказался от этой затеи. Ещё одна проблема - ток потребления вышел в районе 1 ампера. USB, к сожалению, с такой нагрузкой справиться не мог, да и напряжение я решил повысить до 5,8 вольт, тогда всё работало куда более стабильно. Благо, что я сделал лабораторник для таких целей, и он мне здорово помог. Но для дисплея я решил поставить стабилизатор L7805, потому что он на такое напряжение уже не рассчитан, ну и крутануть напругу на БП у меня можно вольт до 18 - Ардуинка выдержит, а дисплей жалко, решил подстраховаться. Ещё при запуске двигателя на нём начинала дрожать подсветка. Ток-то потребления большой. Так что я поставил пару конденсаторов на 1000 микрофарад - дрожание поуменьшилось. Надо бы их в сам блок поставить в перспективе.

Схема проекта (без LCD)



 Результаты и критика


Я выкладываю все свои результаты, как они есть. Скорее для того, чтоб потом самому вспомнить в случае чего. Проект получился ну ооооочень сырой. Но сил моих с ним возиться дальше больше нету. Потому что, во-первых, я пока не представляю, куда можно этот диск прикрутить даже в моём роботе (да-да, к нему я всё ещё хочу вернуться). Во-вторых, тут всё на коленке собрано, без конца разваливается и дальше надо собирать уже более основательно, а я не представляю, во что это хочу развить.

Обороты программа подсчитывает, но как-то очень нестабильно, то их 24, то вдруг уже 30. Предполагаю, что тут надо два МК - один полноценно отвечает за разгон двигателя, второй - выводит с информацией и, вероятно, обрабатывает входящие запросы от пользователя. Я хотел ещё написать возможность регулировать обороты. Но на Ардуино Nano остался последний порт D2, к которому можно подключить прерывания, а одной кнопкой тут особо не науправляешь, особенно, когда каждая микросекунда важна для стабилизации двигателя. В общем, всё получилось как-то на соплях и не до конца. Может, я с этим ещё что-то в перспективе захочу продолжить, но пока что я этот проект закрываю. Прошивку выкладываю, вдруг кому-то что-то пригодится. Всем удачи!

Текст прошивки


// Программа запускает двигатель жёсткого диска и измеряет количество оборотов
#define P 9100 // Начальная задержка для разгона двигателя
#define x 9    // Номер пина к обмотке x
#define y 10   // Номер пина к обмотке y
#define z 11   // Номер пина к обмотке z
unsigned int p;  // Переменная задержки для разгона
long time_pass;  // Таймер
long second; // Переменная для измерения секунды
byte i = 0;  // Счётчик цикла управления фазами двигателя
volatile long Q; 
// Счётчик количества оборотов
#include <LiquidCrystal.h>
LiquidCrystal lcd(13, 12, 4, 5, 6, 7);// Подключили дисплей
void setup()
{
  p = P;// Присваиваем начальное значение задержки для разгона

Serial.begin(9600); // Открываем COM порт для дебага
pinMode(x, OUTPUT); // Установили пины, работающие с двигателем на вывод данных
pinMode(y, OUTPUT);
pinMode(z, OUTPUT);
pinMode(3, INPUT); // Устанавливаем D3 на ввод данных - на него будем подавать синусоиду от датчика вращения
digitalWrite(x, LOW); // Установили начальную фазу двигателя, можно начать с любой из 6 фаз
digitalWrite(y, HIGH);
digitalWrite(z, LOW);
digitalWrite(3, HIGH);// Установили +5V на D3 - туда подключен коллектор транзистора, ему нужны эти 5 вольт
time_pass = micros(); // Обнуление таймера
lcd.begin(16, 2); // Установили режим дисплея
lcd.print ("HA6OP O6OPOTOB"); //Ага, вот такие русские буквы :)
}
void loop()
{
    if ((i < 7) && (micros() - time_pass >= p))    // Если счётчик имеет номер от 0 до 6, и время ожидания смены фазы прошло
      {
       time_pass = micros();   // Обнуляем таймер
     if (i == 0)  { digitalWrite(z, HIGH); }      // Устанавливаем 0 или 1 в зависимости от номера фазы на нужном пине
       if (i == 2)  { digitalWrite(y, LOW);  }
       if (i == 3)  { digitalWrite(x, HIGH); }
       if (i == 4)  { digitalWrite(z, LOW);  }
       if (i == 5)  { digitalWrite(y, HIGH); }
       if (i == 6)  { digitalWrite(x, LOW);  }
   
        i++;    // Плюсуем счётчик фазы
      }
     if (i >= 7) // Если счётчик переполнен
      {
        i = 0;    // Обнуляем счётчик
        if (p > 1500) {p = p - 50;} // Если двигатель ещё не вошёл в максимальную скорость - сокращаем время смены фазы. Рекомендации: если двигатель глохнет - увеличить число 1500 или попробовать уменьшить скорость разгона - отнимать от p не по 50, а по 20 или 10.
     else // Когда разгонка двигателя закончилась
        {
         attachInterrupt(1, calc, RISING); // Настроили прерывание, когда сигнал растёт с 0 на 1 - вызываем функцию calc, 1 - это D3 по прерыванию на Arduino Nano; 0 - D2.
         if ((millis() - second) >= 1000) // Если секунда прошла
          {
            second = millis(); // обнулили таймер
            lcd.clear(); // Очистили дисплей
            lcd.print(Q); // Написали число оборотов. Думаете, я поленился дописать "O6OPOTOB/C"? Нет, у меня из-за лишней строчки слетал ШИМ и двигатель останавливался...
            Q = 0;
          }
        }
      }
   
   
}
void calc () // Вот такая мощная функция подсчёта числа оборотов
{
  Q++;
 

}


Комментариев нет:

Отправить комментарий