Нужен ли еще один последовательный порт для связи по UART

sana555
Offline
Зарегистрирован: 11.05.2018

Пока идут компоненты, решил попробовать связать Arduino и Wemos по UART. И тут задумался, если RX-TX будут подключены к другой плате, то смогу ли я смотреть в монитор порта и отслеживать, что передается с Arduino в Wemos?

 

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

Смотря какой контроллер Ардуино Вы будете использовать.

Если у него 2-4 последовательных порта, то монитор подключается к одному, а Wemos - к другому.

Если только один, обычно используется SoftwareSerial.

sana555
Offline
Зарегистрирован: 11.05.2018

Uno, что то забыл указать...)

sana555
Offline
Зарегистрирован: 11.05.2018

andriano пишет:

Если только один, обычно используется SoftwareSerial.

Если еще захочу посмотреть, какие данные поступили на Wemos, то на нем тоже нужно использовать SoftwareSerial?

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

На одном - аппаратный, на другом - софтверный. Софтверный в один момент времени может работать только один.

Если нужно 3 порта или более - берите Мегу или DUE.

sana555
Offline
Зарегистрирован: 11.05.2018

andriano пишет:

Если нужно 3 порта или более - берите Мегу или DUE.

Нет, мне достаточно два: один для просмотра монитора порта, а другой для связи по UART.

Я правильно понимаю, что для UART нужно использовать Софтверный?

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

sana555 пишет:

Я правильно понимаю, что для UART нужно использовать Софтверный?

Не могли бы Вы как-то переформулировать вопрос?

sana555
Offline
Зарегистрирован: 11.05.2018

Прошу прощения, слизал вашу фразу, видимо не в тему...) Насколько я понял, при помощи библиотеки SoftwareSerial, можно создать  еще один программный последовательный порт, вы его назвали Софтверный(если я правильно вас понял..)), к примеру на 3-4 цифровых пинах. Получается для связи Arduino Uno и Wemos по UART, нужно использовать именно его, а не штатный на 0-1 цифровых пинах?

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

Использовать так, как Вам удобнее.

Собственно, аппаратный на Uno уже подключен к преобразователю USB-UART, поэтому логично именно его использовать для связи с компьютером по USB, а для связи с другим устройством, естественно, остается только программный. Но следует помнить, что программный имеет больше ограничений в использовании, в частности, не может работать на высоких частотах. Если это окажется критичным, то, возможно, окажется целесообразным пртивоположное решение: с компьютером связываться через SoftwareSerial при помощи внешнего USB-UART, а с другим устройством - через аппаратный, проигнорировав установленный на плате USB-UART.

Задачи бывают разные, и они требуют разных решений.

sana555
Offline
Зарегистрирован: 11.05.2018

Понял, благодарю..) Не могу найти, какие можно использовать цифровые пины, для подключения с другими устройствами на Uno и Wemos D1 R2?

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

Если Вы про SoftwareSerial, то, насколько я помню, его можно повесить на любые пины Uno (разумеется, кроме А6 и А7, которых на оригинальном Uno нет).

sana555
Offline
Зарегистрирован: 11.05.2018

Да, про него. У меня были не понятки с wemos, я думал что: d1 - это 1, d2 - это 2, для присвоения пина, сейчас вроде разобрался..)

sana555
Offline
Зарегистрирован: 11.05.2018

Столкнулся с проблемой потери данных, я понимаю что косяк мой...), но не могу его решить... Ситуация следующая. С вемоса раз в две секунды передаются данные в ардуино:

void peredacha()  //передаем данные в ардуино
{                     
  //отправляем в последовательный порт mySerial 
  mySerial.print("<tempRegAndroidD>");  //посылаем ориентировку на прием данных в ардуино
  mySerial.print(123);  
  mySerial.print("</tempRegAndroidD>");
  mySerial.print(" ");     
  mySerial.print("<tempRegAndroidP>");    
  mySerial.print(68);      
  mySerial.print("</tempRegAndroidP>"); 
  //отправляем время
  mySerial.print("<Time>");
  mySerial.print(sTime); 
  mySerial.print("</Time>"); 
}

