'작업대/프로젝트'에 해당되는 글 9

  1. 2019.04.26 Asus Rog 소프트웨어
  2. 2016.10.25 IoT 수위레벨제어장치(C언어,MySQL,PHP,자바) 2
  3. 2016.09.23 앱인벤터를 통한 전용 구동어플 제작
  4. 2016.09.23 DB에 저장된 데이터 출력
  5. 2016.09.21 데이터베이스 연동을 위한 APM 설치
  6. 2016.08.26 IoT 수위레벨 제어장치 전용어플 1
  7. 2016.08.26 이더넷실드를 이용한 FTP 방식
  8. 2016.08.25 0826일자 참고용 주석
  9. 2016.08.24 아두이노를 이용한 초음파 수위측정 #1



모바일정보통신과라는 특징을 살려 졸업작품으로 스마트폰과 다양한 웹플랫폼에서 열람 가능한 IoT수위측정장치를 제작했습니다.

산업현장이나 대형건물에서 사용되는 생활용수를 확인하기 위해  직접 저수조를 확인하지 않아도 수위를 체크할 수 있고 온도를 함께 측정함으로써 동파를 방지하는 것이 목적입니다. 초음파센서를 이용하여 상단에 부착하기만 하면 설비의 규격에 관계없이 측정이 가능한 점이 특징입니다.


컨트롤을 위한 처리작업은 아두이노 보드에 사용되는 Atmega328프로세서를 이용했으며 C언어를 기반으로 하여 프로그래밍 한 뒤 (하드웨어에 대한설명)


수위가 변화되는 상태를 실시간으로 보여드리기 위한 방법으로 평소 쉽게 접할 수 있는 스마트폰에서 쓰이는 OS죠? 안드로이드의 블루투스기능을 먼저 생각했습니다. 자바를 이용한 이클립스에서 개발을 시작하여 추후 컴파일이 용이한 앱인벤터로 옮겨 어플리케이션을 제작했습니다.


실시간으로 확인하는 것으로 그치지 않고 데이터베이스에 측정값을 주기적으로 업로드할 것을 제안했습니다. 이 과정에서 블루투스가 가진 성능의 부족함을 메꾸거나 와이파이모듈을 이용하였고 블루투스로 연동할 당시의 기능이 이 부분(앱에서 BT선택, 온도 수위부분 레이블 가리키며)입니다. 제작이 진행되면서 현재는 비활성화한 상태이지만 개발 과정을 보여드리기 위해 남겨 놓았습니다.

리눅스에서 사용되는 대표적인 웹서버소프트웨어인 Apache를 이용하여 서버를 구축하였고 MySQL에서 데이터베이스의 틀을 갖춘 뒤 PHP를 이용하여 DB에 계측데이터를 올려보내고 이와 동시에 저장된 내용을 웹브라우저에서 열람할 수 있도록 제작하였습니다.


KopoA.aia

앱인벤터 프로젝트 파일

KopoA.apk

안드로이드 설치파일




먼저 우리조 서버와 데이터가 준비되지 않아 준비해놓은 데이터로 출력테스트를 했습니다.


테스트해본 조건은 '최근날짜부터 나열'해서 '3일내'의 데이터만 출력

$result = mysqli_query($conn,"SELECT * FROM dblogin WHERE CreateDate >= DATE_ADD(NOW(), INTERVAL -3 day) ORDER BY CreateDate DESC;");



