Pewaktu otomatis dengan arduino (aplikasi pemberi pakan ikan)

Pewaktu otomatis adalah perangkat bekerja menggunakan real time clock (RTC) sebagai basis waktu dan menghasilkan output aksi tepat pada waktu yang ditentukan.

setting waktu alarm

program ini akan setiap detik menmbandingkan/mencek apakah waktu alarm sama sama dengan waktu saat ini, untuk menentukan waktu alarm dalam contoh ini menggunakan 2 waktu alarm dengan cara mengatur variabel pada bagian ini :


#define waktuMakan1 DateTime(0, 1, 1, 8, 0, 0, 0)//jam 8 pagi
#define waktuMakan2 DateTime(0, 1, 1, 17, 0, 0, 0)//jam 5 sore

kelas date time diisi nilai tahun, bulan, tanggal, jam, menit, detik, hari.
namun untuk pengplikasian di sketch pemberi makanan ikan ini hanya diset bagian jam, menit dan detik dengan tujuan nilai waktu ini berulang setiap hari.

Waktu makan ikan

Pada contoh ini perangkat akan menggerakkan servo pemberi makan ikan pada jam 8 pagi dan jam 5 sore.

skema pemberi makan ikan menggunakan arduino :

 

koding/program feeder ikan berbasis arduino:

#define pinServoMakanan               A0

#define waktuBukaServo                1000//milidetik
#define servoBuka                     20//derajat
#define servoTutup                    60//derajat

#define waktuMakan1                   DateTime(0, 1, 1,  8, 0, 0, 0)//jam 8 pagi
#define waktuMakan2                   DateTime(0, 1, 1, 17, 0, 0, 0)//jam 5 sore

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "Sodaq_DS3231.h"
#include <Servo.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2);//coba juga 0x27
Servo servoMakanIkan;

byte detikSebelumnya;

void setup() {
  Serial.begin(9600);
  Serial.println("Pemberi pakan ikan otomatis");
  Serial.println("https://www.semesin.com/project");
  
  servoMakanIkan.attach(pinServoMakanan);
  servoMakanIkan.write(servoTutup);

  Wire.begin();
  rtc.begin();

  lcd.begin();
  lcd.backlight();

  lcd.print("Pemberi ");
  lcd.setCursor(0, 1);
  lcd.print("pakan ikan");
  delay(3000);
  lcd.clear();

  Serial.println("Sistem mulai");
}

void loop() {

  DateTime now = rtc.now();
  if (detikSebelumnya != now.second())
  {
    char buf[17];
    sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    lcd.setCursor(4, 0);
    lcd.print(buf);

    detikSebelumnya = now.second();

    uint32_t epoch = now.get() % 86400;//hanya jam menit detik

    if ((epoch == waktuMakan1.get()) ||
        (epoch == waktuMakan2.get()))
    {
      char buf[17];
      sprintf(buf, "Pakan = %02d:%02d", now.hour(), now.minute());
      lcd.setCursor(0, 1);
      lcd.print(buf);

      servoMakanIkan.write(servoBuka);
      delay(waktuBukaServo);
      servoMakanIkan.write(servoTutup);

    }
  }
}

 

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("http://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);
    }
  }
}