레이블이 Arduino인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Arduino인 게시물을 표시합니다. 모든 게시물 표시

2018년 3월 8일 목요일

아두이노의 수집된 정보를 서버에 저장 하는 방법

[출처 : http://arduinotronics.blogspot.kr/ ]

Build your own IOT service! Collect sensor data and send it to a web/database server.

Today's project uses an Arduino equipped with a Ethernet shield, and a DHT-11 temperature / humidity sensor.


  Arduino UNO
  Arduino Ethernet Shield
  DHT-11 Module

The Arduino reads the DHT-11, and submits the data to a php script on a hosted web server. That php page inserts the data into a mySQL database, and another php page creates a web page displaying the data as you can see below.

(ESP8266 / BME280 Version)
(UNO / WiFi BME280 Version)

- Arduino 부분
It's Alive, It's Alive. Ok, sounds better if done with a Dr. Frankenstein accent, but the Arduino WiFi wireless weather Server is alive. Starting with a Arduino UNO, we then stacked a Arduino WiFi shield, a adafruit Lithium Polymer battery shield, and a Sparkfun Protoshield with a Embedded Adventures BME280 breakout and a 3.3v - 5v level shifter. A 5v solar panel is on it's way to keep this charged,

Arduino UNO
Arduino WiFi
Adafruit LIPO
Sparkfun Protoshield
Embedded Adventures BME280 (schematics)
Embedded Adventures Level Shifter



Code (Video below)

#include <SPI.h>
#include <WiFi.h>


#include <BME280_MOD-1022.h>

#include <Wire.h>

IPAddress dns(192, 168, 254, 254);
IPAddress ip(192, 168, 254, 16); 
IPAddress gateway(192, 168, 254, 254);
IPAddress subnet(255, 255, 255, 0);

float temp, humidity,  pressure, pressureMoreAccurate, tempF, inHg, rH;
double tempMostAccurate, humidityMostAccurate, pressureMostAccurate;


char ssid[] = "your ssid";      // your network SSID (name)
char pass[] = "your password";   // your network password
int keyIndex = 0;                 // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;

WiFiServer server(80);

// print out the measurements

void printCompensatedMeasurements(void) {

char buffer[80];

  temp      = BME280.getTemperature();
  humidity  = BME280.getHumidity();
  pressure  = BME280.getPressure();
 
  pressureMoreAccurate = BME280.getPressureMoreAccurate();  // t_fine already calculated from getTemperaure() above
 
  tempMostAccurate     = BME280.getTemperatureMostAccurate();
  humidityMostAccurate = BME280.getHumidityMostAccurate();
  pressureMostAccurate = BME280.getPressureMostAccurate();

  Serial.print("Temperature  ");

  tempF = tempMostAccurate * 1.8 + 32.0;
  Serial.print(tempF);

  Serial.print(" ");
  Serial.print(char(176));
  Serial.println("F");
 
  Serial.print("Humidity     ");

  rH = humidityMostAccurate;
  Serial.print(rH);
  Serial.println(" %");

  Serial.print("Pressure     ");

  inHg = pressureMostAccurate * 0.0295299830714;
  Serial.print(inHg, 2);
  Serial.println(" in. Hg");
}


void setup() {
  Wire.begin();
 
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if ( fv != "1.1.0" )
    Serial.println("Please upgrade the firmware");

  // attempt to connect to Wifi network:

 
  WiFi.config(ip, dns, gateway, subnet);
 
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  server.begin();
  // you're connected now, so print out the status:
  printWifiStatus();
}


void loop() {
 
  uint8_t chipID;
 
  chipID = BME280.readChipId();
 
  // find the chip ID out just for fun
  //Serial.print("ChipID = 0x");
  //Serial.print(chipID, HEX);
 

  // need to read the NVM compensation parameters
  BME280.readCompensationParams();
 
  // Need to turn on 1x oversampling, default is os_skipped, which means it doesn't measure anything
  BME280.writeOversamplingPressure(os1x);  // 1x over sampling (ie, just one sample)
  BME280.writeOversamplingTemperature(os1x);
  BME280.writeOversamplingHumidity(os1x);
 
  // example of a forced sample.  After taking the measurement the chip goes back to sleep
  BME280.writeMode(smForced);
  while (BME280.isMeasuring()) {
    Serial.println("Measuring...");
    delay(50);
  }
  Serial.println("Done!");
 
  // read out the data - must do this before calling the getxxxxx routines
  BME280.readMeasurements();
 
  // Example for "indoor navigation"
  // We'll switch into normal mode for regular automatic samples
 
  BME280.writeStandbyTime(tsb_0p5ms);        // tsb = 0.5ms
  BME280.writeFilterCoefficient(fc_16);      // IIR Filter coefficient 16
  BME280.writeOversamplingPressure(os16x);    // pressure x16
  BME280.writeOversamplingTemperature(os2x);  // temperature x2
  BME280.writeOversamplingHumidity(os1x);     // humidity x1
 
  BME280.writeMode(smNormal);
  
  while (1) {
   
   
    while (BME280.isMeasuring()) {


    }
   
    // read out the data - must do this before calling the getxxxxx routines
    BME280.readMeasurements();
    printCompensatedMeasurements();
   
    delay(2000); // do this every 5 seconds
    Serial.println();
 
 
  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // output the value of each sensor

            client.print("Temperature ");
            client.println(tempF);
            client.print("&deg;");
            client.print("F");
            client.println("<br />");
            client.print("Humidity ");
            client.println(rH);
            client.print(" %");
            client.println("<br />");
            client.print("Pressure ");
            client.println(inHg);
            client.print(" in. Hg");
            client.println("<br />");
         
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);

    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}


}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);




  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}









