Нулевые байты по serial port

weary
Offline
Зарегистрирован: 19.01.2018

Добрый день

Есть необходимость принимать пакеты побайтовой информации, вот такого типа 

A0 00 E6 02 00 00 88

Делаю это вроде обычным образом через побайтовое заполнение массива. Массив заполняется, но он состояит из не нулевых байт только, т  е например вместо того что выше я получаю A0 E6 02 88, т е длина массива 4.

Подскажите, как сделать, чтобы получать весь пакет с нулевыми байтами? ниже кусок кода

[code]
 
byte resultPow[7];
 
int a = 0;
while (mySerial.available())  {
  resultPow[a] = mySerial.read();
  a++;
}
 
[/code]

 

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

Для начала проверьте, что именно Вы передаете.

weary
Offline
Зарегистрирован: 19.01.2018

Заливал скейч на прием и передачу с одного порта на другой виртуальный, и пробовал через COM port Toolkit отправлять и получать комманды, всё работает, как нужно. Вот скрин  

b707
Онлайн
Зарегистрирован: 26.05.2017

weary пишет:

Заливал скейч на прием и передачу с одного порта на другой виртуальный, и пробовал через COM port Toolkit отправлять и получать комманды, всё работает, как нужно. Вот скрин  

Не надо скрин того, что работает. Давайте код приемника и передатчика, в которых теряются нулевые байты.

weary
Offline
Зарегистрирован: 19.01.2018
Передатчик это мультиметр PZEM004T. Приемник это NANO, вот ниже её скейч. Отправляем запрос B0 C0 A8 01 01 00 1A, мультиметр отвечает A0 00 E6 02 00 00 88



[code]
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX SoftwareSerial mymySerial
byte VoltageReq[] = {0xB0, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1A}; // отправляем запрос напряжения
byte resultVol[7]; //  принимаем ответ
int volt; 
int updateFreq = 1000;
unsigned long timeread1 = 0;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  mySerial.begin(9600);

}

void loop() {
  if (millis() - timeread1 > updateFreq) {
    timeread1 = millis();
    mySerial.write(VoltageReq, sizeof(VoltageReq));
    delay(10);
    int i = 0;
    while (mySerial.available())  {
      resultVol[i] = mySerial.read();
      mySerial.read();
      i++;
    }
    volt = resultVol[1];
    Serial.print(volt);
    Serial.print(i);  //для отладки, длина массива
    Serial.println(" ");
  }
}
[/code]

 

b707
Онлайн
Зарегистрирован: 26.05.2017

Нули не причем. Вы читаете из Сериала два байта - один в строке 28 и один 29, а сохраняете только первый.

weary
Offline
Зарегистрирован: 19.01.2018

Точно!!  всё работает, большое спасибо

sadman41
Offline
Зарегистрирован: 19.10.2016

Странно вы как-то вольты с посылки вычисляете. Да и проверок нет никаких - ни валидности ответа, ни CRC. 

weary
Offline
Зарегистрирован: 19.01.2018

sadman41 пишет:

Странно вы как-то вольты с посылки вычисляете. Да и проверок нет никаких - ни валидности ответа, ни CRC. 

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

 

А вольты почему странно? Третий байт это целое число вольт. Как правильней?

b707
Онлайн
Зарегистрирован: 26.05.2017

weary пишет:

А вольты почему странно? Третий байт это целое число вольт. Как правильней?

Третий? а в коде вы выводите второй...

sadman41
Offline
Зарегистрирован: 19.10.2016

weary пишет:

А вольты почему странно? Третий байт это целое число вольт. Как правильней?

У меня вот так записано (деталей не вспомню, но полагается поделить на 10, чтобы десятые доли вольта получить):

...
    case SENS_READ_VOLTAGE:
      result = ((_dst[1] << 8) + _dst[2]) * 10 + _dst[3]; 
...

Ну и там еще первый байт проверить на ==(command - 0x10), иначе веры нет ответу.

weary
Offline
Зарегистрирован: 19.01.2018

b707 пишет:

weary пишет:

А вольты почему странно? Третий байт это целое число вольт. Как правильней?

Третий? а в коде вы выводите второй...

Третий в смысле 0 1 2

weary
Offline
Зарегистрирован: 19.01.2018

sadman41 пишет:

weary пишет:

А вольты почему странно? Третий байт это целое число вольт. Как правильней?

У меня вот так записано (деталей не вспомню, но полагается поделить на 10, чтобы десятые доли вольта получить):

...
    case SENS_READ_VOLTAGE:
      result = ((_dst[1] << 8) + _dst[2]) * 10 + _dst[3]; 
...

Ну и там еще первый байт проверить на ==(command - 0x10), иначе веры нет ответу.

 

