Радио модули 433 МГц (ARDUINO)

Радио модули 443 МГц представляют собой передатчик (FS1000A) и приёмник (MX-RM-5V) которые предназначены для передачи данных по радиоканалу, на частоте 433,920 МГц.

Характеристики передатчика FS1000A

  • Рабочая частота: 433.920 МГц (указывается на металлическом корпусе модуля)
  • Тип модуляции: ASK — амплитудная манипуляция
  • Дальность передачи: до 100 м (в зоне прямой видимости, без антенны)
  • Выходная мощность: до 40 мВт
  • Напряжение питания: 3 … 12 В
  • Ток потребления в режиме ожидания: 0 мА
  • Ток потребления в режиме передачи: 20 .. 30 мА

Характеристики приёмника MX-RM-5V

  • Рабочая частота: 433.920 МГц
  • Тип модуляции: ASK — амплитудная манипуляция
  • Дальность приёма: до 100 м (в зоне прямой видимости, без антенны)
  • Напряжение питания: 5 В
  • Ток потребления: 4 мА

На этой странице представлены несколько практических скетчей применения радио модулей. Первый пример скетча тестовое включение радиомодулей, в качестве микроконтроллеров в тестовом скетче можно использовать Atmega8, Atmega88, Atmega168 и Atmega328 (Arduino Nano).

Для увеличения дальности связи рекомендуется к приемнику и передатчику припаять антенны (одножильный медный провод длиной 17,3 см).

Вам понадобится следующие библиотеки:

Для тестового скетча Вам необходимо собрать схему:

Передатчик

// pin DATA === D12
#include <VirtualWire.h>
 
void setup(void)
{
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
}
 
void loop(void)
{
  int number = 12345;
  String symbol = "a";
 
  String strMsg = "z ";
  strMsg += symbol;
  strMsg += " ";
  strMsg += number;
  strMsg += " ";
 
  char msg[255];
 
  strMsg.toCharArray(msg, 255);
 
  vw_send((uint8_t *)msg, strlen(msg));
  vw_wait_tx(); 
  delay(200);
}

Приемник

// pin DATA === D11
#include <VirtualWire.h>
 
void setup(){
  Serial.begin(9600);
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
  vw_rx_start(); 
}
 
void loop(){
  uint8_t buf[VW_MAX_MESSAGE_LEN]; 
  uint8_t buflen = VW_MAX_MESSAGE_LEN; 
 
  if (vw_get_message(buf, &buflen)) {
    int i=4;
    if (buf[0] != 'z'){return; }
    char command = buf[2]; 
    int number = 0;
    while (buf[i] != ' '){
      number *= 10;
      number += buf[i] - '0';
      i++;
    }
    Serial.print(command);
    Serial.print(" ");
    Serial.println(number);
  }
}

После загрузки скетчей откройте монитор порта (приемник), в нем Вы должны увидеть следующее:

Если в мониторе порта приемника отображаются верные значения символов передаваемые передатчиком , то можно приступить к следующему примеру, в котором при нажатии кнопки на D7 будет загораться или гаснуть светодиод на D13 (установлен на плате Arduino Nano).

 

Передатчик

// pin DATA === D12
#include <VirtualWire.h>
 
char symbol;
bool w;
 
void setup(void){
  vw_set_ptt_inverted(true); 
  vw_setup(2000);
  pinMode(7,INPUT_PULLUP); 
}
 
void loop(void){
  if(digitalRead(7)==LOW && w==0){w=1; symbol='a';delay(200);}
  if(digitalRead(7)==LOW && w==1){w=0; symbol='b';delay(200);}
 
  String strMsg = "z ";
  strMsg += symbol;
  strMsg += " ";
 
  char msg[255];
 
  strMsg.toCharArray(msg, 255);
 
  vw_send((uint8_t *)msg, strlen(msg));
  vw_wait_tx(); 
}

Приемник

// pin DATA === D11
#include <VirtualWire.h>
 
void setup(){
  Serial.begin(9600);
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
  vw_rx_start();
  pinMode(13,OUTPUT); 
}
 
void loop(){
  uint8_t buf[VW_MAX_MESSAGE_LEN]; 
  uint8_t buflen = VW_MAX_MESSAGE_LEN; 
 
  if (vw_get_message(buf, &buflen)) {
    int i=4;
    if (buf[0] != 'z'){return; }
    char command = buf[2]; 
 
  if(command=='a'){digitalWrite(13,HIGH);}
  if(command=='b'){digitalWrite(13,LOW);}
 
    Serial.println(command);
  }
}

