В современном мире возможности чата доступны во многих существующих социальных сетях и других сервисах таких как Whatsapp, Facebook, Hangout. Но для организации чата с помощью этих сервисов необходимо подключение к сети Интернет. А что делать когда такое подключение отсутствует? В этой статье мы рассмотрим проект создания приватной комнаты чата в локальной сети (не подключенной к интернету) на основе платы Arduino и радиочастотных модулей nRF24L01.
Объяснение работы проекта
В самом простом случае для реализации этого проекта понадобится 2 платы Arduino и 2 дешевых модуля беспроводной связи, в качестве которых мы выбрали nRF24L01. Причина выбора этих модулей заключается в том, что они поддерживают протокол Zigbee и их легко настроить. Эти модули работают в диапазоне 2.4 ГГц (безлицензионный диапазон ISM на западе) в режиме псевдослучайной перестройки частоты (ППРЧ, в англ. FHSS), что позволяет нам не принимать во внимание возможные электромагнитные помехи.
Используемые нами платы Arduino и радиочастотные модули NRF24L01 будут устанавливать между собой последовательную связь, что позволит им обмениваться информацией друг с другом. NRF24L01 представляют собой полудуплексные приемопередающие модули, способные передавать и принимать информацию.
Для создания комнаты чата мы будем использовать программное обеспечение ‘Processing’, которое способно взаимодействовать через последовательный приемопередатчик Arduino. Мы создадим исполняемый .exe файл на этом языке Processing, который можно будет запустить на любом компьютере с Java Runtime. То есть чтобы организовать наш чат мы должны просто подключить Arduino к компьютеру и запустить на компьютере этот .exe файл.
В этой статье мы рассмотрим комнату чата всего с двумя членами, но модуль nRF24L01 имеет 6 каналов, поэтому этот чат при желании можно расширить до 6 членов. Наш чат будет работоспособен на расстоянии около 100 метров – это дальность работы модулей nRF24L01.
Необходимые компоненты
- Плата Arduino (любая версия или модель) – 2 шт. (купить на AliExpress).
- Модули nRF24L01+ – 2 шт. (купить на AliExpress).
- Регулятор напряжения на 3.3 В (не обязательно) – 2 шт.
- Источник питания.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Работа схемы
На следующем рисунке представлена схема соединений платы Arduino Mega с радиочастотным модулем nRF24L01.
А на следующем - схема соединений платы Arduino Nano с радиочастотным модулем nRF24L01.
Но вы можете использовать любые другие модели плат Arduino – какие у вас есть в наличии.
Основные моменты при выборе (покупке) радиочастотных модулей nRF24L01+
Для того, чтобы ваша работа с модулями nRF24L01+ доставляла вам как можно меньше проблем старайтесь учитывать следующие нюансы при их покупке:
- Большинство модулей nRF24L01+ которые вы можете купить на рынке – фальшивые. Самые плохие среди них – это самые дешевые подобные модули в онлайн магазинах Ebay и Amazon. Их можно заставить работать нормально, но для этого нужно приложить некоторые усилия.
- Основная часть проблем при работе с данными модулями связана с их электропитанием, а вовсе не с программным кодом, который вы используете.
- При внимательном рассмотрении может оказаться что модули, маркированные как NRF24L01+ будут на самом деле Si24Ri (это их дешевые китайские аналоги).
- Дешевые подделки этих модулей потребляют значительно больше электроэнергии чем оригиналы. Поэтому при расчете схем питания для этих подделок не стоит ориентироваться на даташит для nRF24L01+. К примеру, модули Si24Ri потребляют примерно 250 мА.
- Остерегайтесь перепадов напряжения и тока, потому что эти модули весьма чувствительны ко всему этому и их легко сжечь.
- Добавление пары конденсаторов в схему (10 мкФ и 0.1 мкФ), включенных по питанию (через контакты Vcc и Gnd модулей) поможет значительно сгладить возможные проблемы с электропитанием.
Объяснение работы программы
Код программы для обоих используемых в нашем проекте плат (Arduino Nano и Mega) будет одинаков за исключением различий в контактах CE и CS. Рассмотрим принцип работы основных частей этого кода.
Поскольку платы Arduino и модули nRF24L01 будут взаимодействовать через интерфейс SPI (Serial Peripheral Interface - последовательный интерфейс (периферийных устройств), передача по нему идёт бит за битом), то нам будет необходимо подключить библиотеку для работы с этим интерфейсом (SPI library). Также мы использовали в нашем проекте библиотеку RF24, необходимую для работы модулей nRF24L01. Скачать ее можно по следующей ссылке – https://github.com/maniacbug/RF24. После скачивания добавьте ее в ваш Arduino IDE.
#include <SPI.h>
#include "RF24.h"
Модули nRF24L01 подсоединены своими контактами CE и CS к контактам 8 и 10 платы Arduino Nano (в случае с платой Arduino Mega они подключаются к другим контактам платы – смотрите приведенный выше рисунок).
RF24 myRadio (8, 10);
Также в программе мы создали специальную структуру данных под названием package. В этой структуре переменная text[20] будет использоваться для передачи текста через воздушное пространство.
struct package
{
char text[20]; // текст для передачи через воздушное пространство
};
typedef struct package Package;
Package data;
В функции void setup() мы инициализировали передачу последовательных данных со скоростью 9600 бод/с, установили для наших радиочастотных модулей 115-й канал, режим минимальной мощности и режим минимальной скорости (250 кбит/с). В дальнейшем вы можете самостоятельно изменить эти параметры.
void setup()
{
Serial.begin(9600);
delay(1000);
//Serial.print("Setup Initialized");
myRadio.begin();
myRadio.setChannel(115); //115 band above WIFI signals
myRadio.setPALevel(RF24_PA_MIN); //MIN power low rage
myRadio.setDataRate( RF24_250KBPS ) ; //Minimum speed
}
Модули будут работать в режиме передачи при наличии данных в последовательном буфере (Serial buffer), иначе они будут находиться в режиме приема. Данные, поступающие от пользователя, будут сохраняться в символьном массиве (char Array) и поступать в функцию WriteData() для их последующей передачи.
void loop()
{
while(Serial.available()>0) // получение данных от пользователя
{
val = Serial.peek();
if(index < 19) // на 1 меньше чем размер массива
{
inChar = Serial.read(); // считываем символ
inData[index] = inChar; // сохраняем его
index++; // инкремент чтобы перейти к следующему символу
inData[index] = '\0'; // ноль заканчивает (прерывает) строку
}
if (val=='#')
{
strcpy( data.text, inData);
WriteData(); // переводим модуль в режим передачи
while (index!=0)
{
inData[index] = ' ';
index--;
}
}
}
ReadData(); // переводим модуль в режим приема
}
Функция WriteData() записывает данные по адресу 0xF0F0F0F0AA, который будет использоваться как канал передачи для нашего радиочастотного модуля.
void WriteData()
{
myRadio.stopListening(); // завершить прием и начать передачу
myRadio.openWritingPipe(0xF0F0F0F066); // передать данные на указанный 40-битный адрес
myRadio.write(&data, sizeof(data));
delay(300);
}
Функция void ReadData() считывает данные по адресу 0xF0F0F0F066, который будет использоваться как канал приема для нашего радиочастотного модуля.
void ReadData()
{
myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //Which pipe to read, 40 bit Address
myRadio.startListening(); //завершить передачу и начать прием
if ( myRadio.available())
{
while (myRadio.available())
{
myRadio.read( &data, sizeof(data) );
}
Serial.println(data.text);
}
}
Программа в Processing
‘Processing’ представляет собой программное обеспечение с открытым исходным кодом, которое часто используется энтузиастами в графическом дизайне. Также его можно использовать для разработки приложений для Android. Во многом оно похоже на такой инструмент как Android Development IDE.
Код Processing для обоих экранов чата можно скачать по следующим ссылкам:
Сделайте правый клик по этим ссылкам и выберите пункт "Сохранить как" чтобы скачать их. Вам необходимо установить программное обеспечение 'Processing' чтобы открыть эти *.pde файлы и затем запустить их на выполнение, что приведет к открытию окон чата. Куски кода Processing для модуля передатчика и приемника идентичны.
В представленном ниже участке кода команда "port = new Serial(this,Serial.list()[4],9600); //Reads the 4th PORT at 9600 baudrate" очень важна, поскольку определяет по какому каналу будет осуществляться передача/прием данных.
void setup()
{
size(510,500);
port = new Serial(this,Serial.list()[4],9600); //будет использоваться 4-й PORT на скорости 9600 бод/с
println(Serial.list());
background(0);
}
В данном примере мы использовали 4-й порт Arduino, но можно использовать и другой.
Теперь, когда наши программы для Processing и Arduino готовы, просто загрузите программу с вашего компьютера в Arduino и оставьте ее подключенной к компьютеру. Откройте программу в Processing, напишите в открывшемся окне сообщение и нажмите "Enter" – после этого ваше сообщение передастся на другую плату Arduino, которое с помощью приложения Processing на другом компьютере отобразит его на экране. Более подробно эти процессы показаны в видео в конце статьи.
С помощью этого чата вы сможете переписываться с вашими друзьями не имея соединения с Интернетом.
Исходный код программы
Код программы для Arduino Mega
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
#include <SPI.h> #include "RF24.h" // эту библиотеку необходимо скачать по приведенной в статье ссылке RF24 myRadio (49, 53); // CE to 49 and 53 to CS struct package { char text[20]; // текст для передачи по воздушному пространству }; //byte addresses[][6] = {"0"}; char inData[20]; // зарезервируем некоторое пространство под строку char inChar; // где будем хранить считанные символы byte index = 0; // индекс в массиве где хранится символ int val; typedef struct package Package; Package data; void setup() { Serial.begin(9600); delay(1000); //Serial.print("Setup Initialized"); myRadio.begin(); myRadio.setChannel(115); //115 band above WIFI signals myRadio.setPALevel(RF24_PA_MIN); //MIN power low rage myRadio.setDataRate( RF24_250KBPS ) ; //Minimum speed } void loop() { while(Serial.available()>0) //Get values from user { val = Serial.peek(); if(index < 19) // One less than the size of the array { inChar = Serial.read(); // Read a character inData[index] = inChar; // Store it index++; // Increment where to write next inData[index] = '\0'; // Null terminate the string } if (val=='#') { strcpy( data.text, inData); WriteData(); //Put module in Transmit mode while (index!=0) { inData[index] = ' '; index--; } } } ReadData(); //Put module Receive mode } void ReadData() { myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //Which pipe to read, 40 bit Address myRadio.startListening(); //Sopt Transminting and start Reveicing if ( myRadio.available()) { while (myRadio.available()) { myRadio.read( &data, sizeof(data) ); } // Serial.print("\nReceived:"); Serial.println(data.text); } } void WriteData() { myRadio.stopListening(); //Stop Receiving and start transminitng myRadio.openWritingPipe(0xF0F0F0F066);//Sends data on this 40-bit address myRadio.write(&data, sizeof(data)); //Serial.print("\nSent:"); //Serial.println(data.msg); delay(300); } |
Код программы для Arduino Nano
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
#include <SPI.h> #include "RF24.h" // Manicbug LIB to be downloaded RF24 myRadio (8, 10); // CE to 8 and 10 to CS struct package { char text[20]; //Text to transmit on air }; typedef struct package Package; Package data; char inData[20]; // Allocate some space for the string char inChar; // Where to store the character read byte index = 0; // Index into array; where to store the character int val; void setup() { Serial.begin(9600); delay(1000); myRadio.begin(); myRadio.setChannel(115); //115 band above WIFI signals myRadio.setPALevel(RF24_PA_MIN); //MIN power low rage myRadio.setDataRate( RF24_250KBPS ) ; //Minimum speed //Serial.print("Setup Initialized"); } void loop() { while(Serial.available()>0) //Get values from user { val = Serial.peek(); if(index < 19) // One less than the size of the array { inChar = Serial.read(); // Read a character inData[index] = inChar; // Store it index++; // Increment where to write next inData[index] = '\0'; // Null terminate the string } if (val=='#') { strcpy( data.text, inData); WriteData(); //Put module in Transmit mode while (index!=0) { inData[index] = ' '; index--; } } } ReadData(); //Put module Receive mode } void WriteData() { myRadio.stopListening(); //Stop Receiving and start transminitng myRadio.openWritingPipe( 0xF0F0F0F0AA); //Sends data on this 40-bit address myRadio.write(&data, sizeof(data)); //Serial.print("\nSent:"); //Serial.println(data.text); delay(300); } void ReadData() { myRadio.openReadingPipe(1, 0xF0F0F0F066); // Which pipe to read, 40 bit Address myRadio.startListening(); //Stop Transminting and start Reveicing if ( myRadio.available()) { while (myRadio.available()) { myRadio.read( &data, sizeof(data) ); } //Serial.print("\nReceived:"); Serial.println(data.text); } } |