'Programming Language/아두이노, 라즈베리파이'에 해당되는 글 17건

  1. 2024.01.08 아두이노, 화분에 물주기, 관개시스템 1
  2. 2024.01.08 ESP8266 라이브러리, 예제 1
  3. 2024.01.08 ESP8266 샘플 많은 곳 1
  4. 2024.01.08 ESP8266... SoftwareSerial Server 1
728x90

 

토양수분센서에 따른 특성 분석 후 적용이 필요함.

// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

#include "DHT.h"

#define DHT_TYPE DHT11   // DHT 11

// 핀설정
#define DHT_PIN 6     // what digital pin we're connected to
#define SOIL_SENSOR_PIN A0     // what digital pin we're connected to
#define SOIL_RELAY_PIN 8 // 토양센서에 결과에 따른 제어 relay 핀

#define DHT_USE_YN 0
#define SOIL_SENSOR_USE_YN 1
#define WATER_RELAY_USE_YN 1

#define SOIL_HUMIDITY_INDEX 40 // 물을 주기 위한 습도 임계치값. 임계치 이하면, 물을 공급한다.
#define WATER_SUPPLY_TIME 10 // 물 공급 시간 (기본:10초)
#define WATER_SUPPLY_INTERVAL_TIME (60 * 1) // 물공급 인터벌 시간. 기본: 10 분(60초 * 10분)

#define LOOP_INTERVAL_TIME 2 // 루프 인터벌 시간 (기본:2초)

DHT dht(DHT_PIN, DHT_TYPE);

// loop 에서 센서 처리 여부
int checkedSensor = 0;
// 물공급 delya time
int waterDelayTime = 0;

void setup() {
  Serial.begin(9600);
  pinMode(SOIL_RELAY_PIN, OUTPUT);
  
  if(DHT_USE_YN) {
    Serial.println("DHT beging...");
    dht.begin();    
  }
}

// DHT 센서 처리
void processDhtSensor() {  
  // DHT 센서 처리 ////////////////////////////
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }  

  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C");
}

void processSoilSensor() {
  // 토양 센서 처리 //////////////////////////
  int soilAnalogValue = analogRead(SOIL_SENSOR_PIN);
  int soilDigitalValue = map(soilAnalogValue, 0, 630, 0, 100); // Max(물에 잠길때) : 540 ~ 630, Min: 0
  soilDigitalValue = constrain(soilDigitalValue, 0, 100);
  
  Serial.print("Soil moisture(Digital/Analog): ");
  Serial.print(soilDigitalValue);
  Serial.print(" (%) / ");
  Serial.print(soilAnalogValue);
             
  if(WATER_RELAY_USE_YN && soilDigitalValue < SOIL_HUMIDITY_INDEX) {
    // 습도가 0보다는 크고, 인덱스값보다 작을 때 물을 공급한다. 
    if(soilDigitalValue < 1) {
      Serial.print("\t토양센스가 습도를 측정하고 있지 않습니다.");          
    } else {
      waterDelayTime -= LOOP_INTERVAL_TIME;
      if(waterDelayTime < 1) { // 물공급 인터벌 시간이 지나야, 추가로 물을 공급할 수 있다.
        waterDelayTime = WATER_SUPPLY_INTERVAL_TIME;
        digitalWrite(SOIL_RELAY_PIN, HIGH);  
        Serial.print("\trelay on(");    
        Serial.print(WATER_SUPPLY_TIME);    
        Serial.print("초)");    
        delay(WATER_SUPPLY_TIME * 1000);  
        digitalWrite(SOIL_RELAY_PIN, LOW);  
        Serial.print("\trelay off");        
      } else {
        Serial.print("\t물공급 인터벌 시간이 아직 지나지 않았습니다.(");          
        Serial.print(waterDelayTime);          
        Serial.print("초 남음.)");                  
      }      
    }
  }
}


