Mengatur kecepatan servo dengan arduino

Motor servo dikendalikan oleh lebar sinyal (PWM) yang berbanding lurus dengan posisi tap potensio pada kontrol-nya. Oleh karena itu kecepatan servo bergantung pada perbedaan antara nilai setara dari sinyal PWM dan nilai analog potensio yang ada pada motor servo. Semakin besar perbedaannya maka kecepatannya akan semakin tinggi, begitu juga sebaliknya, jika nilai setara-nya sama maka kecepatan servo = 0.

Untuk mengontrol kecepatan servo, dibutuhkan suatu fungsi yang menggerakkan servo setiap derajat perpindahannya (0..180) dengan penambahan waktu jeda diantaranya.

Skema mengendalikan kecepatan servo:

Dan fungsi pengaturan kecepatan servo dalam contoh sketch:

#include <Servo.h>

#define pinServo A0
Servo myservo;

void setup() {
  Serial.begin(9600);
  Serial.println("Mengatur kecepatan servo");
  Serial.println("https://www.semesin.com/project/");
  Serial.println();

  myservo.attach(pinServo);
  myservo.write(0);
  delay(500);
}

void loop() {
  //servoSpeed(Servo servo, int sudut, uint8_t Speed)
  servoSpeed(myservo, 180, 255);//speed dalam derajat/ms
  servoSpeed(myservo, 0, 200);
  servoSpeed(myservo, 180, 150);
  servoSpeed(myservo, 0, 100);
  servoSpeed(myservo, 180, 50);
  servoSpeed(myservo, 0, 0);//berhenti

  while (1);
}

void servoSpeed(Servo servo, int sudut, uint8_t Speed)
{
  if(Speed == 0)
  {
    return;
  }
  int posisiSekarang = servo.read();
  for (int i = posisiSekarang; i != sudut; (posisiSekarang > sudut) ? i-- : i++)
  {
    servo.write(i);
    if (Speed > 174)
    {
      delayMicroseconds((256 - Speed) * 200);//0.12 detik/60 derajat
    }
    else
    {
      delay((uint16_t)(256 - Speed) * 0.2f);//0.12 detik/60 derajat
    }
  }
  servo.write(sudut);
}

Timbangan beras otomatis dengan arduino

Timbangan beras digital ini merupakan timbangan beras pintar yang akan memberitahukan kapasitas beras tersisa dalam silo/tampungan beras ke apk Android melalui bluetooth sehingga pengguna dapat mengatur ketersiaan stok beras dengan mudah. Disamping itu timbangan beras berbasis arduino ini juga akan mengingatkan pengguna melalui suara apabila beras hampir habis.

Memiliki dua timbangan yaitu timbangan beras di silo dan timbangan beras yang akan dikeluarkan melalui slot beras. Beras yang ingin diambil dapat dipilih melalui panel keypad 1.000gr hingga 10.000 gram. Jika slot beras telah terisi sesuai berat yang diminta perangkat akan mengeluarkan peringatan melalui suara.

album : Galeri timbangan beras arduino android

Mengontrol hingga 8 buah servo (multi servo) menggunakan AVR ATmega32

Menggerakkan servo dengan mikrokontroler AVR/atmega biasanya menggunakan PWM (Timer) namun. Namun pada chip AVR seperti ATmega8 hanya memliki 3 pin OC (output dari comparator) juga ATmega16, 32 memiliki 4 pin OC,  ATmega328 5 pin OC.

Untuk menggerakkan servo lebih banyak (multi servo) dari ketersediaan pin OC, bisa digunakan metode dua timer interrupt, yaitu :

  1. Timer1 berfungsi membangkitkan frekuensi 50Hz (periode 2ms) yang ditetapkan spesifikasi servo umum.
  2. Timer0 berfungsi mengatur lebar pulsa untuk masing-masing servo.

pengaturan

Servo memiliki sensor resistansi (potensio) untuk mendeteksi posisi dari aktuator. Terkadang ada servo yang nilai resistansinya berbeda-beda. untuk itu perlu diatur nilai offset dan tick-nya. berikut ini bebera variabel yang harus diatur sebelum digunakan:

Mengatur servo dengan atmega / AVR menggunakan codevision/Atmel studio harus memperhatikan bilangan pecahan, jadi pastikan hasil perhitungan posisi servo tepat.

#define F_CPU 16000000L

#define jumlahServo 8		//Servo 1 = pin 0, servo 2 = pin 1
#define portServo PORTD

//kalibrasi
#define servoTickOffset 1200
#define servoTickMinimum 0
#define servoTickMaksimum 4000L

berikut listing programnya: (AVR Studio 6.2, ATmega32A)

#define F_CPU 16000000L

#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define jumlahServo 8    //Servo 1 = pin 0, servo 2 = pin 1
#define portServo PORTD

//kalibrasi
#define servoTickOffset 1200
#define servoTickMinimum 0
#define servoTickMaksimum 4000L

volatile uint16_t servo[jumlahServo];
#define servoPortMask 0xFF >> (8-jumlahServo)

ISR(TIMER1_COMPA_vect)
{
  portServo = 0xFF;
  TCCR0 = (1<<WGM01) | (1<<CS00); // CTC, prescale 1, top ocr1a
}

ISR(TIMER0_COMP_vect)
{
  uint8_t nilaiPort = 0x00;
  uint8_t byteNilai;
  for(uint8_t i=0;i<jumlahServo;i++)
  {
    uint16_t tick = servo[i] * (uint8_t)((servoTickMaksimum - servoTickMinimum) / 180);
    if(tick + servoTickOffset < TCNT1)
    {
      byteNilai = 0x00;
    }
    else
    {
      byteNilai = 0x80;
    }
    nilaiPort = byteNilai | (nilaiPort >> 1);
  }
  nilaiPort >>=  (8 - jumlahServo);
  nilaiPort &= servoPortMask;
  portServo = nilaiPort ;
  if(TCNT1 > servoTickOffset + servoTickMaksimum)
  {
    TCCR0 = 0;
  }
}

int main (void)
{
  (*(&portServo - 1)) = 0xFF; //port sebagai output
  
  OCR0 = 88 - 1;
  TIMSK = (1<<OCIE0);

  TCCR1A = 0;
  TCCR1B = (1<<WGM12) | (1<<CS11);  // CTC, prescale 8, top ocr1a
  OCR1A = 20000 - 1;//50Hz 
  TIMSK |= (1<<OCIE1A);
  sei();

  while(1)
  {
    for(uint8_t i=0;i<180;i++)
    {
      servo[7] = i;
      _delay_ms(10);
    }

    for(uint8_t i=180;i != 0;i--)
    {
      servo[7] = i;
      _delay_ms(10);
    }
  }
}