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

Arduino 무선 기상 관측소 프로젝트

<메인 클래스="사이트 메인" id="메인">

이 튜토리얼에서는 Arduino 기반의 무선 기상 관측소를 만드는 방법을 배웁니다. 다음 비디오를 보거나 아래에 작성된 튜토리얼을 읽을 수 있습니다.

개요

실외 온도와 습도는 DHT22 센서를 사용하여 측정되며 이 데이터는 NRF24L01 송수신기 모듈을 사용하여 무선으로 실내기로 전송됩니다. 실내기에는 실내 온습도를 측정하는 또 다른 DHT22 센서와 아두이노 전원이 꺼지더라도 시간을 추적할 수 있는 DS3231 Real Time Clock 모듈이 있다. 이 모든 데이터는 0.96인치 OLED 디스플레이에 인쇄됩니다.

Arduino 무선 기상 관측소 회로도

회로도와 이 프로젝트가 어떻게 작동하는지 살펴보겠습니다. 이러한 각 모듈의 작동 방식에 대한 자세한 자습서가 이미 있으므로 NRF24L01 자습서, DHT22 자습서, DS3231 자습서에서 확인할 수 있습니다.

아래 링크에서 이 프로젝트에 필요한 구성요소를 얻을 수 있습니다.

실시간 클럭 모듈과 OLED 디스플레이는 모두 Arduino와 통신하기 위해 I2C 프로토콜을 사용하므로 Arduino Nano 보드의 I2C 핀 또는 아날로그 핀 번호 4와 5에 연결됩니다. NRF24L01 트랜시버 모듈 바로 옆에는 전원 공급 장치를 보다 안정적으로 유지하기 위한 커패시터가 있습니다. 센서가 제대로 작동하도록 하기 위해 DHT22 데이터 핀에 연결된 풀업 저항도 있습니다.

전원은 실내기용 12V DC 전원어댑터를 사용하고, 실외기의 전원은 7.5V 전후의 리튬이온 배터리 2개를 사용했습니다. 이 구성으로 실외기는 배터리가 방전되기 전에 약 10일 동안 작동할 수 있습니다. 왜냐하면 우리는 주기적으로 데이터를 전송하고 그 동안 Arduino를 절전 모드로 전환하여 전력 소비가 약 7mA에 불과하기 때문입니다.

맞춤형 디자인 PCB

전자 부품을 체계적으로 유지하기 위해 회로도에 따라 EasyEDA 무료 온라인 회로 설계 소프트웨어를 사용하여 맞춤형 PCB를 설계했습니다. 동일한 PCB를 실내기와 실외기에 모두 사용할 수 있으며 Arduino 보드만 다르게 프로그래밍해야 함을 알 수 있습니다.

여기에서 설계를 마치면 PCB 제조에 ​​사용되는 Gerber 파일을 간단히 내보낼 수 있습니다. 여기에서 Arduino 무선 기상 관측소의 EasyEDA 프로젝트 파일을 확인할 수 있습니다.

그런 다음 실제로 이 비디오의 스폰서인 JLCPCB에서 PCB를 주문할 수 있습니다.

여기에서 Gerber 파일을 간단히 끌어다 놓을 수 있으며 업로드되면 Gerber 뷰어에서 PCB를 검토할 수 있습니다. 모든 것이 정상이면 계속해서 PCB에 대해 원하는 속성을 선택한 다음 합리적인 가격에 PCB를 주문할 수 있습니다. JLCPCB에서 처음 주문하는 경우 단돈 2달러에 최대 10개의 PCB를 얻을 수 있습니다.

<그림 클래스="aligncenter">

그럼에도 불구하고 며칠 후에 PCB가 도착했습니다. PCB의 품질이 우수하고 모든 것이 디자인과 동일합니다.

나는 PCB에 핀 헤더를 납땜하여 이 프로젝트의 전자 부품을 조립하기 시작했습니다. 이런 식으로 필요할 때 구성 요소를 쉽게 연결하고 분리할 수 있습니다.

