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

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

  • 相关阅读:
    Java安全之JNDI注入
    Visual Studio 2019 升级16.8之后(升级.Net 5),RazorTagHelper任务意外失败
    .Net Core 3.1升级 .Net 5后出现代码错误 rzc generate exited with code 1.
    重走py 之路 ——普通操作与函数(三)
    重走py 之路 ——字典和集合(二)
    设计模式结(完结篇)
    重走py 之路 ——列表(一)
    RestfulApi 学习笔记——分页和排序(五)
    RestfulApi 学习笔记——查询与过滤还有搜索(五)
    Android开发 Error:The number of method references in a .dex file cannot exceed 64K.Android开发 Error:The number of method references in a .dex file cannot exceed 64K
  • 原文地址:https://www.cnblogs.com/esp32/p/iwoox.html
Copyright © 2011-2022 走看看