이유 : " . mysqli_connect_error();
}
		$result = mysqli_query($conn,"SELECT * FROM dblogin
				WHERE CreateDate >= DATE_ADD(NOW(), INTERVAL -3 day) 
				ORDER BY CreateDate DESC;");
		echo "";
		$n = 1;
		while($row = mysqli_fetch_array($result))
{
			echo "<tr>";
			echo "<td>" . $row['gldx'] . "</td>";
			echo "<td>" . $row['uldx'] . "</td>";
			echo "<td>" . $row['gps_lat'] . "</td>";
			echo "<td>" . $row['gps_lon'] . "</td>";
			echo "<td>" . $row['CreateDate'] . "</td>";
			echo "</tr>";
			$n++;
}
?>




졸업작품이 서버연동만을 남겨둔 지금 더 기다려봤자 진행이 없을 것 같아
직접 데이터베이스를 설치해보기로 했습니다.


APM이란?

리눅스OS에서의 사용되는 웹 서버 소프트인 Apache, PHP, MySQL을 가리키며

APMsetup이라는 한국인 개발자가 만든 원클릭 설치 프로그램을 사용합니다.

-공식사이트(http://www.apmsetup.com)가 더이상 운영되지않아 네이버, 오픈소스 자료실에서 다운로드가 가능합니다.




http://software.naver.com/software/summary.nhn?softwareId=MFS_111815

https://kldp.net/apmsetup

마지막 버전은 APMSETUP7로 릴리즈순으로 가장 아래에서 3221-APMSETUP7_2010010300.exe를 사용합니다.




설치를 마치고 실행하면 아래와 같은 창이 뜨며 곧바로 공지를 보여주나 더이상 체크되지 않습니다.


공지창을 닫은 뒤에 뜨는 업데이트를 묻는 창도 마찬가지입니다. 아니오를 눌러 매니저가 꺼지지 않게 합니다.


 

projectproto_2.aia

목표)

초음파센서와 온도센서를 통한 수조내부의 물높이, 수온측정 > 어플로 확인이 용이, 데이터베이스에 저장하므로써 그래프로 통계기능 추가예정


구현내용)

LCD 수위,수온 표시

와이파이실드를 통한 확인페이지 출력

어플상에서 각 4바이트씩 8바이트값을 받아와서 나눠 출력


TH_ftp.zip



http://cafe.naver.com/arduinostory/31761


http://swa.esy.es/

http://31.170.164.122


#include <SPI.h>

#include <Ethernet.h>

#include <minWire.h>

#include <minRTClib.h>

#include <dht.h>



//-------------------------------------DS-1307

RTC_DS1307 rtc;

DateTime  tod;


//-------------------------------------DHT-11

#define DHT11_PIN A0

#define UPLOAD_INTERVAL (uint32_t)60*1000     //1�п� �ѹ� sesnor read. Arduino default�� 16bit int, (uint32_t)�� ���صθ� -5536���� �ǹ�����.


dht DHT;


float humidity;

float temperature;


void DHTPoll();

//-------------------------------------Ethernet

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0x25, 0xC4 };


IPAddress server(31, 170, 164, 122);             //   FTP 서버 IP 입니다. 

EthernetClient client;

EthernetClient dclient;


char outBuf[128];

char outCount;


//-------------------------------------Sensor Identification

char fileName[32];

char sectorID[8] = "T0001";

char sensorID[8] = "S0001";


//-------------------------------------working

uint32_t lastPollTime = 0;


/*-----------------------------------------------------------------------------

   S E T  U P

  -----------------------------------------------------------------------------*/

void setup(){

  Serial.begin(9600);

  Wire.begin();

  rtc.begin();

  Ethernet.begin(mac);

  //rtc.adjust(DateTime(2014, 9, 27, 15, 02, 0));

}

/*-----------------------------------------------------------------------------

   L O O P

  -----------------------------------------------------------------------------*/

void loop(){


  //for test

  if(Serial.read() != -1) DHTPoll();


  if((millis() - lastPollTime) >= UPLOAD_INTERVAL){

    lastPollTime = millis();

    DHTPoll();

  }

}

/*-----------------------------------------------------------------------------

   D H T - 1 1   h a n d l e r

  -----------------------------------------------------------------------------*/

void DHTPoll() {

  if(DHT.read11(DHT11_PIN) == DHTLIB_OK) {

    humidity = DHT.humidity;

    temperature = DHT.temperature;

    makeSensorLog();


    if(doFTP()) Serial.println(F("FTP Upload OK"));

    else Serial.println(F("FTP Upload FAIL"));

  }

}


/*-----------------------------------------------------------------------------

   F T P  File Form


  SectorId_YYMMDD.log


    <SensorID> hh:mm tt.tC hh.h%


    tt.t : temperature

    hh.h : humidity

  -----------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------

   F T P  Upload

  -----------------------------------------------------------------------------*/

