Arduino入门蓝牙气象站

在本文中,我将讨论如何迈向Arduino世界的第一步,并打造自己的气象站。气象站将由两个模块组成:一个模块将从已连接的传感器读取信息,另一个模块将在一个小屏幕上显示读取的数据。我们将使用蓝牙传输信息。

我还将提供有关设置BT模块以相互配合的信息。

图片

所以走吧!

从哪里开始?


首先,为了在Arduino平台上开始您的第一批手工艺品,您不需要广泛的知识。所有信息都可以从Internet上获得,特别是Amperka.ru的培训课程对您有所帮助

准备工作


为了制造原型设备,您需要以下元素:

  • 500kΩ光敏电阻(x1)
  • 气压计BMP085(x1)
  • BT模块HC-05(x2)
  • 液晶显示器,液晶显示器LCM 1602 i2c(x1)
  • 邮件集 组件(面包板,电阻器,二极管)(x1)
  • Arduino UNO R3(x2)

对于固件,我们将使用本地Arduino IDE。

我想提请您注意至少一个模块必须是HC-05(而不是06!)这一事实,这一点很重要。事实是HC-06不支持模式,即 使用两个模块06,我们将无法将它们配置为相互配合。我决定同时使用两个HC-05模块,以避免兼容性问题(如果有)。

下面将介绍设置BT模块的细微差别。

图片

这两个模块都内置在屏蔽中,也就是说,连接到Arduino板应该没有问题。

开始组装


我们连接一个光敏电阻


光敏电阻的电阻取决于入射在其上的光。通过将光敏电阻与常规电阻器配合使用,我们可获得分压器,其中通过光敏电阻的电压会根据照明水平而变化。

从传感器获取有用信息的机制非常简单:analogRead(pin_number)函数将返回一个表示照度的值。可以通过使用不同额定值的电阻器来控制传感器的灵敏度。我认为10kOhm是最佳等级。

图片

代码示例
int lightPin= 0; // ,    
void setup()
{
}
void loop()
{
  int light = analogRead(lightPin);
}


压力和温度传感器


为了测量温度,压力和高度,我们将使用BMP085气压计。

图片

要将BMP085连接到Arduino,我们需要4个引脚:

  • Vcc-连接电源+ 5v
  • SDA-Arduino(A4)上的SDA
  • SCL-Arduino开发板上的SCL(A5)
  • GND-接地

图片

要从传感器获取值,必须连接Adafruit库。