void loop() {
  delay(LOOP_INTERVAL_TIME * 1000);
  
  checkedSensor = 0;
  
  // DHT 센서 처리
  if(DHT_USE_YN) {
    processDhtSensor();  
    checkedSensor++;
    Serial.print("\t");
  }

  // 토양 센서 처리
  if(SOIL_SENSOR_USE_YN) {
    processSoilSensor();
    checkedSensor++;
    Serial.print("\t");
  }

  if(checkedSensor > 0) {
    Serial.println("");  
  }
}

 

토양습도센서 차이 데이터 측정 자료

- 측정일자: 2017-09-21 23시

 

1. 데이터 측정

1.1 큰화분(샤오미, 토양센서...) 측정 값

a) 조건

- 토양센서 다리 5/5 뭍음

b) 데이터측정

⁃ 36%, 57%(587)

⁃ 큰방울토마토 줄기 기준 거리

⁃ 5cm(37%), 10cm(39%), 15cm(52%) => 물을 주는 방법에 따라 수치가 다를 듯.

 

1.2 작은화분1(골드 방울토마토)

a) 조건

- 토양센서 다리 4/5 뭍음.

b) 데이터 측정

   (샤오미, 토양센서)

⁃ 13%, 29%(296) : 처음 측정.

⁃ 200cc 물주고 - 23:58분, 화분 아래 물 흐름 없음

⁃ 1분후, 48%, 71%(729) - 23:59분

⁃ 5분후, 41%, 70%(721)

⁃ 15분후,41%,70%(719)

⁃ 100cc 추가 - 00:15분, 화분아래 물 흐름.

⁃ 2분후, 67%, 71%(731) <- 토양센서 측정 치 max(730-750)

⁃ 샤오미 센서를 빼고, 물을 닦아서 다시 넣었더니 38%... ㅡㅡ;

=> 아마도, 센서에 직접 물이 뭍은 경우에 수치가 많이 올라가는 듯 함. 물이 고이면 데이터 오류가 발생할 수 있음.

 

1.3 작은화분2(땡땡이 방울토마토)

- 땡땡이 방울 토마토는 물줄 때 최대 200cc 이하가 적당함. 초과시 화분에서 물이 넘칠 수 있음.

a) 조건

⁃ 토양센서 다리 4/5 뭍음.

b) 데이터측정

   (샤오미, 토양센서)

⁃ 19%, 44%(453)

⁃ 30%, 68%(697): 물준후 1분(100cc)

⁃ - 33%, 64%(662) : 15분 후

=> 해당건은 샤오미 쪽 센서가 물이 닿지 않은 듯 함

⁃ 60%,69%(716): 추가 100cc 더, 1분 11:36분

⁃ 58%,68%(703): 5분 후

 

1.4 물주는 시간과 물의 양

a) 조건

- 아파트 14층 베란다 수도꼭지 90도 회전시

b) 데이터측정

- 약 200cc/8초 (단, 호스에 공기가 없다는 가정하에)

 

2. 데이터 평가

1) 토양센서를 얼마나 깊이 뭍는지에 따라 값 차이가 심함. 측정은 거의 도금된 센서 다리모두 뭍음.

2) 토양센서 아나로그 값 max는 1023로 설정해야. 실제 max 아노로그 760으로 설정하면 값 왜곡이 더 심해짐.

3) 토양센서는 다리 짧아 상부 흙의 습도 체크 위주 임(3-4cm).샤오미는 7-8cm 깊이

4) 흙은 상부가 더 말라 있음.

- 샤오미를 작는 화분 측정시 습도가 1/2 뭍을땐 7%, 전체 깊이 뭍으면 13%.

5) 식물 줄기 주변에서 물이 빨리 마르므로(뿔리에서 수분흡수), 센서를 적당한 위치에 설치하는 게 중요함.

 

3. 결론

1) 토양센서의 아나로그 값이 정확한 수치를 알수 없으므로, 사용할 센스의 특성에 맞게 수치를 보정해서 적용해야 함.

- 토양센서 제품에 따라, 습도 0%의 아나로그 수치가 0인 경우도 잇고, 1023인 경우도 있음. 반드시 확인 할 것.

- 현재, 몇가기 제품을 측정해보면, 샤오미제품과 비교할 때 습도가 20~25% 차이가 남.

2) 토양센서를 설치할 때, 줄기에서 5cm~10cm 위치에서 설치하고,

보정된 습도가 43% 정도일 때 물을 공급하는 적당할 듯 함.

- 보정수치습도(%) = 아나로그 실수치 습도(%) - 보정값(23~25%)

. 23% ~ 25%은 몇일 화분을 관찰 했을 때, 화분 겉흙이 말랐을 때, 아나로그 수치가 60% 정도로 측정되었음.

보정수치습도(%)가 40%일때도 물이 공급되지 않아, 화분이 말라서, 43% 정도에서 수분을 공급하기 위해,

보정값을 23%~25%로 조정하는 게 적당함.

 

end.

728x90
Posted by 하루y
728x90
 

 

1. 라이브러리 설치

https://github.com/Diaoul/arduino-ESP8266

1) 위 URL 접속 후, "download"버튼 클릭. 내려받은 zip 파일을 아두이노IDE 메뉴 "스케치 > 라이브러리 포함하기 > .zip 라이브러리 추가..." 클릭 후, 다운받은 zip파일을 추가함.

2) 예제, "Complete" 참조

 

 

PS. 아래 소스에서 wifi.read() 할 때, 다음 버퍼보다 큰 데이터가 수신되는 경우, 추가 코딩 필요함.

#include <SoftwareSerial.h>
#include "ESP8266.h"

#define DEBUG true

#define SSID "U+Net5B6F"
#define PASS "1000019118"
#define DST_IP "211.172.246.98" //baidu.com

SoftwareSerial esp8266Serial = SoftwareSerial(2, 3);
ESP8266 wifi = ESP8266(esp8266Serial);

void setup()
{
    Serial.begin(9600);

    // ESP8266
    esp8266Serial.begin(9600);
    wifi.begin();
    wifi.setTimeout(1000);

    /****************************************/
    /******       Basic commands       ******/
    /****************************************/
    // test
    Serial.print("test: ");
    Serial.println(getStatus(wifi.test()));

    // restart
    Serial.print("restart: ");
    Serial.println(getStatus(wifi.restart()));

    // getVersion
    char version[16] = {};
    Serial.print("getVersion: ");
    Serial.print(getStatus(wifi.getVersion(version, 16)));
    Serial.print(" : ");
    Serial.println(version);

    // setWifiMode
    ************************************/
    // joinAP
    Serial.print("joinAP: ");
    Serial.println(getStatus(wifi.joinAP(SSID, PASS)));
    
    // getIP
    Serial.println("getIP: ");
    sendData("AT+CIFSR\r\n", 1000, DEBUG); // wifi mode : 1:station,2:AP, 3:dual

    /****************************************/
    /******       TCP/IP commands      ******/
    /****************************************/
    //서버모드로 하기전에 다중접속모드를 on 해야, 서버시작시 오류가 발생하지 않음.
    sendData("AT+CIPMUX=1\r\n", 1000, DEBUG);
    // createServer
    unsigned int port = 80;
    Serial.print("createServer: ");
    Serial.println(getStatus(wifi.createServer(port))); // port

}

void loop()
{
    /****************************************/
    /******        WiFi commands       ******/
    /****************************************/

    // read data
    unsigned int id;
    int length;
    int totalRead = 0;
    unsigned int bufferSize = 256;    
    char buffer[bufferSize] = {};

    if ((length = wifi.available()) > 0) {
      id = wifi.getId();
      if (length > 0) {
        do {        
          totalRead += wifi.read(buffer, bufferSize);
          Serial.print("Received ");
          Serial.print(totalRead);
          Serial.print("/");
          Serial.print(length);
          Serial.print(" bytes from client ");
          //Serial.print("from client ");
          Serial.print(id);
          Serial.println(": ");
          Serial.println((char*)buffer);
          wifi.flush();
        } while (totalRead < length);
      }
    }
}


void getConnectionStatue(ESP8266 wifi) {
    ESP8266ConnectionStatus connectionStatus;
    ESP8266Connection connections[5];
    unsigned int connectionCount;
    Serial.print("getConnectionStatus: ");
    Serial.print(getStatus(wifi.getConnectionStatus(connectionStatus, connections, connectionCount)));
    Serial.print(" : ");
    Serial.println(connectionCount);
    for (int i = 0; i < connectionCount; i++) {
      Serial.print(" - Connection: ");
      Serial.print(connections[i].id);
      Serial.print(" - ");
      Serial.print(getProtocol(connections[i].protocol));
      Serial.print(" - ");
      Serial.print(connections[i].ip);
      Serial.print(":");
      Serial.print(connections[i].port);
      Serial.print(" - ");
      Serial.println(getRole(connections[i].role));
    }
  delay(200);
}

String getStatus(bool status)
{
    if (status)
        return "OK";

    return "KO";
}

String getStatus(ESP8266CommandStatus status)
{
    switch (status) {
    case ESP8266_COMMAND_INVALID:
        return "INVALID";
        break;

    case ESP8266_COMMAND_TIMEOUT:
        return "TIMEOUT";
        break;

    case ESP8266_COMMAND_OK:
        return "OK";
        break;

    case ESP8266_COMMAND_NO_CHANGE:
        return "NO CHANGE";
        break;

    case ESP8266_COMMAND_ERROR:
        return "ERROR";
        break;

    case ESP8266_COMMAND_NO_LINK:
        return "NO LINK";
        break;

    case ESP8266_COMMAND_TOO_LONG:
        return "TOO LONG";
        break;

    case ESP8266_COMMAND_FAIL:
        return "FAIL";
        break;

    default:
        return "UNKNOWN COMMAND STATUS";
        break;
    }
}

String getRole(ESP8266Role role)
{
    switch (role) {
    case ESP8266_ROLE_CLIENT:
        return "CLIENT";
        break;

    case ESP8266_ROLE_SERVER:
        return "SERVER";
        break;

    default:
        return "UNKNOWN ROLE";
        break;
    }
}

String getProtocol(ESP8266Protocol protocol)
{
    switch (protocol) {
    case ESP8266_PROTOCOL_TCP:
        return "TCP";
        break;

    case ESP8266_PROTOCOL_UDP:
        return "UDP";
        break;

    default:
        return "UNKNOWN PROTOCOL";
        break;
    }
}

void sendData(String command, const int timeout, boolean debug) {
  String response = "";
  esp8266Serial.print(command);
  long int time = millis();

  while((time + timeout) > millis()) {
    while(esp8266Serial.available()) {
      char c = esp8266Serial.read();
      response += c;
    }
  }

  if(debug) {
    Serial.println(response);
  }
}
 
728x90
Posted by 하루y
728x90

# 아두이노에 SoftwareSerial.h 만으로 ESP8266으로 wifi 서버 송수신

728x90
Posted by 하루y
728x90

간단한 예제....

결국 많은 라이브러리 제대로 동작되지 않아, AT명령으로만 구성.

필요한 소스는 다른 라이브러리를 참조해서 작성해야 할 듯....

- AT명령 참조할 것. https://room-15.github.io/blog/2015/03/26/esp8266-at-command-reference/

- 아두이노 보드와 SoftwareSerial 해서 ESP8266 를 통해 wifi는 느리므로, ESP8266 으로 Server 구성해볼 것.

. 아두이노 UNO보드를 이용해서 ESP826 칩으로 업로드하려면, atmega328p 칩을 제거해야함.

 

#include <SoftwareSerial.h>
 
#define DEBUG true
 
SoftwareSerial esp8266(2,3); // make RX Arduino line is pin 2, make TX Arduino line is pin 3.
                             // This means that you need to connect the TX line from the esp to the Arduino's pin 2
                             // and the RX line from the esp to the Arduino's pin 3

unsigned int count = 0;

void setup() {
    Serial.begin(9600);
    esp8266.begin(9600); // your esp's baud rate might be different
    
    Serial.println("");
    Serial.println("ESP8266 ESP-01 module");
    Serial.println("");

    sendData("AT+RST\r\n",2000,DEBUG); // reset module       
    sendData("AT+CWMODE=1\r\n",1000,DEBUG); // configure as access point    
    sendData("AT+CWJAP=\"U+Net5B6F\",\"1000019118\"\r\n", 5000, DEBUG);  
    sendData("AT+CIFSR\r\n",1000,DEBUG); // get ip address      
    //sendData("AT+CWSAP=\"esp8266_j2h\",\"12345678\",5,3\r\n",1000,DEBUG); // ap모드        
    sendData("AT+CIPMUX=1\r\n",1000,DEBUG); // configure for multiple connections    
    sendData("AT+CIPSERVER=1,80\r\n",1000,DEBUG); // turn on server on port 80
}
 
void loop() {
  if(esp8266.available()) // check if the esp is sending a message 
  {
    if(esp8266.find("+IPD,"))
    {
     delay(1000);
 
     int connectionId = esp8266.read()-48; // subtract 48 because the read() function returns 
                                           // the ASCII decimal value and 0 (the first decimal number) starts at 48

      String response = ""; 
      while(esp8266.available()) {
        // The esp has data so display its output to the serial window 
        char c = esp8266.read(); // read the next character.
        response+=c;
      }
        
     if(DEBUG && response.length() > 0) {
      Serial.println("\r\n------------------ response start");      
      Serial.println(response);
      Serial.println("------------------ response end");      
     }
               
    String webpage = "";
    //webpage  = "HTTP/1.1 200 OK\r\n";            // 크롬, IE는 해더로 인식하나, ios에서 인식 안함.
    //webpage += "Content-Type: text/html\r\n";
    //webpage += "Connection: close\r\n";
    //webpage += "Refresh: 10\r\n";
    //webpage += "\r\n";
    webpage += "<!DOCTYPE HTML>\r\n";
    webpage += "<html><body>\r\n";
    webpage += "<h1>Hello</h1><h2>World! " + String(count++) + "</h2><button>LED1</button><button>LED2</button>\r\n"; 
    webpage += "</body></html>\r\n";
    
     String cipSend = "AT+CIPSEND=";
     cipSend += connectionId;
     cipSend += ",";
     cipSend +=webpage.length();
     cipSend +="\r\n";
     
     sendData(cipSend,1000,DEBUG); // cipsend - maxlength 2048
     sendData(webpage,1000,DEBUG);
     /*
     webpage="<button>LED2</button>";
     
     cipSend = "AT+CIPSEND=";
     cipSend += connectionId;
     cipSend += ",";
     cipSend +=webpage.length();
     cipSend +="\r\n";
     
     sendData(cipSend,1000,DEBUG);
     sendData(webpage,1000,DEBUG);
     */
     String closeCommand = "AT+CIPCLOSE="; 
     closeCommand+=connectionId; // append connection id
     closeCommand+="\r\n";
     
     sendData(closeCommand,3000,DEBUG);
    }
  }
}

String sendData(String command, const int timeout, boolean debug)
{
    String response = ""; 
    esp8266.println(command); // send the read character to the esp8266
    long int time = millis();
    delay(20);
    
    while( (time+timeout) > millis()) {
      while(esp8266.available()) {
        // The esp has data so display its output to the serial window 
        char c = esp8266.read(); // read the next character.
        response+=c;
      }  
    }
    
    if(debug && response.length() > 0) {
      Serial.println("\r\n------------------ response start");      
      Serial.println(response);
      Serial.println("------------------ response end");
    }
    
    return response;
}

void clear() {
    while (esp8266.read() != -1) {}
}
728x90
Posted by 하루y