Estación meteorológica Bluetooth Arduino Starter

En este artículo, hablaré sobre cómo dar el primer paso en el mundo de Arduino y crear su propia estación meteorológica. La estación meteorológica constará de dos módulos: un módulo leerá la información de los sensores conectados, el otro mostrará los datos leídos en una pantalla pequeña. Utilizaremos Bluetooth para transmitir información.

También proporcionaré información sobre cómo configurar módulos BT para trabajar entre ellos.

imagen

¡Entonces vamos!

Por donde empezar


Para empezar, para comenzar tus primeras manualidades en la plataforma Arduino, no necesitas un amplio conocimiento. Toda la información se puede obtener de Internet, en particular, las lecciones de capacitación de Amperka.ru ayudaron mucho .

Preparación


Para la fabricación de prototipos de dispositivos necesitará los siguientes elementos:

  • Fotoresistor de 500 kΩ (x1)
  • Barómetro BMP085 (x1)
  • Módulo BT HC-05 (x2)
  • LCD, LCD LCM 1602 i2c (x1)
  • Conjunto de correo electrónico componentes (placa de pruebas, resistencias, diodos) (x1)
  • Arduino UNO R3 (x2)

Para el firmware usaremos el IDE Arduino nativo.

Quiero llamar la atención sobre el hecho de que al menos un módulo debe ser HC-05 (¡no 06!). Esto es importante. El hecho es que el HC-06 no es compatible con el modo maestro , es decir tomando ambos módulos 06 no podremos configurarlos para que funcionen entre sí. Decidí tomar ambos módulos HC-05 al mismo tiempo para evitar problemas de compatibilidad, si los hubiera.

Los matices de la configuración de módulos BT se describirán a continuación.

imagen

Ambos módulos están integrados en el escudo, es decir, no debería haber problemas para conectarse a la placa Arduino.

Iniciar ensamblaje


Conectamos un fotorresistor


La resistencia del fotorresistor depende de la luz incidente sobre él. Usando una fotorresistencia junto con una resistencia convencional, obtenemos un divisor de voltaje en el cual el voltaje que pasa a través de la fotorresistencia cambia, dependiendo del nivel de iluminación.

El mecanismo para obtener información útil del sensor es muy simple: la función analogRead (pin_number) devolverá un valor que representará el grado de iluminación. La sensibilidad del sensor se puede controlar jugando con resistencias de diferentes clasificaciones; En mi opinión, 10kOhm es la calificación óptima.

imagen

Ejemplo de código
int lightPin= 0; // ,    
void setup()
{
}
void loop()
{
  int light = analogRead(lightPin);
}


Sensor de presión y temperatura


Para medir la temperatura, la presión y la altitud, utilizaremos el barómetro BMP085.

imagen

Para conectar el BMP085 a Arduino, necesitamos 4 pines:

  • Vcc - conectar a la alimentación + 5v
  • SDA - SDA en Arduino (A4)
  • SCL - SCL en la placa Arduino (A5)
  • GND - conectar al suelo

imagen

Para tomar valores del sensor, debe conectar la biblioteca Adafruit.

Ejemplo de código

#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 con todos los sensores conectados
image

Conexión de pantalla


Los pines de la pantalla LCD1602 se conectan de la misma manera que para BMP085:

  • LCD SDA -> Arduino SDA (A4)
  • LCD SCL -> Arduino SCL (A5)
  • LCD GND -> Arduino GND
  • LCD VCC -> Arduino 5V

imagen

Ejemplo de código
/*     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


Conexión Bluetooth


Y ahora para la parte divertida. "Plantamos" nuestros escudos con un módulo bt en nuestro Arduino: el

imagen

dispositivo maestro se conectará al dispositivo Esclavo, que esperará una conexión entrante. En uno de los tableros ponemos el interruptor en H, este será nuestro maestro. En el otro tablero, en L, será un esclavo.

imagen

Al conectar los módulos al Arduino, puede comenzar la configuración. Para configurar el maestro, deberá enviar un determinado conjunto de comandos al módulo bt, lo haremos utilizando el Monitor de serie (Ctrl + Shift + M). Al enviar mensajes, se recomienda establecer la velocidad en baudios -> 38400 y "Ambos NL&CR".

Después de enviar el comando AT y hacer clic en enviar, esperamos una respuesta correcta. Si es así, la placa está conectada correctamente, puede continuar. Si no, vale la pena retroceder un par de pasos y verificar la conexión del módulo bluetooth.

Algunos comandos AT importantes que pueden ser útiles:

AT - solo devuelve "OK", entonces ¿todo está bien
AT + NAME? - devolverá el nombre del módulo. ¿Podemos también establecer nuestro propio nombre enviando, por ejemplo, AT + NAME = WEATHER_MONITOR
AT + ROLE? - uno de los comandos de teclado devolverá la función del dispositivo, maestro / esclavo. Puede establecer el valor utilizando AT + ROLE = 0 - cambiar al modo esclavo, o AT + ROLE = 1 - modo maestro.
AT + PSWD? - devolverá el código pin utilizado para conectarse.
AT + ADDR? - devolverá la dirección del dispositivo, por ejemplo, "14: 2: 110007". Vale la pena señalar que cuando se usa la dirección en los comandos AT enviados, los dos puntos ":" deben reemplazarse con comas ",", es decir "14: 2: 110007" -> "14,2,110007".

Configuración esclava


Aquí no se requieren movimientos corporales, así que simplemente conecte la placa a la corriente.

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 = <dirección> - hay una conexión directa al dispositivo esclavo. El comando de conexión puede, por ejemplo, verse así: AT + LINK = 14,2,110007.

Después de ejecutar el último comando, los diodos parpadearán a una frecuencia más baja, lo que indica una conexión exitosa.

Línea de meta


Eso es casi todo. Queda por escribir bocetos en los que leemos, enviamos, aceptamos y mostramos datos meteorológicos. Si lo desea, puede abandonar la placa de pruebas y comenzar a soldar, y luego colocar la estructura en el estuche.

Resultado del trabajo
image
image
image
image

Bocetos:

Código de monitor meteorológico
#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);
      }
}


Código del sensor meteorológico
#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();
}


Eso es todo. Gracias por su atencion!

Source: https://habr.com/ru/post/es388605/


All Articles