Передача данных по RS485 с применением ретранслятора для увеличения дальности передачи.

Тема в разделе "Arduino & Shields", создана пользователем SDV, 16 июн 2018.

  1. SDV

    SDV Нерд

    Доброго времени суток. Помогите пожалуйста написать скетч для ретранслятора на ArduinoUNO.

    Суть следующая, UNO-1 собирает данные с датчиков температуры далее передает их на UNO-2 по RS485, которая просто передает их на UNO-3 также по RS485. (Расстояние между всеми контроллерами 1000 м.)

    Скетч для UNO-1:
    Код (C++):

    #include <Wire.h>
    #include <SoftEasyTransfer.h>
    #include <SoftwareSerial.h>
    #include <OneWire.h>
    #include <DallasTemperature.h>

    // сигнальный провод подключен к 2 пину на Arduino
    #define ONE_WIRE_BUS 2
    // выберем разрешение от 9 до 12
    #define TEMPERATURE_PRECISION 9

    // настроем библиотеку 1-Wire для связи с датчиком
    OneWire oneWire(ONE_WIRE_BUS);

    // создадим объект для работы с библиотекой DallasTemperature
    DallasTemperature sensors(&oneWire);

    // создаем массивы для хранения адреса датчиков
    DeviceAddress insideThermometer, outsideThermometer;

    SoftwareSerial mySerial(7, 6);                // Serial для RS485
    #define DIR 13                                // переключатель прием\передача
    SoftEasyTransfer ET;

    struct SEND_DATA_STRUCTURE{                   // структура которую будем передавать
      float SHT20_T;
      float SHT20_RH;
    };

    SEND_DATA_STRUCTURE txdata;

    // функция вывода адреса датчика
    void printAddress(DeviceAddress deviceAddress){
      for (uint8_t i = 0; i < 8; i++){
        if (deviceAddress[i] < 16) Serial.print("0");
        Serial.print(deviceAddress[i], HEX);
      }
    }


    void setup() {
      Serial.begin(9600);
      mySerial.begin(9600);
     
      sensors.begin();    // инициализируем работу с датчиком

      sensors.getAddress(insideThermometer, 0);    // сделаем запрос на получение адреса датчика
      sensors.getAddress(outsideThermometer, 1);

      sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION); // установим выбранное разрешение датчика
      sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);
      ET.begin(details(txdata), &mySerial);  
      Wire.begin();
     
      pinMode(DIR, OUTPUT);
      digitalWrite(DIR, LOW);                          // включаем прием
    }

    void loop() {  
         
      sensors.requestTemperatures();   // отправляем запрос на измерение температуры
      float tempC0 = sensors.getTempC(insideThermometer);  // создаем переменную для хранения температуры в градусах Цельсия и выводим её значение
      float tempC1 = sensors.getTempC(outsideThermometer);
      delay(500);
     
        txdata.SHT20_T = tempC0;             // пишим данные в структуру
        txdata.SHT20_RH = tempC1;
      digitalWrite(DIR, HIGH);                      // включаем передачу
        delay(1);                                     // небольшая задержка, иначе неуспевает
        ET.sendData();                              // отправляем    
        delay(50);                                  // небольшая задержка, иначе неуспевает      
      digitalWrite(DIR, LOW);                       // включаем прием
         
     
    }


     
    Скетч для UNO-2 который нужно изменить и сделать ретранслятор:
    Код (C++):

    #include <SoftEasyTransfer.h>
    #include <SoftwareSerial.h>

    #define DIR 13                                       // переключатель прием\передача

    SoftwareSerial mySerial(7, 6);                     // Serial для RS485
    SoftEasyTransfer ET;
     
     
    struct RECEIVE_DATA_RS485{
      float SHT20_T;
      float SHT20_RH;
    };
    RECEIVE_DATA_RS485 rxdata;


    void setup(){
      Serial.begin(9600);
      mySerial.begin(9600);
     
      ET.begin(details(rxdata), &mySerial);

     
      pinMode(DIR, OUTPUT);
      digitalWrite(DIR, LOW);                          // включаем прием

    }

    void loop(){
     
      if(ET.receiveData()){                           // если пришли данные
       
        Serial.print("Temp_1: ");
        Serial.print(rxdata.SHT20_T);                 // и отправляем в Serial
        Serial.print(" ");
        Serial.print("Temp_2: ");
        Serial.println(rxdata.SHT20_RH);
       
      }
    }
     
     
  2. parovoZZ

    parovoZZ Гуру

    Я уже где-то выкладывал похожее решение. Там сериал0 надо заменить на софтваресериал. Лень искать))))
     
  3. ostrov

    ostrov Гуру

    Почему нельзя побайтово? Что принял то передал.
     
  4. SDV

    SDV Нерд

    Ребят, если не сложно, скиньте пожалуйста пример скетча.
     
  5. ostrov

    ostrov Гуру

    Вот вам аж двунаправленный:

    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(3, 2); // RX, TX

    void setup()
    {
      Serial.begin(9600);
      mySerial.begin(9600);
      //  while (!Serial) {
      //    ; // ожидаем подключения к последовательному порту. Необходимо только для Leonardo
      //  }
    }

    void loop()
    {
      if (mySerial.available())
        Serial.write(mySerial.read());
      if (Serial.available())
        mySerial.write(Serial.read());
    }
    Ограничение по скорости, софтварный UART после 19200 может глючить. Как вариант - использовать МК с двумя UART.