Antar muka (interface) kalibrasi sensor PH melalui serial monitor Arduino

Sensor PH adalah instrumen untuk mengukur konsentrasi hidrogen dalam sebuah larutan. Baik sensor pH untuk air maupun untuk tanah perlu dikalibrasi berkala agar ke-akuratannya terjamin.

Untuk menjamin keakuratan sensor ph, diperlukan bahan buffer solution dengan pH diketahui dan akurat. buffer solution yang digunakan umumnya adalah dengan pH 4.0 dan pH 7.0.

Beberapa produsen sensor pH juga menyertakan instrumen untuk melakukan kalibrasi secara manual. Namun jika dihubungkan dengan arduino maka, arduino (instrumen baca) juga perlu dikalibrasi. Dalam atikel ini disertakan program interface kalibrasi sensor pH melalui serial monitor, yang merupakan pengembangan dari library sensor pH yang ada. Hasil kalibrasi akan tersimpan dalam EEPROM untuk digunakan dalam pengukuran normal.

Skema mengkalibrasi sensor pH dengan arduino:

Sktech program pengkalibrasian sensor ph pada arduino :

#define pinPH               A1
#define suhuPengukuran      25

#include "DFRobot_PH.h"

DFRobot_PH ph;

float voltagePH;
float phValue;

long millisBacaSensor;

void setup()
{
  Serial.begin(9600);
  Serial.println("Kalibrasi sensor PH melalui serial monitor");
  Serial.println("Buka serial monitor dan kirim (send) sebarang karakter");
  Serial.println("https://www.project.semesin.com");
  Serial.println();

  ph.begin();
}

void loop()
{
  if (millisBacaSensor < millis())
  {
    millisBacaSensor = millis() + 3000;

    voltagePH = analogRead(pinPH) / 1024.0 * 5000;          // read the ph voltage
    phValue    = ph.readPH(voltagePH, suhuPengukuran);      // convert voltage to pH with temperature compensation

    byte PH = round(phValue);

    Serial.println();
    Serial.print("voltagePH = ");
    Serial.println(voltagePH);
    Serial.print("phValue = ");
    Serial.println(phValue);
    Serial.print("PH = ");
    Serial.println(PH);
  }

  if (Serial.available())
  {
    Serial.readString();

    Serial.println();
    Serial.println("Proses kalibrasi, ikuti petunjuk di serial monitor");
    
    ph.calibration(voltagePH, suhuPengukuran, "ENTERPH");

    while (!Serial.available());
    Serial.readString();
    
    voltagePH = analogRead(pinPH) / 1024.0 * 5000;      // read the ph voltage
    ph.calibration(voltagePH, suhuPengukuran, "CALPH");

    ph.calibration(voltagePH, suhuPengukuran, "EXITPH");
  }
}

library : DFRobot_PH.zip

 

Penjadwalan dan durasi aktif relay dengan setting melalui tombol berbasis arduino

Pengontrolan waktu hidup dan mati peralatan sebagai otomasi yang mengurangi ketergantungan dari kontrol operator, bisa dilakukan dengan penjadwalan beban/peralatan. Contohnya dalam pengaturan beban dalam rumah tangga, misalkan terdapat beban yang akan dikontrol seperti berikut :

  1. lampu teras
  2. lampu taman
  3. pompa pengisi air tandon
  4. kran/solenoid Penyiram tanaman
  5. electric water heater

adalah beban-beban listrik yang biasanya hidup dan mati-nya terjadwal.

Untuk mengatur jadwalnya, pada contoh ini menggunakan 3 tombol yaitu set, up dan down. adapun komponen yang digunakan adalah :

  1. Arduino uno
  2. rtc ds3231
  3. lcd 16×02 i2c
  4. relay 8 channel

Skema penjadwalan relay menggunakan arduino :

koding arduino penjadwalan relay :


#define pinTombolSet        A0
#define pinTombolUp         A1
#define pinTombolDown       A2

#define pinRelay1           2
#define pinRelay2           3
#define pinRelay3           4
#define pinRelay4           5
#define pinRelay5           6
#define pinRelay6           7
#define pinRelay7           8
#define pinRelay8           9

#define relayOn             LOW
#define jumlahRelay         8

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

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

