Sistem Monitoring Suhu (Part II)

Posted: February 8, 2011 in Embedded System, Linux

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

atngw100

 

adc modul

 

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….

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s