- 서버 설정 [Source]
 Last week we connected a ICStation BME280 temperature / humidity / barometric pressure sensor to a a ICStation NodeMCU ESP8266. We displayed the collected data (along with Dew Point and Heat Index calculations) in the serial monitor.

This week we modified the sketch to post those variables to a linux server (could be your own local Raspberry Pi) running MySQL and PHP. We have it set to take a reading every 30 seconds, and post the data to a php page that inserts the data into the MySQL database. The index page displays a table of that data. The time and date stamp has been modified to display the data in the timezone of the location of the sensor. We are working on live gauges and graphs to display this data in real time.''

See the live data at http://theiot.zone/templog/

All code can be downloaded from https://drive.google.com/open?id=0ByRIq5k2wjcSXzVvamZ1dk9yQVU

Thanks to Nuno Santos and his tutorial at https://techtutorialsx.com/2016/07/21/esp8266-post-requests/ for some fine tuning of my code.

2017년 2월 1일 수요일

[Arduino] 온습도센서 값을 mysql에 저장

[ 출처 : http://blog.naver.com/sealclear/ ]

[정보]
 - DHT11 온습도센서
 - DHT 라이브러리를 추가하였음
 - 이더넷 쉴드를 장착함.
 - PHP사용하여 DB에 온습도 값 저장
 - MYSQL 테이블 세팅 







[증상 그리고 시도해본 것들]
 - 웹페이지에 접속할 때마다 db에 0값이 들어감
 - 자바스크립트로 자동 refresh 기능을 넣었는데... refresh될 때마다 db에 0값이 들어감
 - 자바스크립트 문제라 판단하여 자바스크립트 소스를 삭제하고 수동으로 refresh를 해보면 똑같이 db에 0이 들어간다.
 - 웃긴 건 php insert 쪽 쿼리문에 if문을 삽입하여 온습도 변수 값이 0인경우 쿼리문을 삽입하지 마라는 조건을 넣었는데... 그 조건을 넣으면 db에 아무런 값이 입력되지 않음.
   근데 지금은 됨... ㅡ ㅅ ㅡ... 저기서 추측컨데 아두이노에서 그럼 0을 보내는건가? 해서 아두이노 소스에 리딩값이 0이면 보내지 마 라는 조건문을 넣었지만 실패...
 - 커넥시간으로 인하여... 즉 온습도 값을 db에 삽입해, 그리고 소팅해서 맨 마지막 레코드를 출력해라는 쿼리가 있는데.. 두번째 쿼리인 경우 시간이 걸린다.. 근데.. 소팅이 완
   료되기 전에 다음 문장을 읽는다면.. 로스가 생기기때문에 0이들어간다고 생각하여 sleep문을 삽입하여 딜레이를 줬었다.. 그래도 db에 여전히 0값이 들어갔었었다...
 - php안에 전역변수와 함수를 만들고  소팅해서 맨 마지막 레코드를 읽을 때 0이 아닌것을 읽어라 라는 소스를 만들었었는데... 함수 외부에 있는 전역변수는 결론적으로 loop
   되는 문장안에 있어서 언젠가는 값이 날라가게 되어 있다... 그래서 슈퍼 전역변수를 사용하려고 했는데... 생각해보면... db에 원인을 알수 없지만 0이 들어간다.. 그런데 해
   결을 못하겠다... 그래서... 0이 아닌것을 읽곘다... 이러면... 트러블슈팅을 하는게 아니라.. 회피하는거라서... 이 방법은 아니라고 생각하고 포기함



[결론]
 - 웹페이지 refresh 마다 db에 0이 들어가는 문제가 해결되었음



[소스]
- 아두이노-
#include "DHT.h"  //DHT 온습도 센서 라이브러리 사용
#include <SPI.h>
#include <Client.h>
#include <Ethernet.h>
#define DHTPIN 2        //디지털 2번 핀 사용
#define DHTTYPE DHT11   // DHT11 사용
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0E, 0xF1, 0x67 };
char server[] = "192.168.0.222"; //접속할 서버 주소 APMSETUP이 실행중인 컴퓨터의 ip
IPAddress ip(192,168,0,215);     //아두이노에 부여하는 ip (고정ip부여함)
IPAddress gateway(192,168,0,1);
IPAddress subnet(255,255,255,0);
EthernetClient client;
DHT dht(DHTPIN, DHTTYPE);  //DHT 라이브러리에 포함된 함수 형태정의
void setup() {
  dht.begin();  //온습도 센서 동작시작
  Serial.println("Sensor Ready");

  Ethernet.begin(mac, ip, gateway, subnet); //이더넷 연결 시작
  Serial.begin(9600);  //시리얼 통신 시작
  delay(1000);
  Serial.println("connecting...");
}
void loop() {
  int humidity = dht.readHumidity();         //습도 읽어
  int temperature = dht.readTemperature();   //온도 읽어
  if(humidity!=0 && temperature!=0) //온습도가 0이면 MYSQL에 값 보내지 마
  {
    if (client.connect(server, 80)) {   // Http 요청 헤더
      client.print( "GET /test6.php?"); //읽을 PHP 파일
      client.print("humidity=");
      client.print( humidity );
      client.print("&&");
      client.print("temperature=");
      client.print( temperature );      //여기까지는 PHP에서 받기로한 데이터들이다
      client.println( " HTTP/1.1");
      client.println( "Host: 192.168.0.222" ); //요청을 보낼 서버의 주소
      client.println( "Content-Type: application/x-www-form-urlencoded" );   
      client.println( "Connection: close" );
      client.println();
      client.stop();
      Serial.print("Current humdity = "); 
      Serial.print(humidity);
      Serial.print("%  ");
      Serial.print("temperature = ");
      Serial.print(temperature);
      Serial.println("C  ");
      Serial.println("OK");
    }  
  }
  delay(5000); //5초에 한번씩 센서 리딩
}

