제조공정
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
| ||||
| ||||
|
우리의 목표는 기본적으로 지역 단위에서 정보를 수집하여 인터넷으로 보내는 것입니다. 이 정보를 보고 있는 지구상의 어느 곳에서든 사용자는 원격 명령을 이 로컬 장치에도 있는 액추에이터에 전송하여 결정을 내릴 것입니다. 모든 센서 또는 액추에이터를 사용할 수 있습니다.
IoT 분야에 대한 제 작업의 대부분은 NodeMCU와 최근에는 ESP32를 사용하는 것이었습니다. 하지만 몇 년 전 Arduino UNO와 오래되고 좋은 ESP8266-01을 사용하여 IoT를 배우기 시작한 초기 단계를 잊지 않는 것이 중요하다고 생각합니다.
그래서 저는 여기에서 (지금은 경험이 조금 더 쌓이면서) 그 당시로 돌아가서 ThingSpeak.com 웹 서비스를 사용하여 클라우드에 연결하고 멋진 장치를 다시 탐색하기로 결정했습니다. 또한 MIT AppInventor를 사용하여 개발한 Android 앱을 사용하여 원격으로 사물을 제어하는 방법도 살펴보겠습니다.
"우리 IoT 프로젝트의 중심"은 ThingSpeak.com이 될 것입니다. 로컬 장치(UNO/ESP-01)는 센서 및 액추에이터 상태에서 데이터를 캡처하여 전송 합니다. 특정 ThingSpeak.com에 "쓰기" 상태 채널 . 지역 단위도 수신 인터넷의 데이터, 특정 ThingSpeak Actuator 채널에서 "읽기" .
Android 앱은 읽기도 됩니다. ThingSpeak.com 상태 채널의 데이터 및 사용자를 위해 이를 표시하는 단계를 포함합니다. 같은 방식으로 사용자는 해당 상태 정보를 기반으로 액츄에이터에 명령을 보낼 수 있습니다. 쓰기 ThingSpeak Actuator 채널에 있습니다(데이터 흐름을 더 잘 이해하려면 위의 블록 다이어그램 참조).
그래서, 우리는 무엇을 할 것인가? 다음 단계에 표시된 블록 다이어그램은 최종 프로젝트에 대한 개요를 제공합니다.
1단계:소개
우리 프로젝트는 공통 센서를 사용하여 여러 데이터를 캡처하여 모든 사람이 인터넷을 통해 볼 수 있는 클라우드로 보냅니다. 이러한 데이터를 처리하기 위해 당사는 해당 데이터를 수집, 분석 및 조치할 수 있는 개방형 IoT 플랫폼인 ThingSpeak.com에서 제공하는 서비스를 사용할 것입니다.
센서가 수집할 데이터
<울>프로젝트에는 2명의 액추에이터가 있습니다. :
<울>해당 액추에이터의 상태("ON/OFF")도 클라우드로 전송되어야 합니다.
따라서 아이디어는 예를 들어 농장과 같은 센서에서 이러한 데이터를 캡처하여 클라우드로 보내는 것입니다. 이러한 데이터를 기반으로 사용자는 다음 진술을 기반으로 결정을 내려야 합니다.
<울>액추에이터를 원격으로 명령하기 위해 Android 앱을 사용합니다.
2단계:BoM - BOM
여기에 나열된 가장 중요한 구성 요소 중 일부에는 링크와 USD의 표시 가격이 있습니다. 해당 링크는 정보용입니다.
<울>
3단계:하드웨어
Project HW를 조립해 봅시다. 이상적인 것은 부품별로 프로젝트를 설치하고 테스트하는 것입니다. 제안 사항으로 다음 단계를 수행할 수 있습니다.
<울>
4단계:센서 연결
센서를 제대로 읽으려면 IDE에 일부 라이브러리가 설치되어 있어야 합니다. 모든 라이브러리가 설치되어 있는지 확인하십시오. 초기 구성은 다음과 같아야 합니다.
// DS18B20#include #include #define ONE_WIRE_BUS 5 // 핀 D5의 DS18B20 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20;0(&oneWire) //DHT#include "DHT.h#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR(Light)#define ldrPIN 1int light =0;// 토양 습도#define 흙HumPIN 0int 흙Hum =0;
설정 및 루프에서 다음을 작성해 보겠습니다.
<사전><코드> 무효 설정(){ Serial.begin(9600); DS18B20.begin(); dht.begin();} 무효 루프(){ readSensors(); 디스플레이 센서(); 지연(10000);}그리고 마지막으로 두 가지 특정 함수를 작성해 보겠습니다. 하나는 센서를 읽고 다른 하나는 직렬 모니터에 값을 표시하는 것입니다.
/************ 센서 값 읽기 *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); 토양 온도 =DS18B20.getTempCByIndex(0); // 센서 0은 섭씨 섭씨의 토양 온도를 캡처할 것입니다.oilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); 빛 =지도(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% }/************ 디스플레이 센서 값 *************/void displaySensors(void){ Serial.print(" 공기 온도(oC):"); Serial.println(공기 온도); Serial.print("에어흠(%):"); Serial.println(airHum); Serial.print("soilTemp(oC):"); Serial.println(토양 온도); Serial.print("soilHum(%):"); Serial.println(soilHum); Serial.print("빛(%):"); Serial.println(빛); Serial.println("");}
아래 시리얼 모니터 사진은 센서 값을 보여줍니다.
내 GITHUB:Sens ors_Test.ino
에서 코드를 다운로드할 수 있습니다.
5단계:ESP8266-01 초기 구성
ESP-01은 직렬 브리지로 사용됩니다. 즉, " AT 명령"을 사용하여 프로그래밍합니다. 첫 번째는 ESP-01이 올바른 전송 속도 통신 속도에 있는지 확인하는 것입니다. 우리의 경우 9,600 보오입니다. 일반적으로 ESP-01은 공장에서 115,200보드로 프로그래밍되어 있으며 9,600보드로 변경해야 합니다.
먼저 위와 같이 ESP-01을 연결해야 합니다.
그런 다음 Arduino를 컴퓨터에 연결하고 IDE를 열고 File> Examples> 01.Basics> BareMinimum에있는 예제를로드하십시오. 이것은 Arduino와 ESP 사이에 통신 충돌이 없도록 하기 위한 빈 코드입니다.
Arduino가 직렬 통신(TX 및 RX)을 사용하지 않도록 ESP-01S에 연결하기 전에 이 코드를 Arduino로 전송했습니다. 이것은 ESP가 제대로 통신할 수 있도록 하는 데 중요합니다.
IDE 직렬 모니터를 열고 속도를 115,200보드로 변경합니다. IDE 직렬 모니터에서 "AT" 명령을 보내기 시작합니다. ESP-01은 "OK"를 반환해야 합니다.
다음으로 속도를 변경해 보겠습니다. 이를 위해 다음 명령을 사용할 수 있습니다.
AT + CIOBAUD =9600
ESP-01은 공장 프로그래밍으로 돌아갈 수 있습니다(FW 버전 때문인지는 모르겠습니다). 적어도 제 경우에는 BaudRate를 결정적으로 변경하려면 다른 명령을 사용해야 했습니다.
AT+ UART_DEF=,,,,
예:9600 보드 / 8 데이터 비트 / 1 정지 비트 및 패리티 및 흐름 제어 없음:
AT + UART_DEF =9600,8,1,0,0
직렬 모니터 하단의 선택 상자에서 속도를 "9600 baud"로 변경하십시오. 통신 테스트:창 상단에서 AT를 입력하고 확인 응답을 확인합니다. 이제 스테이션 모드에서 모듈을 구성해야 합니다. 고객 역할 당신의 Wi-Fi 네트워크의. 다음 명령을 사용하십시오.
AT + CWMODE =1
이제 모듈을 Wi-Fi 네트워크에 연결해야 합니다.
이렇게 하려면 아래 명령을 사용하여 "network_name"을 Wi-Fi 네트워크 이름으로 바꾸고 "network_name"을 암호로 바꿉니다. 따옴표를 유지하십시오.
AT + CWJAP ="네트워크 이름", "네트워크 이름"
아래 답변이 표시되면 연결이 올바르게 설정된 것입니다.
WIFI 연결 WIFI GOT IP
IP를 찾으려면 다음 명령을 실행하십시오.
AT + CIFSR
그리고 시리얼 모니터에 나타날 IP 주소를 기록해 두십시오. 나중에 필요할 수도 있습니다.
6단계:ESP-01 테스트
ESP-01을 구성했으면 최종 회로에 설치해야 합니다. 이를 위해 이전에 수행한 배선을 변경하고 ESP-01을 아래와 같이 UNO에 연결해야 합니다.
<울>ESP-01이 올바르게 설치되고 테스트되었는지 확인하기 위해 간단한 테스트를 해보자. 아래 코드를 입력하세요:
#include SoftwareSerial esp8266(6,7); //Rx ==> 핀 6; TX ==> Pin7 #define speed8266 9600 void setup() { esp8266.begin (speed8266); Serial.begin(speed8266); Serial.println("ESP8266 설정 테스트 - AT coomands 사용");}void loop() { while(esp8266.available()) { Serial.write(esp8266.read()); } 동안(Serial.available()) { esp8266.write(Serial.read()); }}
이제 몇 가지 AT 명령을 시도하고 직렬 모니터에서 결과를 확인하십시오.
* AT =====> ESP8266은 OK*를 반환합니다. AT+RST =====> ESP8266은 다시 시작하고 OK*를 반환합니다. AT+GMR =====> ESP8266은 AT Version을 반환합니다. SDK 버전; ID; OK* AT+CWMODE? => ESP8266은 모드 유형*을 반환합니다. AT+CWLAP ===> ESP8266은 가까운 액세스 포인트를 반환합니다.* AT+CIFSR ===> ESP8266은 지정된 IP를 반환합니다.
코드는 내 GITHUB:ESP_AT_Config.ino
에서 다운로드할 수 있습니다.재설정이 발생할 때마다(또는 Arduino가 꺼지거나 켜질 때마다) WiFi 네트워크에 연결하고 자격 증명을 입력하려면 connectWiFi() 호출을 추가하세요. 설정() 함수의 끝에서 함수:
setup(){ ... connectWiFi(); }코드>
connectWiFi() 함수는 메인 코드의 끝에 있어야 합니다. .ino:
무효 connectWiFi(무효){ sendData("AT+RST\r\n", 2000, 0); // 재설정 sendData("AT+CWJAP=\"사용자 이름\",\"암호\"\r\n", 2000, 0); //네트워크 연결 지연(3000); sendData("AT+CWMODE=1\r\n", 1000, 0); sendData("AT+CIFSR\r\n", 1000, 0); // IP 주소 표시 Serial.println("8266 Connected");}
위의 함수는 다른 sendData(data)를 호출합니다. 코드에도 있어야 하는 함수:
String sendData(문자열 명령, const int timeout, 부울 디버그){ 문자열 응답 =""; EspSerial.print(명령); 긴 int 시간 =millis(); while ( (time + timeout)> millis()) { while (EspSerial.available()) { // esp에는 데이터가 있으므로 출력을 직렬 창에 표시합니다. char c =EspSerial.read(); // 다음 문자를 읽습니다. 응답 +=c; } } if(디버그) { Serial.print(응답); } 반환 응답;}
7단계:센서와 ESP-01 연결
모든 센서를 설치하고 테스트하고 ESP-01도 제대로 작동했으면 모두 함께 살펴보고 인터넷에 데이터를 보낼 준비를 합시다.
8단계:The ThingSpeak
우리 프로젝트의 가장 중요한 부분 중 하나는 수집된 데이터를 수집, 분석 및 실행할 수 있는 개방형 IoT 플랫폼인 ThingSpeak입니다. 아직 계정이 없다면 ThingSpeak 가입으로 이동하여 계정을 만드십시오.
다음으로 2개의 액추에이터, 5개의 센서 및 예비 필드 상태가 있는 새 채널을 만듭니다.
<울>필드 8은 향후 확장 또는 디버그 목적으로 사용하기 위해 예비로 남게 됩니다. 예를 들어, ThingSpeak.com과 Arduino/ESP-01 핸드셰이크 중에 발생하는 각 통신 오류에 대한 "카운터"로 사용하겠습니다.
채널을 만들면(이 경우 상태 채널이 됨) 아래와 같이 키를 기록해 두는 것이 중요합니다.
9단계:클라우드에 상태 보내기
이 시점에서 클라우드 서비스를 사용할 수 있고 센서가 로컬에서 데이터를 캡처합니다. 해당 값을 가져와 ThingSpeak.com으로 보내 보겠습니다. 우리는 ThingSpeak 채널에 쓸 것이고 이를 위해 GET 문자열을 보내야 할 것입니다. 우리는 3 부분으로 할 것입니다:
"시작 cmd"를 보내드립니다:
AT+CIPSTART="TCP","184.106.153.149",80
명령의 "길이" 다음:
AT+CIPSEND=116
상태 채널의 해당 필드에 쓸 GET 문자열 자체:
GET /update?api_key=YOUR_WRITE_KEY_HERE&field1=pump&fieldlamp=0&field3=airTemp&field4=airHum&field5=soilTemp&field6=soilHum&field7=light&field8=예비
아래 코드는 우리를 위해 작업을 수행하고 위의 PrintScreen은 직렬 모니터에 결과를 보여줍니다:
// Thingspeak 문자열 statusChWriteKey ="6SRPQQKIE6AJVQE6"; // 상태 채널 ID:385184#include SoftwareSerial EspSerial(6, 7); // 토양 수신, Tx#define HARDWARE_RESET 8// DS18B20#include #include #define ONE_WIRE_BUS 5 // 핀 D5의 DS18B20 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature =0;//DHT#include "DHT.h#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR(Light)#define ldrPIN 1int light =0;// 토양 습도#define 흙HumPIN 0int 흙Hum =0;// 타이머와 함께 사용할 변수 writeTimingSeconds =17; // ==> 데이터를 보낼 샘플 시간을 초 단위로 정의합니다.long startWriteTiming =0;long elapsedWriteTime =0;// Actuatorsboolean pump =0과 함께 사용할 변수; 부울 램프 =0; int 예비 =0; 부울 오류; 무효 setup(){ Serial.begin(9600); 핀모드(하드웨어_리셋,출력); 디지털 쓰기(하드웨어_리셋, 높음); DS18B20.begin(); dht.begin(); EspSerial.begin(9600); // Comunicacao com 모듈로 WiFi EspHardwareReset(); // 모듈로 WiFi 재설정 startWriteTiming =millis(); // "프로그램 시계" 시작}void loop(){ start://label error=0; 경과된WriteTime =millis()-startWriteTiming; if (elapsedWriteTime> (writeTimingSeconds*1000)) { readSensors(); writeThingSpeak(); startWriteTiming =밀리(); } if (error==1) //전송이 완료되지 않으면 재전송 { Serial.println(" <<<>>>"); 지연(2000); 고토 시작; //레이블 "시작"으로 이동 }}/********* 센서 값 읽기 *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); 토양 온도 =DS18B20.getTempCByIndex(0); // 센서 0은 섭씨 온도에서 토양 온도를 캡처합니다. light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> 빛 100% 흙흠 =map(analogRead(soilHumPIN), 1023, 0, 0, 100); }/************ Conexao com TCP com Thingspeak *******/void writeThingSpeak(void){ startThingSpeakCmd(); // 문자열 준비 GET String getStr ="GET /update?api_key="; getStr +=statusChWriteKey; getStr +="&필드1="; getStr +=문자열(펌프); getStr +="&필드2="; getStr +=문자열(램프); getStr +="&field3="; getStr +=문자열(공기 온도); getStr +="&필드4="; getStr +=문자열(에어흠); getStr +="&필드5="; getStr +=문자열(토양 온도); getStr +="&필드6="; getStr +=String(soilHum); getStr +="&field7="; getStr +=문자열(빛); getStr +="&필드8="; getStr +=문자열(예비); getStr +="\r\n\r\n"; sendThingSpeakGetCmd(getStr); }/************ ESP 재설정 *************/void EspHardwareReset(void){ Serial.println("재설정 중......."); 디지털 쓰기(하드웨어_리셋, 낮음); 지연(500); 디지털 쓰기(하드웨어_리셋, 높음); delay(8000);// Tempo necessário para começar a ler Serial.println("RESET"); }/************ ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar 문자열 cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> cmd 시작:"); 직렬.println(cmd); if(EspSerial.find("오류")) { Serial.println("AT+CIPSTART 오류"); 반품; }}/********* GET cmd를 ThingSpeak로 전송 *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=문자열(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> cmd 길이:"); 직렬.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); 직렬.println(getStr); delay(500);//처리기의 템포 o GET, sem este delay apresenta busy no proximo comando String messageBody =""; while (EspSerial.available()) { 문자열 줄 =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //실제 내용은 빈 줄(길이가 1) 이후에 시작됩니다. messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody 수신:"); Serial.println(messageBody); 반환 messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // 경고 사용자 Serial.println("ESP8266 CIPSEND 오류:재전송"); //재전송... 예비 =예비 + 1; 오류=1; "오류"를 반환합니다. } } 코드>
코드는 내 GITHUB:SendingStatusTS_EXT.ino
에서 다운로드할 수 있습니다.
10단계:Android 앱 첫 번째 부분 - 상태 모니터링
Android 앱의 첫 번째 부분을 만들어 보겠습니다.
먼저 사용자 인터페이스를 디자인합니다. 위의 인쇄 화면은 주요 보이는 요소와 보이지 않는 요소를 보여줍니다. 그런 다음 블록을 설계해야 합니다(아래 숫자는 위 그림에 해당).
2초마다(Clock1에 의해 정의됨) "readArduino"라는 프로시저를 호출합니다.
그림> 그림> <울>위의 마지막 사진은 최종 앱이 작동하는 모습을 보여줍니다.
앱 코드는 내 GITHUB:ArduFarmBot_Status_App_EXT.aia
에서 다운로드할 수 있습니다.
11단계:액추에이터(LED 및 릴레이) 설치
HW를 완성해 봅시다.
이를 위해 Actuator를 설치해야 합니다. 기억하시겠지만 원격으로 펌프와 램프를 켜고 끄라는 명령을 받게 됩니다. Arduino 출력은 릴레이(및 LED)를 활성화하여 이러한 작업을 수행합니다.
우리는 Optocoupler Low-Level Trigger가 있는 Relay 모듈을 사용할 것입니다. 또한 별도의 핀을 통해 5V를 공급하므로 입력 핀에 필요한 전류를 공급할 필요가 없습니다. 모듈은 우리를 위해 그것을 합니다.
위의 그림은 액츄에이터가 어떻게 연결되어야 하는지 보여줍니다. Realy GND는 Arduino GND에 연결되어 있지 않습니다. 이렇게 하면 릴레이가 작동할 때 노이즈가 발생하지 않는 데 도움이 됩니다.
단순화를 위해 다이어그램에서 센서를 꺼냈습니다. 그러나 이미 설치하고 테스트한 센서를 제거하지 않고 프로젝트에 액추에이터 회로를 추가할 수 있습니다.
12단계:ThingSpeak 액추에이터 채널 구성
상태에 대해 했던 것과 같은 방식으로 각 액추에이터에 대해 하나씩 2개의 새 채널을 생성합니다. 각각에서 채널 ID, 읽기 및 쓰기 키를 기록해 둡니다. 필드 1에만 작성합니다. 각 채널의 예를 들어 제 경우:
채널 ID 375598 ==> LED 빨간색(펌프)
<울>채널 ID 375599 ==> LED 녹색(램프)
<울>
13단계:액추에이터로 Arduino 코드 설치 및 테스트
웹에 데이터를 보낼 때 우리가 한 일은 ThingSpeak 채널(채널 상태)에 WRITE하여 데이터를 "전송"(업로드)하는 것이었습니다. 이제 ThingSpeak 채널(액츄에이터 채널)에서 데이터를 "수신"(다운로드)해야 합니다.
ThingSpeak 채널에서 읽을 것이며 이를 위해 GET 문자열을 보내야 합니다. 우리는 3 부분으로 할 것입니다:
"시작 cmd"를 보내드립니다:
AT+CIPSTART="TCP","184.106.153.149",80
명령의 "길이" 다음:
AT+CIPSEND=36
그리고 각각의 액츄에이터 채널의 필드 1에서 읽는 GET 문자열 자체:
GET /channels/375598/fields/1/last
10초 간격으로 ThingSpeak 채널에서 읽을 것입니다. 위의 GET 명령을 보낸 후 "LAST VALUE STORED ON FIELD 1"을 호출하는 응답의 특정 위치에 대해 "1" 또는 "0"이어야 하는 ThingSpeak의 응답을 받게 됩니다. 도착하면 무시해야 합니다.
코드의 이 부분과 이전 부분(상태 데이터 보내기)의 주요 차이점은 다음과 같은 기능입니다.
readThingSpeak(문자열 채널 ID)
아래 코드는 우리를 위해 작업을 수행하고 위의 PrintScreen은 직렬 모니터에 결과를 보여줍니다:
// Thingspeak 문자열 canalID1 ="375598"; //Actuator1String canalID2 ="375599"; //액츄에이터2#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// timerslong과 함께 사용할 변수 readTimingSeconds =10; // ==> 데이터 수신을 위한 샘플 시간(초) 정의long startReadTiming =0;long elapsedReadTime =0;//Relays#define ACTUATOR1 10 // RED LED ==> Pump#define ACTUATOR2 12 // GREEN LED ==> Lampboolean 펌프 =0; 부울 램프 =0; int 예비 =0; 부울 오류; 무효 setup(){ Serial.begin(9600); 핀모드(ACTUATOR1,OUTPUT); 핀모드(ACTUATOR2,OUTPUT); 핀모드(하드웨어_리셋,출력); 디지털 쓰기(ACTUATOR1, HIGH); // 모듈과 관련하여 LOW digitalWrite(ACTUATOR2, HIGH); // 모듈과 관련하여 LOW digitalWrite(HARDWARE_RESET, HIGH); EspSerial.begin(9600); // Comunicacao com 모듈로 WiFi EspHardwareReset(); // 모듈로 WiFi 재설정 startReadTiming =millis(); // "프로그램 시계" 시작}void loop(){ start://label error=0; elapsedReadTime =millis()-startReadTiming; if (elapsedReadTime> (readTimingSeconds*1000)) { int 명령 =readThingSpeak(canalID1); if (명령 !=9) 펌프 =명령; 지연(5000); 명령 =readThingSpeak(canalID2); if (명령 !=9) 램프 =명령; 테이크액션(); 읽기 시작 시간 =밀리(); } if (error==1) //전송이 완료되지 않으면 재전송 { Serial.println(" <<<>>>"); 지연(2000); 고토 시작; //레이블 "시작"으로 이동 }}/********* ThingSpeak 명령에 따라 작업 수행 *************/void takeActions(void){ Serial.print( "펌프:"); Serial.println(펌프); Serial.print("램프:"); Serial.println(램프); if (펌프 ==1) digitalWrite(ACTUATOR1, LOW); 그렇지 않으면 digitalWrite(ACTUATOR1, HIGH); if (램프 ==1) digitalWrite(ACTUATOR2, LOW); else digitalWrite(ACTUATOR2, HIGH);}/************ ThingSpeak에서 액추에이터 명령 읽기 *************/int readThingSpeak(String channelID){ startThingSpeakCmd(); 정수 명령; // 문자열 준비 GET String getStr ="GET /channels/"; getStr +=채널ID; getStr +="/필드/1/마지막"; getStr +="\r\n"; 문자열 messageDown =sendThingSpeakGetCmd(getStr); if (messageDown[5] ==49) { 명령 =messageDown[7]-48; Serial.print("명령 수신:"); Serial.println(명령어); } 그렇지 않으면 명령 =9; return command;}/********* ESP 재설정 *************/void EspHardwareReset(void){ Serial.println("재설정 중......." ); 디지털 쓰기(하드웨어_리셋, 낮음); 지연(500); 디지털 쓰기(하드웨어_리셋, 높음); delay(8000);// Tempo necessário para começar a ler Serial.println("RESET"); }/************ ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar 문자열 cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> cmd 시작:"); 직렬.println(cmd); if(EspSerial.find("오류")) { Serial.println("AT+CIPSTART 오류"); 반품; }}/********* GET cmd를 ThingSpeak로 전송 *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=문자열(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> cmd 길이:"); 직렬.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); 직렬.println(getStr); delay(500);//처리기의 템포 o GET, sem este delay apresenta busy no proximo comando String messageBody =""; while (EspSerial.available()) { 문자열 줄 =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; } }코드>
The code can be downloaded from my GITHUB:ReadingCommandTS_EXT.ino
Step 14:Sending Commands to Actuators
At this point, we have the actuators channels configured on ThingSpeak and changing the value of Field 1 on each channel, we must see the actuators changing accordingly. On our final project we will do this task, using the Android App, but for testing proposes we can also do it using a normal browser. Let's do it.
The commands are:
Turn ON Pump (RED LED):
https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=1
Turn OFF Pump (RED LED):
https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=0
Turn ON Lamp (GREEN LED):
https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=1
Turn OFF Lamp (GREEN LED):
https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=0
Above you can see a print screen of a command to TurnOn the Pump sent from a browser and how it will appear at Serial Monitor. Obviously, the LED Red and relay will be also be turned on.
Step 15:Completing the Android APP
Let's complete the APP. Previously we have developed a simple App that gets the status from ThingSpeak (READ from Staus Channel). Now we must WRITE on Actuator channels, so those commands could be read by Arduino and act on Pump and Lamp accordingly.
For a user to pass the commands to the App, we will use "buttons". A pair of buttons (ON and OFF) for each one of the Actuators.
When a button is pressed, the color of its text changes.
<울>Above you can see the set of blocks for each one of the pairs of buttons.
Test the App, sending commands to turn ON and OFF the actuators. Check on Serial Monitor, the messages exchanged between ESP-01 and ThingSpeak.
The complete App code can be downloaded from my GITHUB:ArduFarmBot_V1_EXT.aia
Step 16:Putting All Together
완벽한! At this point, you have a full Android APP, a complete HW but you still do not have a code that will continuously read and write on ThingSpeak. Let's combine all that we have developed previously.
On the final code, you will find additional portions to verify for example if the ESP-01 is not freezing. We will do it, sending an AT command to it before any read or write. As we saw at the very beginning of this tutorial, sending an AT command should return from ESP-01 an OK. If this does not happen, we will proceed with an HW reset, commanded by SW (as we do once during setup phase).
The complete code for our project can be downloaded from my GITHUB:ArduFarmBot_Light_EXT.ino
Step 17:Conclusion
There is a lot to be explored in IoT arena with those great little devices, the Arduino Uno, and the ESP8266-01. We will return soon with new tutorials! Keep following MJRoBot tutorials!
As always, I hope this project can help others find their way in the exciting world of electronics, robotics, and IoT!
Please visit my GitHub for updated files:ArduFarmBot_Light
For more projects, please visit my blog:MJRoBot.org
Saludos from the south of the world!
See you at my next tutorial!
Thank you,
Marcelo
섹션> <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">// DS18B20#include#include #define ONE_WIRE_BUS 5 // DS18B20 on pin D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;
void setup(){ Serial.begin(9600); DS18B20.begin(); dht.begin();}void loop(){ readSensors(); displaySensors(); delay (10000);}
/********* Read Sensors value *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soilTemp =DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius soilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% }/********* Display Sensors value *************/void displaySensors(void){ Serial.print ("airTemp (oC):"); Serial.println (airTemp); Serial.print ("airHum (%):"); Serial.println (airHum); Serial.print ("soilTemp (oC):"); Serial.println (soilTemp); Serial.print ("soilHum (%):"); Serial.println (soilHum); Serial.print ("light (%):"); Serial.println (light); Serial.println ("");}
#includeSoftwareSerial esp8266(6,7); //Rx ==> Pin 6; TX ==> Pin7 #define speed8266 9600 void setup() { esp8266.begin (speed8266); Serial.begin(speed8266); Serial.println("ESP8266 Setup test - use AT coomands");}void loop() { while(esp8266.available()) { Serial.write(esp8266.read()); } while(Serial.available()) { esp8266.write(Serial.read()); }}
* AT =====> ESP8266 returns OK* AT+RST =====> ESP8266 restart and returns OK* AT+GMR =====> ESP8266 returns AT Version; SDK version; ID; OK* AT+CWMODE? => ESP8266 returns mode type* AT+CWLAP ===> ESP8266 returs close access points* AT+CIFSR ===> ESP8266 returs designided IP
// Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; // Status Channel id:385184#includeSoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 on pin D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;// Variables to be used with timerslong writeTimingSeconds =17; // ==> Define Sample time in seconds to send datalong startWriteTiming =0;long elapsedWriteTime =0;// Variables to be used with Actuatorsboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(HARDWARE_RESET, HIGH); DS18B20.begin(); dht.begin(); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startWriteTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedWriteTime =millis()-startWriteTiming; if (elapsedWriteTime> (writeTimingSeconds*1000)) { readSensors(); writeThingSpeak(); startWriteTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<< >>>"); delay (2000); goto start; //go to label "start" }}/********* Read Sensors value *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soilTemp =DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% soilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); }/********* Conexao com TCP com Thingspeak *******/void writeThingSpeak(void){ startThingSpeakCmd(); // preparacao da string GET String getStr ="GET /update?api_key="; getStr +=statusChWriteKey; getStr +="&field1="; getStr +=String(pump); getStr +="&field2="; getStr +=String(lamp); getStr +="&field3="; getStr +=String(airTemp); getStr +="&field4="; getStr +=String(airHum); getStr +="&field5="; getStr +=String(soilTemp); getStr +="&field6="; getStr +=String(soilHum); getStr +="&field7="; getStr +=String(light); getStr +="&field8="; getStr +=String(spare); getStr +="\r\n\r\n"; sendThingSpeakGetCmd(getStr); }/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); 지연(500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); return; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; } }
// Thingspeak String canalID1 ="375598"; //Actuator1String canalID2 ="375599"; //Actuator2#includeSoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// Variables to be used with timerslong readTimingSeconds =10; // ==> Define Sample time in seconds to receive datalong startReadTiming =0;long elapsedReadTime =0;//Relays#define ACTUATOR1 10 // RED LED ==> Pump#define ACTUATOR2 12 // GREEN LED ==> Lampboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(ACTUATOR1,OUTPUT); pinMode(ACTUATOR2,OUTPUT); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(ACTUATOR1, HIGH); //o módulo relé é ativo em LOW digitalWrite(ACTUATOR2, HIGH); //o módulo relé é ativo em LOW digitalWrite(HARDWARE_RESET, HIGH); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startReadTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedReadTime =millis()-startReadTiming; if (elapsedReadTime> (readTimingSeconds*1000)) { int command =readThingSpeak(canalID1); if (command !=9) pump =command; delay (5000); command =readThingSpeak(canalID2); if (command !=9) lamp =command; takeActions(); startReadTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<< >>>"); delay (2000); goto start; //go to label "start" }}/********* Take actions based on ThingSpeak Commands *************/void takeActions(void){ Serial.print("Pump:"); Serial.println(pump); Serial.print("Lamp:"); Serial.println(lamp); if (pump ==1) digitalWrite(ACTUATOR1, LOW); else digitalWrite(ACTUATOR1, HIGH); if (lamp ==1) digitalWrite(ACTUATOR2, LOW); else digitalWrite(ACTUATOR2, HIGH);}/********* Read Actuators command from ThingSpeak *************/int readThingSpeak(String channelID){ startThingSpeakCmd(); int command; // preparacao da string GET String getStr ="GET /channels/"; getStr +=channelID; getStr +="/fields/1/last"; getStr +="\r\n"; String messageDown =sendThingSpeakGetCmd(getStr); if (messageDown[5] ==49) { command =messageDown[7]-48; Serial.print("Command received:"); Serial.println(command); } else command =9; return command;}/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); 지연(500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); return; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; } }
제조공정
구성품 및 소모품 Arduino UNO × 1 Microchip Technology ATtiny85 × 1 전해 디커플링 커패시터 - 10uF/25V × 1 점퍼 와이어 M/M × 1 이 프로젝트 정보 저는 다른 위치에서 여러 센서 데이터를 읽어야 하는 프로젝트를 진행 중입니다. 여기에는 몇 개의 PWM 핀만 필요하므로 여러 Arduino Uno를 사용하는 것은 비용이 많이 들고 불필요합니다. 그래서 Arduino Uno 개발 보드 대신 A
이 Arduino Tutorial에서는 MIT App Inventor 온라인 응용 프로그램을 사용하여 Arduino를 제어하기 위한 맞춤형 Android 응용 프로그램을 구축하는 방법을 배웁니다. 다음 비디오를 보거나 아래에 작성된 튜토리얼을 읽을 수 있습니다. 개요 이 자습서에는 두 가지 예가 있습니다. 첫 번째는 간단한 LED를 제어하는 것이고 두 번째는 스마트폰을 이용하여 Stepper Motor를 제어하는 것이다. 이전 튜토리얼에서 우리는 이미 HC-05 블루투스 모듈을 사용하여 Arduino 보드와 스마트폰 사이