Anda di sini

Pemrograman

[TUTORIAL - LENGKAP] Membuat Monitor dan Pencatat Suhu Ruangan dengan Visual Studio C# & MS SQL

Aditya Suranata - 13 November 2015 10:56:04 11

1. Dasar Teori

LM35 merupakan salah satu dari sekian banyak sensor analog untuk mengukur suhu. Perubahan suhu disekitar sensor menyebabkan terjadinya perubahan nilai tahanan pada sensor, sehingga turut menyebabkan perubahan nilai tegangan output dari sensor. Perubahan nilai tegangan inilah yang dimanfaatkan oleh komponen Analog to Digital Converter (ADC) pada mikrokontroler untuk menyediakan data digital berupa data suhu yang kemudian bisa dibaca oleh mikrokontroler.

Data digital yang telah diterima oleh mikrokontroler dalam hal ini masih berupa sampel data (data mentah) sehingga perlu dilakukan kalibrasi. Kalibrasi dilakukan dengan cara memasukan sampel data tersebut ke sebuah fungsi yang didapat dari hasil perhitungan dengan kondisi suhu pada pengukuran sebenarnya (perbandingan antara hasil terukur dan aktual). Setelah data suhu sebenarnya diketahui, data suhu tersebut dikirim ke komputer menggunakan komunikasi serial untuk ditampilkan pada interface.

Aplikasi interface pada komputer selanjutnya membaca port serial (COM) tempat dimana data suhu tersebut akan dikirim oleh mikrokontroler. Data serial yang telah diterima kemudian ditampilkan pada sebuah grafik sehingga bisa terlihat data suhu pada rentang waktunya, dan dalam interval waktu tertentu fungsi catat akan mencatat data suhu ke database.

2. Alat Dan Bahan

a. Perangkat Keras

  • 1 Arduino Uno R3 x 1
  • 2 Kabel USB A to B x 1
  • 3 Kabel Jumper x 3
  • 4 Sensor Suhu LM35 x 1

b. Perangkat Lunak

  • 1 Arduino IDE Ver. 1.0.5 >
  • 2 Microsoft Visual Studio Ver. 2008 >
  • 3 ZedGraph class library Ver. 5.1.5 (Lihat cara setupnya disini)
  • 4 Microsoft SQL Server 2008 R2 >

3. Ranah Kerja

Proses pengerjaannya akan dibagi menjadi tiga bagian, yaitu :

  1. Perakitan Perangkat Keras
  2. Pemrograman arduino
  3. Pemrograman Interface & Database

3.1 Perakitan Perangkat Keras

Perangkat keras dirakit berdasarkan gambar berikut :

3.2 Program Pada Arduino

/** Workshop Dasar Mikrokontroler 2014 
RADE - Robotics AnD Embedded Systems STMIK STIKOM Bali 
**/
//Pin wiper pada sensor LM32 (terminal tengah) tersambung ke Analog //Pin 3
//Yang disamping tersambung ke 5V dan Ground
int analogPin = 3;
 
//Variabel untuk menyimpan data suhu
float suhu;
 
void setup() {
    //Setup serial dengan baud 9600
    Serial.begin(9600);
}
void loop() {
    //Baca pin input 
    suhu = analogRead(analogPin);
    //Lakukan kalibrasi
    suhu = suhu * 0.48828125;
    //Kirim ke komputer melalui serial
    Serial.println(suhu);
    //Delay sebelum melakukan pembacaan selanjutnya
    delay(50);
}

3.3 Program Pada Interface dan Database

Pertama kita akan membuat database untuk menyimpan data suhu. Buka SQL Server Management Studio dan buat query baru dengan mengklik menu New Query. Masukan query berikut dan klik Execute !

/** Buat Database DB_SUHU **/
CREATE DATABASE DB_SUHU
GO
 
/** Gunakan Database DB_SUHU **/
USE DB_SUHU
GO
 
/** Buat Tabel tbl_suhu **/
CREATE TABLE tbl_suhu
(
id int PRIMARY KEY IDENTITY(1,1),
suhu float,
waktu datetime
)
GO
 