При нажатии кнопки передатчик отсылает в приемник символ «a», загорается светодиод, при повторном нажатии кнопки передатчик отсылает в приемник символ «b», светодиод гаснет.

В следующем примере уже используется 4-е кнопки в передатчике и 4-е выхода управления реле в приемнике.

 

Передатчик

// pin DATA === D12
#include <VirtualWire.h>
 
int number;
bool w1,w2,w3,w4;
 
void setup(void){
  vw_set_ptt_inverted(true); 
  vw_setup(2000);
  pinMode(7,INPUT_PULLUP); 
  pinMode(6,INPUT_PULLUP); 
  pinMode(5,INPUT_PULLUP); 
  pinMode(4,INPUT_PULLUP); 
}
 
void loop(void){
  if(digitalRead(7)==LOW && w1==0){w1=1;number |= (1<<0);delay(200);}
  if(digitalRead(7)==LOW && w1==1){w1=0;number &=~(1<<0);delay(200);}
 
  if(digitalRead(6)==LOW && w2==0){w2=1;number |= (1<<1);delay(200);}
  if(digitalRead(6)==LOW && w2==1){w2=0;number &=~(1<<1);delay(200);}
 
  if(digitalRead(5)==LOW && w3==0){w3=1;number |= (1<<2);delay(200);}
  if(digitalRead(5)==LOW && w3==1){w3=0;number &=~(1<<2);delay(200);}
 
  if(digitalRead(4)==LOW && w4==0){w4=1;number |= (1<<3);delay(200);}
  if(digitalRead(4)==LOW && w4==1){w4=0;number &=~(1<<3);delay(200);}      
 
  String strMsg = "z ";
  strMsg += number;
  strMsg += " ";
 
  char msg[255];
 
  strMsg.toCharArray(msg, 255);
 
  vw_send((uint8_t *)msg, strlen(msg));
  vw_wait_tx(); 
}

Приемник

// pin DATA === D11
#include <VirtualWire.h>
 
void setup(){
  Serial.begin(9600);
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
  vw_rx_start();
  pinMode(2,OUTPUT); 
  pinMode(3,OUTPUT); 
  pinMode(4,OUTPUT); 
  pinMode(5,OUTPUT); 
}
 
void loop(){
  uint8_t buf[VW_MAX_MESSAGE_LEN]; 
  uint8_t buflen = VW_MAX_MESSAGE_LEN; 
 
  if (vw_get_message(buf, &buflen)) {
    int i=2;
    if (buf[0] != 'z'){return; }
 
    int number = 0;
    while (buf[i] != ' '){
      number *= 10;
      number += buf[i] - '0';
      i++;
    }
 
    Serial.println(number);
    if(((number >> 0) & 1) ==1){digitalWrite(2,HIGH);}else{digitalWrite(2,LOW);}
    if(((number >> 1) & 1) ==1){digitalWrite(3,HIGH);}else{digitalWrite(3,LOW);}
    if(((number >> 2) & 1) ==1){digitalWrite(4,HIGH);}else{digitalWrite(4,LOW);}
    if(((number >> 3) & 1) ==1){digitalWrite(5,HIGH);}else{digitalWrite(5,LOW);}
 
  }
}

В этом примере нажатие определенной кнопки передатчика меняет состояние битов байта number, приемник получает этой байт и в зависимости от состояния битов байта number, меняет состояние цифровых выходов D2 D3 D4 D5, к которым можно подключить четыре модуля реле или другой исполнительный элемент.

Далее рассмотрим пример создания простого электронного термометра с диапазоном измерения о 0 до 100 °С, в качестве датчика температуры будет использован цифровой датчик DS18B20, который подключается к передатчику, информация о температуре передается в приемник и выводится на LCD1602 с I2C модулем.

Передатчик

// pin DATA === D12
#include <VirtualWire.h>
#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip
 
  OneWire  ds(2); // Вход датчика 18b20
 
void setup(void){
  vw_set_ptt_inverted(true); // Необходимо для DR3100
  vw_setup(2000); // Устанавливаем скорость передачи (бит/с)
 
}
 
void loop(void)
{
  int number = dsRead(0)*100;
  char symbol = 'c';
 
  String strMsg = "z ";
  strMsg += symbol;
  strMsg += " ";
  strMsg += number;
  strMsg += " ";
 
  char msg[255];
 
  strMsg.toCharArray(msg, 255);
 
  Serial.println(msg);
 
  vw_send((uint8_t *)msg, strlen(msg));
  vw_wait_tx(); // Ждем пока передача будет окончена
  delay(2000);
}
 
float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}

Приемник

// pin DATA === D11
#include <VirtualWire.h>
#include <LiquidCrystal_I2C.h>  // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
#include <Wire.h>
 
 LiquidCrystal_I2C lcd(0x27,16,2);
 byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
 byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
 byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
 byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
 byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
 byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
 byte d1,d2,d3,d4,d5,d6,e1,e2,e3,a[6],x;
 
void setup(){
  Serial.begin(9600);
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
  vw_rx_start();
  Wire.begin();lcd.init();lcd.backlight();
  lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);
  lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
}
 
void loop(){
  uint8_t buf[VW_MAX_MESSAGE_LEN]; 
  uint8_t buflen = VW_MAX_MESSAGE_LEN; 
 
  if (vw_get_message(buf, &buflen)){
    int i=4;
    if (buf[0] != 'z'){return;}
    char command = buf[2]; 
    int number = 0;
    while (buf[i] != ' '){
      number *= 10;
      number += buf[i] - '0';
      i++;
    }
    Serial.print(command);
    Serial.print(" ");
    Serial.println(number);
 
     a[0]=number/1000;
     a[1]=number/100%10;
     a[2]=number/10%10;
     a[3]=number%10;
     if(number<1000){a[0]=10;}
     if(number<100){a[1]=10;}
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=1,e3=2;break;
        case 1: e1=3,e2=4,e3=5;break;
        case 2: e1=7,e2=8,e3=9;break;
        case 3: e1=10,e2=11,e3=12;break;
   }digit();}
   lcd.setCursor(6,1);lcd.print(".");
   lcd.setCursor(14,1);lcd.write((uint8_t)223);;lcd.print("C");
   lcd.setCursor(15,0);lcd.print("*");
   delay(200);
  }
  else{lcd.setCursor(15,0);lcd.print(" ");}
}
 
void digit(){
  switch(a[x]){
    case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
    case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
    case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
    case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
    case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
    case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
    case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
    case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
    case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    case 10:d1=150,d2=150,d3=150,d4=150,d5=150,d6=150;break;
    }
lcd.setCursor(e1,0);lcd.write((uint8_t)d1);
lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);lcd.setCursor(e1,1);
lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);}

Передатчик с интервалом в 2 секунды передает температуру, приемник получет значение температуры и выводит ее на LCD дисплей, в момент получения информации на экран выводится символ «*».

Следующий скетч демонстрирует работу двух передатчиков и одного приемника.

Как видно на скриншоте первый передатчик отсылает символ «а» и число 12345, а второй передатчик символ «b» и число 6789. В мониторе порта приемника Вы можете увидеть одновременный прием информации с обеих передатчиков.

Передатчик 1

#include <VirtualWire.h>
 
void setup(void)
{
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
}
 
void loop(void)
{
  int number = 6789;
  String symbol = "b";
 
  String strMsg = "v ";
  strMsg += symbol;
  strMsg += " ";
  strMsg += number;
  strMsg += " ";
 
  char msg[255];
 
  strMsg.toCharArray(msg, 255);
 
  vw_send((uint8_t *)msg, strlen(msg));
  vw_wait_tx(); 
  delay(200);
}

Передатчик 2

#include <VirtualWire.h>
 
void setup(void)
{
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
}
 
void loop(void)
{
  int number = 12345;
  String symbol = "a";
 
  String strMsg = "z ";
  strMsg += symbol;
  strMsg += " ";
  strMsg += number;
  strMsg += " ";
 
  char msg[255];
 
  strMsg.toCharArray(msg, 255);
 
  vw_send((uint8_t *)msg, strlen(msg));
  vw_wait_tx(); 
  delay(200);
}

Приемник

#include <VirtualWire.h>
 
int i;
char command_z,command_v;
int number_z,number_v;
 
void setup(){
  Serial.begin(9600);
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
  vw_rx_start(); 
}
 