byte doFTP(){


  //--------------------

  // command port connection (21)

  //--------------------

  if (client.connect(server,21)) {

    Serial.println(F("Command connected"));

  } 

  else {

    Serial.println(F("Command connection failed"));

    return 0;

  }

  if(!eRcv(0)) return 0;


  //--------------------

  // USER

  //--------------------

  client.println(F("USER swa"));         //사용자 아이디

  if(!eRcv(0)) return 0;


  //--------------------

  // PASS

  //--------------------

  client.println(F("PASS 951753"));                //사용자 비밀번호

  if(!eRcv(0)) return 0;


  //--------------------

  // CWD

  // goto log folder

  //--------------------

  client.println(F("CWD /Temp_Humidity_log/"));        //파일을 저장할 경로

  if(!eRcv(0)) return 0;


  //--------------------

  // SIZE

  // check file exist

  //--------------------

  makeLogFileName();

  client.print(F("SIZE "));

  client.println(fileName);

  byte openType = eRcv(1);


  //--------------------

  // PASV

  // Passive mode, get data port number

  //--------------------

  client.println(F("PASV"));

  if(!eRcv(0)) return 0;


  char *tStr = strtok(outBuf,"(,");

  int array_pasv[6];

  for ( int i = 0; i < 6; i++) {

    tStr = strtok(NULL,"(,");

    array_pasv[i] = atoi(tStr);

    if(tStr == NULL)Serial.println(F("Bad PASV Answer"));    

  }


  unsigned int hiPort,loPort;

  hiPort = array_pasv[4] << 8;

  loPort = array_pasv[5] & 255;


  Serial.print(F("Data port: "));

  hiPort = hiPort | loPort;

  Serial.println(hiPort);


  //--------------------

  // Upload

  //--------------------

  if (dclient.connect(server,hiPort)) {

    Serial.println(F("Data connected"));

  } 

  else {

    Serial.println(F("Data connection failed"));

    client.stop();

    return 0;

  }


  if(openType) client.print(F("APPE "));  

  else client.print(F("STOR "));

  

  client.println(fileName);

  if(!eRcv(0)){

    dclient.stop();

    return 0;

  }


  Serial.println(F("Writing"));


  makeSensorLog();

  dclient.write(outBuf,strlen(outBuf));


  dclient.stop();

  Serial.println(F("Data disconnected"));

  if(!eRcv(0)) return 0;


  client.println(F("QUIT"));

  if(!eRcv(0)) return 0;


  client.stop();

  Serial.println(F("Command disconnected"));


  return 1;

}


byte eRcv(byte errRet){

  byte respCode;

  byte thisByte;


  while(!client.available()) delay(1);


  respCode = client.peek();


  outCount = 0;


  while(client.available())

  {  

    thisByte = client.read();    

    Serial.write(thisByte);


    if(outCount < 127)

    {

      outBuf[outCount] = thisByte;

      outCount++;      

      outBuf[outCount] = 0;

    }

  }

  if(respCode >= '4')

  {

    if(!errRet)efail();

    return 0;  

  }


  return 1;

}



void efail()

{

  byte thisByte = 0;


  client.println(F("QUIT"));


  while(!client.available()) delay(1);


  while(client.available())

  {  

    thisByte = client.read();    

    Serial.write(thisByte);

  }


  client.stop();

  Serial.println(F("Command disconnected"));

}


//-----------------------------------------------------------------------------

void makeLogFileName(void){


  int i;

  char *pc = fileName;


  for(i=0;i<strlen(sectorID);i++){

    *pc++ = sectorID[i];

  }

  *pc++ = '_';


  DateTime now = rtc.now();

  simpleInt2Arry((byte)(now.year() - 2000), pc);

  pc += 2;

  simpleInt2Arry(now.month(), pc);

  pc += 2;  

  simpleInt2Arry(now.day(), pc);  

  pc += 2;    

  *pc++ = '.';

  *pc++ = 'l';

  *pc++ = 'o';

  *pc++ = 'g';  

  *pc = 0x00;    

}

//-----------------------------------------------------------------------------

void makeSensorLog(void){

  byte i;


  char *pc = outBuf;


  *pc++ = '<';

  for(i=0;i<strlen(sensorID);i++){

    *pc++ = sensorID[i];

  }

  *pc++ = '>';  

  *pc++ = ' ';


  DateTime now = rtc.now();

  simpleInt2Arry(now.hour(), pc);

  pc += 2;  

  *pc++ = ':';

  simpleInt2Arry(now.minute(), pc);  

  pc += 2;    

  *pc++ = ' ';


  dtostrf(temperature, 5, 1, (char *)pc);  //-12.3C

  pc = outBuf + strlen(outBuf);

  *pc++ = 'C';

  *pc++ = ' ';  


  dtostrf(humidity, 5, 1, (char *)pc);  //100.3%

  pc = outBuf + strlen(outBuf);

  *pc++ = '%';


  *pc++ = 0x0d;  

  *pc++ = 0x0a;  

  *pc = 0x00;  

}  


