用arduino制作具有無線數據傳輸功能的氣象站


 

本項目是用arduino開源硬件,來快速制作具有無限數據傳輸功能的氣象站,我之前做過一個帶數據記錄功能的氣象站項目,這次算是升級和改進的版本。

 arduino制作具有無限數據傳輸功能的氣象站

 

第1步:構想

首先,需要增加從氣象站到室內接收器的無線數據傳輸功能,去掉了SD卡模塊,換成Arduino Uno接口擴展板。

這樣做的主要原因是為了節省空間,接口擴展版完全兼容Arduino Uno,因此無需使用導線進行連接。氣象站支架也進行了重新設計。之前的支架太低,而且不穩,所以我又做了一個新的支架(更高而且更穩)。對於直接安裝到氣象站支架上的外殼而言,我還增加了一個新的托架。此外,還增加了用於供電的太陽能板。

 arduino官網

2步:原材料

 

arduino制作具有無限數據傳輸功能的氣象站

arduino制作具有無限數據傳輸功能的氣象站

arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站

arduino制作具有無限數據傳輸功能的氣象站

 

硬件清單:

 

 

 

在制作氣象站支架時需要:

  • 大約3.4米長的鋼管(或者鋼板)。
  • 鋼絲(大約4米)
  • 鋼絲夾(8x)
  • 不銹鋼螺絲扣(2x)
  • fi10鋼棒(大約50厘米)
  • 鋼吊環螺母(4x)

 

您還將需要以下工具:

  • 烙鐵
  • 螺絲刀
  • 鉗子
  • 電鑽
  • 焊機
  • 角磨機
  • 鋼刷

 

3步:小結

如前文所述,本篇教程是對上篇氣象站教程的升級。

arduino制作具有無限數據傳輸功能的氣象站

 

如果您想了解如何組裝氣象站套件,請看組裝視頻:

 

 

 

4步:氣象站安裝方案

還有一個問題,那就是如何安裝能夠承受室外條件的氣象站支架。

關於氣象站支架的類型和設計,我做了一些研究。最后我決定使用3米長的鋼管來制作支架。通常建議將風速計安裝到最高點(大約10米(33英尺)),但是由於我使用的是一體化氣象站套件,我選擇了套件建議的高度 - 大約3米(10英尺)。

我考慮的主要問題是,這個支架必須模塊化且易於拆卸,這樣便於轉移到其他位置。

 

組裝:

1、先從fi18 3.4m(11.15ft)長鋼管開始。在鋼管上塗一層酸性除銹劑,對鋼管進行除銹處理。

2、2到3小時后,除銹完成,接着把鋼管焊接起來。先把吊環螺母焊到鋼管兩端,然后把鋼管放到距地面2米的位置。當然還可以放到更高的位置,但是不能更低,否則靠上的部分就會變得不穩。

3、然后,需要在每一側制作一個“錨”。為此我使用了兩個fi12 50cm(1.64ft)鋼棒。在每個鋼棒的頂端焊上一個吊環螺母和一個小鋼板,這樣就可以把它踩到或用錘子砸到地里面。

如圖所示:

arduino制作具有無限數據傳輸功能的氣象站

 

4、然后,使用鋼絲把“錨”上的吊環連到支架兩端。先拿來兩根1.7 m(5.57ft)長的鋼絲,一端用鋼絲夾直接固定到吊環螺母上,另一端固定到不銹鋼螺絲扣上。不銹鋼螺絲扣用於緊固鋼絲。

 arduino制作具有無限數據傳輸功能的氣象站

 

5、然后,使用一個3D打印托架將塑料接線盒安裝到支架上。更多詳情參見第5步。

6、最后,對每一個鋼制零件都塗上兩層底漆。在此基礎上,您可以塗上任何喜歡的顏色。

 

5步:3D打印零件

為使安裝支架易於拆卸,需要制作一些3D打印零件。每一個零件都是我親自設計並使用PLA塑料打印出來的。

 

arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站

arduino制作具有無限數據傳輸功能的氣象站

 

塑料接線盒托架