그런 다음 커패시터와 풀업 저항도 삽입하고 납땜했습니다. 이 단계가 완료되면 이제 부품을 PCB의 핀 헤더에 간단히 부착할 수 있습니다.

다음으로, 나는 프로젝트의 케이스를 만드는 일을 계속했습니다. 이를 위해 8mm 눈금 MDF 판을 사용하고 원형 톱을 사용하여 모든 조각을 크기에 맞게 자릅니다.

정확한 온도 및 습도 측정을 위해서는 케이스 측면에서 케이스로 공기가 들어갈 수 있어야 합니다. 그래서 드릴과 줄을 사용하여 실내기와 실외기의 측면 패널에 여러 개의 슬롯을 만들었습니다.

<그림 클래스="aligncenter">

또한 전면 패널에 OLED 디스플레이용 슬롯을 만들고 나중에 장식용으로 전면 패널에 붙일 크기로 작은 알루미늄 조각을 잘라냈습니다.

<그림 클래스="aligncenter">

케이스를 조립하기 위해 목공풀과 클램프, 나사를 사용했습니다.

<그림 클래스="aligncenter">

스프레이 페인트를 사용하여 케이스를 그렸습니다. 실외기는 흰색, 실내기는 검정색을 사용했습니다. 페인트가 마른 후 케이스에 PCB를 삽입하기만 하면 됩니다.

<그림 클래스="aligncenter">

실내기 뒷면에는 전원 잭과 전원 스위치를 삽입했고, 실외기에는 간단한 점퍼선을 전원 스위치로 사용했습니다.

<그림 클래스="aligncenter">

그게 다야, 우리의 Arduino 무선 기상 관측소는 이제 작동하지만 이 비디오에 남은 것은 프로그램이 어떻게 작동하는지 살펴보는 것입니다.

Arduino 무선 기상 관측소 코드

Arduino 기상 관측소 실외기 코드:

 /* Arduino 무선 통신 튜토리얼 실외기 - Dejan Nedelkovski의 송신기, www.HowToMechatronics.comLibraries:NRF24L01 - TMRh20/RF24 , https://github.com/tmrh20/RF24/DHT22 - DHTlib, https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlibLowPower - https://github.com/rocketscream/Low-Power */#include #include #include #include #include #define dataPin 8 // DHT22 데이터 pindht DHT; // DHT 객체 생성RF24 radio(10, 9); // CE, CSNconst 바이트 주소[6] ="00001";char thChar[32] ="";String thString ="";void setup() { radio.begin(); radio.openWritingPipe(주소); radio.setPALevel(RF24_PA_MIN); radio.stopListening();} 무효 루프() { int readData =DHT.read22(dataPin); // 센서에서 데이터를 읽습니다. int t =DHT.temperature; // 온도 값을 가져옵니다. int h =DHT.humidity; // 습도 값을 가져옵니다. thString =String(t) + String(h); thString.toCharArray(thChar, 12); // 무선으로 실내기에 데이터 전송 for (int i =0; i <=3; i++) { // 데이터 3회 전송 radio.write(&thChar, sizeof(thChar)); 지연(50); } // 2분 동안 절전, 15*8 =120초 for (int sleepCounter =15; sleepCounter> 0; sleepCounter--) { LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); }} 코드 언어:Arduino(arduino) 

설명: 실외기는 무선 통신의 송신기이므로 여기에 먼저 RF24 라이브러리, DHT 라이브러리 및 Arduino를 절전 모드로 전환하는 데 사용되는 LowPower 라이브러리를 포함해야 합니다.

인스턴스, 모듈이 연결된 핀 및 일부 변수를 정의한 후 설정 섹션에서 무선 통신 주소를 초기화해야 합니다. 그런 다음 루프 섹션에서 먼저 DHT22 센서의 데이터 또는 온도와 습도를 읽습니다. 처음에는 이 값들이 정수로 구분되어 하나의 String 변수로 변환하여 문자 배열에 넣고 radio.write() 함수를 사용하여 이 데이터를 실내기로 전송합니다. for 루프를 사용하여 데이터를 3번 전송하여 전송 시 컨트롤러가 사용 중인 경우 수신자가 데이터를 받을 수 있도록 합니다.