//-----------------------------------------------------------------------------

void simpleInt2Arry(byte i, char* pc){

  *(pc + 1) = (i % 10) + 0x30;

  i /= 10;

  *pc = (i % 10) + 0x30;

}





#include "Ultrasonic.h"                     //초음파센서 외부라이브러리
#include <LiquidCrystal.h>               //LCD 라이브러리
//#include <SoftwareSerial.h>           //블루투스 라이브러리

//와이파이 라이브러리
#include <SPI.h>
#include <WiFi.h>
//#include <Ethernet.h> //이더넷 라이브러리 - 사용하지않음



// SoftwareSerial(RX, TX) 블루투스 핀번호 지정
//SoftwareSerial BTSerial(9, 10);

LiquidCrystal lcd(0, 1, 2, 3, 4, 5);     // LCD 핀번호 지정 BS E D4 D5 D6 D7

Ultrasonic ultrasonic(7,6);                // 초음파센서 핀번호 지정 Tring,Echo

// 데이터를 수신 받을 버퍼
byte buffer[1024];
int bufferPosition;
//--------------------------------------------------------------
int DHpin = 8;                             //습온도센서 핀번호 지정
byte dat [5];
byte read_data () {
  byte data;
  for (int i = 0; i < 8; i ++) {
    if (digitalRead (DHpin) == LOW) {
      while (digitalRead (DHpin) == LOW); // wait for 50us
      delayMicroseconds (30); // determine the duration of the high level to determine the data is '0 'or '1'
      if (digitalRead (DHpin) == HIGH)
        data |= (1 << (7-i)); // high front and low in the post
      while (digitalRead (DHpin) == HIGH); // data '1 ', wait for the next one receiver
     }
  }
return data;
}

//습온도센서 함수
void start_test () {
  digitalWrite (DHpin, LOW); // bus down, send start signal
  delay (30); // delay greater than 18ms, so DHT11 start signal can be detected
 
  digitalWrite (DHpin, HIGH);
  delayMicroseconds (40); // Wait for DHT11 response
 
  pinMode (DHpin, INPUT);
  while (digitalRead (DHpin) == HIGH);
  delayMicroseconds (80); // DHT11 response, pulled the bus 80us
  if (digitalRead (DHpin) == LOW);
  delayMicroseconds (80); // DHT11 80us after the bus pulled to start sending data
 
  for (int i = 0; i < 4; i ++) // receive temperature and humidity data, the parity bit is not considered
    dat[i] = read_data ();
 
  pinMode (DHpin, OUTPUT);
  digitalWrite (DHpin, HIGH); // send data once after releasing the bus, wait for the host to open the next Start signal
}

//-----------------------------------------------

char ssid[] = "솔라씨";      //  연결되는 와이파이 SSID
char pass[] = "01094062682";   // 네트워크 보안키

int status = WL_IDLE_STATUS;

WiFiServer server(80);  // 80  포트를 사용하는 웹서버 선언














void setup() {
  // LCD 초기화 (16 rows, 2 columns)
  lcd.begin(16, 2);
  Serial.begin(9600);
//  BTSerial.begin(9600);
 
  // 버퍼 위치 초기화
  bufferPosition = 0;
  pinMode (DHpin, OUTPUT);

//와이파이
 if (WiFi.status() == WL_NO_SHIELD) { // 현재 아두이노에 연결된 실드를 확인
    Serial.println("WiFi shield not present");
    while (true);  // 와이파이 실드가 아닐 경우 계속 대기ㅇㅇ
  }
 
  // 와이파이에 연결 시도
  while ( status != WL_CONNECTED) { //연결될 때까지 반복ㅇㅇ
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);  // WPA/WPA2 연결
  }//ㅇㅇ

  server.begin();

  printWifiStatus();  // 연결 성공시 연결된 네트워크 정보를 출력
}

//--------------------------------------------------------------
char Ldistance[4] = {0,};
 













