Обмен данными между двумя UART

alias095
Offline
Зарегистрирован: 22.04.2014

Здравствуйте. Проблема такая есть два устройства работают по uart между собой на скорости 38400

но необходими в процессе их обмена между собой(одно устройство посылает данные другое принимает и шлет ответ) подменять команду ответ не трогать пока потом видно будет.

Собрал в протеусе тестовую схему на основе arduino mega 2560 и реально на столе 

зашиваю простую программу чтобы они для начала просто обменивались командами а arduino был как бы посредником и два устройства перестают друг друга видеть, подскажите что я делаю не так

void setup()  
{
   Serial.begin(38400);
   Serial1.begin(38400);
 
}

void loop()
{
  
    if (Serial.available())
    {
     Serial1.println(Serial.read());
    }
    
  if (Serial1.available())
    {
     Serial.println(Serial1.read());
   }
    
 delay(1000);
}

 

 

alias095
Offline
Зарегистрирован: 22.04.2014

6335d5c58787t.jpg

схема в протеусе, к ком порту подключен реальное устройство а в терминал я ввожу команды, отклика нет совсем и даже светодиоды rx tx на устройстве молчат как будто что то не так, пробывал соединять по разному вдруг не так rx tx определил .....

com
Offline
Зарегистрирован: 06.09.2013

пара моментов

1. пересылаете один байт и ждете одну секунду... скорость обмена 1байт/сек?

2. читаете один байт, а пересылаете дальше три (println добавляет 0D0A)? лучше write

alias095
Offline
Зарегистрирован: 22.04.2014

пробывал использовать и write ,  скорость обмена даже не знаю я только начинаю изучать

знаю скорость порта 38400 ,передаются AT команды 

leshak
Offline
Зарегистрирован: 29.09.2011

Перечитайте еще раз что вам написал com. Особенно пункт 1. Там говорится не про "что изучить нужно", а что "что вы сделали своим скетчем". Разберитесь что У ВАС делает КАЖДАЯ строка. Например, что происходит в строке (21)? В Вашем коде, недолжно присутсвовать ничего назначение чего Вы не понимаете.

P.S. И write, в данном случае нужно не "пробовать", а "использовать". Именно она является "зеркальным отражением" read-а.

alias095
Offline
Зарегистрирован: 22.04.2014

21 строка задержка в одну секунду...

но даже если все это переписать к виду

void setup()  
{
   Serial.begin(38400);
   Serial1.begin(38400);
 
}

void loop()
{
  
    if (Serial.available())
    {
     Serial1.write(Serial.read());
    }
    
  if (Serial1.available())
    {
     Serial.write(Serial1.read());
   }
    
}

Чуда не происходит... поэтому и прошу помощи знатоков, потому как данный скреч простой пример и я не могу понять что тут не так 

leshak
Offline
Зарегистрирован: 29.09.2011

>21 строка задержка в одну секунду..

Верно. И возникает вопорос "а зачем она там вообще появилась?" :)

> и я не могу понять что тут не так 

Ну может быть потому что "теперь тут все так"? :)  И дальше уже проблему нужно искать не в скетче.

В настройках протеуса, качестве его эмулиции т.п.

Попробуйте подцепить два терминала, а не терминал и разъем. Посмотрите бегают ли данные между ними.

Попрбуйте сделать Serial.println("Hello from Serial"); Serial1.println("Hellow from Serial1");  убедитесь что вы вообще видите что-нибудь в терминалах от ардуины.

Да вообще, банальный блинк в нее залейте. И попробуйте увидеть что светик мигает. Может у вас вообще скетч в нее заливается/выполняется или частота камня выставлена неправильно.

P.S. Правда у меня было, один раз когда конструкция вида

Serial.write(Serial1.read())

Не хотела работать (вернее "работала", но почему-то \r\n игнорила). А вот в таком виде

byte ch=Serial1.read();
Serial.write(ch);

Все работало без проблем. Хотя, теоретически разницы между этими вариантами нет. Но я, тогда, забил выяснять почему "так работает, а так нет".

com
Offline
Зарегистрирован: 06.09.2013

соедините земли обоих устройств и ардуино. я чего-то на схему вашу и не посмотрел сначала... 