마지막에는 전력 소모를 최소화하기 위해 Arduino를 특정 시간 동안 절전 모드로 전환합니다.

Arduino 기상 관측소 실내기 코드:

/* Arduino 무선 통신 자습서 실내기 - Dejan Nedelkovski의 수신기, www.HowToMechatronics.com 라이브러리:DS3231 - http://www.rinkydinkelectronics.com/library.php?id=73 U8G2 - https://github.com/olikraus/u8g2*/#include #include #include #include #include #include #include #define dataPin 8 // DHT22 sensordht DHT; // DHT 객체 생성DS3231 rtc(SDA, SCL);U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);RF24 radio(10, 9); // CE, CSNconst 바이트 주소[6] ="00001";char text[6] ="";int readDHT22, t, h;String inTemp, inHum, outTemp, outHum;String rtcTime, rtcDate;int draw_state =0; unsigned long previousMillis =0;긴 간격 =3000;#define Temperature_20Icon_width 27#define Temperature_20Icon_height 47static const unsigned char Temperature_20Icon_bits[] U8X8_0,0,0,0,0,0x8_PROGMEM ={ 0x00, 0x00, 0x00,0,0 0x00, 0xc0, 0xe1, 0x00, 0x00, 0xe0, 0xc0, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x60, 0x60, 0x60, 0x80, 0x79 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x79, 0x00, 0x60, 0x60, 0x9e. 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x09e, 0x01, 0x00, 0x70, 0x9e, 0x03, 0x00, 0x38, 0x1e, 0x07, 0x00, 0x18, 0x3e, 0x0e, 0x00, 0x1c, 0x3f, 0x0c, 0x00, 0x0c, 0x7f, 0x18, 0x00, 0x8c, 0xff. 0x00, 0x8e, 0xff, 0x38, 0x00, 0xc6, 0xff, 0x31, 0x00, 0xc6, 0xff, 0x31, 0x00, 0x31, 0x00, 0xc6, 0xff, 0x31, 00x00 0x0c, 0x7f, 0x1c, 0x00, 0x3c, 0x1c, 0x0e, 0x00, 0x78, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0x00,0x 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};#정의 습도 _20ICON_WIDTH 27#define humity_20ICON_HEIGHT 47STATIC UNSIGNED CHUMIDITY_20ICON_BITS [] u8x8_progmem ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xf8, 0x00, x , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 0 , 0 0 0 , 0 0 0 , 0 1, 00, 0x0 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x03, 0x07, 0x00, 0x80, 0x03, 0x06, 0x00, 0x80, 0x01, 0x0c, 0x00, 0xc0, 0x01, 0x1c, 0x0c, 0x0c0, 0x00, 0x00, 0x1c. 0x00, 0x 0x00, 0x00, 0x38, 0x00, 0x60, 0x00, 0x30, 0x00, 0x70, 0x00, 0x70, 0x00, 0x0, 0x30, 0x00, 0x00, 0x00, 000x3 0x00, 0x80, 0x01, 0x0c, 0x00, 0x80, 0x03, 0x0e, 0x00, 0x80, 0x03, 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x03, 0x07, 0x00, 0x0, 0x07, 0x03, 0x03, 0x03, 0x03, 0x06. 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06, 0xe3, 0x3, 0x0, 0x06, 0x06, 0xc7, 0x00, 0x00, 0x06, 0xc6, 0x01, 0x00, 0x07, 0x86, 0x03, 0x00, 0x03, 0x0e, 0x1f, 0x00, 0x03, 0x0e, 0x1e, 0x80, 0x01, 0x1c, 0x01, 0x01, 0x01 0x38, 0x00, 0xe0, 0x00, 0x78, 0x00, 0x70, 0x00, 0xf0, 0x00, x , 0 , 0 , 0 , 0 , 0 , 0 , 0 0 , 0 0 7 , 0 1 0 0 0 0 0, 0 0x00, 0x00, 0x00}; 무효 설정() { radio.begin(); radio.openReadingPipe(0, 주소); radio.setPALevel(RF24_PA_MIN); radio.startListening(); u8g2.begin(); rtc.begin();} 무효 루프() { if (radio.available()) { radio.read(&text, sizeof(text)); // 들어오는 데이터 읽기 outTemp =String(text[0]) + String(text[1]) + char(176) + "C"; // 실외 온도 outHum =String(text[2]) + String(text[3]) + "%"; // 실외 습도 } unsigned long currentMillis =millis(); if (currentMillis - previousMillis> 간격) { previousMillis =currentMillis; u8g2.firstPage(); do { switch (draw_state ) { 경우 0:drawDate(); 부서지다; 사례 1:drawInTemperature(); 부서지다; 사례 2:drawInHumidity(); 부서지다; 사례 3:drawOutTemperature(); 부서지다; 사례 4:drawOutHumidity(); 부서지다; } } 동안 ( u8g2.nextPage() ); 무승부 상태++; if (draw_state> 4) { draw_state =0; } }}무효 drawDate() { 문자열 dowa =rtc.getDOWStr(); dowa.remove(3); rtcDate =dowa + " " + rtc.getDateStr(); u8g2.setFont(u8g2_font_timB14_tr); u8g2.setCursor(0, 15); rtcTime =rtc.getTimeStr(); // DS3231 RTC 시간 rtcTime.remove(5); u8g2.print(rtc날짜); u8g2.setFont(u8g2_font_fub30_tf); u8g2.setCursor(8, 58); u8g2.print(rtcTime);} 무효 drawInTemperature() { readDHT22 =DHT.read22(dataPin); // 센서에서 데이터를 읽습니다. t =DHT.temperature; // 온도 값을 가져옵니다. inTemp =String(t) + char(176) + "C"; u8g2.setFont(u8g2_font_helvR14_tr); u8g2.setCursor(24, 15); u8g2.print("실내"); u8g2.setFont(u8g2_font_fub30_tf); u8g2.setCursor(36, 58); u8g2.print(inTemp); u8g2.drawXBMP( 0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);}무효 drawInHumidity() { h =DHT.humidity; // 습도 값을 가져옵니다. inHum =String(h) + "%"; u8g2.setFont(u8g2_font_helvR14_tr); u8g2.setCursor(24, 15); u8g2.print("실내"); u8g2.setFont(u8g2_font_fub30_tf); u8g2.setCursor(36, 58); u8g2.print(inHum); u8g2.drawXBMP(0, 17, 습도_20Icon_width, 습도_20Icon_height, 습도_20Icon_bits);}무효 drawOutTemperature() { u8g2.setFont(u8g2_font_helvR14_tr); u8g2.setCursor(12, 15); u8g2.print("야외"); u8g2.setFont(u8g2_font_fub30_tf); u8g2.setCursor(36, 58); u8g2.print(출력온도); u8g2.drawXBMP(0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);}무효 drawOutHumidity() { u8g2.setFont(u8g2_font_helvR14_tr); u8g2.setCursor(12, 15); u8g2.print("야외"); u8g2.setFont(u8g2_font_fub30_tf); u8g2.setCursor(36, 58); u8g2.print(outHum); u8g2.drawXBMP( 0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);} 코드 언어:Arduino(arduino) 