在上一篇教程中,我用鋼板制作了托架,但是不是特別實用。所以我決定使用3D打印零件再做一個。一共有五個3D打印零件,損壞的零件可以快速更換。

 

arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站

arduino制作具有無限數據傳輸功能的氣象站

 

有了這個托架,塑料接線盒就能直接安裝到鋼管上。安裝高度也可以靈活調節。

 

溫濕度傳感器外殼

我需要為溫濕度傳感器設計一個外殼。在參考網上資料之后,我確定了這個外殼的最終形狀。我設計了帶托架的史蒂文森百葉箱,這樣所有部件都可以安裝到鋼管上。 

它一共包括10個零件。主體底座由兩部分組成,頂部是一個“蓋子”,這樣就可以實現密封,不會進水。每一個零件都是使用PLA耗材打印而成。

 

6步:室內數據接收器

本項目的主要升級就是增加了無線數據傳輸功能。所以還需要增加一個室內數據接收器。

為此,我使用了適合Arduino的430 MHz接收器,然后使用17厘米(6.7英寸)天線對其進行了升級。接着,需要測試一下該模塊的通信距離。第一項測試在室內進行,以確定牆壁對信號范圍的影響,以及會不會造成信號中斷。第二項測試是在室外進行。結果表明,該模塊的通信距離在10米(33英尺)以上,遠遠超出室內接收器的要求。

 arduino制作具有無限數據傳輸功能的氣象站

arduino制作具有無限數據傳輸功能的氣象站

 

接收器所需零件:

  • Arduino Nano
  • Arduino 430 MHz接收器模塊
  • RTC模塊
  • LCD顯示器
  • 一些接頭

 

如圖所示,這個接收器可以顯示室外溫度和濕度、日期和時間。

 

arduino制作具有無限數據傳輸功能的氣象站

 

7步:測試

在將各零部件組裝起來之前,必須進行一些測試。

首先要測試Arduino的發送和接收模塊。先得找到合適的代碼,然后進行修改以使其符合項目需求。我從最簡單的例子開始,從發射器向接收器發送一個字,測試成功之后再發送更多的數據。

arduino制作具有無限數據傳輸功能的氣象站

arduino制作具有無限數據傳輸功能的氣象站

 

然后需要對這兩個模塊的范圍進行測試。先把天線去掉,測試發現通信距離非常短,大約4米(13英尺)。然后把天線加上進行測試。通過相關研究和分析,我認為天線長度最好是17厘米(6.7英寸)。之后分別在室內和室外進行了測試,以確定環境對信號的影響。

 

最后,將發射器置於室外,接收器置於室內,再進行測試,以確定能否實現良好的室內接收效果。最初有一些信號中斷的問題,因為接收到的數據和發射的數據不一致。后來換上從ebay購買的433 Mhz模塊天線,才解決了這個問題。

 

 arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站

 

這個模塊整體不錯,因為非常便宜,而且簡單易用,只不過由於存在信號中斷問題,使用距離會受到一定的限制。

 

代碼:

#include <SD.h>   //SD
#include <SPI.h>  //SD

File myFile;      //SD

int pinCS = 10;
////////////
//LCD
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

#define BACKLIGHT_PIN 3