В ардуино их принимаю только, если увижу вначале фразу: "<tempRegAndroidD>":

void priem()  //принимаем данные от Wemos WIFI
{  
  if (mySerial.available()>0) {  //проверка последовательного программного порта mySerial на наличие поступающих данных 
    //в Wemos пакет(условно)передаваемых данных, начинается с фразы "<tempRegAndroidD>", поэтому наличие этой фразы 
    //будет условием начала приема данных, иначе могут быть пропуски    
    if (mySerial.find("<tempRegAndroidD>")) {  //поиск ключевой фразы, после которой можно начать принимать 
                                               //данные(задается на другой стороне-Wemos)
      sTempRegD = mySerial.parseInt();  //считывание целых данных без точки(считываются только цифры до первого 
                                  //знака/буквы/пробела)       
        Serial.print(sTempRegD);
        Serial.print(" ");                   
               
      if (mySerial.find("<tempRegAndroidP>")) {
        sTempRegP = mySerial.parseInt();        
          Serial.print(sTempRegP);
          Serial.print(" ");                
      }      
      
      if (mySerial.find("<Time>")) {           
        sTime=mySerial.readStringUntil('<');  //принимаем строку до знака '<'
        Serial.println(sTime);      
      }
      sFlag1 = 1;  //данные получили, флаг того что теперь можно передавать
    }  
  }   
}  

Далее по флагу  sFlag1, передаю данные обратно в вемос:

void peredacha()  //передаем данные в Wemos WIFI
{
  if (sFlag1 == 1){  //передаем только тогда, когда данные получили, иначе программные порт не может нормально принять/передать!!!
//    delay(5);  //обязательно ждем 1-5 милисекунд(можно больше) перед отправкой данных в Wemos, после приема данных с Wemos
    //отправляем в последовательный порт mySerial    
//  len = sizeof(tempD);  //можно узнать количество байт в числе и при надобности тоже отправить в порт.
    sTempD = 236.56; 
    sTempRegD = 100;
    sTempRegP = 60; 
    mySerial.print("<tempD>");                //посылаем ориентировку на прием данных в Wemos
    mySerial.print(sTempD);               //температура духовки (обрезаем число до десятых: 36,6)
//    mySerial.print("</tempD>"); 
     
    mySerial.print("<tempP>"); 
//    float sTempP1 = round(sTempP*5000)/5000;  //округляем до десятых        
    mySerial.print(sTempP);               //температура духовки (обрезаем число до десятых: 36,6)      
//    mySerial.print("</tempP>"); 
    
    mySerial.print("<tempRegD>");      
    mySerial.print(sTempRegD);  //температура регулировки духовки       
//    mySerial.print("</tempRegD>");   
     
    mySerial.print("<tempRegP>");    
    mySerial.print(sTempRegP);  //температура регулировки продукта    
//    mySerial.print("</tempRegP>");
    
    mySerial.print("<sTimeReg>");    
    mySerial.print(sTimeReg);   //время регулировки
//    mySerial.print("</sTimeReg>");
    
    mySerial.print("<pr>");    
    mySerial.print(pr);         //номер выбранной программы 
//    mySerial.print("</pr>");

    mySerial.print("<sPressUp>");    
    mySerial.print(sPressUp);   //флаг закладки продуктов в духовку
//    mySerial.print("</sPressUp>");
//
    mySerial.print("<sDone>");    
    mySerial.print(sDone);      //флаг завершения программы
//    mySerial.print("</sDone>");

    int sRelayOn = digitalRead(sNull);  //если равно 0, то значит выключено, и наоборот
    mySerial.print("<sRelayOn>");    
    mySerial.print(sRelayOn);     //состояние реле вкл./выкл.
//    mySerial.print("</sRelayOn>"); 

    mySerial.print("<sRelay>");    
    mySerial.print(sRelay);     //флаг вышедшего реле из строя
//    mySerial.print("</sRelay>");
       
    mySerial.print("<TimeA>");
    mySerial.print(sTime);      //отправляем обратно полученное время(для контроля зависания ардуино)
    mySerial.print("</TimeA>");      
    
    mySerial.print("<ledGreen>");    
    mySerial.print(ledGreen);       //статус зеленого светодиода
    mySerial.println("</ledGreen>");  
    sFlag1 = 0;  //обнуляем флаг о принятых данных        
  }  
}    

