Remote Temperature/Humidity Checker using TTS

2015. 10. 8. 14:442018년 이전 관심사/개발관련

반응형

Remote Temperature/Humidity Checker & LED controller

앞에서 설명한 mbed RPC Library와 Python Interface를 활용한 예제를 만들어 보려고 하다 보니 제목이 거창해 진거 같다.

간단하게 말하자면, 본 예제는 아래와 같은 기능을 수행한다.

  • mbed platform의 3색 LED 제어 ( On/Off )
  • mbed platform의 현재 LED 상태 확인 ( Smartphone의 TTS 기능을 이용하여 Green,Blue,Red 인지 상태 확인 기능 )
  • mbed platform으로 부터 온도, 습도 정보를 확인 ( Smartphone의 TTS 기능을 이용하여 온/습도 정보를 확인 가능)

본 예제에서는 mbed RPC를 이용하여 스마트폰에서 mbed platform을 제어하고 있으며, 스마트폰의 Application은 python 기반의 kivy 라이브러리를 사용하였다.

20150727_132817

mbed HTTP RPC Server

본 장에서는 위에서 설명한 동작을 수행하기 위한 mbed code를 구현하는 방법에 대해 설명한다. 아래 코드는 mbed rpc와 HTTP Server 등을 구동하기 위한 코드이며, 사용된 라이브러리는 아래와 같다. mbed platform에 아래 코드를 컴파일해서 Upload 하면, 외부에서 HTTP Data를 이용하여 mbed platform을 제어 할 수 있다.

  • DHT : 온/습도 센서를 제어 하기 위한 라이브러리
  • HTTPServer : HTTP Server를 위한 라이브러리
  • mbed-rpc : mbed RPC를 위한 라이브러리
  • WIZnetInterface : 별도의 Software stack 없이 Ethernet을 사용하기 위한 라이브러리

Example Code는 아래 경로에서 다운로드 할 수 있다.
RPC_HTTP_WIZnetInterface

#include "mbed.h"
#include "EthernetInterface.h"
#include "HTTPServer.h"
#include "mbed_rpc.h"
#include "DHT.h"

RpcDigitalOut led1(D9,"led1");
RpcDigitalOut led2(D10,"led2");
RpcDigitalOut led3(D11,"led3");

//RPCVarialbe<float> RPCTemperature(&GetTemperature, "Temperature");
//RPCVarialbe<float> RPCHumidity(&GetHumidity, "Humidity");
void Get_Temp_and_Humidity(Arguments * input, Reply * output);

RPCFunction Temp_and_Humidity_Finder(&Get_Temp_and_Humidity, "Temp_and_Humidity_Finder");

EthernetInterface eth;  
HTTPServer svr;

DHT sensor(D4, DHT11);

void Get_Temp_and_Humidity(Arguments * input, Reply *output){
    int error = 0;
    float h = 0.0f, c = 0.0f;
    char arg[100];

    error = sensor.readData();
    if (0 == error) {
        c   = sensor.ReadTemperature(CELCIUS);
        h   = sensor.ReadHumidity();
        sprintf(arg,"Temperature in Celcius: %4.2f, Humidity is %4.2f",c, h);

        output->putData(arg);
    }
}

int main() {
  //Turn the LEDs off
  uint8_t mac_addr[6] = {0x00, 0x08, 0xDC, 0x32, 0x23, 0x42}; 
  led1.write(0);
  led2.write(0);
  led3.write(0);

  RPC::add_rpc_class<RpcDigitalOut>();

  printf("Setting up...\n");
  eth.init(mac_addr);
  int ethErr = eth.connect();
  if(ethErr < 0)
  {
    printf("Error %d in setup.\n", ethErr);
    return -1;
  }
  svr.addHandler<HTTPRpcRequestHandler>("/rpc");

  //attach server to port 80
  printf("Listening...\n");
  svr.start(80, &eth);

  Timer tm;
  tm.start();
  //Listen indefinitely
  while(true)
  {
    svr.poll();
    if(tm.read()>.5)
    {
      tm.start();
    }
  }
}
  • 7~8 : 3색 LED를 위한 GPIO를 RPC에 등록
  • 15 : 온/습도를 얻어 오기 위한 Custom 함수를 RPC에 등록
  • 22~35 : Custom 함수의 구현 부
    • mbed RPC client로 부터 요청이 들어오면 온/습도를 추출한 후, Temperature in Celcius : … “ 데이터를 RPC client에게 송신 한다.
  • 54 : HTTPRPC Request 등록

