Главная > Hard > Простой способ управлением сервоприводом SG90

Простой способ управлением сервоприводом SG90

IDE для Arduino предлагает готовую библиотеку Servo для управления сервоприводами. Это хорошее решение, если надо управлять ими в простом проекте. При работе над более сложной задумкой приходится бороться за каждый байт кода и думать над нестандартными решениями.

В предыдущих статьях была описана работа с камерой OV7670 . Данный пример основан на одном из таймеров Arduino Uno, для которого была изменена частота и отключены прерывания. Из-за этого и неудачи при портировании библиотеки Servo в AtmelStudio от готового решения пришлось отказаться.

Ниже будет предложен альтернативный способ управления сервоприводом SG90 без библиотеки Servo.

Сервопривод SG90

Для начала стоит сказать, что сервопривод управляется импульсами определённой длительности и частоты. От длительности зависит угол поворота. 544 мкс — поворот в 0 градусов. 2400 мкс — поворот в 180 градусов. Импульсы для SG90 должны посылаться с частотой 50Гц. Это даёт интервал 20000 мкс между импульсами.

Как работает сервопривод SG90

Вся задача управления сводится к подаче нужного количества импульсов определенной длинны на сервопривод. Из-за невозможности вызвать функцию _delay_us с динамическим значением, приходится разбивать интервал от 544 до 2400 на 18 шагов с величиной 103, чтоб минимальный шаг сервопривода был 10 градусов.

В примере ниже управляющий провод подключается к порту D3 и сервопривод поворачивается от 0 до 180 градусов с шагом 10.

Подключение SG90

#define MIN_PULSE_WIDTH       544 
#define MAX_PULSE_WIDTH      2400
#define ANGLE_PULSE_WIDTH      103
#define PULSE_WIDTH         20000  

#define NUMBER_OF_TIMES 18
#define PORT      0x08 //Digital 3 (D3)
#define DELAY      100000

int main(void) {
  DDRD = PORT; //Set D3 as output
  while(1) {
    int i = 0;
    for (i = 0; i <= 18; i++) {
        angle(i);
    }

  }
}

void angle(int angle) {
    int i = 0;
    int j = 0;
    
    PORTD = 0x00;

    for (i = 0; i < NUMBER_OF_TIMES; i++) {
        PORTD = PORT;

        _delay_us(MIN_PULSE_WIDTH);
        for (j = 0; j < angle; j++) {
            _delay_us(ANGLE_PULSE_WIDTH);
        }

        PORTD = 0x00;

        _delay_us(PULSE_WIDTH - MAX_PULSE_WIDTH);
        int remaining = (MAX_PULSE_WIDTH - MIN_PULSE_WIDTH - angle*ANGLE_PULSE_WIDTH)/ANGLE_PULSE_WIDTH;
        for (j = 0; j < remaining; j++) {
            _delay_us(ANGLE_PULSE_WIDTH);
        }
    }
    _delay_us(DELAY);
}
Categories: Hard Tags: , ,
  1. Пока что нет комментариев.
  1. Пока что нет уведомлений.