если не заработает (а внутренний голос мне подсказывает, что не заработает, хотя и должно) надо будет пробовать читать-писать без второго устройства

зы.

еще раз посмотрел на схему. вы действительно ком-порт напрямую подключили к ардуино?

alias095
Offline
Зарегистрирован: 22.04.2014

нет через 232 преобразователь, если я цепляю второй терминал то байты бегают но передается не полностью команда или слово а симфол, т.е по одному знаку

com
Offline
Зарегистрирован: 06.09.2013

о! а терминалов-то два уже оказывается.

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

alias095
Offline
Зарегистрирован: 22.04.2014

Я пишу о том что всячески пробывал.... 

и простые блинки я делать умею, и если бы вы чита выше то там написано что так сказать дубль схемы лежит на столе и на нем я тоже обкатываю

com
Offline
Зарегистрирован: 06.09.2013

leshak пишет:

 

P.S. Правда у меня было, один раз когда конструкция вида

Serial.write(Serial1.read())

Не хотела работать (вернее "работала", но почему-то \r\n игнорила). А вот в таком виде

byte ch=Serial1.read();
Serial.write(ch);

Все работало без проблем. Хотя, теоретически разницы между этими вариантами нет.

разница таки есть. serial.read возвращает int, т.е два байта

alias095
Offline
Зарегистрирован: 22.04.2014

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

com
Offline
Зарегистрирован: 06.09.2013

alias095 пишет:

Я пишу о том что всячески пробывал.... ладно всем телепатам спасибо

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

leshak
Offline
Зарегистрирован: 29.09.2011

alias095 пишет:

если я цепляю второй терминал то байты бегают

Что и требовалось доказать. Значит со скетчем все нормально. И трабла где-то в вашем преобразователе.

Попробуйте напрямую из "преобразователя" направить "в терминал". Без промежуточного звена в виде ардуины.

alias095 пишет:

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

Ну а как же иначе? Serial шина - по другому не работает. На самом деле он передает даже не по одному символу, а "по одному биту". А биты в байты(символы) собирает уже сам железный Uart в ардуине. Если вы хотите еще и "байты" собирать в "строки" - то это уже "сами ручками" (на форуме не одна тема по этому поводу есть).

Но, если вам нужно "просто перенаправить поток из одного Serial в другой", то вообщем-то "собирать в строки" - не нужно. Побайтовой пересылки будет достаточно (а "в строку", пусть собирает тот кому мы посылаем).

leshak
Offline
Зарегистрирован: 29.09.2011

com пишет:

разница таки есть. serial.read возвращает int, т.е два байта

ну и что? В чем разница?  А write принимает byte. Какая разница в какой момент будет выброшен старший байт? В момент вызова write или когда мы присваем переменной ch (которая типа byte)? IMHO - никакой.

Естественно, оба варианта были обернуты в if(Serial1.available()), так что Serial1.read(), вернуть -1 нам не мог (единственный случай когда int "вступает в игру"). Что-бы он не вернул - старший байт у него всегда равен нулю и игнорируется в обоих вариантах.

mal333
Offline
Зарегистрирован: 23.04.2014

Поддерживаю автора в его недоумении. Если соединить RX1 с TX2, а  TX1 с RX2 и залить скетч

