Отправка нулей через SoftwareSerial.

seregap
Offline
Зарегистрирован: 14.01.2017

Здравстввуйте!

Плата Adruino Uno и Mini.

Требуется считать пакет в виде "1f 00 00 00 00 43 56" из Serial порта платы номер 1 и передать через SoftwareSerial на плату номер 2. На плате на, на приеме получается только "1f",

Если отправлять пакет вида "1f 00 12 00 32 43 56", то он приходит целиком. Но как только 2 байта с нулями идут подряд, перед ними обрываются данные.

Пробовал через Serial.readString и переменную string, Serial.readBytes в массив char[].  Результат одинаковый.

Подскажите, как решить данную задачу?

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

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

У меня такое было с MIDI устройством. Пришлось вместо стандартной частоты 31250 прописывать в скетче 31500.

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

andriano пишет:

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

У меня такое было с MIDI устройством. Пришлось вместо стандартной частоты 31250 прописывать в скетче 31500.

можно тактировать контроллеры от одного кварца

Волшебник
Offline
Зарегистрирован: 22.12.2016

Не уверен но что если не принт а врайт? http://arduino.ru/Reference/Serial/Write

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

Волшебник пишет:

Не уверен но что если не принт а врайт? http://arduino.ru/Reference/Serial/Write

какая в жопу разница?

Волшебник
Offline
Зарегистрирован: 22.12.2016

Один ... а другой дразнится.

size_t Print::print(const String &s)
{
  return write(s.c_str(), s.length());
}

Я думаю, что стандартный принт интерпретирует 0-й байт как символ окончания строки, обычно С строка всегда заканчиватся 0-ём.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

seregap пишет:

Подскажите, как решить данную задачу?

А скетч не судьба показать?

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

ЕвгенийП пишет:

А скетч не судьба показать?

я запретил.

seregap
Offline
Зарегистрирован: 14.01.2017

Простите за сумбурный вопрос.

Снова добрался до задачи.

2 платы.

На одной обычный softwareserial из примера, для сбора данных и отправки дальше.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
    Serial.begin(19200);
    mySerial.begin(19200);
  }

void loop() { // run over and over
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }
}

 

На второй PubSubClient, опять же из примера. Он соеденятся с mqtt брокером moqsuitto и отсылает ему данные в виде char.