LiquidCrystal_I2C lcd(0x20, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 
///////////
int sensorPin = A0;    //battery voltage pin
int sensorValue = 0;
/////////////////// 
int sensorPin_solar = A1;  //solar panel voltage pin
int sensorValue_solar = 0;
////////////////

char                 databuffer[35];
double               temp;

void getBuffer()                                                                    //Get weather status data
{
  int index;
  for (index = 0;index < 35;index ++)
  {
    if(Serial.available())
    {
      databuffer[index] = Serial.read();
      if (databuffer[0] != 'c')
      {
        index = -1;
      }
    }
    else
    {
      index --;
    }
  }
}

int transCharToInt(char *_buffer,int _start,int _stop)                               //char to int)
{
  int _index;
  int result = 0;
  int num = _stop - _start + 1;
  int _temp[num];
  for (_index = _start;_index <= _stop;_index ++)
  {
    _temp[_index - _start] = _buffer[_index] - '0';
    result = 10*result + _temp[_index - _start];
  }
  return result;
}

int WindDirection()                                                                  //Wind Direction
{
  return transCharToInt(databuffer,1,3);
}

float WindSpeedAverage()                                                             //air Speed (1 minute)
{
  temp = 0.44704 * transCharToInt(databuffer,5,7);
  return temp;
}

float WindSpeedMax()                                                                 //Max air speed (5 minutes)
{
  temp = 0.44704 * transCharToInt(databuffer,9,11);
  return temp;
}

float Temperature()                                                                  //Temperature ("C")
{
  temp = (transCharToInt(databuffer,13,15) - 32.00) * 5.00 / 9.00;
  return temp;
}

float RainfallOneHour()                                                              //Rainfall (1 hour)
{
  temp = transCharToInt(databuffer,17,19) * 25.40 * 0.01;
  return temp;
}

float RainfallOneDay()                                                               //Rainfall (24 hours)
{
  temp = transCharToInt(databuffer,21,23) * 25.40 * 0.01;
  return temp;
}

int Humidity()                                                                       //Humidity
{
  return transCharToInt(databuffer,25,26);
}

float BarPressure()                                                                  //Barometric Pressure
{
  temp = transCharToInt(databuffer,28,32);
  return temp / 10.00;
}

void setup()
{

  lcd.begin (20,4);  
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home ();
  //////////
  Serial.begin(9600);
  ////////
   pinMode(pinCS, OUTPUT);
  // SD Card Initialization
  if (SD.begin())
  {
    Serial.println("SD card is ready to use.");
  } else
  {
    Serial.println("SD card initialization failed");
    return;
  }
  //////////
}
void loop()
{ 
  //////////////////
  sensorValue = analogRead(sensorPin);                 //Monitoring battery voltage
  float voltage = sensorValue*(5.0/1023.0);
  lcd.setCursor(0,3); //0,3
  lcd.print("Voltage bat: ");
  lcd.print(voltage);
  lcd.print(" V");
  /////////////////
  sensorValue_solar = analogRead(sensorPin_solar);
  float voltage_solar = 2*sensorValue_solar*(5.0/1023.0)-0.07;
  Serial.println(voltage_solar);
 // lcd.setCursor(0,2);              //This is example how to set your LCD commands
//  lcd.print("Voltage sol: ");
//  lcd.print(voltage_solar);
// lcd.print(" v");

  /////////////////////
  getBuffer();              //Begin!
  ///////
  if(WindDirection()==0){
    Serial.print("Wind Direction: ");
    Serial.print("SW");
    Serial.println("  ");
  }
  if(WindDirection()==45){
    Serial.print("Wind Direction: ");
    Serial.print(" W");
    Serial.println("  ");
  }
  if(WindDirection()==90){
    Serial.print("Wind Direction: ");
    Serial.print("NW");
    Serial.println("  ");
  }
  if(WindDirection()==135){
    Serial.print("Wind Direction: ");
    Serial.print(" N");
    Serial.println("  ");
  }
  if(WindDirection()==180){
    Serial.print("Wind Direction: ");
    Serial.print("NE");
    Serial.println("  ");
  }
  if(WindDirection()==225){
    Serial.print("Wind Direction: ");
    Serial.print(" E");
    Serial.println("  ");
  }
  if(WindDirection()==270){
    Serial.print("Wind Direction: ");
    Serial.print("SE");
    Serial.println("  ");
  }
  if(WindDirection()==315){
    Serial.print("Wind Direction: ");
    Serial.print(" S");
    Serial.println("  ");
  }
 // Serial.print("Wind Direction: ");
  //Serial.print(WindDirection());
 // Serial.println("  ");
  Serial.print("Average Wind Speed (One Minute): ");
  Serial.print(WindSpeedAverage());
  Serial.println("m/s  ");
  Serial.print("Max Wind Speed (Five Minutes): ");
  Serial.print(WindSpeedMax());
  Serial.println("m/s");
 // lcd.setCursor(0,0);
 // lcd.print("Max Speed");
 // lcd.print(" ");
  //lcd.print(WindSpeedMax());
 // lcd.print(" ");
 // lcd.print("m/s");
  Serial.print("Rain Fall (One Hour): ");
  Serial.print(RainfallOneHour());
  Serial.println("mm  ");
  Serial.print("Rain Fall (24 Hour): ");
  Serial.print(RainfallOneDay());
  Serial.println("mm");
  Serial.print("Temperature: ");
  Serial.print(Temperature());
  Serial.println("C  ");
 // lcd.setCursor(0,2);
 // lcd.print("Temperature: ");
 // lcd.print(Temperature());
 // lcd.print("C ");
  Serial.print("Humidity: ");
  Serial.print(Humidity());
  Serial.println("%  ");
  Serial.print("Barometric Pressure: ");
  Serial.print(BarPressure());
  Serial.println("hPa");
  Serial.println("");
  Serial.println("");


 
   ////
   myFile = SD.open("test.txt", FILE_WRITE);
  if (myFile) {    
     if(WindDirection()==0){
    myFile.print("Wind Direction: ");
    myFile.print("SW");
    myFile.println("  ");
  }
  if(WindDirection()==45){
    myFile.print("Wind Direction: ");
    myFile.print(" W");
    myFile.println("  ");
  }
  if(WindDirection()==90){
    myFile.print("Wind Direction: ");
    myFile.print("NW");
    myFile.println("  ");
  }
  if(WindDirection()==135){
    myFile.print("Wind Direction: ");
    myFile.print(" N");
    myFile.println("  ");
  }
  if(WindDirection()==180){
    myFile.print("Wind Direction: ");
    myFile.print("NE");
    myFile.println("  ");
  }
  if(WindDirection()==225){
    myFile.print("Wind Direction: ");
    myFile.print(" E");
    myFile.println("  ");
  }
  if(WindDirection()==270){
    myFile.print("Wind Direction: ");
    myFile.print("SE");
    myFile.println("  ");
  }
  if(WindDirection()==315){
    myFile.print("Wind Direction: ");
    myFile.print(" S");
    myFile.println("  ");
  }
 // myFile.print("Wind Direction: ");
 // myFile.print(WindDirection());
 // myFile.println("  ");
  myFile.print("Average Wind Speed (One Minute): ");
  myFile.print(WindSpeedAverage());
  myFile.println("m/s  ");
  myFile.print("Max Wind Speed (Five Minutes): ");
  myFile.print(WindSpeedMax());
  myFile.println("m/s");
  myFile.print("Rain Fall (One Hour): ");
  myFile.print(RainfallOneHour());
  myFile.println("mm  ");
  myFile.print("Rain Fall (24 Hour): ");
  myFile.print(RainfallOneDay());
  myFile.println("mm");
  myFile.print("Temperature: ");
  myFile.print(Temperature());
  myFile.println("C  ");
  myFile.print("Humidity: ");
  myFile.print(Humidity());
  myFile.println("%  ");
  myFile.print("Barometric Pressure: ");
  myFile.print(BarPressure());
  myFile.println("hPa");
  myFile.println("");
  myFile.println("");
  myFile.print("Voltage bat: ");
  myFile.print(voltage);
  myFile.println(" V");
  myFile.print("Voltage sol: ");
  myFile.print(voltage_solar);
  myFile.println(" V"); 
  
  
    myFile.close(); // close the file
  }
  // if the file didn't open, print an error:
  else {
    Serial.println("error opening test.txt");
  }
  delay(100);
}

  

 

總結

 

arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站arduino制作具有無限數據傳輸功能的氣象站

 

這個項目從最初的想法變成最終的產品,整個過程非常有趣,也很有挑戰性。你需要花時間思考不同的選項。所以,整個項目要順利完成,就需要投入大量時間和精力,才能讓它變成你真正想要的樣子。

 但是類似的項目也提供了很好的機會,讓你能夠不斷擴充升級在設計和電路方面的知識。此外,項目還包含了許多其他技術領域,比如3D建模、3D打印、焊接等等。所以,它不僅能讓你了解某一個技術領域,更重要的是讓你了解不同的技術領域如何交互作用,從而實現一個完整的項目。

該項目設計簡單,只要具備電路、焊接、研磨、設計等方面的基本技能,每個人都可以完成。最關鍵的要素還是時間。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM