산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

도모틱 온실

구성품 및 소모품

Arduino MKR1000
× 1
Arduino UNO
× 1
DHT22 온도 센서
× 1
Arduino Wifi Shield 101
× 1
Android 기기
× 1
Arduino Infineon용 BTN8982가 포함된 DC 모터 제어 실드
× 1

앱 및 온라인 서비스

Arduino IDE
일식

이 프로젝트 정보

개요

온실 환경 조건은 지속적으로 변화하므로 효율적인 모니터링이 필요합니다.

자동 시스템을 사용하면 많은 이점이 있습니다. 예를 들어 작업량이 적거나 가장 중요한 것은 사용자가 집에서 PC나 스마트폰으로 자신의 투자를 확인할 수 있다는 것입니다.

또 다른 중요한 이점은 데이터를 데이터베이스에 저장할 수 있다는 것입니다. 이것은 돈을 벌거나 잃는 차이를 만들 수 있습니다.

또한 실시간 시스템 제어를 통해 즉시 개입하여 재배 문제를 예방할 수 있습니다.

온실의 자동 모니터링 시스템은 환경 데이터를 읽는 센서와 "슬레이브"라는 액추에이터로 구성됩니다. 그들은 "마스터"라는 중앙 장치와 무선을 통해 통신합니다. 후자는 가능한 변경 사항(예:임계값 변경)을 슬레이브에 보내고 WiFi를 통해 웹 서버에도 데이터를 보냅니다.

1. 어떻게 작동합니까?

이 프로젝트를 세 부분으로 나눌 수 있습니다.