В свою очередь в вемос их принимаю только, если увижу фразу:"<tempD>":

void priem() {  //принимаем данные от ардуино  
  if (mySerial.available()>0) {  
    if (mySerial.find("<tempD>")) {      
      sTempD = mySerial.parseFloat();  //считывание целых данных без точки(считываются только цифры 
                                       //до первого знака/буквы/пробела)             
      Serial.print("sTempD: "); 
      Serial.print(sTempD);
      Serial.print(" ");
       
      if (mySerial.find("<tempP>")) {
        sTempP = mySerial.parseFloat();        
        Serial.print("sTempP: ");    
        Serial.print(sTempP);
        Serial.print(" ");                         
      }        
      if (mySerial.find("<tempRegD>")) {
        sTempRegD = mySerial.parseInt();  //считывание целых данных с плавающей точкой(считываются только 
                                          //цифры с точкой до первого другого знака/буквы/пробела)                 
        Serial.print("sTempRegD: ");
        Serial.print(sTempRegD);
        Serial.print(" ");               
      }                    
      if (mySerial.find("<tempRegP>")) {
        sTempRegP = mySerial.parseInt();        
        Serial.print("sTempRegP: ");
        Serial.print(sTempRegP);
        Serial.print(" ");       
      }       
      if (mySerial.find("<sTimeReg>")) {
        sTimeReg = mySerial.parseInt();        
        Serial.print("sTimeReg: ");
        Serial.print(sTimeReg);
        Serial.print(" ");              
      }       
      if (mySerial.find("<pr>")) {
        pr = mySerial.parseInt();        
        Serial.print("pr: ");
        Serial.print(pr);
        Serial.print(" ");       
      }            
      if (mySerial.find("<sPressUp>")) {
        sPressUp = mySerial.parseInt();        
        Serial.print("sPressUp: ");
        Serial.print(sPressUp);
        Serial.print(" ");              
      }      
      if (mySerial.find("<sDone>")) {
        sDone = mySerial.parseInt();        
        Serial.print("sDone: ");
        Serial.print(sDone);
        Serial.print(" ");       
      }      
      if (mySerial.find("<sRelayOn>")) {
        sRelayOn = mySerial.parseInt();        
        Serial.print("sRelayOn: ");
        Serial.print(sRelayOn);
        Serial.print(" ");             
      }      
      if (mySerial.find("<sRelay>")) {
        sRelay = mySerial.parseInt();        
        Serial.print("sRelay: ");
        Serial.print(sRelay);
        Serial.print(" ");         
      }
      
      if (mySerial.find("<TimeA>")) {  //принимаем время обратно с ардуино           
        sTimeA=mySerial.readStringUntil('<');  //принимаем строку до знака '<'
        Serial.print("sTimeA: ");
        Serial.println(sTimeA);     
        Serial.print(" ");              
      }      
      if (mySerial.find("<ledGreen>")) {  //принимаем статус зеленого светодиода           
        ledGreen = mySerial.parseInt();        
        Serial.print("ledGreen: ");
        Serial.println(ledGreen);                
      }
      if (mySerial.find("</ledGreen>")) {
        Serial.println("OK");  
      }
      sFlag1 = 0;  //обнуляем флаг о принятых данных  
    }
  }    
}

Но в мониторе порта вемоса не всегда корректные данные(то пропуски каких то переменных, то не правильные данные, то не находит несколько подряд идущих данных):

sTempD: 236.56 sTempP: 3.00 sTimeReg: 0 pr: 0 sPressUp: 0 sDone: 0 sRelayOn: 0 sRelay: 0 sTimeA: 19:44:26
 ledGreen: 0
Time: 19:50:03
sTempD: 236.56 sTempP: 39.00 sTempRegD: 100 sTempRegP: 60 sPressUp: 0 sDone: 0 sRelayOn: 0 sRelay: 0 sTimeA: 19:44:26
 ledGreen: 0