설명: 다른 한편으로 실내기나 수신기에는 DS3231 실시간 클록 모듈용과 OLED 디스플레이용 U8G2 라이브러리 등 두 개의 라이브러리를 더 포함해야 합니다. 이전과 같은 방법으로 아래 프로그램에 필요한 인스턴스, 핀 및 일부 변수를 정의해야 합니다. 또한 여기에서 온도 및 습도 아이콘을 비트맵으로 정의해야 합니다.

온도 아이콘 비트맵:

#define Temperature_20Icon_width 27#define Temperature_20Icon_height 47정적 const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM ={ 0x00, ,0f,0,0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0xe0, 0xc0, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x79, 0x00, 0x60, 0x60, 0x60, 0x60, 0x79 , 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x60, 0x8c, 0x79, 0x00, 0x60, 0x90, 0x90, 0x90, 0x00, 0x01 , 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x79, 0x00, 0x60, 0x60, 0x60, 0x60 , 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x70, 0x9e, 0x03, 0x3, 0x3, 0x3, 0x9e. , 0x07, 0x00, 0x18, 0x3e, 0x0e, 0x00, 0x1c, 0x3f, 0x0c, 0x00, x , 0x0c, 0x7f, 0x18, 0x00, 0x8c, 0x0xff, , 0x 00, 0xc6, 0xff, 0x31, 0x00, 0xc6, 0xff, 0x31, 0x00, 0x8e, 0xff, 0x38, 0x00, xf, 0x38, 0x00, 0x8c, 0xff, 0x18, 0x00,0 0x78, 0x00, 0x06, 0x00, 0xe0, 0x80, 0x07, 0x00, 0xe0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x0, 0x1, 0x0, 0x00, 0x00, 0x1 /코드> 코드 언어:Arduino(arduino)