<울>
  • 마스터
  • 노예
  • 웹 서버
  • 마스터에는 Arduino/Genuino MKR1000을, 슬레이브에는 Arduino/Genuino Uno를 사용했습니다.

    Master는 WiFi(WINC1500 통합)를 통해 Web Server와 통신하고, Slave는 DHT22 센서로 온습도를 획득하여 WiFi(WiFi shield WINC1500)를 통해 Master에게 데이터를 전송합니다.

    2. 마스터

    Master는 "Access Point mode"에 있고 Slave 연결이 정교화되어 Web Server로 전송되는 온도와 습도를 수신하기를 기다립니다.

    마스터는 사용 가능한 데이터가 있는지 확인합니다. 이 경우 새 임계값과 CRC로 구성된 UDP 패킷을 생성합니다. 사실, 슬레이브가 수신한 설정의 유효성을 검사하는 데 사용할 CRC를 계산합니다.

    마스터는 "액세스 포인트 모드"를 종료한 후 Wi-Fi에 연결하여 데이터를 WebServer에 전송하여 그래프에 넣습니다.

    3. 노예

    Slave는 DHT22 센서에 의해 온도와 습도를 획득하고 5분 후에 Master로 데이터를 보냅니다. 또한 UDP 패킷을 생성하고 마스터에 연결한 다음 데이터를 보냅니다.

    나중에 새 임계값과 같은 사용 가능한 데이터가 있으면 기다립니다. 이 경우 Slave는 새로운 설정을 수신하고 Dallas-Maxim 공식을 사용하여 CRC를 계산합니다.

    그 후 계산된 CRC는 마스터로부터 받은 CRC와 비교됩니다. 두 CRC가 같으면 Slave는 EEPROM에 새 설정을 저장합니다.

    4. 웹 서버

    웹 서버는 나중에 기록에 저장할 수 있는 모든 데이터를 저장합니다.

    이를 위해 데이터베이스에 연결하고 두 가지 다른 방식으로 데이터를 표시하는 PHP 스크립트를 사용했습니다.

    <울>
  • 그래프에서 다른 PHP 스크립트 사용
  • Android 앱에서 다른 PHP 스크립트를 사용하는 JSON 형식
  • 5. 앱

    앱을 사용하면 데이터를 데이터베이스로 참조할 수 있습니다.

    첫 번째 화면에서 표시할 타이밍 범위를 선택할 수 있으며 "GRAPHIC" 버튼을 사용하여 웹 서비스에 접속하여 데이터를 가져옵니다.

    앱은 데이터를 그래픽으로 보여줍니다.


    <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

    코드

    <울>
  • 그래픽 만들기
  • 스크립트 웹사이트 연결
  • 표 만들기
  • 온실 도모틱 마스터
  • 온실 Domotic 노예
  • getdata
  • 그래픽PHP 만들기
    이것을 사용하여 그래픽
    SetScale("textlin");$theme_class=new UniversalTheme;$graph->SetTheme($theme_class);$graph->img->SetAntiAliasing( false);$graph->title->Set('제목');$graph->SetBox(false);$graph->img->SetAntiAliasing();$graph->yaxis->HideZeroLabel();$graph ->yaxis->HideLine(false);$graph->yaxis->HideTicks(false,false);$graph->xgrid->Show();$graph->xgrid->SetLineStyle("단색");$ 그래프->xaxis->SetTickLabels($time_axis);$graph->xgrid->SetColor('#E3E3E3');$graph->xaxis->SetLabelAngle(90);$graph->legend->SetPos(0.5, 0.08,'center','top');// 첫 번째 라인 생성$p1 =new LinePlot($parameter1);$graph->Add($p1);$p1->SetColor("#6495ED");$ p1->SetLegend('your_parameter1');$graph->yscale->SetGrace(0);// 두 번째 라인 생성$p2 =new LinePlot($parameter2);$graph->Add($p2);$p2 ->SetColor("#B22222");$p2->SetLegend('your_parameter2');$graph->yscale->SetGrace(0);$graph->legend->SetFrameWeight(1);// 출력 라인$ 그래프->Stroke();?>
    스크립트 웹사이트 연결PHP
    이것을 사용하여 DB
    ";에코 "매개변수1". $_GET['매개변수1']. "
    "; echo "parameter2 ". $_GET['매개변수2']. "
    ";// 연결 생성$conn =mysqli_connect($servername, $username, $password, $dbname);// 연결 확인if (!$conn) { die("연결 실패:" . mysqli_connect_error() );}$sql ="INSERT INTO 온실(이름, 매개변수1, 매개변수2)VALUES('".$name."', '".$parameter1."', '".$parameter2."')";if( mysqli_query($conn, $sql)) { echo "새 레코드가 성공적으로 생성되었습니다.";} else { echo "오류:" . $sql . "
    " . mysqli_error($conn);}mysqli_close($conn);?>
    테이블 생성SQL
    이 스크립트를 사용하여
    CREATE TABLE IF NOT EXISTS `greenhouse` ( `id` int(11) NOT NULL, `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `temp` float NOT NULL, `umid` float NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    Greenhouse Domotic 마스터C/C++
    이것은 마스터의 코드입니다.
    /*자동화 온실 프로젝트*//*Autors:Antonio La Mura, Umberto Festa*//*날짜:03/03/2016*//*우리의 아이디어는 과일을 사는 사용자를 허용하는 것입니다. 화학 비료 및 기타 유사한 제품의 사용과 같은 제품의 모든 재배 단계를 정확히 알기 위해 온실에서 자란 야채. 판매되는 상품에 QR코드를 찍어 특정 스마트폰 앱으로 읽어준다. 제품이 재배된 환경 조건과 사용된 화학 제품에 대한 정보를 제공합니다. 온실의 자동 모니터링 시스템은 환경 데이터를 읽는 센서와 Slave라는 액추에이터로 구성됩니다. 그들은 마스터라는 중앙 장치와 무선을 통해 통신합니다. 후자는 슬레이브에 가능한 변경 사항(예:임계값 변경)과 WiFi를 통해 웹 서버에도 데이터를 보냅니다. 제품이 판매될 준비가 되면 웹 서비스에 QR 코드 생성을 요청하고 패키지에 넣습니다. 시스템의 마지막 부분은 QR 코드 스캔을 담당하고 사용자에게 관련 정보를 보여주는 모바일 앱입니다.*//*Master*//*DEVO AGGIUNGERE SOLO LA PARTE CHE MI SERVE PER RICEVERE LE NUOVE SOGLIE CHE VENGONO INVIATE DALL'APP*//*사용된 라이브러리*/#include #include #include #include #include /* 연결 변수*/char ssid[] ="SSID"; /*네트워크 SSID(이름)*/char pass[] ="pass"; /*U 우리의 네트워크 암호(WPA에 사용하거나 WEP에 키로 사용)*/int keyIndex =0; /* 네트워크 키 인덱스 번호(WEP에만 필요)*/char ssid_ap[] ="Arduino"; /*생성된 AP 이름*/char pass_ap[] =""; /*(아직 지원되지 않음)*/int status =WL_IDLE_STATUS;unsigned int localPort =2390; /*수신할 로컬 포트*/char server[] ="www.cormaz.altervista.org"; /*Google의 이름 주소(DNS 사용)*/WiFiServer server_ap(80);WiFiClient client_ap;WiFiUDP Udp;RTCZero rtc;WiFiClient client;char packetBuffer[255]; /* 들어오는 패킷을 담을 버퍼*/char ReplyBuffer[255]; /*다시 보낼 문자열*//*새 임계값에 대한 변수*/float humax =0;float humin =0;float tumax =0;float tumin =0;/*액세스 포인트처럼 작동(플래그 =false), 연결 to WebServer (flag =true)*/boolean flag =false;boolean threeshold_available =false;void setup() { /*직렬을 초기화하고 포트가 열릴 때까지 기다립니다:*/ Serial.begin(9600); 동안 (! 직렬) {; /*직렬 포트가 연결될 때까지 기다립니다. 기본 USB 포트에만 필요*/ } Serial.println();}void loop() { int packetSize; 이중 온도; 더블 윙윙거림; 정수 아이디; 바이트 crc; 문자열 strURL; //방패가 있는지 확인:/****************************************** ***********************************************/ 만약 ( WiFi.status() ==WL_NO_SHIELD) { Serial.println("와이파이 쉴드가 없습니다"); /*계속하지 않음:*/ while (true); } /************************************************ **************************************/ //WiFi 네트워크 연결 시도:/* ************************************************** ***********************************/ while (status !=WL_CONNECTED) { Serial.print("생성 중 네트워크 이름:"); Serial.println(ssid_ap); /*WPA/WPA2 네트워크에 연결합니다. 개방형 또는 WEP 네트워크를 사용하는 경우 이 줄을 변경하십시오.*/ status =WiFi.beginAP(ssid_ap); /*연결을 위해 10초 대기:*/ delay(10000); server_ap.begin(); } Serial.println("와이파이에 연결되었습니다"); /**************************************************** *************************************/ //UDP 통신 시작 /****** ************************************************** ******************************/ Udp.begin(localPort); printWifiStatus(); client_ap =server_ap.available(); if (client_ap) { /*클라이언트가 있는 경우*/ /*정보를 기다리고 있습니다*/ Serial.println("new client"); /*직렬 포트로 메시지 출력*/ /*사용 가능한 데이터가 있으면 패킷을 읽습니다.*/ packetSize =Udp.parsePacket(); if (packetSize) { Serial.print("수신된 크기의 패킷 "); Serial.println(패킷 크기); Serial.print("에서 "); IP 주소 remoteIp =Udp.remoteIP(); Serial.print(원격IP); Serial.print(", 포트 "); Serial.println(Udp.remotePort()); /*패킷을 packetBuffer로 읽어들임*/ int len ​​=Udp.read(packetBuffer, 255); if (len> 0) packetBuffer[len] =0; Serial.println("내용:"); Serial.println(패킷 버퍼); char* 명령 =strtok((char *)packetBuffer, ";"); 정수 개수 =0; while (command !=0) { /*정보 나누기*/ switch (count) { case 0:id =atoi(command); 부서지다; 경우 1:온도 =atof(명령) / 10; 부서지다; 사례 2:윙윙거리는 소리 =atof(명령) / 10; 부서지다; } 명령 =strtok(0, ";"); 카운트++; } Serial.print("패키지 수신"); Serial.print(id); Serial.print(" T:"); Serial.print(temp, 1); Serial.print(" H:"); Serial.println(흠, 1); /**************************************************** *************************************/ 지연(20); /*CRC-8을 계산하므로 바이트 배열을 생성합니다.*/ /************************************** *********************************************/ 바이트 bhmax =( 바이트) 휴맥스; 바이트 bhmin =(바이트) 인간; 바이트 btmax =(바이트)tumax; 바이트 btmin =(바이트) tumin; 바이트 crc32_str[4] ={ bhmax, bhmin, btmax, btmin }; crc =CRC8(crc32_str); Serial.println("CRC:"); Serial.println(crc); /**************************************************** *******************************/ if (threshold_available ==true) { snprintf(ReplyBuffer, sizeof(ReplyBuffer), " %d;%d;%d;%d;%d;%d", id, (int)humax, (int)humin, (int)tumax, (int)tumin, (int)crc); /*우리가 받은 패킷을 보낸 IP 주소와 포트로 응답을 보냅니다.*/ Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(응답 버퍼); Udp.endPacket(); } } /*직렬 모니터를 출력합니다*/ /*연결을 닫습니다:*/ client_ap.stop(); Serial.println("클라이언트 연결 끊김"); 플래그 =참; }/*좋은 AP*/ /****************************************** **************************************/ /*서버에 연결하여 데이터베이스에 데이터 보내기 */ /**************************************************** *********************************/ if (flag ==true) { /*Wifi 네트워크 연결 시도 :*/ while (status !=WL_CONNECTED) { Serial.print("SSID 연결 시도 중:"); Serial.println(ssid); /*WPA/WPA2 네트워크에 연결합니다. 개방형 또는 WEP 네트워크를 사용하는 경우 이 줄을 변경하십시오.*/ status =WiFi.begin(ssid, pass); /*연결을 위해 10초 대기:*/ delay(10000); } Serial.println("와이파이에 연결되었습니다"); printWifiStatus(); strURL ="GET /YourAddress.php?id="; strURL +=아이디; strURL +="¶meter1="; strURL +=임시; strURL +="¶meter2="; strURL +=흠; strURL +=" HTTP/1.1 "; Serial.println("\n서버 연결 시작 중..."); // 연결되면 직렬을 통해 다시 보고합니다. if (client.connect(server, 80)) { Serial.println("connected to server"); // HTTP 요청 만들기:client.println(strURL); client.println("호스트:www.cormaz.altervista.org"); client.println("연결:닫기"); 클라이언트.println(); client.stop(); Serial.println("알았어!"); } /*서버의 연결이 끊어지면 클라이언트를 중지합니다.*/ if (!client.connected()) { Serial.println(); Serial.println("서버에서 연결을 끊습니다."); client.stop(); /*영원히 아무것도 하지 않음:*/ while (true); } 플래그 =거짓; } /************************************************ *****************************/}/*CRC-8 알고리즘 계산 ​​- Dallas/Maxim 공식 기반*/ 바이트 CRC8(const 바이트 * 데이터) { 바이트 crc =0x00; while (*data) { 바이트 추출 =*data++; (바이트 tempI =8, tempI, tempI--) { 바이트 합계 =(crc ^ 추출) &0x01; crc>>=1; if (합) { crc ^=0x8C; } 추출>>=1; } } return crc;}void printWifiStatus() { /*연결된 네트워크의 SSID를 인쇄합니다.*/ Serial.print("SSID:"); Serial.println(WiFi.SSID()); /*WiFi 실드의 IP 주소 인쇄:*/ IPAddress ip =WiFi.localIP(); Serial.print("IP 주소:"); 직렬.println(ip); /*수신된 신호 강도 출력:*/ long rssi =WiFi.RSSI(); Serial.print("신호 강도(RSSI):"); Serial.print(rssi); Serial.println("dBm");}
    온실 Domotic 슬레이브C/C++
    이것은 Slave의 코드입니다.
    /*자동화 온실 프로젝트*//*Autors:Antonio La Mura, Umberto Festa*//*날짜:21/03/2016*//*우리의 아이디어는 과일을 사는 사용자를 허용하는 것입니다. 화학 비료 및 기타 유사한 제품의 사용과 같은 제품의 모든 재배 단계를 정확히 알기 위해 온실에서 자란 야채. 판매되는 상품에 QR코드를 찍어 특정 스마트폰 앱으로 읽어준다. 제품이 재배된 환경 조건과 사용된 화학 제품에 대한 정보를 제공합니다. 온실의 자동 모니터링 시스템은 환경 데이터를 읽는 센서와 Slave라는 액추에이터로 구성됩니다. 그들은 마스터라는 중앙 장치와 무선을 통해 통신합니다. 후자는 슬레이브에 가능한 변경 사항(예:임계값 변경)과 WiFi를 통해 웹 서버에도 데이터를 보냅니다. 제품이 판매될 준비가 되면 웹 서비스에 QR 코드 생성을 요청하고 패키지에 넣습니다. 시스템의 마지막 부분은 QR 코드 스캔을 담당하고 사용자에게 관련 정보를 보여주는 모바일 앱입니다.*//*Slave*//*사용된 라이브러리*/#include #include #include #include #include //모든 PIN 정의#define HUMIDIFIER A4#define HEATER A5#define DHT22_PIN 4//Define 모터#define IS_1 0 #define IS_2 1#define IN_1 3#define IN_2 11#define INH_1 12#define INH_2 13#define TCONST 100 //단계 사이의 지연 시간//재설정을 위한 변수 millis()extern unsigned long timer0_millis;int status =WL_IDLE_STATUS; [] ="아두이노"; // 네트워크 SSID(이름)char pass[] =""; // 네트워크 비밀번호(WPA용으로 사용하거나 WEP용 키로 사용)int keyIndex =0; // 네트워크 키 인덱스 번호(WEP에만 필요) unsigned int localPort =2390; // 수신 대기할 로컬 포트 ​​onchar packetBuffer[255]; // 들어오는 패킷을 담을 버퍼WiFiUDP Udp;//DHT22DHT22 정의 myDHT22(DHT22_PIN);//sendfloat hmin =0;float hmax =0;float tmin =0;float tmax =0;int duty_motor =0;부동 습도; float 온도;//10초마다 보낼 변수 unsigned long interval =600000;void setup() { Serial.begin(9600); 동안 (! 직렬) {; // 직렬 포트가 연결될 때까지 기다립니다. 기본 USB 포트에만 필요 } //PIN 초기화(INPUT - OUTPUT) pinMode(HEATER, OUTPUT); digitalWrite(히터, LOW); 핀모드(가습기, 출력); digitalWrite(가습기, 낮음); //팬에 대한 PIN 설정 pinMode(IN_1, OUTPUT); 핀모드(IN_2, 출력); 핀모드(INH_1, 출력); 핀모드(INH_2, 출력); //재설정 reset_ports(); 디지털 쓰기(INH_1, 1); 디지털 쓰기(INH_2, 1); Serial.println("시작 중... "); delay(2000);}void loop() { // 사용 가능한 데이터가 있으면 패킷을 읽습니다. int packetSize =Udp.parsePacket(); 부호 없는 긴 시간 =millis(); 부호 없는 긴 currentMillis =millis(); DHT22_ERROR_t 오류 코드; 정수 나는 =0; 문자 이름[] ="clie1"; 습도 =myDHT22.getHumidity() * 10; 온도 =myDHT22.getTemperatureC() * 10; char toSend[32]; errorCode =myDHT22.readData(); 바이트 crc; int crc_ric; //센서 습도 및 온도 확인 DHT22 오류 /**************************************** ****************************************/ 스위치(errorCode) { 케이스 DHT_ERROR_NONE:char 버프[128]; sprintf(buf, "정수 전용 판독값:온도 %hi.%01hi C, 습도 %i.%01i %% RH", myDHT22.getTemperatureCInt() / 10, abs(myDHT22.getTemperatureCInt() % 10), myDHT22. getHumidityInt() / 10, myDHT22.getHumidityInt() % 10); 부서지다; 경우 DHT_ERROR_CHECKSUM:중단; 케이스 DHT_BUS_HUNG:중단; 경우 DHT_ERROR_NOT_PRESENT:중단; 경우 DHT_ERROR_ACK_TOO_LONG:중단; 경우 DHT_ERROR_SYNC_TIMEOUT:중단; 경우 DHT_ERROR_DATA_TIMEOUT:중단; 경우 DHT_ERROR_TOOQUICK:중단; } /************************************************ *****************************/ //값이 변경되면 값을 인쇄합니다. /******* ************************************************** ***********************/ if (습도 !=myDHT22.getHumidity() * 10 || 온도 !=myDHT22.getTemperatureC() * 10) { Serial.print("T:"); Serial.print(myDHT22.getTemperatureC(), 1); Serial.print("C"); Serial.print(" H:"); Serial.print(myDHT22.getHumidity(), 1); Serial.println("%"); } /************************************************ ********************************/ //매개변수를 10분마다 전송 /******** ************************************************** **********************/ if (millis()> interval) { //AP 연결 /************ ************************************************** ******************/ // 쉴드가 있는지 확인:if (WiFi.status() ==WL_NO_SHIELD) { Serial.println("WiFi 쉴드가 존재하지 않음 "); // 계속하지 않음:while(true); } // Wifi 네트워크 연결 시도:while ( status !=WL_CONNECTED) { Serial.print("Attempting to connect to SSID:"); Serial.println(ssid); // WPA/WPA2 네트워크에 연결합니다. 개방형 또는 WEP 네트워크를 사용하는 경우 다음 행을 변경하십시오. status =WiFi.begin(ssid); // 연결을 위해 10초 대기:delay(10000); } Serial.println("와이파이에 연결되었습니다"); /**************************************************** *******************************/ Serial.println("\n서버 연결 시작 중..."); // 연결되면 직렬을 통해 보고합니다. Udp.begin(localPort); snprintf(toSend, sizeof(toSend), "%s;%d;%d", 이름, (int)습도, (int)온도); // 우리가 받은 패킷을 보낸 IP 주소와 포트로 응답을 보냅니다. Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(toSend); Udp.endPacket(); Serial.println("전송 완료"); resetMillis(); 동안 (밀리() <10000) { 패킷 크기 =Udp.parsePacket(); if (packetSize) { /*패킷을 packetBuffer로 읽어들임*/ int len ​​=Udp.read(packetBuffer, 255); if (len> 0) packetBuffer[len] =0; Serial.println("내용:"); Serial.println(패킷 버퍼); char* 명령 =strtok((char *)packetBuffer, ";"); 정수 개수 =0; while (command !=0) { /*정보 나누기*/ switch (count) { case 0:snprintf(name, sizeof(name), "%s", command); 부서지다; 경우 1:hmax =atof(명령) / 10; //atof(char*) 이중 중단에서 un tipo char*를 변환합니다. 경우 2:hmin =atof(명령) / 10; 부서지다; 경우 3:tmax =atof(명령) / 10; 부서지다; 경우 4:tmin =atof(명령) / 10; 부서지다; 사례 5:crc_ric =atoi(명령); 부서지다; } 명령 =strtok(0, ";"); 카운트++; } Serial.print("답변:"); Serial.print(이름); Serial.print(";"); Serial.print(hmax, 1); Serial.print(";"); Serial.print(hmin, 1); Serial.print(";"); Serial.print(tmax, 1); Serial.print(";"); Serial.println(tmin, 1); Serial.print("CRC 수신:"); Serial.println(crc_ric); //CRC-8을 계산하고 바이트의 배열을 얻습니다. /************************************ ********************************************/ 바이트 bhmax =(바이트 )hmax; 바이트 bhmin =(바이트) hmin; 바이트 btmax =(바이트)tmax; 바이트 btmin =(바이트)tmin; 바이트 crc32_str[4] ={ bhmax, bhmin, btmax, btmin }; crc =CRC8(crc32_str); Serial.println("CRC:"); Serial.println(crc); /**************************************************** *******************************/ if (crc_ric ==(int)crc) { //EEPROM EEPROM_writeDouble에 저장 (0, tmax); EEPROM_writeDouble(4, tmin); EEPROM_writeInt(8, hmax); EEPROM_writeInt(10, hmin); } } } 지연(10); } /************************************************ *****************************/ WiFi.disconnect(); //센서 값에 따라 HUMIDIFIER, HEATER, Fan 관리 /**************************************** ************************************************** */ //HEATER if (myDHT22.getTemperatureC()>=tmax) { digitalWrite(HEATER, HIGH); } if (myDHT22.getTemperatureC() <=tmin + 1) { digitalWrite(히터, 낮음); } // HUMIDIFIER if ((int)myDHT22.getHumidity()>=hmax) { digitalWrite(HUMIDIFIER, HIGH); } if ((int)myDHT22.getHumidity() <=hmin + 1) { digitalWrite(HUMIDIFIER, LOW); } //팬, 브러시리스 모터 if (myDHT22.getTemperatureC()>=tmax + 4) { //온도에 따른 모터 회전, duty -> 0 per t =tmax+4 및 duty -> 100 per t> tmax+10 //Rotazione del motore al variare della 온도, duty -> 0당 t =tmax+4 e Duty -> t당 100> tmax+10 duty_motor =map(i , tmax + 4, tmax + 10, 0, 100); if (tmax> tmax + 10) { 듀티 모터 =100; } analogWrite(IN_2, 듀티 모터); 지연(TCONST); } if (myDHT22.getTemperatureC() <=(tmax + tmin) / 2) { reset_ports(); //온도에 따른 모터 회전, duty -> 0 per t =tmax+4 and duty -> 255 per t> tmax+10 duty_motor =0; analogWrite(IN_2, 듀티 모터); 지연(TCONST); } /************************************************ **************************************/ delay(1000);}//두 배 저장 EEPROMvoid EEPROM_writeDouble(int ee, 이중 값) { byte* p =(byte*)(void*)&value; for (int i =0; i >=1; if (합) { crc ^=0x8C; } 추출>>=1; } } return crc;}//millis()void resetMillis() { cli(); timer0_millis =0; sei();}
    getdatiPHP
    우리는 이것을 사용하여 우리의 앱을 database
    ";//데이터베이스 선택 work with$selected =mysql_select_db("serra",$dbhandle) or die("예제를 선택할 수 없습니다"); $datada =$_GET["datada"];$dataa =$_GET["dataa"];//SQL 쿼리를 실행하고 레코드를 반환합니다.$result =mysql_query("SELECT hum,temp,date FROM 레코드 WHERE date>=' ".$datada."' 및 날짜 <='".$dataa."'");$records=array();//데이터베이스에서 데이터를 가져오는 동안 ($row =mysql_fetch_array($result)) { $ tmp =array("hum"=>$row{'hum'}, "temp"=>$row{'temp'}, "date"=>$row{'date'}); array_push($레코드,$tmp); //에코 "HUM:".$row{'hum'}." TEMP:".$row{'temp'}."날짜:". //결과 표시 $row{'date'}."
    ";}echo json_encode($records);//연결 종료mysql_close($dbhandle);?>
    그렌하우스 앱
    첫 번째 페이지에서 두 개의 DatePicker를 사용하여 날짜를 설정해야 합니다. "GRAPHIC" 버튼을 누르면 선택한 매개변수와 날짜를 보내는 PHP 스크립트 "getdati"에 대한 HTTP GET 호출이 수행됩니다. 그런 다음 JSON을 수신하고 이를 디코딩한 후 GraphViewhttps://github.com/cormaz/app_greenhouse.git
    라이브러리를 사용하여 그래픽을 생성합니다.

    회로도

    연결:Arduino UNO - DHT22 - 릴레이

    제조공정

    1. ILI9341 TFT 터치스크린 디스플레이 실드의 비트맵 애니메이션
    2. 웹 운영 DMX 컨트롤러
    3. Arduino 스파이봇
    4. FlickMote
    5. 수제 TV B-Gone
    6. 마스터 시계
    7. HSVC시계
    8. Raspberry Motor Shield를 사용한 Android 제어 장난감
    9. 나를 찾기
    10. Arduino Power