На вольтах десятые не интересуют, а вот для ампер выведу.

Что значит такая запись _dst[1] << 8

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

weary пишет:

Точно!!  всё работает, большое спасибо

Да уж...

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

sadman41
Offline
Зарегистрирован: 19.10.2016

weary пишет:

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

Для ампер можно с сотыми, у меня вот так (надо поделить на 100):

      result = ((_dst[1] << 8) + _dst[2]) * 100 + _dst[3];

В принципе десятые уже идут [3] - можно ничего не умножать и пр., но мне такая формула нужна для своей процедуры.

weary пишет:

Что значит такая запись _dst[1] << 8

То же самое, что у вас resultVol[1]*256 в ответ передается два байта, значит нужно сгрузить их все в одну переменную.

weary
Offline
Зарегистрирован: 19.01.2018

sadman41, а как вы реализовали отправку комманд по кругу  с заданной задержкой?

sadman41
Offline
Зарегистрирован: 19.10.2016

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

weary
Offline
Зарегистрирован: 19.01.2018

sadman41 пишет:

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

 

Одну комманду, отправлял обычным if (millis() - timeread1 > updateFreq) { timeread1 = millis();...

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

А вот с 4 коммандами так не получилось. Нужно еще условие, а какое не пойму пока.

weary
Offline
Зарегистрирован: 19.01.2018

Вот так работает, но выглядит не солидно

[code]
  if ((millis() - timeread1 > updateFreq) && triger1) {
    timeread1 = millis();
    triger1 = 0;
    triger2 = 1;
    triger3 = 0;
    triger4 = 0;
    mySerial.write(voltageReq, sizeof(voltageReq));
  }
  if (millis() - timeread1 > updateFreq && triger2) {
    timeread1 = millis();
    triger1 = 0;
    triger2 = 0;
    triger3 = 1;
    triger4 = 0;
    mySerial.write(CurrentReq, sizeof(CurrentReq));
  }
  if (millis() - timeread1 > updateFreq && triger3) {
    timeread1 = millis();
    triger1 = 0;
    triger2 = 0;
    triger3 = 0;
    triger4 = 1;
    mySerial.write(PowerReq, sizeof(PowerReq));
  }
  if (millis() - timeread1 > updateFreq && triger4) {
    timeread1 = millis();
    triger1 = 1;
    triger2 = 0;
    triger3 = 0;
    triger4 = 0;
    mySerial.write(EnergyReq, sizeof(EnergyReq));
  }

[/code]

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Солидно будет если вы ардуине разъемы позолотите...

А в вашей ситуации можно было бы сделать, например так:

byte req[] = {0xB0, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1A};
byte metric = 0;
...

  if (millis() - timeread > updateFreq) {
    switch (metric) {
      case 0:
        Req[0] =  0xB0; // 'voltage' cmd
        Req[6] =  0x1A; // CRC for 'voltage' cmd
        break;
      case 1:
        Req[0] =  0xB1; // 'current' cmd
        Req[6] =  0x??; // CRC for 'current' cmd
        break;
      case 2:
        ...
        break;
      case 3:
        ...
        break;
      default:
        break; // Never executed
    }
    mySerial.write(Req, sizeof(Req));
    ...
    ans[i] = mySerial.read();    
    ...
    resultWholePart = ((ans[1] << 8) + ans[2]);
    resultFraqPart = ans[3];
    switch (metric) {
      case 0:
        voltageWholePart = resultWholePart;
        voltageFraqPart = resultFraqPart;
        break;
      case 1:
        currentWholePart = resultWholePart;
        currentFraqPart = resultFraqPart;
        break;
      ...
    }

    metric++;
    if (metric > 3) { metric=0; }
    timeread = millis();
  }

 

weary
Offline
Зарегистрирован: 19.01.2018

sadman41 пишет:

Солидно будет если вы ардуине разъемы позолотите...

А в вашей ситуации можно было бы сделать, например так:

byte req[] = {0xB0, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1A};
byte metric = 0;
...

  if (millis() - timeread > updateFreq) {
    switch (metric) {
      case 0:
        Req[0] =  0xB0; // 'voltage' cmd
        Req[6] =  0x1A; // CRC for 'voltage' cmd
        break;
      case 1:
        Req[0] =  0xB1; // 'current' cmd
        Req[6] =  0x??; // CRC for 'current' cmd
        break;
      case 2:
        ...
        break;
      case 3:
        ...
        break;
      default:
        break; // Never executed
    }
    mySerial.write(Req, sizeof(Req));
    ...
    ans[i] = mySerial.read();    
    ...
    resultWholePart = ((ans[1] << 8) + ans[2]);
    resultFraqPart = ans[3];
    switch (metric) {
      case 0:
        voltageWholePart = resultWholePart;
        voltageFraqPart = resultFraqPart;
        break;
      case 1:
        currentWholePart = resultWholePart;
        currentFraqPart = resultFraqPart;
        break;
      ...
    }

    metric++;
    if (metric > 3) { metric=0; }
    timeread = millis();
  }

 

 

Локанично, спасибо, переделал

variator
Offline
Зарегистрирован: 26.01.2018

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

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

Хочу понять как использовать в коде бинарные данные. Например, для управления DFPlayer-ом. Как управлять помощью обычных функций (mp3_play;) в сети примеров масса и проблем нет. А вот как с serial командами, ни одной статьи не могу найти.

Что посоветуете почитать?

 

 

 

 

 

 

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

variator пишет:

Что посоветуете почитать?

Документацию к Arduino, в частности, Serial.write пишет в UART данные в виде байт.

variator
Offline
Зарегистрирован: 26.01.2018

Спасибо! C практикой сложновато.
В даташите к плееру есть табличка:
0x01   Play next
0x02   Play previous
и т.д.

Во второй табличке пример:
7E FF 06 3D 00 00 01 xx xx EF. 

Как с первой таблички перейти во вторую - об этом инфы негде не встречал.
 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

variator пишет:

Спасибо! C практикой сложновато.
В даташите к плееру есть табличка:
0x01   Play next
0x02   Play previous
и т.д.

Во второй табличке пример:
7E FF 06 3D 00 00 01 xx xx EF. 

Как с первой таблички перейти во вторую - об этом инфы негде не встречал.
 

В даташите к командам плеера, ВНЕЗАПНО, описан формат пакета, который надо отсылать. Собирайте пакет ручками - и отсылайте, это не проблема. Собственно, библиотека так и делает - можете посмотреть, как там реализовано.

variator
Offline
Зарегистрирован: 26.01.2018

Так на английском написано. Понятно что можно перевести, дойти интуитивно.
Просто странно, что негде об этом внятно не рассказано. Инфы то на абзац будет. Скольким бы новичкам время сэкономило. 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

variator пишет:

Так на английском написано. Понятно что можно перевести, дойти интуитивно.
Просто странно, что негде об этом внятно не рассказано. Инфы то на абзац будет. Скольким бы новичкам время сэкономило. 

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

variator
Offline
Зарегистрирован: 26.01.2018

Не для спора но скажу. Сам не электронщик, занимаюсь по необходимости, (профессия связана со звуком). Заметил, что в электронной среде весьма распространено кокетничание своими знаниями. Вместо ответа - какие-то абстрактные суждения с нравоучительным подтекстом. Это отличный способ самоутверждения но с небольшой червоточинкой. Дело в том, что подлинное самоутверждение возможно лишь в случае творческой работы: например, написать код более изящно и лаконично чем другие. А здесь всего лишь обознанность с некими алгоритмами и схемами, которые по сути знанием и не являются. До этого преимущественно бывал на профильных форумах и сравнив с элетронными замечу - контрастность разительная. На вопрос по звуке, какой бы он дурацкий не был, я бы уже давно получил ответ, а здесь на нескольких сайтах одно и то же. Вероятно, это связано с тем, что в музыке техника вторична, и никто не заморачивается с хранением в неприкосновенности своих "знаний". А здесь же получается порочный круг. К примеру, задумай я стать элеткронщиком и пройдя сходный "путь обретения знаний" я бы сам так же ревниво обращался к новоприбывшим. Ни в коей не хочу обобщать всех завсегдатаев данного ресурса. На нем есть реально знающие люди (например автор, который этюды) пишет. Но а вы, ребята, не самоутвержайесь таким вот низким методом. Лучше не отвечайте, если вам нечего сказать. Без обид.

sadman41
Offline
Зарегистрирован: 19.10.2016

Возможно, что вы по звуку задаете вопросы правильно, а не "как вместо ля сыграть си"?

sadman41
Offline
Зарегистрирован: 19.10.2016

variator пишет:

Как с первой таблички перейти во вторую - об этом инфы негде не встречал.

Вот, я вам за пяток минут нашёл: http://www.trainelectronics.com/Arduino/MP3Sound/TalkingTemperature/FN-M16P%20Embedded%20MP3%20Audio%20Module%20Datasheet.pdf

3.4. Examples of Sending Serial Commands

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

variator, сколько нот нужно знать чтобы написать симфонию?

И, самое главное - какие? (опубликуйте список необходимых)

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

variator пишет:

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

Каким низким-то? Совет почитать даташит, где всё как раз описано нормальным человеческим английским языком - теперь низкий метод? Али ты хочешь, чтобы тебе оттуда выдернули, что тебе нужно, перевели, прожевали, и за тебя ещё и проглотили? Некисло, чо.

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

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