CommonLisp와 RaspberryPi로 웹 애플리케이션 ~ I2C 온도 센서 ~

소개



이번에는 I2C에서 ADT7410 을 사용한 온도 센서 모듈을 제어하고 싶습니다.

회로도, 디바이스 주소의 확인은 CommonLisp에서 RaspberryPi 전자 공작 ~I2C 온도 센서~ 의 기사를 참조해 주세요.

또한 이번에도 L치카편 같은 각종 라이브러리를 최신으로 할 필요가 있습니다.

패키징



cffi, clack, clack-app-route, cl-markup을 Quicklisp로 로드하고 패키지 정의.

packages.lisp
;; Load CFFI, Clack, cl-markup
(ql:quickload :cffi)
(ql:quickload :clack)
(ql:quickload :clack-app-route)
(ql:quickload :cl-markup)

;; Declare as a package
(defpackage cl-iot
  (:use :common-lisp
        :cffi
        :clack
        :clack.request
        :clack.app.route
        :cl-markup))

API 래퍼 작성



이전부터 전자 공작에서 사용하고 있던 것을 사용.
이번에는 I2C 라이브러리 사용

libwiringPi.lisp
(define-foreign-library libwiringPi
  (:unix "libwiringPi.so"))

(use-foreign-library libwiringPi)

;;;; Core function

;; Initialization of the wiringPi
(defcfun "wiringPiSetupGpio" :int)

;; Set the mode of the GPIO pin
(defcfun "pinMode" :void (pin :int) (mode :int))

;; GPIO pin output control
(defcfun "digitalWrite" :void (pin :int) (value :int))

;; Waiting process
(defcfun "delay" :void (howlong :uint))

;; Set the state when nothing is connected to the terminal
(defcfun "pullUpDnControl" :void (pin :int) (pud :int))

;; Read the status of the GPIO pin
(defcfun "digitalRead" :int (pin :int))

;;;; I2C Library

;; Initialization of the I2C systems.
(defcfun "wiringPiI2CSetup" :int (fd :int))

;; Writes 8-bit data to the instructed device register.
(defcfun "wiringPiI2CWriteReg8" :int (fd :int) (reg :int) (data :int))

;; It reads the 16-bit value from the indicated device register.
(defcfun "wiringPiI2CReadReg16" :int (fd :int) (reg :int))

웹 애플리케이션을 통한 I2C 온도 센서 프로그램



웹 브라우저에 "Update"라는 이름의 버튼을 하나 표시하고 해당 버튼을 누를 때마다 ADT7410에서 데이터를 검색하고 결과를 iframe에 표시하는 프로그램입니다.

I2C 온도 센서의 프로그램은 거의 지난번 과 같습니다.

iot-temperature.lisp
;; Load packages
(load "packages.lisp" :external-format :utf-8)

(in-package :cl-iot)

;; Load wrapper API
(load "libwiringPi.lisp" :external-format :utf-8)

;; I2C device address (0x48)
(defconstant +i2c-addr+ #X48)

;; i2c initial setting
(defparameter *fd* (wiringPiI2CSetup +i2c-addr+))

;; Set to register "0x03" to acquire temperature as 16-bit data
(wiringPiI2CWriteReg8 *fd* #X03 #X80)

(defun byte-swap (num-value)
  (let (str-value temp-msb temp-lsb)
    ;; Convert numeric value to character string
    (setq str-value (write-to-string num-value :base 16))
    ;; Get upper two digits (MSB)
    (setq temp-msb (subseq str-value 0 2))
    ;; Get the lower 2 digits (LSB)
    (setq temp-lsb (subseq str-value 2))
    ;; Swap to join
    (setq str-value (concatenate 'string temp-lsb temp-msb))
    ;; Convert string to numeric value
    (parse-integer str-value :radix 16)))

(defun get-temperature ()
  (* (byte-swap (wiringPiI2CReadReg16 *fd* #X00)) 0.0078))

;; Create Web page
(defun web-page ()
  (list
   (markup
    (html
     (:head
      (:meta :content "text/html" :charset "UTF-8")
      (:title "Web Application with Common Lisp and RaspberryPi"))
     (:body
      (:p "Temperature") (:br)
      (:form :method "post" :action "/post" :target "iframe"
             (:input :type "submit" :name "temperature" :value "Update"))
      (:iframe :name "iframe"))))))

;; Create index
(defun index (env)
  (declare (ignore env))
  `(200
    (:content-type "text/html")
    ,(web-page)))

;; POST process
(defun post (env)
  (declare (ignore env))
  `(200
    (:content-type "text/plain")
    ,(list
      (format nil "Temperature : ~a" (get-temperature)))))

;; Web Application Function
(defroutes app (env)
  (GET "/" #'index)                ; Call "function index" when GET is called "/"
  (POST "/post" #'post))           ; Call "function post" when POST is called "/"

;; Main function
(defun main ()
  ;; Clack UP
  (clackup #'app :port 5000 :debug t))

;; Execution
(main)

실행



다음 명령으로 실행합니다.
sbcl --load iot-temperature.lisp

clack-handler-hunchentoot까지 로드가 성공하면, 여러가지 단말로부터 「http://"RaspberryPi의 IP주소":5000/」에 Web브라우저로부터 액세스 해 보세요.

이하 실행중인 모습

Update 버튼을 누르면 iframe 내에 온도가 표시됩니다.



다시 Update 버튼을 누르면 온도가 업데이트됩니다.



마지막으로



I2C 온도 센서로부터 취득한 데이터를 웹 브라우저상에 표시하는 것으로, LAN내의 다른 디바이스로부터 확인할 수 있게 되었습니다~! ∩(・ω・)∩
이것을 LAN내 뿐만이 아니라 인터넷상에서 볼 수 있도록 하면 외출처에서도 집의 온도를 확인할 수 있네요.
뭐, 그 경우 시큐리티에 대해서 더 제대로 생각하지 않으면 안됩니다만・・・.

이번 소스 코드는 Github에서 공개하고 있습니다.
잘하면 아래에서 부디 ~.
· Github

좋은 웹페이지 즐겨찾기