Передача данных от ардуино нано к NodeMCU

Unreal334
Offline
Зарегистрирован: 03.04.2015

Добрый день!

Стоит задача передачи данных (состояния освещенности, движения, температуры и др.) от ардуино к NodeMCU для последующего отображения на андроид устройствах и т.д. Почему сразу не на NodeMCU? - мало входов, да и ардуинок хватает. попробывал передавать строкой через Serial - работает, но надо конвертировать String в Integer, правильно ли это? Т.е. мне надо, чтобы ардуино собирала все данные и передавала их NodeMCU, а она в свою очередь уже будет управлять освещением и тд. Подскажите, пожалуйста, может есть способ проще? (желательны ссылки и примеры).Спасибо, скетчи ниже

#include <OneWire.h>
#include <DallasTemperature.h>
#include <DS1302.h>


      // освещение начало
  const int pinPhotoTualet = A0;        // Фоторезистор в туалете с подтягивающим резистором 10 кОм на А0
  const int pinPhotoKoridor = A1;       // Фоторезистор в коридоре с подтягивающим резистором 10 кОм на А1
  const int pinPhotoWanna = A2;         // Фоторезистор в ванной с подтягивающим резистором 10 кОм на А2
  const int pinPhotoKuhnia = A3;        // Фоторезистор на кухне с подтягивающим резистором 10 кОм на А3
  
  int rawTualet = 0;                    // Освещенность в туалете
  int rawKoridor = 0;                   // Освещенность в коридоре
  int rawWanna = 0;                     // Освещенность в ванной
  int rawKuhnia = 0;                    // Освещенность на кухне
  
  int lightTualet = 0;                  //переменная для хранения состояния света ( 1 - вкл/0 - выкл) 
  int lightKoridor = 0; 
  int lightWanna = 0; 
  int lightKuhnia = 0; 
     //освещение конец
     
     //движение начало
  int moveTualet = 0;                  //переменная для хранения состояния движения
  int moveKoridor = 0;
  int moveWanna = 0;
  int moveKuhnia = 0;

  int pirPinTualet = 2;                //пины подключения датчиков движения
  int pirPinKoridor = 3;
  int pirPinWanna = 4;
  int pirPinKuhnia = 5;

  int calibrationTime = 10;           //Время калибровки датчика движения 30 сек (10-60 сек. по даташиту)
  int ledPin = 13;

  
void setup()
{
  pinMode( pinPhotoTualet, INPUT );
  pinMode( pinPhotoKoridor, INPUT );
  pinMode( pinPhotoWanna, INPUT );
  pinMode( pinPhotoKuhnia, INPUT );

  digitalWrite(pirPinTualet, LOW);
  digitalWrite(pirPinKoridor, LOW);
  digitalWrite(pirPinWanna, LOW);
  digitalWrite(pirPinKuhnia, LOW);

  delay(500);
  
  for(int i = 0; i < calibrationTime; i++)                 //калибровка 30 сек
  {
    //Во время калибровки будет мигать сигнальный диод
    i % 2 ? digitalWrite(ledPin, HIGH) : digitalWrite(ledPin, LOW);
    delay(1000);
  }  
  digitalWrite(ledPin, HIGH);                             //По окончанию калибровки зажжем сигнальный диод
  delay(50);
  
  Serial.begin(115200);  
}