if (Serial.available()) {
  String stringVar=Serial.readString();
 
char charVar[sizeof(stringVar)];
stringVar.toCharArray(charVar, sizeof(charVar));

    mqtt.publish(serial_in, charVar );

 

Я запутался в преобразованиях данных. Мне нужно что бы вход с UART отправлялся в виде CHAR "как есть", без преобразования в ASCII.

Тоесть в "сыром" виде. Но преобразования данных подрозумевают что на входе будет ASCII. Соответственно нули и отбрасываются. т.к. в аски ноль это 0x30.

Задача - преобразовать hex в ascii, что бы оно выглядело как первоначальный пакет. Так наверное. Запутался уже.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да Вы тут много в чём запутались.

Для начала, размер массива charVar Вы указали sizeof(stringVar). И чему это по-вашему равно? Напечатайте - узнаете.

А если Вам не надо преобразовывать, так зачем Вы преобразовываете? Зачем String приплели? У Вас же в врехнем скетче всё нормально написано. Ну и делайте также в нижнем.

Выбросьте кашу из головы и делайте то, что нужно Вам, а не то, что Вы где-то увидели.

seregap
Offline
Зарегистрирован: 14.01.2017

Евгений, спасибо за ответ.

String для чтения из потра данных. Потом преобразование из string в char, т.к. pubsub со стрингом не работает.

Если читать сразу в char, то выход для пакета ABCDEA принимает такой вид:

32 3f ef bf bd 1f 2f ef bf bd d5 b8 ef bf bd ef bf bd ef bf bd 7d ef bf bd 5e 44 ef bf bd ef bf bd ef bf bd 2a 0f ef bf bd ef bf bd ef bf bd d3 bb 74 ef bf bd ef bf bd ef bf bd 77 45 19 ef bf bd 54 ef bf bd ef bf bd ef bf bd ef bf bd 47 ef bf bd ef bf bd ef bf bd 05 ef bf bd 7e 74 ef bf bd ef bf bd ef bf bd cd b0 ef bf bd ef bf bd 2e 2e 2e

Это в терминале смотрю. 

Если читать в string, потом  в char преобразовывать, то вид нормальный, что пишу то и принимаю. Но на нулях обрывается передача.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

seregap пишет:

вид нормальный

Нормальный - это какой?

И не забудьте про sizeof (я Вам писал) - Вы зря думаете, что в нём сидит длина Вашей строки.

seregap
Offline
Зарегистрирован: 14.01.2017

ЕвгенийП пишет:

Пробовал размер менять, без особых изменений.

Я вижу выход таким образом - преобразовать исходные данные в ascii.  

Т.е. пакет вида ABCDEA0000 каким то образом должен принять вид  

"0х41 0х42 0х43 0х44 0х45 0х41 0х30 0х30 0х30 0х30"

И уже его отсылать дальше.

Пока не знаю как это провернуть.

Вкратце, нужно действие аналогично Serial.println(char, HEX), только без вывода в порт, а с сохранением в виде char.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Что Вы там пробовали менять? sizeof не имеет никакого отношения к длине строки.

ПАо поводу проеобразований, Вы её еще на бумагу напечатайте и руками вводите.

Скажите чётко что Вам надо? Как пришло, так и отправлять или что?

seregap
Offline
Зарегистрирован: 14.01.2017

Ставил фиксированную длинну (64), потом поменял на stringVar.length(). В итоге убрал вообще это преобразование.

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

Попробую обьяснить, не ругайтесь сильно.

Смысл такой. С порта забрать байты и преобразовать их в ASCII с хранением в  типе char.

То есть, забрать из порта последовательность вида "ABCDEA0000" и сохранить в типе char её же, но в виде  ASCII.

Т.е. char должен содержать в себе информацию типа "41424344454130303030", для отправки ее дальше. Т.к. pubsubclient работает только с ascii, и если  я буду пересылать напрямую с порта после чтения в char сразу, то pubsubclient отправит данные "как есть", т.е. "ABCDEA0000". На нулях посылка оборвется, и все что будет после нулей не придет.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, если надо преобразовывать, так преобразовывайте, но не стринг же ради этого притягивать

seregap
Offline
Зарегистрирован: 14.01.2017

Т.е. считывать в char? А потом что с ним делать не совсем понимаю. Serial.Println(char, HEX) отрабатывает все как надо, но выводит в порт только. Можно как нибудь сохранить этот вывод?

seregap
Offline
Зарегистрирован: 14.01.2017

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

if (Serial.available() > 0) {
       
         

str1= Serial.readString();
char buffer[2*sizeof(str1)];
char* buffPtr = buffer;

for(byte i = 0; i < sizeof(str1) - 1; i++){
   itoa((uint8_t)str1[i],buffPtr,16);
   buffPtr += strlen(buffPtr); 
   *buffPtr = ' '; 
   buffPtr++; 
 }
 buffPtr--; 
 *buffPtr = '\0';

 
 Serial.println(buffer);

   
  } 

Тип char buffer хранит в себе аски коды того, что пришло на входе порта. Как то так. Это решение волне работает с передачей данных через PubSubClient.

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

Вы находите, что две приведенный ниже цитаты исключают друг друга?

seregap пишет:

Т.е. пакет вида ABCDEA0000 каким то образом должен принять вид  

"0х41 0х42 0х43 0х44 0х45 0х41 0х30 0х30 0х30 0х30"

seregap пишет:

Т.е. char должен содержать в себе информацию типа "41424344454130303030"

И еще. ASCII - американский телеграфный код. Что Вы подразумевате под

seregap пишет:

преобразовать исходные данные в ascii.

понимаете только Вы.

ASCII - это способ кодировки текста. "ABCDEA0000" - это УЖЕ текст, а потому это УЖЕ ASCII. Куда его дальше преобразовывать?

seregap
Offline
Зарегистрирован: 14.01.2017

В чем я не прав?

ABCDEA0000 после преобразования имеет вид "41424344454130303030". Для более удобного восприятия я написал с нулями и пробелами. Тут согласен, мог запутать кого.

Я использую данные с порта в "сыром" виде. Не через терминал, который из УЖЕ в ASCII шлет.

Например модбас-пакет. О каком аски или тексте там речь может идти?

 

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

Для того, чтобы выяснить, в чем Вы не правы, нужно:

1. Понять, что именно Вам нужно.

2. Узнать, что Вы для этого делавете.

3. Выяснить, чем первое отличается от второго.

Я, честно говоря, забуксовал уже на первом пункте.

Насколько я понял (пункт 2), Вы берете текст (в частности "ABCDEA0000"), зачем-то рассмиатриваете его как бинарные данные и записываете их снова в виде текста в hex-формате. Либо я не правильно понял, что именно Вы делаете, либо совершенно не могу взять в толк, зачем это нужно. Зачем с текстом делать какие-то еще преобразования?

seregap
Offline
Зарегистрирован: 14.01.2017

andriano пишет:

Для того, чтобы выяснить, в чем Вы не правы, нужно:

1. Понять, что именно Вам нужно.

2. Узнать, что Вы для этого делавете.

3. Выяснить, чем первое отличается от второго.

Я, честно говоря, забуксовал уже на первом пункте.

Насколько я понял (пункт 2), Вы берете текст (в частности "ABCDEA0000"), зачем-то рассмиатриваете его как бинарные данные и записываете их снова в виде текста в hex-формате. Либо я не правильно понял, что именно Вы делаете, либо совершенно не могу взять в толк, зачем это нужно. Зачем с текстом делать какие-то еще преобразования?

 

ABCDEA0000 это не текст, а бинарные данные с порта. Устройство-передатчик не совместимо с ascii и не умеет впринципе текст передавать. itoa() - как раз для этиц целей.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

seregap пишет:

Устройство-передатчик не совместимо с ascii и не умеет впринципе текст передавать. itoa() - как раз для этиц целей.

Простите, но Вы бредите. Текст - это такие же байты (числа) как и нетекст. Текстом они становятся только в человеческой голове. Компьютер или любое другое техническое устройство никак не отличает текст от нетекста - для него это просто числа.

Снчала я не понял чего Вам надо, теперь вот коллега тоже не понял. А по Вашему посту я вижу, что Вы сами не понимаете - и проблема именно в этом.

Постарайтесь понять сами и тогда обяснить нам.

seregap
Offline
Зарегистрирован: 14.01.2017

Все решено уже и сделано. Код выше запостил.