В данной статье я расскажу о том, как сделать первый шаг в мир Arduino и смастерить собственную метеостанцию. Метеостанция будет состоять из двух модулей: один модуль будет считывать информацию с подключенных датчиков, другой — выводить считанные данные на небольшой экран. Для передачи информации будем использовать Bluetooth.
Также приведу информацию по настройке BT-модулей для работы друг с другом.
С чего начать?
Начнем с того, что для того чтобы начать свои первые поделки на платформе Arduino не требуется обширных знаний. Всю информацию можно получить из интернета, в частности, очень помогли обучающие уроки от Amperka.ru.
Подготовка
Для изготовления прототипов устройств понадобятся следующие элементы:
- Фоторезистор 500 кОм (x1)
- Барометр BMP085 (x1)
- BT-модуль HC-05 (x2)
- LCD дисплей, ЖК экран LCM 1602 i2c (x1)
- Набор эл. компонентов (макетная плата, резисторы, диоды) (x1)
- Arduino UNO R3 (x2)
Для прошивки будем использовать родную Arduino IDE.
Хочу обратить внимание на то, что хотя бы один модуль должен быть HC-05 (не 06!), это важно. Дело в том, что HC-06 не поддерживает режим master, т.о. взяв оба модуля 06 нам не удастся настроить их на работу друг с другом. Я решил взять оба модуля HC-05 чтобы заодно избежать проблем с совместимостью, если таковые возникнут.
Нюансы настройки BT-модулей будут описаны ниже.
Оба модуля встроены в шилд, то есть проблем с подключением к плате Arduino возникнуть не должно.
Начинаем сборку
Подключаем фоторезистор
Сопротивление фоторезистора зависит от света, попадающего на него. Используя фоторезистор в связке с обычным резистором, мы получаем делитель напряжения, в котором напряжение проходящее через фоторезистор, изменяется, в зависимости от уровня освещенности.
Механизм получения полезной информации от датчика очень прост: функция analogRead(pin_number) вернет значение, которое будет представлять степень освещенности. Чувствительностью датчика можно управлять играясь с резисторами разных номиналов; на мой взгляд, 10кОм — оптимальный номинал.
int lightPin= 0; //номер входа, к которому подключен фоторезистор void setup() { } void loop() { int light = analogRead(lightPin); }
Датчик давления и температуры
Для измерения температуры, давления, а также высоты над уровнем моря будем использовать барометр BMP085.
Для подключения датчика BMP085 к Arduino нам понадобится 4 контакта:
- Vcc – подключаем к питанию +5в
- SDA – SDA на плате Arduino (A4)
- SCL – SCL на плате Arduino (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); } }
Подключение дисплея
Контакты дисплея LCD1602 подключаются аналогично, как и для BMP085:
- ЖК SDA -> Arduino SDA (A4)
- ЖК SCL -> Arduino SCL (А5)
- ЖК 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
Подключение Bluetooth
А теперь самое интересное. «Насаживаем» наши шилды с bt-модулем на нашу Arduino:
Master-устройство будет подключаться к Slave-устройству, которое будет ждать входящего подключения. На одной из плат устанавливаем переключатель в H, это и будет наш master. На другой плате — в L, это будет slave.
Прикрепив модули к Arduino можно начинать настройку. Для настройки master-a нужно будет послать некоторый набор команд в bt-модуль, будем делать это с помощью Serial Monitor (Ctrl+Shift+M). При обмене сообщениями рекомендуется выставить Baud rate -> 38400 & «Both NL&CR».
Послав команду «AT» и нажав отправить, мы ожидаем ответ «OK». Если это так — плата подключена правильно, можно продолжать. Если нет — стоит вернуться на пару шагов назад и проверить корректность подключения bluetooth-модуля.
Несколько важных АТ-команд, которые нам могу пригодиться:
AT — просто вернет «OK», значит всё в порядке
AT+NAME? — вернет имя модуля. Мы также можем задать своё имя, послав, например, AT+NAME=WEATHER_MONITOR
AT+ROLE? — одна из ключевых команд, вернет роль устройства, master/slave. Задать значение можно с помощью AT+ROLE=0 — перевести в режим slave, либо AT+ROLE=1 — режим master.
AT+PSWD? — вернёт пин-код, используемый для подключения.
AT+ADDR? — вернёт адрес устройства, например «14:2:110007». Стоит заметить, что при использовании адреса в посылаемых AT-командах двоеточия ":" нужно заменять запятыми ",", т.о. «14:2:110007» -> «14,2,110007».
Настройка Slave’a
Тут никаких телодвижений не требуется, поэтому просто подключаем плату к питанию.
Настройка Master’a
Этап первый. Конфигурация.
- Посылаем AT+ORGL, тем самым возвращая модуль к его изначальной конфигурации
- Имя модуля можно изменить, послав AT+NAME=myname.
- AT+RMAAD — удаляем информацию о предыдущих «спариваниях».
- AT+PSWD=1234 — устанавливаем пароль
- AT+ROLE=1 — говорим устройству, что оно будет работать в master режиме.
- AT+CMODE=1 — говорим устройству, что оно будет подключаться к любым адресам.
Этап второй. Подключение.
- Отправляем команду AT, чтобы удостовериться, что модуль подключен и готов к работе.
- AT+INIT — инициализация. Если в ответ получаем ERROR(17) — ничего страшного, значит команда инициализации уже посылалась, продолжаем работу.
- AT+INQ — начинаем поиск доступных BT-устройств, ответ будет содержать список из адресов
- AT+LINK=<адрес> — тут происходит непосредственно подключение к slave-устройству. Команда на подключение может, например, выглядеть так: AT+LINK=14,2,110007.
После выполнения последней команды диоды начнут мигать с меньшей частотой, что говорит об успешном подключении.
Финишная прямая
На этом почти всё. Остается написать скетчи, в которых мы считываем-отправляем-принимаем-отображаем погодные данные. При желании можно отказаться от макетной платы и приступить к пайке, а затем поместить конструкции в корпуса.
Скетчи:
#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(); }
На этом всё. Спасибо за внимание!
ссылка на оригинал статьи http://geektimes.ru/post/268524/
Добавить комментарий