Hallo kembali…
Kembali membahas tentang proyek yang sebelumnya telah di bahas pada http://sonyfernando.wordpress.com/2009/09/01/sistem-monitoring-suhu/, berikut ini adalah pembahasan solusi untuk masalah tersebut.
Sebelumnya, berikut ini adalah spesifikasi developtment board yang digunakan:
- Support linux operating system
- Memiliki ethernet port
- Memiliki serial port
- Mendukung web service
Dari kebutuhan tersebut, Berikut ini adalah Perangkat yang digunakan:
- SBC yang digunakan adalah ATNGW100
- Menggunakan sensor suhu LM35
- Menggunakan microcontroller ADC (10 bit, terconfigurasi 8bit sebagai output)
- Sistem operasi linux dengan kernel versi 2.6.27
Berikut adalah pembahasan mengenai implementasi sistem monitoring suhu:
PEMBAHASAN
1. Implementas Device Driver
Device Driver merupakan sebuah applikasi yang berada di sisi kernel, yang berfungsi sebagai interface antara user application dengan perangkat keras (hardware). Kernel driver ini ditulis menggunakan bahasa pemograman C, dan dicompile dengan menggunakan avr32-linux-gcc. Berikut ini adalah source code device driver:
/*
* gadc.c – device driver for ADC using GPIO
* Copyright (c)2010
* Author: Sony F Gultom <sony.gultom@gmail.com>
*
* Released under the General Public License (GPL)
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <linux/spinlock.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/setup.h>
#include “gadc.h”
#define DRIVER_VERSION “v0.1 rc-01″
#define DRIVER_AUTHOR “Sony F Gultom <sony.gultom@gmail.com>”
#define DRIVER_DESC “ADC Device Driver Using GPIO framework”
/* dev id */
static int dev_open = 0;
/*
* gadc_open – Open gadc device driver interface
* Return 0 on SUCCESS, otherwise negative error (see below)
* – EBUSY: Device busy
*
*/
static int gadc_open(struct inode *inode, struct file *file)
{
/* we don’t want to talk to two processes at the same time */
if (dev_open) {
return -EBUSY;
}
dev_open++;
try_module_get(THIS_MODULE);
return SUCCESS;
}
/*
* gadc_read – Read gadc device driver interface
*
* Ropy current temperature to user space.
* This return value is a value of 8-bit data from gpio pin
* after converted to ADC voltage.
*
* Return count on SUCCESS, otherwise negative error (see below)
* – EFAULT : Bad address
*
*/
static ssize_t gadc_read(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
{
char tmp = 0;
char volt_val = 0;
int i = 0;
int shift = 7;
/* get value from gpio input data register */
for (i = PIN_DATA8; i >= PIN_DATA1; i–) {
tmp = gpio_get_value(i);
tmp <<= shift–;
volt_val |= tmp;
}
tmp = volt_val;
/* copy temperature to user space */
if (copy_to_user(buf, &tmp, sizeof(tmp))) {
return -EFAULT;
}
return count;
}
/*
* gadc_release – Close gadc device driver interface
* Return 0 on SUCCESS, otherwise negative error (see below)
*
*/
static int gadc_release(struct inode *inode, struct file *file)
{
dev_open–; /* we’re now ready for our next caller */
module_put(THIS_MODULE);
return SUCCESS;
}
/*
* struct fops – Struct file operation of gadc device driver
*/
struct file_operations fops = {
.owner = THIS_MODULE,
.open = gadc_open,
.read = gadc_read,
.release = gadc_release, /* aka close */
};
/*
* gadc_init – Tnitialize kernel module
*
* Initialize kernel module by register the character device driver,
* and initialize pin gpio and interrupt.
* Return 0 on SUCCESS, otherwise negative error (see below)
*/
static int __init gadc_init(void)
{
int i = 0;
int rv = 0;
/* request gpio pin data & set their direction */
for (i = PIN_DATA1; i <= PIN_DATA8; i++) {
rv = gpio_request(i, “gpio_in_data”);
if (rv) {
printk(KERN_ALERT “unable to request pin-%d\n”, i);
goto err1;
}
rv = gpio_direction_input(i);
if (rv) {
printk(KERN_ALERT “unable to set direction pin-%d\n”, i);
goto err2;
}
}
/* register the character device driver
* mknod /dev/gadc c 100 0
*/
register_chrdev(DEV_MAJOR, DEV_NAME, &fops);
printk(KERN_INFO “%s %s init\n”, DRIVER_DESC, DRIVER_VERSION);
return rv;
err2:
while (i >= PIN_DATA1) {
gpio_free(i);
i–;
}
goto done;
err1:
if (i != PIN_DATA1) {
while (i > PIN_DATA1) {
gpio_free(i – 1);
i–;
}
gpio_free(PIN_DATA1);
}
done:
return rv;
}
/*
* gadc_exit – Clean up kernel module
*/
static void __exit gadc_exit(void)
{
int i = 0;
/* unregister character device driver */
unregister_chrdev(DEV_MAJOR, DEV_NAME);
/* free gpio pin data block */
for (i = PIN_DATA1; i <= PIN_DATA8; i++) {
gpio_free(i);
}
printk(KERN_INFO “%s %s exit\n”, DRIVER_DESC, DRIVER_VERSION);
}
module_init(gadc_init);
module_exit(gadc_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(“GPL”);
Berikut ini adalah gadc.h file
/** gadc.h – header file for gadc device driver
*
* Copyright (c)2010
* Author: Sony F Gultom <sony.gultom@gmail.com>
*
* Released under the General Public License (GPL)
*/
#ifndef _GADC_H_
#define _GADC_H_
#include <mach/board.h>
#include <mach/init.h>
#include <mach/at32ap700x.h>
#define DEV_NAME “msuhu”
#define DEV_MAJOR 100
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define PIN_DATA1 GPIO_PIN_PB(7)
#define PIN_DATA2 GPIO_PIN_PB(8)
#define PIN_DATA3 GPIO_PIN_PB(9)
#define PIN_DATA4 GPIO_PIN_PB(10)
#define PIN_DATA5 GPIO_PIN_PB(11)
#define PIN_DATA6 GPIO_PIN_PB(12)
#define PIN_DATA7 GPIO_PIN_PB(13)
#define PIN_DATA8 GPIO_PIN_PB(14)
#define SUCCESS 0
#endif /* _GADC_H */
2. Pembuatan Applikasi
Berikut ini adalah applikasi end user, yang membaca data suhu dari device driver, dan menyimpannya pada sebuah file text. Applikasi dicompile dengan menggunakan avr32-gcc.
/*
* logger.c – applikasi logger pada user space
*
* applikasi logger berfungsi untuk membaca
* data tegangan ADC, dan menyimpan data hasil
* konversinya dalam satuan derajat celcius,
* pada file log
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#define DEV_NAME “/dev/msuhu”
#define FILE_LOG “/home/suhu.log”
#define FILE_TMP “/home/tmp.log”
#define MAX_LOG 10
/*
* convert_suhu() – konversi tegangan ADC ke satuan
* derajat celcius
* v_adc[IN] : tegangan ADC
* RETURN:
* – Data Suhu (jika sukses)
* – negatif jika error
*/
int convert_suhu(int v_adc)
{
int suhu = 0;
int vin = 0;
int vref = 3300; /* on mV */
/* N = (vin / vref )* 256
* N : ADC Data register
* vref : 3.3 v (3300 mV)
* 256: 8bit data register
*/
vin = (v_adc * vref) / 1024;
/* konversi suhu LM35 -> Vin = 10/oC */
suhu = vin / 10;
return suhu;
}
/*
* check_max() – cek maksimum data pada file log
*/
void check_max(void)
{
FILE *fp, *tmp;
int i = 0;
char data_suhu[MAX_LOG + 2][3];
char buff[3];
fp = fopen(FILE_LOG, “r”);
while (!feof(fp)) {
/* simpan data sebagai temporari */
fscanf(fp, “%s”, buff);
strcat(buff, “”);
memset(data_suhu[i], 0×00, sizeof(buff));
memcpy(data_suhu[i++], buff, sizeof(buff));
}
fclose(fp);
/* cek jumlah data */
if (i > MAX_LOG + 1) {
int j;
/* update data file log juka data > 10 */
tmp = fopen(FILE_TMP, “a+”);
for (j = 0; j < MAX_LOG; j++) {
fprintf(tmp, “%s\n”, data_suhu[j + 1]);
}
fclose(tmp);
system(“mv /home/tmp.log /home/suhu.log”);
}
}
/*
* main() – applikasi utama
*/
int main (void)
{
char data_reg = 0;
int fd = 0;
int ret = 0;
int suhu = 0;
FILE *fp;
/* open device driver */
fd = open(DEV_NAME, O_RDONLY);
if (fd < 0) {
perror(“open device”);
return fd;
}
while (1) {
/* baca tegangan ADC */
ret = read(fd, &data_reg, sizeof(data_reg));
if (ret < 0) {
perror (“read device”);
goto err0;
}
/* convert to celcius */
suhu = convert_suhu((int) data_reg);
/* save to file log */
fp = fopen(FILE_LOG, “a+”);
fprintf(fp, “%d\n”, suhu);
fclose(fp);
/* cek maksimum data pada file log */
check_max();
/* delay 1s */
sleep(1);
}
ret = 0;
err0:
close(fd);
return ret;
}
Penjelasan diatas adalah penjelasan tentang core applikasi untuk sistem pemantauan suhu ruangan. Masih terdapat beberapa hal kecil lainnya, yang harus digunakan untuk mendukung berjalannya sistem pemantau suhu ruangan tersebut. Hal-hal lainnya adalah seperti memasukkan kernel modul kedalam sistem kernel. Hal tersebut dapat dilakukan dengan menggunakan perintah linux yaitu insmod. Hal lain yang perlu diperlukan adalah membuat applikasi berbasis web, sehingga pemantauan dapat dilakukan pada browser.
Sekian pembahasan tentang sistem monitoring suhu menggunakan linux embedded system, semoga bermanfaat.
cheers….