/** Seting format waktu ke tanggal-bulan-tahun jam:menit:detik **/
SET DATEFORMAT dmy;
GO

Setelah database terbentuk, dilanjutkan dengan membuat interface pada Visual Studio. Buka Visual Studio IDE, buat proyek baru dengan tipe Visual C# dan pilih Windows > Windows Forms Application. Ketik nama proyek Monitor Suhu kemudian OK.

Mulai membuat interface dengan mendrag-and-drop masing-masing kontrol ke form. Kemudian untuk kode pada form1 atau form utama gunakan kode berikut :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
//namespace untuk zedGrpah
using ZedGraph;
//namespace untuk class serial
using System.IO.Ports;
//namespace untuk melihat setting global komputer
using System.Globalization;
//Namespace untuk databse MSSQL
using System.Data.SqlClient;
 
namespace Monitor_Suhu
{
    public partial class Form_utama : Form
    {
        /**Inisialisaisi arduino
         * Setup port serial dengan nama port COM65,
         * dan baud rate sebesar 9600.
         * Baud rate disini dengan di arduino harus sama
         * **/
        SerialPort arduino = new SerialPort("COM65",9600);
 
        /**Inisialisasi databse
         * setup string koneksi 
         * **/
        SqlConnection cs = new SqlConnection("Data Source=localhost;Initial Catalog=DB_SUHU;Integrated Security=True");
        SqlDataAdapter da = new SqlDataAdapter();
 
        //Array list untuk menyimpan data suhu dan waktu
        double[] bufferSuhu = new double[10];
        double[] bufferWaktu = new double[10];
 
        List<double> listSuhu = new List<double>();
        List<double> listWaktu = new List<double>(); 
         
        //waktu mulai dalam milidetik
        double waktuStart = 100;
        //interval simpan ke database (menit)
        int intervalSimpan = 1;
        //pencacah interval
        int counter = 0;
 
        //konstruktor
        public Form_utama()
        {
            InitializeComponent();
        }
 
        //event ketuka tombol start diklik
        private void btn_kontrol_start_Click(object sender, EventArgs e)
        {
            //start detak untuk mulai mengaktifkan grapher
            try
            {
                //matikan tombol start
                btn_kontrol_start.Enabled = false;
                //nyalakan tombol stop
                btn_kontrol_stop.Enabled = true;
                //set batas waktu pembacaan serial sebelum dinyatakan gagal
                arduino.ReadTimeout = 1000;
                //set batas waktu penulisan serial
                arduino.WriteTimeout = 1000;
 
                //nyalakan detak
                Detak.Enabled = true;
                //mulai detak
                Detak.Start();                      
            }
            catch (Exception gagal)
            {
                //Error handling
                //MessageBox.Show(gagal.ToString());
            }
        }
 
         
        //event ketika detak dimulai
        private void Detak_Tick(object sender, EventArgs e)
        {
            try
            {
                //increment-kan pencacah
                counter++;
 
                //Mulai komunikasi dengan arduino
                arduino.Open();
 
                //get item kurva pertama pada grafik
                LineItem kurvaSuhu = zedGraphSuhu.GraphPane.CurveList[0] as LineItem;
 
                //get PointPairList
                IPointListEdit listSuhu = kurvaSuhu.Points as IPointListEdit;
 
                //waktu yang terlewati
                double waktu = (Environment.TickCount - waktuStart) / 1000.0;
 
                //baca data suhu yang dikirim arduino,
                //konversi data tersebut (string) ke double,
                //dan tambahkan ke listSuhu
                float dataSuhu = float.Parse(arduino.ReadLine(), CultureInfo.InvariantCulture.NumberFormat);
                listSuhu.Add(waktu, Convert.ToDouble(dataSuhu));
 
                //Tutup komunikasi dengan arduino
                arduino.Close();
 
                //Buat scale X tetap rolling dalam interval 30 detik, dengan satu
                //langkah besar antara nilai X maksimal dan akhir dari axis
                Scale xScale = zedGraphSuhu.GraphPane.XAxis.Scale;
                if (waktu > xScale.Max - xScale.MajorStep)
                {
                    xScale.Max = waktu + xScale.MajorStep;
                    xScale.Min = xScale.Max - 30.0;
                }
 
                // Pastikan Y axis di scale ulang untuk mengakomodir data aktual
                zedGraphSuhu.AxisChange();
 
                // Redraw paksa
                zedGraphSuhu.Invalidate();
 
                /** 
                 * Mencatat suhu ke database
                 * **/
 
                //lakukan hanya pada interval yang telah ditentukan
                //intervalSimpan (menit) x 60 x 2, karena 1 detak = 500 milidetik / 1/2 detik
                if(counter == (intervalSimpan*60*2))
                {
                    //Buat query untuk insert catatan
                    da.InsertCommand = new SqlCommand("INSERT INTO tbl_suhu (suhu, waktu) VALUES(@SUHU, @WAKTU)",cs);
                    da.InsertCommand.Parameters.AddWithValue("@SUHU", SqlDbType.Float).Value = dataSuhu;
                    da.InsertCommand.Parameters.AddWithValue("@WAKTU", SqlDbType.DateTime).Value = DateTime.Now;
 
                    //buka koneksi ke database
                    cs.Open();
                    //eksekusi query insert
                    da.InsertCommand.ExecuteNonQuery();
                    //tutup koneksi ke database
                    cs.Close();
 
                    //reset pencacah
                    counter = 0;
                }
            }
            catch (Exception gagal)
            {
                //error handling
                //tutup komunikasi dengan arduino jika masih terhubung
                if (arduino.IsOpen)
                {
                    arduino.Close();
                }
                //MessageBox.Show(gagal.ToString());
            }
 
        }
 