이를 위해 오픈 소스 이미지 편집기인 GIMP를 사용할 수 있습니다. 이를 통해 무엇이든 그린 다음 비트맵(.xbm)으로 내보낼 수 있습니다.

그런 다음 메모장을 사용하여 이 파일을 열고 여기에서 비트맵을 Arduino 코드로 복사할 수 있습니다.

<그림 클래스="aligncenter">

여기에서 PROGMEM 변수 수정자를 사용하여 비트맵을 상수로 정의할 수 있으며, 그렇게 하면 비트맵이 Arduino 보드의 SRAM 대신 플래시 메모리에 저장됩니다.

static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM // 플래시 메모리에 저장 static unsigned char Temperature_20Icon_bits[] // SRAM에 저장

설정 섹션에서 무선 통신을 초기화하고 OLED 디스플레이와 실시간 시계 모듈을 초기화해야 합니다.

그런 다음 루프 섹션에서 NRF24L01 모듈을 통해 읽을 수 있는 수신 데이터가 있는지 지속적으로 확인합니다. 참이면 radio.read() 함수를 사용하여 이를 읽고 처음 두 문자를 온도 문자열 변수에 저장하고 다음 두 문자를 습도 문자열 변수에 저장합니다.

그런 다음 3초로 설정한 간격 변수로 정의된 간격으로 디스플레이에 다양한 데이터를 표시하기 위해 millis() 함수를 사용합니다. 우리는 millis() 함수를 사용하고 있습니다. 이런 식으로 나머지 코드를 반복적으로 실행할 수 있기 때문입니다. 반면 delay() 함수를 사용하는 경우 프로그램은 해당 기간 동안 대기하므로 들어오는 데이터를 놓칠 수 있습니다. 실외기에서.

다음으로 U8G2 라이브러리의 firstPage() 및 nextPage() 함수를 사용하여 사용자 정의 함수로 정의된 5개의 다른 화면을 인쇄합니다.

drawDate() 사용자 정의 함수는 실시간 시계 모듈에서 날짜 및 시간 정보를 가져와 디스플레이에 적절하게 인쇄합니다. drawInTemperature() 함수는 실내 온도를 읽어 디스플레이에 적절하게 출력합니다. 실제로 디스플레이의 모든 화면을 인쇄할 때도 동일한 방법이 사용됩니다.

그게 다야, 이 Arduino 프로젝트를 즐기고 새로운 것을 배웠기를 바랍니다. 아래 댓글 섹션에서 언제든지 질문하세요.


제조공정

  1. Raspberry Pi 기반 기상 관측소
  2. Raspberry Pi 2 기상 관측소
  3. 라즈베리 파이 기상 관측소
  4. Weather Station V 2.0
  5. 오디오 주파수 감지기
  6. 무선 조명 스위치 조작기
  7. Tech-TicTacToe
  8. Arduino 카운트다운 타이머
  9. $10 휴대용 Arduino 기상 관측소(AWS)
  10. eDOT - Arduino 기반 정밀 시계 및 기상 관측소