Нужна помощь! Протокол передачи данных

Тема в разделе "Arduino & Shields", создана пользователем sanik, 4 янв 2018.

  1. sanik

    sanik Гик

    Добрый вечер! Сил больше нету, Перепробовал кучу библиотек и вариантов боле менее мне понятных, Но так ничего и не добился с прошлого года в ступоре. Помогите пожалуйста с передачей данных по проводам между двумя Arduino. Пробовал библиотеки Tiny_ModBusRTU iarduino_I2C_connect и другие ничего не смог добиться не хватает знаний. Вот последняя моя попытка привожу часть кода так как кода очень большие но в этих частях и есть основная задача, Подскажите что можно сделать а лучше на примере.
    вот код мастера
    Задача такая мастер передает несколько данных слейву и читает данные от него
    Код (C++):
    // центральный контроллер с протоколом ModBus master
    // передаем слейву установленную температуру и влажность
    // передаем состояние вентилятора и состояние света
    #include <TimerOne.h>
    #include <Tiny_ModBusRTU_Master.h>
    #include <OLED_I2C.h>
    #include <Servo.h>
    #include <PID_v1.h>
    Tiny_ModBusRTU_Master master(8, 30, 13);
    #include <OLED_StatusIcons.h>
    OLED  myOLED(SDA, SCL, 8);
    extern uint8_t RusFont[];
    extern uint8_t SmallFont[];
    extern uint8_t MediumNumbers[];
    #include <EEPROM.h>
    #include "DHT.h"
    Servo servoOut; // серво входной заслонки
    #define FanPin 10// пин  для подключения реле

    #define rPin 4
    #define gPin 5
    #define bPin 7
    byte key() {
      int val = analogRead(2); /
      if (val < 50) return 1;
      else if (val < 155) return 2;
      else if (val < 350) return 3;
      else return 0;
    }
    #define MQ2_PIN A0 // 3
    #define LightPin1 A3 //0
    #define LightPin2 A1

    #define DHTPIN 2 // =======================================12
    #define DHTTYPE DHT11   // DHT 11
    //#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
    //#define DHTTYPE DHT21   // DHT 21 (AM2301)
    DHT dht(DHTPIN, DHTTYPE);

    #define INTERVAL_SENS 500
    // #define INTERVAL_SERIAL 1000
    #define DELTA 10 // погрешность на случайные наводки датчика

    byte mode = 0; // режим: 0 - чтение, 1 - запись
    unsigned int REG_Massive[9];  // таблица регистров
    unsigned int DatasetHum = 0;// передача установленой влажности
    unsigned int DatasetTerm = 0; // передача установленой температуры
    unsigned int fanState = HIGH; // состояние ВКЛ/ВЫКЛ
    unsigned int dataLight_2;  // сигнал отправки
    unsigned int dataLight_1;  // сигнал отправки
    unsigned int TempStreet;//переменная для температуры на улице Dallas
    int TempStreet_old;//старое значение температуры на улице Dallas
    int angleshutter; //текущий угол заслонки
    int angleshutter_old; //старый угол заслонки
    byte flagshutter = 0;// флаг для полного открытия заслонки запрещающий работу PID
    double Setpoint2, Input2, Output2;
    PID shutterPID(&Input2, &Output2, &Setpoint2, 1, 0.4, 90, DIRECT);
    byte StreetSet = 10; // установка температуры на улице
    int flagSmoke = 0;
    int mq2 = 0;
    int previous_mq2 = 0;
    int mass_mq2[10] = {0}; // Массив 10 значений c датчика
    unsigned long smokeWork = 1;

    int setTerm;
    int setHum;

    int Light1;//Пееременная для хранения значения освещенности считанная с фоторезистора
    int Light2;//Пееременная для хранения значения освещенности считанная с фоторезистора
    int Term;//Пееременная для хранения значения температуры считанная с датчика
    int Hum;//Пееременная для хранения значения влажности считанная с датчика
    byte flag = 0; // Флаг кнопок
    byte workTerm = 0;
    byte workHum = 0;
    byte flagLight = 0;


    void(* resetFunc) (void) = 0; // Reset MC function
    //byte timeCount = 0;


    //======================================================================================
    void setup() {
      Serial.begin(9600);
      dht.begin();
      myOLED.begin();
      myOLED.setFont(RusFont);
      myOLED.clrScr();
      shutterPID.SetOutputLimits(1, 255);//  устанавливаем границы выходного сигнала для ПИД-регулятора
      angleshutter_old = -100;// старый угол сервы пида
      shutterPID.SetMode(AUTOMATIC);//включаем ПИД-регулятор
      pinMode(rPin, OUTPUT);
      digitalWrite(rPin, HIGH);
      pinMode(gPin, OUTPUT);
      digitalWrite(gPin, HIGH);
      pinMode(bPin, OUTPUT);
      digitalWrite(bPin, HIGH);
      pinMode(FanPin, OUTPUT);
      //digitalWrite(FanPin, fanState);
      pinMode(LightPin1, INPUT);
      pinMode(LightPin2, INPUT);

      Timer1.initialize(500); // инициализация таймера 1, период 500 мкс
      Timer1.attachInterrupt(timerInterrupt, 500); // задаем обработчик прерываний
      master.read(1, REG_Massive, 0, 9); // инициация чтения 9 регистров хранения начиная с адреса 0, у контроллера с адресом 1, в массив REG_Massive
    }
    //==================================================================================
    void loop() {
      byte KEY = key();
      Anglshutter();
      if ( KEY == 0) {
        flag = 0;
      }
      if (KEY == 2 && flag == 0) {
        flag = 1;
        menuSetup();
      }

      //*************************************************************************************

      if ( (mode & 1) == 0 ) {// чтение регистров хранения
        if (master.state != 1) {// операция завершена
          if (master.state == 0) {// данные получены
            TempStreet       = REG_Massive[0] << 8; // Считываем старший байт установленого значения температуры в  1 ячейку массива REG_Massive
            TempStreet       = REG_Massive[1]; // Считываем младший байт установленого значения температуры во 2 ячейку массива REG_Massive
          }
          else {
            // ошибка обмена
            myOLED.setFont(SmallFont);
            myOLED.print("ErBUS", RIGHT, 10);
            myOLED.setFont(RusFont);
            myOLED.invertText(true);
            myOLED.print("Ntvg yf ek", LEFT, 24);
            myOLED.update();
          }
          REG_Massive[2]    = DatasetHum >> 8; // Сохраняем старший байт значения влажности в  1 ячейку массива REG_Massive
          REG_Massive[3]    = DatasetHum; // Сохраняем младший байт значения влажности во 2 ячейку массива REG_Massive
          REG_Massive[4]    = DatasetTerm >> 8; // Сохраняем старший байт значения температуры в  1 ячейку массива REG_Massive
          REG_Massive[5]    = DatasetTerm; // Сохраняем младший байт значения температуры во 2 ячейку массива REG_Massive
          REG_Massive[6]    = fanState; // Сохраняем байт состояния вентилятора в ячейку массива REG_Massive
          REG_Massive[7]    = dataLight_1; // Сохраняем байт состояния света в ванной в ячейку массива REG_Massive
          REG_Massive[8]    = dataLight_2; // Сохраняем байт состояния света в туалете в ячейку массива REG_Massive
          master.writeMultiple(1, REG_Massive, 2, 7); // запись 7 регистров хранения начиная с адреса 2, контроллер с адресом 1 master.writeSingle(1, (unsigned int)button1.flagPress, 5); // запись регистра хранения (светодиод)
          mode++;
        }
      }
      //*************************************************************************************
      myOLED.clrScr();
      if (flagLight == 1) {
        myOLED.print("DRK ", 30, 55); //ВКЛ
      }
      if (flagLight == 0) {
        myOLED.print("DSRK ", 30, 55); // ВЫКЛ
      }
      if (fanState == HIGH) {
        myOLED.print("DRK ", 100, 55);  //ВКЛ
      }
      if (fanState == LOW) {
        myOLED.print("DSRK", 100, 55); // ВЫКЛ
      }
      if (fanState == LOW  && flagLight == 0) {
        digitalWrite(rPin, LOW);
        digitalWrite(gPin, HIGH);
        digitalWrite(bPin, LOW);
      }
      if (fanState == LOW && flagLight == 1) {
        digitalWrite(rPin, HIGH);
        digitalWrite(gPin, LOW);
        digitalWrite(bPin, LOW);
      }
      if (fanState == HIGH && flagLight == 0) {
        digitalWrite(rPin, HIGH);
        digitalWrite(gPin, HIGH);
        digitalWrite(bPin, LOW);
      }
      if (fanState  == HIGH && flagLight == 1) {
        digitalWrite(rPin, HIGH);
        digitalWrite(gPin, LOW);
        digitalWrite(bPin, HIGH);
      }

      DTHsensor();
      myOLED.print("Ntvg", LEFT, 5);
      myOLED.setFont(MediumNumbers);
      myOLED.printNumI(Term, 50, 0);
      myOLED. drawCircle(88, 8, 2);
      myOLED. drawLine(0, 20, 100, 20);
      myOLED. drawLine(0, 46, 100, 46);
      myOLED.setFont(RusFont);
      myOLED.print("C", 78, 10);
      myOLED.print("dkf;y", LEFT, 30);
      myOLED.setFont(MediumNumbers);
      myOLED.printNumI(Hum, 50, 26);
      myOLED.setFont(RusFont);
      myOLED.print("%", 85, 35);
      myOLED.print("Cdtn", 0, 55);
      myOLED.print("Dtyn", 70, 55);
      myOLED.update();
      //*************************************************************************************

    //--------------------------- обработчик прерывания 500 мкс
    void timerInterrupt() {
      master.update(); // проверка данных обмена
    }
     
  2. sanik

    sanik Гик

    Второй код
    Код слейва, причем что странно он отказывается работать на библиотеке TimerOne пока активна строка Timer1.attachInterrupt(timerInterrupt, 500) не работает дисплей, в отличие от мастера работает только с MsTimer2
    Код (C++):
    //slave
    //принимаем от мастера заданную температуру влажность и состояние вентилятора
    // передаем мастеру температуру на улице
    #include <OneWire.h>
    #include <Tiny_ModBusRTU_Slave.h>
    //#include <TimerOne.h>
    #include <PID_v1.h>
    #include <Servo.h>
    #include "DHT.h"
    #include <DallasTemperature.h>
    #include <OLED_I2C.h>
    #include <MsTimer2.h>
    #include <OLED_StatusIcons.h>
    OLED  myOLED(SDA, SCL, 8);
    extern uint8_t RusFont[];
    extern uint8_t SmallFont[];
    extern uint8_t MediumNumbers[];

    #define ONE_WIRE_BUS 10 // датчик Dalas
    #define DHTPIN 4  
    Servo myservo;//Сервопривод пид регулятора
    Servo servoIN; // серво входной заслонки
    #define Releheater 6 // реле нагревателя
    #define fan  7
    #define beeper_pin 11 // пищалка
    #define DHTTYPE DHT11   // DHT 11
    //#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
    //#define DHTTYPE DHT21   // DHT 21 (AM2301)
    DHT dht(DHTPIN, DHTTYPE);
    #define error 10 // время вывода ошибки DHT11
    //#define TEMPERATURE_PRECISION 9
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire); // определяем название для дальнейших функций
    int tempC;//текущая температура PID DHT
    int temp_old = 0;//старое значение температуры
    byte angle; //угол поворота мотора
    byte angle_old;//старый угол поворота мотора
    double Setpoint, Input, Output;
    PID myPID(&Input, &Output, &Setpoint, 15, 10, 50, DIRECT); //создаем ПИД-регулятор
    byte percent; // вывод на экран мощности пидрегулятора
    float StreetTemp;//переменная для температуры на улице Dallas
    float StreetTemp_old;//старое значение температуры на улице Dallas
    byte angleshutter; //текущий угол заслонки
    byte angleshutter_old; //старый угол заслонки
    byte flagshutter = 0;// флаг для полного открытия заслонки запрещающий работу PID
    double Setpoint2, Input2, Output2;
    PID shutterPID(&Input2, &Output2, &Setpoint2, 1, 0.4, 90, DIRECT);
    byte StreetSet = 10; // установка температуры на улице
    unsigned long currentTime;
    unsigned long errorTime;// таимер ошибок
    byte flagBut = 0; //флаг нажатия кнопки
    int hum ;//переменная для влажности

    void(* resetFunc) (void) = 0; // Reset MC function

    // Объявляем переменные и константы:
    unsigned int REG_Massive[9];
    Tiny_ModBusRTU_Slave slave(1, 8, REG_Massive, 9); // создаем объект, адрес 1, таймаут 4 мс, массив regTable, размер 9
    unsigned int   DatasetTerm;      // объявляем переменную для чтения значения
    unsigned int   TempOUT;          // объявляем переменную для передачи значения
    unsigned int   DatasetHum;       // объявляем переменную для чтения значения
    unsigned int   dataLight_1;             // свет
    unsigned int   dataLight_2;             // свет
    unsigned int   fanState;              // Состояние вентилятора вытяжки
    //int           REG_Massive[9];       // объявляем массив, данные которого будут доступны для чтения/записи по шине I2C

    void setup() {
      Serial.begin(9600);
      dht.begin();
      sensors.begin();
      myOLED.begin();
      myOLED.setFont(RusFont);
      myOLED.clrScr();
      myPID.SetOutputLimits(1, 255);//  устанавливаем границы выходного сигнала для ПИД-регулятора
      shutterPID.SetOutputLimits(1, 255);
      myservo.attach(3); // устанавливаем пин управления servo
      angle_old = -100;// старый угол сервы пида
      angleshutter_old = -100;
      myPID.SetMode(AUTOMATIC);//включаем ПИД-регулятор
      shutterPID.SetMode(AUTOMATIC);
      pinMode(fan, OUTPUT);       // реле вентилятора
      digitalWrite(fan, LOW);
      pinMode(Releheater, OUTPUT); // реле нагревателя heater
      digitalWrite(Releheater, LOW);
      currentTime = millis();            // считываем время, прошедшее с момента запуска программы
      MsTimer2::set(500, timerInterrupt); // задаем период прерывания по таймеру 500 мс
      MsTimer2::start();              // разрешаем прерывание по таймеру
    // Timer1.initialize(500); // инициализация таймера 1, период 500 мкс
    // Timer1.attachInterrupt(timerInterrupt, 500); // задаем обработчик прерываний
    }

    void loop() {
      TempOUT  = StreetTemp;
      noInterrupts(); // останавливаем прерывания
      REG_Massive[0]    = TempOUT >> 8; // Сохраняем старший байт значения температуры в  1 ячейку массива REG_Massive
      REG_Massive[1]    = TempOUT; // Сохраняем младший байт значения температуры во 2 ячейку массива REG_Massive
      DatasetHum        = REG_Massive[2] << 8; // Считываем старший байт установленого значения влажности в  1 ячейку массива REG_Massive
      DatasetHum        = REG_Massive[3]; // Считываем младший байт установленого значения влажности во 2 ячейку массива REG_Massive
      DatasetTerm       = REG_Massive[4] << 8; // Считываем старший байт установленого значения температуры в  1 ячейку массива REG_Massive
      DatasetTerm       = REG_Massive[5]; // Считываем младший байт установленого значения температуры во 2 ячейку массива REG_Massive
      fanState          = REG_Massive[6]; // Считываем состояние  вытяжки
      dataLight_1       = REG_Massive[7]; // считываем состояние
      dataLight_2       = REG_Massive[8]; // считываем состояние
      interrupts();
      myOLED.clrScr();
      // myOLED.invertText(false);
      myOLED.setFont(RusFont);
      if (digitalRead(Releheater) == HIGH) {
        myOLED.print("DRK ", 30, 55); //ВКЛ
      }
      if (digitalRead(Releheater) == LOW) {
        myOLED.print("DSRK ", 30, 55); // ВЫКЛ
      }
      if (digitalRead(fan) == HIGH ) {
        myOLED.print("DRK ", 100, 55);  //ВКЛ
      }
      if (digitalRead(fan) == LOW) {
        myOLED.print("DSRK", 100, 55); // ВЫКЛ
      }
      myOLED.print("Vjoy", LEFT, 5); // Мощьность PID
      myOLED.setFont(MediumNumbers);
      myOLED.printNumI(percent, 40, 0);
      myOLED. drawLine(0, 20, 120, 20);
      myOLED. drawLine(0, 48, 120, 48);
      myOLED.setFont(RusFont);
      myOLED.print("%", 80, 10);
      myOLED.print("Ntvg yf ek", LEFT, 24); // Температура на улице
      myOLED.printNumI(StreetTemp, 70, 24);
      myOLED.print("C", 98, 24);
      myOLED. drawCircle(108, 23, 1);
      myOLED.print("Dkf;y", LEFT, 37); // уст влажн
      myOLED.printNumI(DatasetHum, 35, 37);
      myOLED.print("%", 48, 35);
      // myOLED. drawCircle(58, 34, 1);
      myOLED.print("Ntvg", 60, 37); // уст Темп
      myOLED.printNumI(DatasetTerm, 90, 37);
      myOLED.print("C", 108, 35);
      myOLED. drawCircle(118, 34, 1);
      myOLED.print("Dtyn", 70, 55); // Вент
      myOLED.print("Yfuh", 0, 55); // Нагрев
      myOLED.update();
      Setpoint = DatasetTerm;//заданная температура нагрева
      Anglshutter(); //управляем заслонкой

      if (digitalRead(Releheater) == HIGH) {
        percent = map(Output, 1, 255, 0, 100);
        percent = constrain(percent, 0, 100);
      }

      /* if (isnan(tempC) || isnan(hum)) //проверка (что мы получаем на запрос из датчика - цифры?)датчик DHT
        {
         currentTime = millis(); // считываем время с момента включения
         while (millis() - currentTime <= (errorTime + (error * 60000)))//и вывод на экран ERROR "Failed to read from DHT"
         {
           myOLED.setFont(SmallFont);
           myOLED.print("ErDht", RIGHT, 0);
           myOLED.setFont(RusFont);
           myOLED.invertText(true);
           myOLED.print("Dkf;y", LEFT, 37);
           myOLED.print("Ntvg", 60, 37); // уст Темп
           myOLED.update();
         }
        }
        ///////////////проверка датчика далас
        if (StreetTemp == 127) //if (tempC == -127)
        {
         currentTime = millis(); // считываем время с момента включения
         if (millis() - currentTime <= (errorTime + (error * 60000)))// вывод на экран ERROR while
         {
           myOLED.setFont(SmallFont);
           myOLED.print("ErDls", RIGHT, 10);
           myOLED.setFont(RusFont);
           myOLED.invertText(true);
           myOLED.print("Ntvg yf ek", LEFT, 24);
           myOLED.update();
         }
        }
      */


      if (fanState == 1) {
        fanON();
      }
      else if (dataLight_1 == 1 && dataLight_2 == 1) {
        fanON();
      }
      else {
        fanOFF();
      }
    }

    // обработчик прерывания
    void timerInterrupt() {
      slave.update();
      sensors.requestTemperatures();
      StreetTemp = sensors.getTempCByIndex(0); //получаем температуру с уличного датчика Dallas
      tempC = dht.readTemperature(); //получаем температуру с датчика DHT
      hum = dht.readHumidity(); //получаем влажность с датчика DHT
    }