byte setting[jumlahRelay * 4];
byte menu = 0;
char buf[32];
DateTime now;
byte detikSebelumnya = 60;
byte pinRelay[] = {pinRelay1, pinRelay2, pinRelay3, pinRelay4, pinRelay5, pinRelay6, pinRelay7, pinRelay8};

void setup()
{
  pinMode(pinTombolSet, INPUT_PULLUP);
  pinMode(pinTombolUp, INPUT_PULLUP);
  pinMode(pinTombolDown, INPUT_PULLUP);

  for (byte i = 0; i < jumlahRelay; i++)
  {
    digitalWrite(pinRelay[i], !relayOn);
    pinMode(pinRelay[i], OUTPUT);
  }

  Serial.begin(9600);
  Serial.println(F("Penjadwalan dan durasi aktif relay dengan setting melalui tombol berbasis arduino"));
  Serial.println(F("https://www.project.semesin.com"));
  Serial.println();
  
  Wire.begin();
  rtc.begin();
  DateTime dt(2011, 11, 10, 15, 18, 0, 5); // set tanggal dan waktu (format): tahun, bulan tanggal, jam, menit, detik, hari (1=minggu, 7=sabtu)
  rtc.setDateTime(dt);

  Wire.beginTransmission(0x3F);
  if (Wire.endTransmission())
  {
    lcd = LiquidCrystal_I2C(0x27, 16, 2);
  }
  lcd.begin();

  lcd.backlight();
  lcd.print("Jadwal relay");
  lcd.setCursor(0, 1);
  lcd.print("www.Semesin.com");
  delay(3000);

  lcd.clear();

  if (EEPROM.read(0) != 12)
  {
    EEPROM.update(0, 12);
    for (byte i = 0; i < jumlahRelay * 4; i++)
    {
      setting[i] = 0;
    }
    EEPROM.put(1, setting);
  }
  EEPROM.get(1, setting);

  Serial.println("Sistem mulai");

}


void loop()
{
  now = rtc.now();
  if (detikSebelumnya != now.second())
  {
    detikSebelumnya = now.second();
    if (now.second() == 0)
    {
      for (byte i = 0; i < jumlahRelay; i++)
      {
        uint16_t unixNow = (now.hour() * 60) +  now.minute();
        uint16_t unixWaktu = ((setting[(i * 4) + 0] * 60) +  setting[(i * 4) + 1]);
        uint16_t unixDurasi = ((setting[(i * 4) + 2] * 60) +  setting[(i * 4) + 3]);
        if (unixNow == unixWaktu)
        {
          digitalWrite(pinRelay[i], LOW);
          Serial.print("Relay ");
          Serial.print(i + 1);
          Serial.println(" aktif");
        }
        if (unixNow == unixWaktu + unixDurasi)
        {
          digitalWrite(pinRelay[i], HIGH);
          Serial.print("Relay ");
          Serial.print(i + 1);
          Serial.println(" tidak aktif");
        }
      }
    }
    if (!menu)
    {
      sprintf(buf, "%02d/%02d/%04d", now.date(), now.month(), now.year());
      lcd.setCursor(3, 0);
      lcd.print(buf);
      sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
      lcd.setCursor(4, 1);
      lcd.print(buf);
    }
  }

  if (menu)
  {
    if (!digitalRead(pinTombolUp))
    {
      delay(50);
      while (!digitalRead(pinTombolUp))
      {
        setting[menu - 1]++;
        if ((menu - 1) % 2)
        {
          if (setting[menu - 1] >= 60)
          {
            setting[menu - 1] = 0;
          }
        }
        else
        {
          if (setting[menu - 1] >= 24)
          {
            setting[menu - 1] = 0;
          }
        }

        tampilanMenu();
        delay(100);
      }
    }
    if (!digitalRead(pinTombolDown))
    {
      delay(50);
      while (!digitalRead(pinTombolDown))
      {

        if ((menu - 1) % 2)
        {
          if (setting[menu - 1] == 0)
          {
            setting[menu - 1] = 59;
          }
          else
          {
            setting[menu - 1]--;
          }
        }
        else
        {
          if (setting[menu - 1] == 0)
          {
            setting[menu - 1] = 23;
          }
          else
          {
            setting[menu - 1]--;
          }
        }

        tampilanMenu();
        delay(100);
      }
    }
  }

  if (!digitalRead(pinTombolSet))
  {
    delay(50);
    if (!digitalRead(pinTombolSet))
    {
      menu++;

      if (menu == jumlahRelay * 4 + 1)
      {
        menu = 0;
        lcd.clear();
        lcd.noCursor();
        EEPROM.put(1, setting);
      }
      else
      {
        lcd.clear();
        lcd.setCursor(2, 0);
        lcd.print("Set Relay ");
        lcd.print(((menu - 1) / 4) + 1);
        tampilanMenu();
      }
      
      long miliisTekanPanjang = millis() + 3000;
      while (!digitalRead(pinTombolSet))
      {
        if (miliisTekanPanjang < millis())
        {
          menu = 0;
          lcd.clear();
          lcd.noCursor();
          EEPROM.put(1, setting);

        }
      }
    }
  }
}
void tampilanMenu()
{
  sprintf(buf, "%s : %02d:%02d", ((menu - 1) % 4) / 2 ? "Durasi" : "Waktu ", setting[(menu - 1) & 0xFE], setting[((menu - 1) & 0xFE) + 1]);
  lcd.setCursor(0, 1);
  lcd.print(buf);

  lcd.setCursor(((menu - 1) % 2) ? 12 : 9, 1);
  lcd.cursor();
}
  1. LiquidCrystal-I2C.zip
  2. Sodaq_DS3231.zip

Remot kontrol android untuk mobil arduino melalui bluetooth

Remot kontrol adalah instrumen jarak jauh (remot) yang mengendalikan perangkat untuk melaksanakan fungsi-fungsi sesuai perintah. Komunikasi antara remot kontrol dan perangkat (rtu) bisa menggunakan kabel atau tanpa kabel (bluetooth, wifi, radio).

Android bisa dimanfatkan sebagai remot kontrol dengan memanfatkan fasilitas sensor-sensor yang dimilikinya. Dalam contoh ini (pengontrolan mobil arduino) memanfatkan fitur berikut :

  1. Bluetooth
  2. Sensor orientasi/kemiringan
  3. Touch screen

Pengendalian remot kontrol bisa dilakukan dalam 2 mode yaitu mode steer dan mode sensor orientasi.

Prototipe mobil arduino dibuat dari komponen berikut :

  1. Arduino uno
  2. Driver motor L298
  3. Motor DC
  4. Bluetooth HC-05 dan resistor pembagi tegangan
  5. Rangka miniatur mobil

Fokus dalam perancangan mobil arduino ini adalah pengendalian kecepatan motor kiri dan kanan sehingga diperoleh gerakan yang mulus/smooth. jadi tidak seperti kendali steer mobil pada umumnya yang menggunakan metode putaran poros roda untuk melakukan belokan. Untuk itu digunakan formula gerakan menggunakan pwm (pulse width modulation) dan pengaturan kecepatan roda kiri dan kanan sehingga dihasilkan gerakan yang halus.

berikut skema pengendalian gerakan mobil-mobilan arduino melalui android :

sketch arduino untuk mobil remot dengan gerakan yang halus:

#include <SoftwareSerial.h>

#define pinMotorKiriPlus            5
#define pinMotorKiriMinus           6
#define pinMotorKananPlus           10
#define pinMotorKananMinus          11

SoftwareSerial bluetooth(2, 3);

int x = 128;
int y = 128;
byte kiri;
byte kanan;
char buffer[32];
bool statusBerhenti;

void setup() {
  pinMode(pinMotorKiriPlus, OUTPUT);
  pinMode(pinMotorKiriMinus, OUTPUT);
  pinMode(pinMotorKananPlus, OUTPUT);
  pinMode(pinMotorKananMinus, OUTPUT);

  Serial.begin(9600);
  Serial.println(F("Remot kontrol android untuk mobil arduino melalui bluetooth"));
  Serial.println(F("https://www.project.semesin.com"));
  Serial.println();
  
  bluetooth.begin(9600);

  Serial.println("Sistem mulai");

}

void loop() {

  while (bluetooth.available())
  {
    char c = bluetooth.read();
    switch (c)
    {
      case 'x':
        x = bluetooth.parseInt();
        break;
      case 'y':
        y = bluetooth.parseInt();
        break;
    }
  }

  if ((y > 96) && (y < 160))
  {
    if (!statusBerhenti)
    {
      digitalWrite(pinMotorKiriPlus, LOW);
      digitalWrite(pinMotorKiriMinus, LOW);
      digitalWrite(pinMotorKananPlus, LOW);
      digitalWrite(pinMotorKananMinus, LOW);
      Serial.println("berhenti");
      statusBerhenti = true;
    }

  }
  else
  {
    float rasioKiri = 1.0 * x / 255;
    float rasioKanan = 1.0 * (255 - x) / 255;
    byte kecepatan = abs(y - 128) * 2;

    if (rasioKiri > rasioKanan)
    {
      rasioKanan += 1 - rasioKiri;
      rasioKiri = 1;
    }
    else
    {
      rasioKiri += 1 - rasioKanan;
      rasioKanan = 1;
    }

    kiri = constrain(rasioKiri * kecepatan, 0 , 255);
    kanan = constrain(rasioKanan * kecepatan, 0 , 255);

    sprintf(buffer, "%s : kiri: %d, kanan: %d", y < 128 ? "Maju" : "mundur", kiri, kanan);
    Serial.println(buffer);

    if (y < 128)
    {
      analogWrite(pinMotorKiriPlus, kiri);
      analogWrite(pinMotorKananPlus, kanan);
      digitalWrite(pinMotorKiriMinus, LOW);
      digitalWrite(pinMotorKananMinus, LOW);
    }
    else
    {
      analogWrite(pinMotorKiriMinus, kiri);
      analogWrite(pinMotorKananMinus, kanan);
      digitalWrite(pinMotorKiriPlus, LOW);
      digitalWrite(pinMotorKananPlus, LOW);
    }
    statusBerhenti = false;
  }
}

block app inventor remot kontrol android:

screenshoot Remot kontrol arduino pengendali mobil-mobilan:

File app inventor remot kontrol:

1. Setir_Android.apk
2. Setir_Android.aia

Sistem kontrol PID close loop – stabilizer tegangan – menggunakan arduino melalui simulink matlab

Sistem kontrol PID (Proportional–Integral–Derivative controller) bertujuan memperoleh hasil optimum yang menggunakan mekanisme umpan balik (sistem tertutup / close loop). sistem kontrol PID juga bisa diterapkan pada arduino. Untuk menambah kemampuan numerik pada arduino, bisa dikombinasikan dengan program matlab.

Program Matlab (Matrix Laboratory) yang memiliki fitur simulink dapat dapat digunakan untuk memprogram arduino, dan dengan kelebihan matlab bisa dengan mudah mengembangkan sistem kontrol (dan keperluan numerikal lain) kedepannya.

Untuk pemrograman arduino menggunakan matlab, diperlukan add-ons matlab berikut ini:

  1.  Simulink Support Package for Arduino Hardware
  2. MATLAB Support for MinGW-w64 C/C++ Compiler

Dalam contoh ini menggunakan plant pengatur tegangan keluaran pwm dengan beban kapasitor.

Skema / plant / rangkaian percobaan sistem kontrol pid loop tertutup berbasis arduino:

Model simulink matlab sistem kontrol tegangan

respon keluaran pengontrolan tegangan dengan arduino dan simulink

file simulink pengontrolan pid tegangan pwm:

pidArduino.slx

 

 

Input string melalui keypad menggunakan arduino

Keypad (dalam konteks arduino) sama halnya dengan keypad pada handphone lawas (tuts) yang terdiri dari setidaknya 12 tombol berupa angka 0 hingga 9 serta karakter * dan karakter #. Untuk menuliskan karakter huruf, maka tuts keypad harus ditekan beberapa kali hingga karakter yang diinginkan muncul.

String / text terdiri atas karakter-karakter penyusunnya, penggunaan keypad 3×4 (numerik) membutuhkan trik khusus dan terdapat bermacam-macam metode, dalam contoh ini menggunakan metode entry deret.

 

aturan pemakaian umum:

  1. Masing-masing tuts memiliki beberapa karakter, untuk memilih karakter maka tuts yang sama ditekan berulang-ulang hingga karakter yang diinginkan tampil.
  2. Jika tuts/tombol tidak ditekan selama 3 detik, maka karakter sebelumnya dimasukkan dalam memory dan sistem lanjut ke karakter berikutnya.
  3. Jika tuts yang ditekan berbeda dengan tuts sebelumnya, maka karakter terakhir akan dimasukkan dalam memory.
  4. tuts * berfungsi untuk menghapus karakter terakhir
  5. jika tuts * pada saat belum ada karakter yang dimasukkan, maka sistem akan kembali ke sistem normal (dalam contoh ini kembali ke keadaan awal).
  6. tuts # berfungsi seperti ‘enter’ untuk menyimpan string dan kembali ke sistem normal (dalam contoh ini kembali ke keadaan awal).