void loop()
{
  rawTualet = analogRead( pinPhotoTualet );
  rawKoridor = analogRead( pinPhotoKoridor );
  rawWanna = analogRead( pinPhotoWanna );
  rawKuhnia = analogRead( pinPhotoKuhnia );
  
if(rawTualet >= 400)                           
  lightTualet = 1;
  else
  lightTualet = 0;
  
if(rawKoridor >= 400)                 
  lightKoridor = 1;
  else 
  lightKoridor = 0;
  
if(rawWanna >= 400)                
  lightWanna = 1;
  else
  lightWanna = 0;
  
if(rawKuhnia >= 400)                    
  lightKuhnia = 1;
  else
  lightKuhnia = 0;

  if(digitalRead(pirPinTualet) == HIGH)     
  moveTualet = 1;
  else
  moveTualet = 0;

  if(digitalRead(pirPinKoridor) == HIGH)    
  moveKoridor = 1;
  else
  moveKoridor = 0;

  if(digitalRead(pirPinWanna) == HIGH)   
  moveWanna = 1;
  else
  moveWanna = 0;

  if(digitalRead(pirPinKuhnia) == HIGH)    
  moveKuhnia = 1;
  else
  moveKuhnia = 0;

String test = "T1";
       test += lightTualet;
       test += "1T"; 
       test += "T2";
       test += lightKoridor; 
       test += "2T";
       test += "T3";
       test += lightWanna;
       test += "3T";
       test += "T4";
       test += lightKuhnia;
       test += "4T";
       test += "T5";
       test += moveTualet; 
       test += "5T";
       test += "T6";
       test += moveKoridor;
       test += "6T";
       test += "T7";
       test += moveWanna;
       test += "7T";
       test += "T8";
       test += moveKuhnia;
       test += "8T";

Serial.println(test);

  // вывожу в порт для настройки
  //Serial.print("Illumination Tualet");
  //Serial.println( rawTualet );
  //Serial.print("Illumination Koridor");
  //Serial.println( rawKoridor );
 // Serial.print("Illumination Wanna");
  //Serial.println( rawWanna );
  //Serial.print("Illumination Kuhnia");
  //Serial.println( rawKuhnia );
  
  delay (500);
  }

Приемник

String T1, T2, T3, T4, T5, T6, T7, T8;
int lightTualet, lightKoridor, lightWanna, lightKuhnia, moveTualet, moveKoridor, moveWanna, moveKuhnia;

void setup() {
  pinMode( 2, OUTPUT );
  Serial.begin(115200);
}

void loop() {
if(Serial.available()){    
String Var="";  
while (!Serial.available()) delay(20); 
delay(400); 
while (Serial.available())  
Var = Var + (char)(Serial.read());
 
T1=Var.substring(Var.indexOf("T1")+2,Var.indexOf("1T")); 
T2=Var.substring(Var.indexOf("T2")+2,Var.indexOf("2T")); 
T3=Var.substring(Var.indexOf("T3")+2,Var.indexOf("3T")); 
T4=Var.substring(Var.indexOf("T4")+2,Var.indexOf("4T"));
T5=Var.substring(Var.indexOf("T5")+2,Var.indexOf("5T"));
T6=Var.substring(Var.indexOf("T6")+2,Var.indexOf("6T"));
T7=Var.substring(Var.indexOf("T7")+2,Var.indexOf("7T"));
T8=Var.substring(Var.indexOf("T8")+2,Var.indexOf("8T"));


lightTualet = (T1.toInt());
lightKoridor = (T2.toInt());
lightWanna = (T3.toInt());
lightKuhnia = (T4.toInt());
moveTualet = (T5.toInt());
moveKoridor = (T6.toInt());
moveWanna = (T7.toInt());
moveKuhnia = (T8.toInt());


Serial.print(lightTualet);
Serial.print(lightKoridor);  
Serial.print(lightWanna);
Serial.print(lightKuhnia);
Serial.print(moveTualet);
Serial.print(moveKoridor);
Serial.print(moveWanna);
Serial.println(moveKuhnia);
}

if (lightTualet == 1)   
  digitalWrite(2, LOW);
  
if(lightTualet == 0)   
  digitalWrite(2, HIGH);
  
Serial.print("SVET: ");
Serial.println(lightTualet);
}

 

Unreal334
Offline
Зарегистрирован: 03.04.2015

Вот ещё, ардуино соединена с NodeMCU проводами RX-TX, TX-RX, GND-GND

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Можно все одним байтом передать, 8 бит как раз. Ну или если планируется наращивать можно двумя тремя байтами, там и до пакетной передачи дойдете :)

Unreal334
Offline
Зарегистрирован: 03.04.2015

Penni пишет:

Можно все одним байтом передать, 8 бит как раз. Ну или если планируется наращивать можно двумя тремя байтами, там и до пакетной передачи дойдете :)

) подскажите, пожалуйста, может где пример есть доходчивый