-php-
<?php
  //php info
  $mysql_hostname = 'localhost';
  $mysql_username = 'root';
  $mysql_password = 'apmsetup';
  $mysql_database = 'arduino';

  //DB연결
  $connect = new mysqli($mysql_hostname, $mysql_username, $mysql_password, $mysql_database);
  //DB연결 확인
  if($connect->connect_errno){
 echo '[연결실패] : '.$connect->connect_error.'<br>';
  } else {
 echo '[연결성공]<br>';
  }
   $humidity = $_GET['humidity'];         //습도 읽어와
   $temperature = $_GET['temperature'];   //온도 읽어와
 
   if($humidity!=0){    //온습도 값을 DB에 삽입하는 쿼리
    $query = "insert into temp(humidity, temperature) values('$humidity', '$temperature')";
    $connect->query($query);  //쿼리실행
   }
 
   do {  //맨 마지막 레코드를 읽는 쿼리
 $query3 = "select * from temp order by no desc limit 1;";
    $result = $connect->query($query3);  //쿼리실행
    $row = mysqli_fetch_object($result); //실행된 쿼리값을 읽음
   } while($row->humidity == 0);

   echo date("Y-m-d H:i:s") . "<br />\n";  //날짜와 시간 표시
   echo "$row->no  ";
   echo "$row->humidity  ";
   echo "$row->temperature";
   if($row->temperature>27) { //온도가 27도 넘으면 경보음 울림(로컬 컴퓨터 하단경로에 MP3파일 넣을 것)
 echo '<embed src="c:\test.mp3" loop=-1> </embed>';  
   }

 //하단 자바스크립트: 웹페이지 자동 REFRESH기능
?>
<script language='javascript'>
  window.setTimeout('window.location.reload()',6000); //1초마다 리플리쉬 시킨다 1000이 1초가 된다.
</script>