代码示例

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);
void setup(void)
{
/* Initialise the sensor */
  if(!bmp.begin())
  {
    /* There was a problem detecting the BMP085 ... check your connections */
    Serial.print("Ooops, no BMP085 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
}
void loop(void)
{
  sensors_event_t event;
  bmp.getEvent(&event);
  if (event.pressure)
  {
    float pressure = event.pressure;
    
    float temperature;
    bmp.getTemperature(&temperature);

    float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
    float altitude = bmp.pressureToAltitude(seaLevelPressure, event.pressure); 
  }
}


连接了所有传感器的Arduino
image

显示连接


LCD1602显示引脚的连接方式与BMP085的连接方式相同:

  • LCD SDA-> Arduino SDA(A4)
  • LCD SCL-> Arduino SCL(A5)
  • LCD GND-> Arduino GND
  • 液晶显示VCC-> Arduino 5V

图片

代码示例
/*     LCD  1602. */  
#include <Wire.h>
#include <LiquidCrystal_I2C.h>  
LiquidCrystal_I2C lcd(0x27,16,2); // :  ,    
void setup()
{
    lcd.init();
    //  lcd
    lcd.backlight();
    //  
    //     1 
    lcd.print("Hello");
    //  
    lcd.setCursor(0, 1);
    //     2 
    lcd.print("World!");
    //  
}  
void loop()
{ }
// : http://xrobot.by/modules/lcd_4_4#ixzz3vQXoFKOj


蓝牙连接


现在是有趣的部分。我们在Arduino上用bt模块“植入”屏蔽:

图片

主设备将连接到从设备,从设备将等待传入连接。在其中一个板上,我们将开关设置为H,这将是我们的主控板。在另一块板上-在L中,它将是从属。

图片

通过将模块连接到Arduino,您可以开始设置。要配置主站,您需要向bt-module发送一组特定的命令,我们将使用串行监视器(Ctrl + Shift + M)进行此操作。进行消息传送时,建议设置波特率-> 38400和“ Both NL&CR”。

发送AT命令并单击“发送”后,我们希望得到一个确定的响应。如果是这样-电路板已正确连接,则可以继续。如果没有,那么就应该退后几步并检查蓝牙模块的连接。

一些重要的AT命令可能会派上用场:

AT-仅返回“ OK”,那么
AT + NAME没问题吗?-将返回模块的名称。我们还可以通过发送例如AT + NAME = WEATHER_MONITOR
AT + ROLE来设置自己的名称吗?-关键命令之一将返回设备的角色,主/从。您可以使用AT + ROLE = 0-切换到从机模式,或AT + ROLE = 1-主模式来设置值。
AT + PSWD?-将返回用于连接的密码。
AT + ADDR?-将返回设备的地址,例如“ 14:2:110007”。值得注意的是,在发送的AT命令中使用地址时,冒号“:”必须替换为逗号“,”,即 “ 14:2:110007”->“ 14,2,110007”。

从站设置


这里不需要任何身体移动,因此只需将开发板插入电源即可。

Master'a


. .

  1. AT+ORGL,
  2. , AT+NAME=myname.
  3. AT+RMAAD — «».
  4. AT+PSWD=1234 —
  5. AT+ROLE=1 — , master .
  6. AT+CMODE=1 — , .

. .

  1. AT, , .
  2. AT+INIT — . ERROR(17) — , , .
  3. AT+INQ — BT-,
  4. AT + LINK = <地址>-到从设备的直接连接。例如,连接命令可能看起来像这样:AT + LINK = 14,2,110007。

执行最后一条命令后,二极管将以较低的频率闪烁,表明连接成功。

终点线


差不多了。剩下的就是写一些草图,在这些草图中我们读取并发送显示天气数据。如果愿意,您可以放弃面包板并开始焊接,然后将结构放在盒中。

工作成果
image
image
image
image

草图:

天气监控代码
#include <SoftwareSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>  

LiquidCrystal_I2C lcd(0x27,16,2); // :  ,    

#define rxPin 2
#define txPin 3

SoftwareSerial btSerial(rxPin, txPin);

bool isDisplayingMode = true;
 
void setup()
{
   lcd.init();
   lcd.backlight();
   // define pin modes for tx, rx pins:
   pinMode(rxPin, INPUT);
   pinMode(txPin, OUTPUT);
   btSerial.begin(38400); 
   Serial.begin(38400);
   Serial.println("Serial started");
   
           
   lcd.print("    Waiting");
   lcd.setCursor(0, 1);
   lcd.print(" for connection");
   
   btSerial.println("AT");
   while (!btSerial.available());
   while (btSerial.available() > 0)
        char c = btSerial.read();
   btSerial.println("AT+INIT");
   while (!btSerial.available());
   while (btSerial.available() > 0)
        char c = btSerial.read();
   btSerial.println("AT+INQ");
   while (!btSerial.available());
   while (btSerial.available() > 0)
        char c = btSerial.read();
   btSerial.println("AT+LINK=2014,5,191146");  
   while (!btSerial.available());
   while (btSerial.available() > 0)
        char c = btSerial.read();   
}

void loop()
{   
  int i = 0;
  char someChar[32] = {0};
  // when characters arrive over the serial port...
  bool availible = Serial.available();
  if(availible) {
    do{
        someChar[i++] = Serial.read();
      //As data trickles in from your serial port you are grabbing as much as you can, 
      //but then when it runs out (as it will after a few bytes because the processor 
      //is much faster than a 9600 baud device) you exit loop, which then restarts, 
      //and resets i to zero, and someChar to an empty array.So please be sure to keep this delay 
      delay(3);                  
 
    }while (Serial.available() > 0);

    lcd.clear();
    Serial.println(i);
    btSerial.println(someChar);
    Serial.println(someChar);
  }
 
  lcd.setCursor(0, 0);
  while(btSerial.available()) 
      {
        if (isDisplayingMode)
        {
          lcd.clear();
          isDisplayingMode = false;
        }
        char c = (char)btSerial.read();
        Serial.print(c);          
        if (c != 13 && c != 10)
          lcd.print(c);
        if (c == '\n')
          lcd.setCursor(0, 1);
      }
}


天气传感器代码
#include <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>

Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);
int lightSensorPin = 0;

#define rxPin 2
#define txPin 3

SoftwareSerial btSerial(rxPin, txPin);

struct SensorData
{
  float Pressure;
  float Temperature;
  float Altitude;
  float Lightness;
  void DisplaySensorData()
{
    Serial.print("Light:       ");
    Serial.print(this->Lightness, 2);
    Serial.println("%");
    Serial.print("Altitude:    "); 
    Serial.print(this->Altitude); 
    Serial.println(" m");
    Serial.print("Temperature: ");
    Serial.print(this->Temperature);
    Serial.println(" C");
    /* Display atmospheric pressue in hPa */
    Serial.print("Pressure:    ");
    Serial.print(this->Pressure);
    Serial.println(" hPa");
    Serial.println("");
}

void DisplaySensorDataInTwoRows()
{
    Serial.print("Temp: "); Serial.print(this->Temperature); Serial.println(" C");
    Serial.print("Pr: "); Serial.print(this->Pressure); Serial.println(" Pa");
    delay(1000);    
    Serial.print("Alt: "); Serial.print(this->Altitude); Serial.println(" m");
    Serial.print("Light: "); Serial.print(this->Lightness); Serial.println(" %");
    delay(1000);
}
void SendDataToRemote()
{
    btSerial.print("Temp: "); btSerial.print(this->Temperature); btSerial.print(" C\n");
    btSerial.print("Pr:   "); btSerial.print(this->Pressure); btSerial.print(" hPa\n");
    delay(5000);    
    btSerial.print("Alt:   "); btSerial.print(this->Altitude); btSerial.print(" m\n");
    btSerial.print("Light: "); btSerial.print(this->Lightness); btSerial.print(" %  \n");
    delay(5000);
}
};



void displaySensorDetails(void)
{
  sensor_t sensor;
  bmp.getSensor(&sensor);
  
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" hPa");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" hPa");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" hPa");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void setup(void) 
{
   // define pin modes for tx, rx pins:
   pinMode(rxPin, INPUT);
   pinMode(txPin, OUTPUT);
   btSerial.begin(38400);
   
  Serial.begin(9600);
  Serial.println("Pressure Sensor Test"); Serial.println("");
  
   
  /* Initialise the sensor */
  if(!bmp.begin())
  {
    /* There was a problem detecting the BMP085 ... check your connections */
    Serial.print("Ooops, no BMP085 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
    
  /* Display some basic information on this sensor */
  displaySensorDetails();
}
int counter = 0;
void loop(void) 
{
  /* Get a new sensor event */ 
  sensors_event_t event;
  bmp.getEvent(&event);
  SensorData data;
  /* Display the results (barometric pressure is measure in hPa) */
  if (event.pressure)
  {
    data.Pressure = event.pressure;
    
    float temperature;
    bmp.getTemperature(&temperature);
    data.Temperature = temperature;

    /* Then convert the atmospheric pressure, and SLP to altitude         */
    /* Update this next line with the current SLP for better results      */
    float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
    float altitude = bmp.pressureToAltitude(seaLevelPressure, event.pressure);
    data.Altitude = altitude;  
    
    int lightValue = analogRead(lightSensorPin);
    float lightValueInPercent = 1.0 * lightValue / 1024 * 100;
    data.Lightness = lightValueInPercent;
    
    //data.DisplaySensorDataInTwoRows();    
  }
  else
  {
    Serial.println("Sensor error");
  }
  Serial.println("");
  data.SendDataToRemote();
}


仅此而已。感谢您的关注!

Source: https://habr.com/ru/post/zh-CN388605/


All Articles