Добрый вечер! Сил больше нету, Перепробовал кучу библиотек и вариантов боле менее мне понятных, Но так ничего и не добился с прошлого года в ступоре. Помогите пожалуйста с передачей данных по проводам между двумя 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(); // проверка данных обмена }
Второй код Код слейва, причем что странно он отказывается работать на библиотеке 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 }