не силеня в програмировании, что поделать)

 

dimin21590
dimin21590 аватар
Offline
Зарегистрирован: 26.10.2016

А не проще взять радиомодули и передавать сразу масив или пременную?

1 вариант.

2 вариант.

 

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Примеры не знаю где искать :) Если кратко то у вас 4 зоны, в каждой зоне два типа датчика (как я понял датчик движения и датчик освещенности) тогда все эти данные можно уместить в 8 бит. Допустим есть переменная byte state; бит 7 отвечает за освещенность в туалете (1 освещен 0 нет) 6 бит за освещенность в коридоре 5 в ванне 4 в кухне, 3й за движение в туалете 2й в коридоре 1й в ванне и 0й в кухне. Тогда ваши условия будут такими

if(rawTualet >= 400)                          
  bitSet(state, 7);
else
  bitClear(state, 7);

и дальше по аналогии. Имеете один байт и передаете его Serial.write(state);

На стороне приемника получаете этот байт и bitRead(state, 7) читаете и делаете что надо.

Номера битов лучше прописать константами или дефайнами типа #define bit_lightTualet 7

Unreal334
Offline
Зарегистрирован: 03.04.2015

Penni пишет:

Примеры не знаю где искать :) Если кратко то у вас 4 зоны, в каждой зоне два типа датчика (как я понял датчик движения и датчик освещенности) тогда все эти данные можно уместить в 8 бит. Допустим есть переменная byte state; бит 7 отвечает за освещенность в туалете (1 освещен 0 нет) 6 бит за освещенность в коридоре 5 в ванне 4 в кухне, 3й за движение в туалете 2й в коридоре 1й в ванне и 0й в кухне. Тогда ваши условия будут такими

if(rawTualet >= 400)                          
  bitSet(state, 7);
else
  bitClear(state, 7);

и дальше по аналогии. Имеете один байт и передаете его Serial.write(state);

На стороне приемника получаете этот байт и bitRead(state, 7) читаете и делаете что надо.

Номера битов лучше прописать константами или дефайнами типа #define bit_lightTualet 7

#define bit_lightTualet 7
#define bit_lightKoridor 6
#define bit_lightWanna 5
#define bit_lightKuhnia 4
#define bit_moveTualet 3
#define bit_moveKoridor 2
#define bit_moveWanna 1
#define bit_moveKuhnia 0

byte state;

void loop()
{
  rawTualet = analogRead( pinPhotoTualet );
  rawKoridor = analogRead( pinPhotoKoridor );
  rawWanna = analogRead( pinPhotoWanna );
  rawKuhnia = analogRead( pinPhotoKuhnia );


if(rawTualet >= 400)                         
  bitSet(state, bit_lightTualet);
else
  bitClear(state, bit_lightTualet);

if(rawKoridor >= 400)                         
  bitSet(state, bit_lightKoridor);
else
  bitClear(state, bit_lightKoridor);
  
if(rawWanna >= 400)                         
  bitSet(state, bit_lightWanna);
else
  bitClear(state, bit_lightWanna);
  
if(rawKoridor >= 400)                         
  bitSet(state, bit_lightKuhnia);
else
  bitClear(state, bit_lightKuhnia);

Serial.write(state);
Serial.println(state);

так?

Unreal334
Offline
Зарегистрирован: 03.04.2015

т.е. я посылаю переменную state вида byte где каждый из восьми бит этой переменной содержит значение 0 или 1?

а странные значения в com это преобразование в аски?

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Да, все правильно понимаете. Так довольно удобно работать с булевыми величинами

Unreal334
Offline
Зарегистрирован: 03.04.2015

Penni пишет:

Да, все правильно понимаете. Так довольно удобно работать с булевыми величинами

Пока спасибо огромное за помощь, завтра попробую правильно принять)

Unreal334
Offline
Зарегистрирован: 03.04.2015

Ещё на будующее, если у меня будет больше переменных (температура, влажность и др), то можно ли таким же образом передать, например, температуру от 18b20 равную 25,56 градуса?

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Значения в порту нормальные, кубик это от write перевод в аски. По поводу температуры: как минимум два байта целая и дробная часть, а проще наверное просто float передавать и все.

Unreal334
Offline
Зарегистрирован: 03.04.2015

Что-то не получается принять)

#define bit_lightTualet 7
#define bit_lightKoridor 6
#define bit_lightWanna 5
#define bit_lightKuhnia 4
#define bit_moveTualet 3
#define bit_moveKoridor 2
#define bit_moveWanna 1
#define bit_moveKuhnia 0

byte state;

void setup() {
  pinMode( 2, OUTPUT );
  Serial.begin(115200);
}

void loop() {
  if (Serial.available() > 0) {
    
    state = Serial.read();
}

if (bitRead(state, bit_lightTualet) == 1)   
  digitalWrite(2, LOW);
  
if(bitRead(state, bit_lightTualet) == 0)   
  digitalWrite(2, HIGH);
  Serial.println(state);
}

 

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Передавайте именно Serial.write потому что println добавляет еще служебные символы.

Unreal334
Offline
Зарегистрирован: 03.04.2015

Penni пишет:

Передавайте именно Serial.write потому что println добавляет еще служебные символы.

класс, получилось)

откуда Вы всё это знаете?))

Unreal334
Offline
Зарегистрирован: 03.04.2015

а как теперь послать две переменные byte и принять каждую, как понять где какая?

b707
Offline
Зарегистрирован: 26.05.2017

Unreal334 пишет:

а как теперь послать две переменные byte и принять каждую, как понять где какая?

Посылаете сначала X, а потом Y. При приеме та, что пришла первой - будет X.

... и откуда я это все знаю? - сам удивляюсь....

Unreal334
Offline
Зарегистрирован: 03.04.2015

b707 пишет:

Unreal334 пишет:

а как теперь послать две переменные byte и принять каждую, как понять где какая?

Посылаете сначала X, а потом Y. При приеме та, что пришла первой - будет X.

... и откуда я это все знаю? - сам удивляюсь....

т.е. посылаю

Serial.write(state);

Serial.write(state1);

и принимать надо в той же последовательности?

void loop() {
  if (Serial.available() > 0) {
    
    state = Serial.read();
    state1 = Serial.read();
так?
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

можно лексический анализатор пабыстренькаму прикрутить

Unreal334
Offline
Зарегистрирован: 03.04.2015

DetSimen пишет:

можно лексический анализатор пабыстренькаму прикрутить

ну Вы валите))

Unreal334
Offline
Зарегистрирован: 03.04.2015

мне бы попроще

Unreal334
Offline
Зарегистрирован: 03.04.2015

Товарищи, с битами вроде разобрался. А как передать значение температуры с датчика?

Unreal334
Offline
Зарегистрирован: 03.04.2015

Penni пишет:

Можно все одним байтом передать, 8 бит как раз. Ну или если планируется наращивать можно двумя тремя байтами, там и до пакетной передачи дойдете :)

Подскажите, пожалуйста, а как еще можно передавать данные через  Serial? может с каким-то идентификатором, чтобы принимающая NodeMCU знала, что это значение относится к такой-то переменной?

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Отправляйте не 1 байт а 3. Пусть первый байт будет state а два других это температура float. Принимаете это все дело в буфер размером 3и байта. А дальше с первым байтом понятно что делать, а второй и третий байт можно либо через указатели обработать либо memcpy скопировать, если предполагается, что буфер может затереться. Получится подобие "пакета".

Вариантов много, можно смотреть сколько байт приняли, если 1 то это state если два то это температура. Можно собрать полный пакет с заголовком, контрольной суммой и прочими штуками.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Penni пишет:

Отправляйте не 1 байт а 3. Пусть первый байт будет state а два других это температура float.

float - 4 байта

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

andriano пишет:

float - 4 байта

Да, точно, спасибо, флоат 4 байта, я просто думал об отправке температуры в виде двух байт (целое и после запятой) ну и под это дело затупил.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

"2 байта: целое и после запятой" - это fixed (8.8).