/*
#include <HardwareSerial.h>
String inputString = "";     // a string to hold incoming data
String inputString1 = "";  
boolean stringComplete = false;  // whether the string is complete.
boolean stringComplete1 = false; 
byte evt2=0;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial2.begin(9600);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);
  inputString1.reserve(200);
}

void loop() {
  // print the string when a newline arrives:
  if (stringComplete) {

    Serial1.print(inputString);
   
    Serial.println("First if");
    Serial.println(evt2);
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
 if (stringComplete1) {
    Serial.print(inputString1);
    Serial.println("Second if");
    // clear the string:
    inputString1 = "";
    stringComplete1 = false;

  }

}


void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();// add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}


void serialEvent2() {
  while (Serial2.available()) {
    // get the new byte:
    char inChar = (char)Serial2.read();
    // add it to the inputString:
    inputString1 += inChar;
    evt2=inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete1 = true;
    }
  }
}

 

 - обрабатывается только первый if
Что делать- тоже в растерянности, т.к. ну не видно(мне) ошибок!
com
Offline
Зарегистрирован: 06.09.2013

чего-то многовато будет 3 сериала, не? откуда и куда читаете-пишите поясните, а то запутано

alias095
Offline
Зарегистрирован: 22.04.2014

С обменом я разобрался была железячная проблема, и в протеусе с настройка ми поигрался, щас два устройства работают через ардуино. Щас вопрос вот в чем. Одно устройство отправляет AT команды другому , другое следовательно шлет ответ. 

Подскажите пожалуйста как сделать подмены AT команды с одной на другую, при этом ответ не трогать , как я понимаю

нужно в блоке строк с 11 по 14 или с 16 по 19 (в зависимости от того куда зачеплю устройство которое шлёт команды), добавить код который будет сравнивать команду и подменять ? 

Щас пытался сделать конструкциями вида

 

if (Serial.read()=='010D\r')
{
Serial1.println('send ok\r');
}
else
{
Serial1.write(Serial.read());
}

но тогда в терминал летит хрень

com
Offline
Зарегистрирован: 06.09.2013

вы принимаете команды п_о_б_а_й_т_н_о поэтому Serial.read()=='010D\r' неверно

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

зы

сейчас заметил - у вас же именно это в коде и было:

inputString1 += inChar;

разберитесь таки со своим собственным кодом!

alias095
Offline
Зарегистрирован: 22.04.2014

У меня этого в коде не было код выше озвучил другой участник, что ж так всё во штыки воспринимаете. к вам обращаются за помощью а вы просто тыкаете носом как .....

com
Offline
Зарегистрирован: 06.09.2013

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

чего обижаться, вам же leshak уже пытался разъяснить

leshak пишет:

Ну а как же иначе? Serial шина - по другому не работает. На самом деле он передает даже не по одному символу, а "по одному биту". А биты в байты(символы) собирает уже сам железный Uart в ардуине. Если вы хотите еще и "байты" собирать в "строки" - то это уже "сами ручками" (на форуме не одна тема по этому поводу есть).

а вы почему-то это проигнорировали. а он ведь писал, объяснял, старался.... как думаете, а ему не обидно, что это все было зря?

alias095
Offline
Зарегистрирован: 22.04.2014

А я где то писал про то чтобы написать за меня  или напишите мне???? Понятно я признаю ошибки. спрашиваю. Если бы вы не разводили демагогию а просто примерчик, отрезок кода кинули чтобы понять , так то если вам трудно или же просто обидно не пишите...

 

И просто простите меня все у кого я время украл или же обидел!!! 

Вообщем просто нет слов, люди добрые!

 

alias095
Offline
Зарегистрирован: 22.04.2014

Как склеивать я вроде разобрался, а как распознать окончание команды , в моём случаем символ этот переход на новую строку

leshak
Offline
Зарегистрирован: 29.09.2011

>Если бы вы не разводили демагогию а просто примерчик, отрезок кода кинули чтобы понять

А как у вас с демагогией обстоит? Вам посоветовали "поискать"... неужели ни одной ветки где "собирается строка" или обсуждается прием/передача строк и данных через Serial не нашли?

Только я, лично, если память не изменяет, участвовал в штуках в пяти. "Кидал примеры", объяснял что-бы человек сам понял как делать (что в итоге и произошло)... И еще фигову тучу веток подобных уже тупо игнорил, потому как "ну сколько же можно.." 

>как распознать окончание команды , в моём случаем символ этот переход на новую строку

Посмотрите на скетч в #16. Там есть пример детектирования новой строки. Если трудно его увидеть - переведите комметарии.

Кстати этот скетч, явно  сделан на базе туториала (обучающего примера) с официального сайта. То есть вот mal333 почему-то смог найти место где уже кинули "кусок кода что-бы понять". 

alias095
Offline
Зарегистрирован: 22.04.2014

вообщем с текущеми задачами разобрался кому нужно кусок кода делающий склейку и подмену команды



while (Serial.available()) {
delay(2);
char currSymb = Serial.read();
if ('\r' == currSymb) {
if (currStr=="010D"){
Serial.println("210D");
}
else
{
Serial.println(currStr);
}
currStr = "";
}
else if ('\n' != currSymb) {
currStr += String(currSymb);
}
}

Вечером все в один код скину и на железе опробую

leshak
Offline
Зарегистрирован: 29.09.2011

2mal333: 

1. Не нужно телепатов предполагать. Можно конечно догадатся по коду что вы пытались делать и с чего у вас "все начинается" (откуда вообще изначально идут данные), но... лучше в явном виде описывать а. Steps to Reproduce б. Что вы ожидаете
2. Кстати вы не сказали, даже, на какой плате вы пытаетесь все это забубенить
3.  А с кодом все нормально. Оба условия работают. Так что ищите проблему либо в том как вы изначально данные шлете (хотя - маловероятно, тогда бы у вас и первый не работал) или в том "что куда вы соединили" (по описанию ... опять-таки все верно, а вот как там в реале... вернее "по описанию" даже избыточно TX1-->RX2 уже достаточно для запуска)

P.S. А вообще, лично я не люблю String, предпочитаю "теплый ламповый" string. И использования SerialEvent(), вот кроме как в туториалах - нигде не видел. Обычно просто в loop() проверяют if(Serial1.available()). Но, это уже "вопросы вкуса". С точки зрения "работоспособности и грубых ошибок" - у вас все верно сделано.

com
Offline
Зарегистрирован: 06.09.2013

alias095 пишет:

А я где то писал про то чтобы написать за меня  или напишите мне????

...

вот опять обиделись. я вообще-то не вас имел в виду....

mal333
Offline
Зарегистрирован: 23.04.2014

1. Цель - проверить работоспособность меж-UART обмена в пределах контроллера и аппаратных прерываний. Цепочка следующая - через ардуино-монитор шлем в контроллер любую строку-> отправляем ее в СОМ1 ->СОМ1 соединен с СОМ2-> ловим строку в СОМ2 и отправляем в качестве ответа в окно монитора. Так вот при правильности программы ничего не происходит, кроме вывода в монитор "First if"

2. Arduino Mega, как и указал топикстартер.

3. Ну невозможно же неверно соединить 1 и 17 вывод контроллера( TX1-->RX2)?

Без SerialEvent() вообще, мне думается, невозможно сделать передачу UART-UART в пределах контроллера, т.к. SoftwareSerial может только принимать либо только передавать данные в один момент времени.

 

leshak
Offline
Зарегистрирован: 29.09.2011

mal333 пишет:

3. Ну невозможно же неверно соединить 1 и 17 вывод контроллера( TX1-->RX2)?

Значит возможно. Потому что ВАШ скетч. Без каких либо модификаций (ну разве что /* из первой строки выкинул, иначе не компилится вообще) . С одним проводком. У меня дает такой вывод:

Так что есть три варианта:

1. Что-то не досоединяли
2. Наоборот, еще что-то лишние посоединили
3. Не долили скетч (учитывая /* он у вас вообще не компилился, не вливался. возможно вы его в дуину не влили, и смотрели на вывод "старой версии).

leshak
Offline
Зарегистрирован: 29.09.2011

mal333 пишет:

3. Ну невозможно же неверно соединить 1 и 17 вывод контроллера( TX1-->RX2)?

А блин!!!! Сказал же "перероверять", а не "спорить" :)

С какго испуга TX1 вдруг стал первым выводом (D1). Это вы соединили TX->RX2, а не TX1-->RX2

Так что "невозможное - возможно" ;)

P.S. TX1 Это D18 на меге.

mal333
Offline
Зарегистрирован: 23.04.2014

Блин! Вот описАлся же! :) Естественно ТХ1(18) с RX2(17). И да, /* - остаток от удаленного комментария, чтобы не длиннить код. С ним будет не скетч, а просто длинный комментарий :)
Вопрос заодно несколько не в тему: а верно ли утверждение, что RX TX -это то, что мы видим в мониторе ардуины, т.е. передавая что-то через Serial.Print() это появляется на ТХ?

leshak
Offline
Зарегистрирован: 29.09.2011

> т.е. передавая что-то через Serial.Print() это появляется на ТХ?

Да. 

Tx - это "передатчик".

RX - приемник.

mal333
Offline
Зарегистрирован: 23.04.2014

О! Заработало внезапно! Осталось выяснить откуда этот "0", но это уже мелочи. Благодарю всех откликнувшихся!

leshak
Offline
Зарегистрирован: 29.09.2011

mal333 пишет:

О! Заработало внезапно!

Ну вам же говорили. Проверяйте :)  "Электроника - наука о контактах" ;)

mal333 пишет:

Осталось выяснить откуда этот "0", но это уже мелочи. Благодарю всех откликнувшихся!

Это первое что меня тоже заинтересовало. Но... а че долго думать? Строка 26-ть. evt2

hong_10
Offline
Зарегистрирован: 30.10.2013

Народ подскажите плз. На ардуино подцепил gsm щит(http://dvrobot.ru/shop/i197.gsm_gprs_schit_dlya_arduino.htm), а на него bluetooth(http://dvrobot.ru/shop/i195.bluetooth_modul.htm) С c# посылаю байт serialPort1.Write("0"); а вот код на ардуино. Смс не приходит. Это происходит, потому что нельзя 2 устройства с rx tx, подцеплять на ардуино? даже если использую разные пины

 

01 #include <SoftwareSerial.h>
02 #include "SIM900.h"
03 #include "sms.h"
04 SMSGSM sms;
05 boolean started=false;
06 SoftwareSerial mySerial(11, 12);
07 char ch;
08 void setup()
09 {
10   mySerial.begin(9600);
11  
12   pinMode(9,OUTPUT);
13  
14   digitalWrite(9,HIGH);
15   if (gsm.begin(2400))
16   {   
17     started=true
18   }
19   digitalWrite(9,LOW);
20 }
21 void loop()
22 {
23   if (mySerial.available())
24   {
25     ch = mySerial.read();
26   }
27    if ((started) && (ch==48))
28    {   
29      sms.SendSMS("+79******""arduino");
30    }
31   
32 }

 

leshak
Offline
Зарегистрирован: 29.09.2011

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

hong_10
Offline
Зарегистрирован: 30.10.2013

без bluetooth смс приходит, gsm щит работает четко) и bluetooth работает без gsm щита.

leshak
Offline
Зарегистрирован: 29.09.2011

А при совместном подключении кто из них работает не четко?

hong_10
Offline
Зарегистрирован: 30.10.2013

void loop()
{
  if (mySerial.available())
  {
    ch = mySerial.read();
  }
  if (ch==48) digitalWrite(13,HIGH);
   if (started) 
   {    
     sms.SendSMS("+79*****", "arduino");
   
   }
  
}

при совместной работе, при таком коде смс приходит. А на 13 пину нет напряжения. 

leshak
Offline
Зарегистрирован: 29.09.2011

То есть делаем вывод, что и GSM шилд и блюпуп у вас работают. Верно? Вы согласны с моим выводом?

 

leshak
Offline
Зарегистрирован: 29.09.2011

Хотя нет... вывод неверный. Это значит что GSM шилд работает. А про блюпуп - пока не понятно. То ли команды вы шлете распознаете "криво", то ли сам блюпуп не работает.

Правильно я рассуждаю?

hong_10
Offline
Зарегистрирован: 30.10.2013

когда я снимаю gsm щит, и bluetooth модуль напрямую подключаю к ардуинке все работает. на 13 пину есть напряжение

void loop()
{
  if (mySerial.available())
  {
    ch = mySerial.read();
  }
  if (ch==48) digitalWrite(13,HIGH);
   
  
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

>когда я снимаю gsm щит,

Ну вы же не только "сняли шилд", но еще и код поменяли. Убрали работу с шилдом. Не только железо.

Попробуйте, при эксперементах менять только что-то одно за один раз.

А то, к примеру, я вот не уверен что в одном случае вы не делали попытку послать из C#, а второй раз руками из Serial. Или наоборот.

Или скажем, паралельно, при "прямом подключении", вешаете его в точности на те же 11,12 пины.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Как минимум одна грубая ошибка, если хотя бы раз придёт '0', будет постоянный посыл Смс. ch надо делать локальной переменной и инициализировать например кодом '\0', а потом уже проверять, получено что то или нет.