void loop() {
  lcd.clear();
  // LCE에 표시되는 메시지
  lcd.print("Blueswa ;)");
  // Display Temperature in C
  // -----------------------------------------------------------
  lcd.setCursor(11, 0);
 

  start_test ();
  //lcd.print ("Current humdity ="); //습도 - 사용하지않음
  //lcd.print (dat [0], DEC); // display the humidity-bit integer 상수;
  //lcd.print ('.');
  //lcd.print (dat [1], DEC); // display the humidity decimal places 소수점;
  //lcd.println ('%');

 
  //lcd.print ("Current temperature ="); //온도
//  char a =dat [2];
  lcd.print(dat [2], DEC); // display the temperature of integer bits 상수;
  lcd.print('.');
  lcd.print(dat [3], DEC); // display the temperature of decimal places 소수점;
  lcd.print('C');
  //------------------------------------------------------------
 
  // 두번재 줄로 이동한다.
  lcd.setCursor(0, 1);

  lcd.print("Distance: ");
  // 거리를 측정한다.
  int b = ultrasonic.Ranging(CM);
  sprintf(Ldistance,"%03d",b); //초음파센서로 측정한 값을 Ldistance에 3자리로 저장한다
  lcd.print(Ldistance);
 
  lcd.print("cm");
 
  delay(500);
 
 
  WiFiClient client = server.available();  // 들어오는 클라이언트를 수신한다.
  if (client) {  // 클라이언트를 수신 시
    Serial.println("new client");  // 클라이언트 접속 확인 메시지 출력
    boolean currentLineIsBlank = true;

    while (client.connected ()) {
      if (client.available()) {
        char c = client.read();
        // 문자의 끝을 입력 받으면 http 요청이 종료되고, 답신을 보낼 수 있습니다.
        if (c == '\n' && currentLineIsBlank) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.println("Refresh: 1"); // 1초당 페이지 refresh
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<meta charset=utf-8/>");
          client.print("<meta name=view content=width=device-width, ");
          client.println("initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no />");
          client.println("<html>");
          client.println("<head>"); 
          client.println("<title>Many Sensor</title>");
          client.println("</head>");
          client.println("<h1>Many Sensor</h1>");
          client.println("<div data-role=content>");
          client.print("DH Sensor value : ");
          client.println(dat [2], DEC);           // 온도 센서 값 출력,dec(십진수)
          client.println("<br>");
          client.println("<br>");
          client.print("UltraSonic Sensor value : ");
          client.println(Ldistance);              // 초음파 센서 값 출력
          client.println("<br>");
          client.println("</div>");
          client.println("</body>");
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        }

        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
    Serial.println("client disonnected");
    // 클라이언트와 연결을 끊는다.
  }
 
















  // 블루투스로 데이터 수신-------------------------------------------
  int Temp = dat [2]; //온도
  int Distance = ultrasonic.Ranging(CM); //초음파센서
  char BTvalue[9] = {0,}; //전송문자열 정의
  sprintf(BTvalue,"%04d%04d",Temp,Distance); //문자열에 두측정값을 각 4자리로 순서대로 표기
//  BTSerial.print(BTvalue); //출력
 
}


void printWifiStatus() {  // 연결된 네트워크 정보 출력
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  // 네트워크 SSID 출력

  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  // 네트워크 ip 출력

  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
  // 수신 강도 출력
}



작품선정 > 플랫폼계획 > 재료구입 > 아두이노학습 > 부분구현 > 연동 > 디자인


졸업작품으로 고려한 항목을 나열해보면


  • 모바일통신과로서 데이터베이스를 활용한 네트워크, 어플연동
  • 졸업작품으로 끝나지않고 실질적인 사용이 가능한가
  • 많이 이용되는 기술을 사용하여 내가 배울 점이 있는지


Arduino Uno (ATmega328)

아두이노는 주로 Atmel사의 AVR을 사용하는 오픈소스 마이크로컨트롤러 보드 


기존의 수업에서 기판 납땜을 통해 RS통신과 8051 프로그래밍의 기초개념은 잡을 수 있으나 오래된 기술이라 자료가 부족했고 아두이노로 개발할 시 막히더라도 구글링을 통해 곧바로 문제점을 찾을 수 있었다.


추가적인 아두이노의 특징으로는

USB포트를 이용한 프로그램 업로드가 용이

3V와 5V의 전원단자를 지원하여 추가적인 전원회로가 필요하지않음