skema pemanfaatan keypad sebagai entry teks:

koding/sketch masukan keypad sebagai string / teks :

#define periodaKeypad         3000

#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2);

const byte ROWS = 4;
const byte COLS = 3;
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {11, 10, 9, 8};
byte colPins[COLS] = {7, 6, 5};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


char pad[11][11] = {
  "0 ",
  "1?!*#:=/+-",
  "2AaBbCc",
  "3DdEeFf",
  "4GgHhIi",
  "5JjKkLl",
  "6MmNnOo",
  "7PpQqRrSs",
  "8TtUuVvWw",
  "9XxYyZz",
};

byte padCounter;
char padChar;
bool padDitekan;
byte charCounter;
byte keySebelumnya;
char bufferKeypad[17];
char *bufferKeypadPtr;

long millisKeypad;

void setup() {
  Serial.begin(9600);
  Serial.println(F("Input string malalui keypad menggunakan arduino"));
  Serial.println(F("https://www.project.semesin.com"));
  Serial.println();

  Wire.begin();
  Wire.beginTransmission(0x3F);
  if (Wire.endTransmission())
  {
    lcd = LiquidCrystal_I2C(0x27, 16, 2);
  }
  lcd.begin();

  resetInput();
}

void loop() {
  char key = keypad.getKey();

  if (key) {
    switch (key)
    {
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':

        millisKeypad = millis() + periodaKeypad;
        if ((key == keySebelumnya) || (keySebelumnya == 0))
        {
          padChar = pad[key - '0'][charCounter];
          keySebelumnya = key;
        }
        else if ((padDitekan) && (padCounter < sizeof(bufferKeypad) - 1))
        {
          *bufferKeypadPtr++ = padChar;
          keySebelumnya = key;
          charCounter = 0;
          padCounter++;
          padChar = pad[key - '0'][charCounter];
        }

        padDitekan = true;

        lcd.setCursor(padCounter, 1);
        lcd.print(padChar);
        lcd.setCursor(padCounter, 1);

        charCounter++;
        if (!pad[key - '0'][charCounter])
        {
          charCounter = 0;
        }
        break;

      case '*':
        if (padCounter)
        {
          if (keySebelumnya)
          {
            keySebelumnya = 0;
          }
          lcd.setCursor(padCounter, 1);
          lcd.print(' ');
          charCounter = 0;
          padCounter--;
          bufferKeypadPtr--;
          padChar = *bufferKeypadPtr;

          lcd.setCursor(padCounter, 1);
        }
        else
        {
          resetInput();
        }
        break;
      case '#':
        if ((padDitekan) && (padCounter < sizeof(bufferKeypad) - 1))
        {
          *bufferKeypadPtr++ = padChar;
        }
        *bufferKeypadPtr = 0;

        Serial.print("String input = ");
        Serial.println(bufferKeypad);

        lcd.clear();
        lcd.noBlink();
        lcd.setCursor(0, 0);
        lcd.print("String input = ");
        lcd.setCursor(0, 1);
        lcd.print(bufferKeypad);
        delay(3000);

        resetInput();
        break;
    }
  }

  if ((padDitekan) && (padCounter < sizeof(bufferKeypad) - 1))
  {
    if (millisKeypad < millis())
    {
      *bufferKeypadPtr++ = padChar;
      keySebelumnya = key;
      charCounter = 0;
      padCounter++;
      padDitekan = false;

      lcd.setCursor(padCounter, 1);
      lcd.print(' ');
      lcd.setCursor(padCounter, 1);
    }
  }
}

void resetInput()
{
  bufferKeypadPtr = bufferKeypad;
  charCounter = 0;
  padCounter = 0;
  keySebelumnya = 0;
  padDitekan = false;

  lcd.clear();
  lcd.print("Masukkan string");
  lcd.setCursor(padCounter, 1);
  lcd.blink();
}

library entry teks melalui keypad berbasis arduino :
LiquidCrystal-I2C.zip
Keypad.zip