用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打印、焊接等等。所以,它不仅能让你了解某一个技术领域,更重要的是让你了解不同的技术领域如何交互作用,从而实现一个完整的项目。

该项目设计简单,只要具备电路、焊接、研磨、设计等方面的基本技能,每个人都可以完成。最关键的要素还是时间。

 

posted on 2019-07-03 15:08  开源硬件爱好者  阅读(1306)  评论(2编辑  收藏  举报