        //event ketika tombol stop diklik
        private void btn_kontrol_stop_Click(object sender, EventArgs e)
        {
            try
            {
                //nyalakan kembali tombol start
                btn_kontrol_start.Enabled = true;
                //matikan tombol stop
                btn_kontrol_stop.Enabled = false;
                //stop detak
                Detak.Stop();
                //matikan detak
                Detak.Enabled = false;
                //jika komunikasi masih terbuka, tutup komunikasi
                if (arduino.IsOpen)
                {
                    arduino.Close();
                }
            }
            catch (Exception gagal)
            {
                //error handling
                //MessageBox.Show(gagal.ToString());
            }
        }
         
        //event ketika form utama dibuka
        private void Form_utama_Load(object sender, EventArgs e)
        {
            try
            {
                //catat waktu pertama sebagai referensi
                waktuStart = Environment.TickCount;
 
                //Inisialisasi ZedGraph
                GraphPane grafikSuhu = zedGraphSuhu.GraphPane;
                grafikSuhu.Title.Text = "Grafik Suhu";
                grafikSuhu.XAxis.Title.Text = "Waktu (Detik)";
                grafikSuhu.YAxis.Title.Text = "Suhu (Celcius)";
 
                //Simpan 120 point. Pada 500 ms sampel rate.
                //RollingPointPairList adalah class penyimpanan yang efisien 
                //dengan tetap merolling kumpulan point data tanpa perlu
                //men-shift nilai data apapun
                RollingPointPairList listSuhu = new RollingPointPairList(120);
 
                //Inisialisasi kurva
                LineItem kurvaSuhu = grafikSuhu.AddCurve("Suhu", listSuhu, Color.Red, SymbolType.None);
            }
            catch (Exception gagal)
            {
                //error handling
                //MessageBox.Show(gagal.ToString());
            }
        }
 
        //event ketika tombol lihat diklik
        private void btn_lihat_Click(object sender, EventArgs e)
        {
            try
            {
                //dari tanggal
                DateTime dari = Convert.ToDateTime(dtPicker_dari.Text);
                //hingga tanggal
                DateTime hingga = Convert.ToDateTime(dtPicker_hingga.Text);
 
                //string koneksi untuk mengambil data dari database
                da.SelectCommand = new SqlCommand("SELECT * FROM tbl_suhu WHERE waktu >= @DARI AND waktu <= @HINGGA ORDER BY id ASC", cs);
                da.SelectCommand.Parameters.AddWithValue("@DARI", SqlDbType.DateTime).Value = dari;
                da.SelectCommand.Parameters.AddWithValue("@HINGGA", SqlDbType.DateTime).Value = hingga;
 
                //buka koneksi ke database
                cs.Open();
                //eksekusi query select
                da.SelectCommand.ExecuteNonQuery();
                //tutup koneksi ke database
                cs.Close();
 
                //buat datatable untuk menampung catatan suhu
                DataTable dt_suhu = new DataTable();
                //kosongkan dt_suhu
                dt_suhu.Clear();
                //isi dt_suhu dengan catatan dari database
                da.Fill(dt_suhu);
                //tampilkan pada datagrid
                dataGrid_suhu.DataSource = dt_suhu;
            }
            catch (Exception gagal)
            { 
                //error handling
                //MessageBox.Show(gagal.ToString());
            }
        }
 
    }
}

Lakukan pengujian dengan menghubungkan Arduino ke komputer. Periksa nama port COM yang digunakan oleh Arduino dari Device Manager, kemudian pastikan tidak ada program lain yang menggunakan port tersebut termasuk Arduino IDE agar tidak bentrok. Kemudian cocokan nama port serialnya dengan yang tertulis di program. Run program untuk memulai debugging.

Jika terjadi kesalahan atau program tidak bekerja, uncomment syntax MessageBox pada block catch masing-masing kode untuk mentracing kesalahan yang menyebabkan program tidak bekerja.

21.382
Image

Aditya Suranata

Aditya suka menulis, bukan hanya sekedar hobi, menulis menjadi medianya untuk mencurahkan pikiran dan perasaan. Di TutorKeren.com kebanyakan menyumbang tulisan sesuai dengan minat dan keahliannya yaitu pada kategori pemrograman dan elektronika. Selain itu juga gemar menulis mengenai hal-hal umum, seperti ilmu alam, sosial dan beberapa pengalamannya yang mungkin bisa berguna untuk orang lain.

Artikel Menarik Lainnya

Komentar

Hai, Saya sedang mengikuti tutorial ini. Namun, ada hal berbeda yang ingin saya lakukan, yaitu saat tombol Start ditekan, saya ingin Visual C# mengirimkan data string "on" ke Arduino. Hal ini saya lakukan karena pada program Arduino yang saya gunakan, saya membuat conditional code if(Serial.available()>0){ start = Serial.read(); if(start == "on"){ servoMotor.write(40); } } code tersebut untuk memutar servo sebesar 40 derajat ketika arduino menerima data serial "on". Nah setelah code tersebut di eksekusi, maka arduino langsung menjalankan code analog read yang selanjutnya akan diambil oleh Visual C#. Yang saya bingung adalah, pada tutorial ini prinsip programnya adalah ketika tombol start diklik, maka method detak yang isinya open port arduino (untuk terima data serial) akan berjalan selama satu detik, lalu port arduino akan close. Kalau seperti ini, apakah bisa saya menambahkan code if (arduino.IsOpen) { arduino.WriteLine("on"); //untuk kirim "on" ke Arduino }di program Visual C# saya? kalau bisa, pada bagian mana? Kalau tidak bisa, apakah ada cara lain untuk mengirim dan menerima data serial secara simultan? Terima kasih sebelumnya Smile

Mohon maaf sebelumnya mas, saya sudah sempat replay komentarnya namun ternyata tidak masuk... baru setelah ada komentar baru diatas saya tahu kalau komentarnya tidak masuk sad

Kembali ke topik, siapa tahu ada orang lain yg mengalami hal serupa, mengenai bagaimana mengirim data ke Arduino sebelum dilakukan pembacaan, caranya mudah cukup tambah pada bagian event handler untuk tombol start (skrip tambahan saya tandai dengan //START TAMBAH & //END TAMBAH ):

        //event ketika tombol start diklik
        private void btn_kontrol_start_Click(object sender, EventArgs e)
        {
            //start detak untuk mulai mengaktifkan grapher
            try
            {
                //START TAMBAH
                arduino.Open();
                arduino.WriteLine("on"); //untuk kirim "on" ke Arduino
                arduino.Close();
                //END TAMBAH
                //matikan tombol start
                btn_kontrol_start.Enabled = false;
                //nyalakan tombol stop
                btn_kontrol_stop.Enabled = true;
                //set batas waktu pembacaan serial sebelum dinyatakan gagal
                arduino.ReadTimeout = 1000;
                //set batas waktu penulisan serial
                arduino.WriteTimeout = 1000;
  
                //nyalakan detak
                Detak.Enabled = true;
                //mulai detak
                Detak.Start();                      
            }
            catch (Exception gagal)
            {
                //Error handling
                //MessageBox.Show(gagal.ToString());
            }
        }

Itu akan mengirim "on" ke Arduino sesaat sebelum pembacaan realtime dilakukan, semoga membantu...

HTSL://HIGH THINKING SIMPLE LIVING . ME

Dalam hal ini saya menggunakan bahasa Visual Basic + arduino uno + sensor Dht11. Sama seperti tutorial diatas ketika tombol start di klik maka dilakukan pembacaan data dari sensor setiap 1 detik, yang saya bingungkan bagaimana menyimpannya kedalam database. Apakah penyimpanannya melalui pembacaan data langsung dari port atau menyimpan melalui pembacaan dari label yang saya set untuk menampilkan data dari sensor tsb? logikanya lah. Mohon pencerahan krn saya masih newbe, terima kasih sebelumnya. Smile

Halo mas,

pada tutorial diatas, saya melakukan penyimpanan pada method Detak_Tick yang dieksekusi sejalan dengan interval detak yaitu setiap 1/2 detik, nah... namun pada method Detak_Tick itu proses penyimpanannya tidak langsung saya lakukan pada setiap detak, tapi saya filter lagi dengan kondisi... alasannya karena saya tidak ingin membebani database dengan record data yang terlalu intens (setiap 1/5 detik atau dua kali dalam sedetik), saya pakai kondisi if untuk memfilter agar proses penyimpanan dilakukan setiap satu menit.

Caranya mudah, cukup buat variabel counter , lalu increment setiap detak, dan cek menggunakan if jika counternya sudah sampai 120 baru kemudian simpan data yang dikirim langsung oleh arduino ke database... bisa dilihat pada bagian kode ini:

//lakukan hanya pada interval yang telah ditentukan
//intervalSimpan (menit) x 60 x 2, karena 1 detak = 500 milidetik / 1/2 detik
if(counter == (intervalSimpan*60*2))
{

semoga membantu, jika kurang jelas silahkan tanya lagi

HTSL://HIGH THINKING SIMPLE LIVING . ME

Halo, tutorialnya keren bang. Tapi disini saya ada sedikit masalah, saya sudah nyari-nyari sendiri masih belom bisa. Jadi, inti permasalahannya itu yang di tab pencatat itu datanya ga ada yang menyimpan. Dari program saya baca data suhu masuk setiap 1 menit, tapi itu sudah saya tunggu sampai bermenit-menit kok ga ada yang masuk ya? Saya liat dari Microsoft SQL Server bagian database DB_Suhu -> Table juga masih Null (No Data). Mungkin Mas Aditya bisa menjelaskan atau memberikan solusi hehehe Terima kasih.

Halo, tutorialnya keren bang. Tapi disini saya ada sedikit masalah, saya sudah nyari-nyari sendiri masih belom bisa. Jadi, inti permasalahannya itu yang di tab pencatat itu datanya ga ada yang menyimpan. Dari program saya baca data suhu masuk setiap 1 menit, tapi itu sudah saya tunggu sampai bermenit-menit kok ga ada yang masuk ya? Saya liat dari Microsoft SQL Server bagian database DB_Suhu -> Table juga masih Null (No Data). Mungkin Mas Aditya bisa menjelaskan atau memberikan solusi hehehe Terima kasih.

Halo, terimakasih sudah mampir ke blog saya...

Untuk masalah yg mas alami, mungkin ada masalah dengan koneksi ke databasenya. Coba lakukan troubleshooting dengan membuka block catch pada event handler Detak_Tick, dan btn_kontrol_start_Click.. caranya cukup uncomment bagian //MessageBox.Show(gagal.ToString());

Sebelumnya coba pastikan dulu kalau arduino sudah mengirim data melalui serial (bisa di print ke console variabelnya yg bernama dataSuhu), jika tidak ada masalah dengan arduino berarti masalah ada pada bagian koneksi dengan database...

HTSL://HIGH THINKING SIMPLE LIVING . ME

Halo, terima kasih sudah merespon komentar saya! Error handling sudah saya coba sebelumnya, saya tampilkan error dalam bentuk message box, yang keluar kalimat sejenis seperti "cannot convert variable float.... " atau apa gitu, panjang terus ga bisa di-copy soalnya hehehe. Untuk serialnya sudah bisa, soalnya dilihat dari grafiknya sudah keluar dan berjalan dengan baik. Saya tes input suhu LM35 dalam bentuk label.text juga keluar. Disini kalau memungkinkan saya ada dua pertanyaan yang butuh anda jawab: 1. Mungkin bisa diperjelas cara koneksi database dengan visual studionya itu bagaimana? Saya kurang paham di bidang itu. 2. Untuk grafiknya terkadang kok kurang stabil ya? Jadi agak sering kejadian dari suhu 25 - 40 tiba-tiba melonjak jadi 2100 - 3000. Alhasil merusak tampilan grafiknya (terutama sumbu Y nya jadi besar sekali, membuat grafik suhu <50 jadi nyaris tidak kelihatan karena mepet dengan sumbu X). Terima kasih.

Maaf late reply,

mengenai error "cannot convert variable float.... " itu berarti tipe data field databasenya tidak dibuat dengan benar, saya kurang jelas database yang mas pakai sekarang apa? Jika tidak pasti, coba ganti tipe data field di databasenya menjadi varchar

mengenai pertanyaannya:

1. Cara koneksi C# ke Microsoft SQL sangat mudah, cukup install MS SQL lalu eksekusi script yang saya tulis pada bagian program databasenya. Atau jika ingin buat manual silahkan merujuk ke halaman dokumentasi MS SQL dan C#.

2. Untuk grafiknya, jika keadaannya seperti itu berarti data yang dikirim oleh Arduino tidak stabil. Coba tambahkan filter dengan kondisi if, dan set batas wajar atas dan batas wajar bawah dari data yang dikirim oleh Arduino sebelum ditampilkan ke grafik/disimpan ke database. Jika datanya tidak wajar maka abikan dengan else.

Semoga membantu, jika masih kurang jelas silahkan diskusi lagi

HTSL://HIGH THINKING SIMPLE LIVING . ME

Assalamu'alaikum kang Disini saya sedang mencoba membuat aplikasi monitoring suhu menggunakan VB.net 2010. Disini saya mempunyai kendala. Saya belum paham untuk menghubungkan koneksi antara vb. net dan arduino uno. Sebelumnya saya mencoba beberapa kali namun hasilnya tetap gagal. Karena keterbatasan sumber dan referensi saya membuat coding seadanya tetapi tetap salah. Mungkin bisa dijelaskan coding yg sesuai untuk masalah ini. Terimakasih.

Halo Kang,

maaf late reply, untuk menghubungkan Arduino dengan VB.net hampir sama dengan C#. Kuncinya adalah kita bermain dengan port Serial (karena Arduino terhubung ke komputer melalui komunikasi serial). Selebihnya akang bisa coba main ke halaman dokumentasi dari VB.net di sini https://msdn.microsoft.com/en-us/library/system.io.ports.serialport(v=vs.110).aspx dan di sini https://msdn.microsoft.com/en-us/library/7ya7y41k.aspx

Semoga membantu

HTSL://HIGH THINKING SIMPLE LIVING . ME

Mari Gabung

Halo Emo 51 , Ada yang ingin disampaikan? Jangan sungkan untuk gabung diskusi ini. Silahkan Login dulu atau Daftar baru.