OK
Time: 19:50:07
sTempD: 236.56 sTempP: 39.09 sTempRegP: 60 sTimeReg: 0 pr: 0 sPressUp: 0 sDone: 0 sRelayOn: 0 sRelay: 0 sTimeA: 19:44:26
 ledGreen: 0
OK
Time: 19:50:09
sTempD: 236.56 sTempP: 39.09 sTempRegP: 60 sTimeReg: 0 pr: 0 sPressUp: 0 sDone: 0 sRelayOn: 0 sRelay: 0 sTimeA: 19:44:26
 ledGreen: 0
OK
Time: 19:50:11
sTempD: 236.56 sTempP: 39.00 sTempRegD: 100 pr: 0 sPressUp: 0 sDone: 0 sRelayOn: 0 sRelay: 0 sTimeA: 19:44:26
 ledGreen: 0
OK
Time: 19:50:16
sTempD: 236.56 sTempP: 3909.00 sTempRegP: 60 sTimeReg: 0 pr: 0 sPressUp: 0 sDone: 0 sRelayOn: 0 sRelay: 0 sTimeA: 19:44:26
sTempD: 236.56 sTempP: 39.00 sTempRegD: 100 

 

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

sana555, слишком много сущностей разом, так программы не отлаживают. Сделайте подробный вывод в сериал после первой передачи данных, убедитесь. что на этом этапе нет ошибок. Если все ОК - переходите к следующей, и отлаживайте каждую передачу в отдельности.

sana555
Offline
Зарегистрирован: 11.05.2018

А как сделать подробный вывод?

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

sana555 пишет:

А как сделать подробный вывод?

вот как вы на последнем этапе выводите - так в монитор порта и выводите значения АндроидП АндроидД и так далее. Только не просто выводите всю принятую строку целиком - а по отдельности значение каждого поля, чтобы видеть, что ваш разбор принимаемых данных работает правильно.

sana555
Offline
Зарегистрирован: 11.05.2018

То есть так не достаточно:?

if (mySerial.find("<tempP>")) {
        sTempP = mySerial.parseFloat();        
        Serial.print("sTempP: ");    
        Serial.print(sTempP);
        Serial.print(" ");                         
      }

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

sana555
Offline
Зарегистрирован: 11.05.2018

Так?

void priem()  //принимаем данные от Wemos WIFI
{  
  if (mySerial.available()>0) {  //проверка последовательного программного порта mySerial на наличие поступающих данных 
    //в Wemos пакет(условно)передаваемых данных, начинается с фразы "<tempRegAndroidD>", поэтому наличие этой фразы 
    //будет условием начала приема данных, иначе могут быть пропуски    
    if (mySerial.find("<tempRegAndroidD>")) {  //поиск ключевой фразы, после которой можно начать принимать 
                                               //данные(задается на другой стороне-Wemos)
      sTempRegD = mySerial.parseInt();  //считывание целых данных без точки(считываются только цифры до первого 
                                  //знака/буквы/пробела)  
        Serial.print(sTempRegD);
        Serial.print(" ");                   
               
      if (mySerial.find("<tempRegAndroidP>")) {
        sTempRegP = mySerial.parseInt();        
        Serial.print(sTempRegP);
        Serial.print(" ");                
      }else{
        Serial.print("<tempRegAndroidP>");
        Serial.print("NO");
      }
            
      
      if (mySerial.find("<Time>")) {           
        sTime=mySerial.readStringUntil('<');  //принимаем строку до знака '<'
        Serial.println(sTime);      
      }else{
        Serial.print("<Time>");
        Serial.println("NO");
      }
      sFlag1 = 1;  //данные получили, флаг того что теперь можно передавать
    }  
  }   
}    

 

5N62V
Offline
Зарегистрирован: 25.02.2016

andriano пишет:

 Софтверный в один момент времени может работать только один.

 

если на прием и на передачу - то один, если только на передачу - то работают несколько, но прием по софтсериал при этом отваливается.

sana555
Offline
Зарегистрирован: 11.05.2018

Оказывается тот код, который я выложил, у меня все принимает нормально, без ошибок..) Я просто случайно(пробовал по разному) закоментировал свой флаг:

if (sFlag1 == 1){

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