Smartphone Simple Application

본 장에서는 Smartphone에서 mbed device를 제어하기 위한 간단한 Application을 만드는 방법을 설명한다. 본 예제는 python으로 구현 하였으며, UI를 위해 kivy 라이브러리를 사용하였다. 본 예제를 구현 및 구동하기 위해서는 아래와 같은 절차를 수행 해야 한다.

Download Qpython

Android 폰에서 python을 구동하기 위해서는 Qpython 이라는 프로그램이 필요 하며, 다운로드 경로는 아래와 같다.
QPython Download

20150727_140513

앞에서 설명한 것과 같이 python으로 UI를 만들기 위해서는 kivy 라이브러리가 필요하며, 스마트폰의 TTS(Text to Speach) 기능을 사용하기 위해서는 AndroidHelper 라이브러리가 있어야 한다. 각각의 라이브러리는 아래 그림과 같은 절차를 수행하면 설치 할 수 있다.

20150727_140920 20150727_141000 20150727_141026

20150727_141051 20150727_141110 20150727_141151 20150727_141247

Edit Source Code

스마트폰 앱으로 소스코드를 작성하는 일은 매우 불편하다. 다행히도 QPython은 미리 작성한 코드를 FTP로 핸드폰에 저장하는 기능을 지원하고 있다.
나는 이 기능을 이용해서 PC에서 미리 구현해 놓은 프로그램을 스마트폰에 복사 한 후 실행하는 절차로 코드를 구현 및 디버깅 했다. ( 이 또한 매우 불편 하였다. )

Setting for FTP

아래 그림과 같은 절차를 수행하면 Qpython의 FTP 기능을 사용 할 수 있다.

20150727_143112 20150727_143133 20150727_143156

Upload Source Code to Smartphone

아래 그림들은 PC에서 QPython의 FTP Server에 접속해서 미리 작성한 코드를 업로드 하는 방법을 나타낸다.

20150727_143344

FTP 접속에 성공하면 아래와 같이 Qpython의 폴더 트리를 볼 수 있다. 폴더 트리에 나오는 폴더를 하나 선택하여 미리 작성한 코드를 업로드 하면 된다.

20150727_143413

나는 project3/RPC_TTS 폴더를 만들고 kivy.py와 mbedRPC.py를 복사 해서 사용한다.
mbedRPC.py는 앞에서 설명한 mbed python RPC library이며, kivy.py는 Application의 UI 및 동작을 구현한 파일이다.

20150727_143443

Source code of kivy.py

#-*-coding:utf8;-*-
#qpy:2
#qpy:kivy

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from mbedRPC import *
import androidhelper

class CommandScreen(GridLayout):
    def __init__(self, **kwargs):
        super(CommandScreen, self).__init__(**kwargs)
        self.cols = 2
        self.row = 2
        self.row_force_default=True
        self.row_default_height=200

        self.add_widget(Label(text='Device IP'))
        self.m_text_device_ip = TextInput(multiline=False,text="192.168.18.121")
        self.add_widget(self.m_text_device_ip)

        self.m_button_init = Button(text="Init")
        self.m_button_init.bind(on_press=self.mbedInit)
        self.add_widget(self.m_button_init)

        self.m_button_GetTemp = Button(text="Get Temp")
        self.m_button_GetTemp.bind(on_press=self.GetTemp)
        self.add_widget(self.m_button_GetTemp)

        self.btn_onLed1 = Button(text="Turn On",background_color=(1,0,0,1))
        self.btn_onLed1.bind(on_press=self.TurnOnLed1)
        self.add_widget(self.btn_onLed1)

        self.btn_offLed1 = Button(text="Turn Off",background_color=(1,0,0,1))
        self.btn_offLed1.bind(on_press=self.TurnOffLed1)
        self.add_widget(self.btn_offLed1)

        self.btn_onLed2 = Button(text="Turn On",background_color=(0,1,0,1))
        self.btn_onLed2.bind(on_press=self.TurnOnLed2)
        self.add_widget(self.btn_onLed2)

        self.btn_offLed2 = Button(text="Turn Off",background_color=(0,1,0,1))
        self.btn_offLed2.bind(on_press=self.TurnOffLed2)
        self.add_widget(self.btn_offLed2)

        self.btn_onLed3 = Button(text="Turn On",background_color=(0,0,1,1))
        self.btn_onLed3.bind(on_press=self.TurnOnLed3)
        self.add_widget(self.btn_onLed3)

        self.btn_offLed3 = Button(text="Turn Off",background_color=(0,0,1,1))
        self.btn_offLed3.bind(on_press=self.TurnOffLed3)
        self.add_widget(self.btn_offLed3)

        self.btn_getLedStatus = Button(text="LED Status")
        self.btn_getLedStatus.bind(on_press=self.GetLedStatus)
        self.add_widget(self.btn_getLedStatus)

        self.btn_getA0Status = Button(text="Get A0 Status")
        self.btn_getA0Status.bind(on_press=self.GetA0Status)
        self.add_widget(self.btn_getA0Status)


    def mbedInit(self,event):
        self.droid = androidhelper.Android()

        self.mbed = HTTPRPC(self.m_text_device_ip.text)
        self.led1 = DigitalOut(self.mbed,"led1")
        self.led2 = DigitalOut(self.mbed,"led2")
        self.led3 = DigitalOut(self.mbed,"led3")
        self.temp_humidity = RPCFunction(self.mbed,"Temp_and_Humidity_Finder")

        box = BoxLayout(orientation='vertical')
        box.add_widget(Label(text='Init Complete'))
        button_close = Button(text='Close me!')
        box.add_widget(button_close)

        popup = Popup(title='message', content=box,
                      size_hint=(None,None),size=(400,400), auto_dismiss=False)

        button_close.bind(on_press=popup.dismiss)
        popup.open()


    def GetTemp(self,event):
        resp = self.temp_humidity.run("")
        self.droid.ttsSpeak(resp)

    def TurnOnLed1(self,event):
        self.led1.write(1)

    def TurnOffLed1(self,event):
        self.led1.write(0)

    def TurnOnLed2(self,event):
        self.led2.write(1)

    def TurnOffLed2(self,event):
        self.led2.write(0)

    def TurnOnLed3(self,event):
        self.led3.write(1)

    def TurnOffLed3(self,event):
        self.led3.write(0)

    def GetLedStatus(self,event):
        if( self.led1.read()[0] == '1' ): self.droid.ttsSpeak("Turn on red.")
        if( self.led2.read()[0] == '1' ): self.droid.ttsSpeak("Turn on green.")
        if( self.led3.read()[0] == '1' ): self.droid.ttsSpeak("Turn on blue.")

    def GetA0Status(self,event):
        print ''

class MyApp(App):
    def build(self):
        return CommandScreen()        

if __name__ == '__main__':
    MyApp().run()
  • 15 ~ 65 : App Button 및 UI 초기화
  • 68 ~ 86 : mbed RPC library 초기화
  • 89 : mbed platform으로 부터 온/습도 데이터를 수신 후 TTS로 출력
  • 93 ~ 109 : LED1/2/3 On/Off
  • 111 ~ 114 : 현재 mbed platform의 LED 색깔을 확인 후 TTS로 출력

Result after run

20150727_130822

Demo Video

반응형