void loop(){
  uint8_t buf[VW_MAX_MESSAGE_LEN]; 
  uint8_t buflen = VW_MAX_MESSAGE_LEN; 
 
  if (vw_get_message(buf, &buflen)) {
    i=4;
    if (buf[0] == 'v'){ 
     command_v = buf[2]; 
     number_v = 0;
    while (buf[i] != ' '){
      number_v *= 10;
      number_v += buf[i] - '0';
      i++;
    }}
 
    i=4;
    if (buf[0] == 'z'){ 
     command_z = buf[2]; 
     number_z = 0;
    while (buf[i] != ' '){
      number_z *= 10;
      number_z += buf[i] - '0';
      i++;
    }}
    Serial.print(command_z);
    Serial.print(" ");
    Serial.println(number_z);
 
    Serial.print(command_v);
    Serial.print(" ");
    Serial.println(number_v);
  }
}

Энергосбережение

Во всех выше показанных скетчах передатчики непрерывно отсылают пакеты информации, в каких то проектах это необходимо, например в скетче электронного термометра, но в таком примере как управление 4-я реле в постоянной отсылке пакетов информации нет необходимости, тем более передатчик в подобном проекте лучше запитывать от батареи или аккумулятора, поэтому ниже показан скетч на примере управления 4-я реле который отсылает пакет информации в приемник только в момент нажатия кнопки. Это дает возможность более эффективно использовать элемент питания который питает передатчик.

Передатчик

// pin DATA === D12
#include <VirtualWire.h>
 
int number;
bool w1,w2,w3,w4,w;
 
void setup(void){
  vw_set_ptt_inverted(true); 
  vw_setup(2000);
  pinMode(7,INPUT_PULLUP); 
  pinMode(6,INPUT_PULLUP); 
  pinMode(5,INPUT_PULLUP); 
  pinMode(4,INPUT_PULLUP); 
}
 
void loop(void){
  if(digitalRead(7)==LOW && w1==0){w1=1;number |= (1<<0);delay(200);w=1;}
  if(digitalRead(7)==LOW && w1==1){w1=0;number &=~(1<<0);delay(200);w=1;}
 
  if(digitalRead(6)==LOW && w2==0){w2=1;number |= (1<<1);delay(200);w=1;}
  if(digitalRead(6)==LOW && w2==1){w2=0;number &=~(1<<1);delay(200);w=1;}
 
  if(digitalRead(5)==LOW && w3==0){w3=1;number |= (1<<2);delay(200);w=1;}
  if(digitalRead(5)==LOW && w3==1){w3=0;number &=~(1<<2);delay(200);w=1;}
 
  if(digitalRead(4)==LOW && w4==0){w4=1;number |= (1<<3);delay(200);w=1;}
  if(digitalRead(4)==LOW && w4==1){w4=0;number &=~(1<<3);delay(200);w=1;}      
 
if(w==1){w=0;
  String strMsg = "z ";
  strMsg += number;
  strMsg += " ";
 
  char msg[255];
 
  strMsg.toCharArray(msg, 255);
 
  vw_send((uint8_t *)msg, strlen(msg));
  vw_wait_tx(); 
}
}

Приемник

// pin DATA === D11
#include <VirtualWire.h>
 
void setup(){
  Serial.begin(9600);
  vw_set_ptt_inverted(true); 
  vw_setup(2000); 
  vw_rx_start();
  pinMode(2,OUTPUT); 
  pinMode(3,OUTPUT); 
  pinMode(4,OUTPUT); 
  pinMode(5,OUTPUT); 
}
 
void loop(){
  uint8_t buf[VW_MAX_MESSAGE_LEN]; 
  uint8_t buflen = VW_MAX_MESSAGE_LEN; 
 
  if (vw_get_message(buf, &buflen)) {
    int i=2;
    if (buf[0] != 'z'){return; }
 
    int number = 0;
    while (buf[i] != ' '){
      number *= 10;
      number += buf[i] - '0';
      i++;
    }
 
    Serial.println(number);
    if(((number >> 0) & 1) ==1){digitalWrite(2,HIGH);}else{digitalWrite(2,LOW);}
    if(((number >> 1) & 1) ==1){digitalWrite(3,HIGH);}else{digitalWrite(3,LOW);}
    if(((number >> 2) & 1) ==1){digitalWrite(4,HIGH);}else{digitalWrite(4,LOW);}
    if(((number >> 3) & 1) ==1){digitalWrite(5,HIGH);}else{digitalWrite(5,LOW);}
 
  }
}

Как видно из скетча, в код нажатия кнопки добавлена переменная «w», при нажатии нажатии кнопки состояние переменной меняется на 1, далее если переменная равна 1 исполняется код отправки сообщения  и переменная меняет свое состояние на 0, что не дает повторно отправить сообщение пока не будет снова нажата кнопка.

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=6463#p6463

Добавить комментарий

Войти с помощью: