Вообще, если я правильно понял, то String тормозит контроллер, возможно что большое количество обработки, не дает ему нормально работать. Ну это я предполагаю всеголишь.
Со стрингами вы намутили, конечно. Попробую вам подмогнуть.
Какой у вас формат ответа устройства? Как определяется конец пакета, какие разделители строк?
Сделайте вывод с Serial.print("'"); Serial.print((char) inChar); Serial.print("' => 0x "); Serial.println((byte) inChar, HEX) для всего входящего пакета и спрячьте под коврик (как сворачивающийся код)
Т.е. я правильно понимаю, что нужно выдрать числа в ET0PE() и, в зависимости от того, каким пришел этот параметр, рассматривать его, как вольты, амперы или киловатты (например) ? Т.е. они всегда приходят в одном и том же порядке?
<STX>данные<ETX><BCC>, где данные – значения запрашиваемых параметров в формате группового чтения.
Значения параметра выдаются в скобках после имени параметра. Однотипные поля значения разделяются запятой или имеют «жесткий» формат, разнотипные – выдаются без разделителей.
Да там оптимизировать надо примерно так: поймали 0x02 - начинаем читать до появления скобки, скобку задетектили - начинаем писать в буфер до появления закрывающей скобки. Скобку заловили - буфер затерминировали нулем и скормили его atof(), результат записали в массив значений. CRLF попалось - позицию в массиве значений заинкрементировали. 0x03 выловили - конец работы.
а для чего контрольную сумму считатть? для проверки полученных данных?
Типа того. Решать - доверять полученным данным или нет. Вдруг вы по итогам считывания будете обесточивать дом.
Вот такой код я накидал. Особо не старался, конечно, но суть, надеюсь, передал. К RS485.read() прикрутите, думаю.
char serialBuffer[] = "\x02""ET0PE(21289.6077754)\x0D\x0A""ET0PE(13880.1965646)\x0D\x0A""ET0PE(4313.440324)\x0D\x0A""ET0PE(3095.9708868)\x0D\x0A""ET0PE(123.456)\x0D\x0A""ET0PE(0.0)\x0D\x0A\x03\x39";
float values[10];
char strBuffer[20];
uint8_t valueIdx = 0, strBufferPos = 0, incomingCharPos = 0, packetProcessing = false, catchedCR = false;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Let's begin \n");
}
void loop() {
// it like if (RS485.available() > 0)
if (incomingCharPos < sizeof(serialBuffer)) {
char inChar = serialBuffer[incomingCharPos];
//Serial.print("'"); Serial.print((char) inChar); Serial.print("' => 0x"); Serial.println((byte) inChar);
incomingCharPos++;
switch (inChar) {
// STX
case 0x02:
// put floats to value array from item #0
valueIdx = 0;
// packet processing is started
packetProcessing = true;
break;
// ETX
case 0x03:
// packet processing is finished
packetProcessing = false;
// show all floats
for (uint8_t i = 0; i < valueIdx; i++) {
Serial.print("Value["); Serial.print(i); Serial.print("]="); Serial.println(values[i]);
}
break;
// CR
case 0x0D:
catchedCR = true;
break;
// LF followed by CR
case 0x0A:
if (packetProcessing && catchedCR) {
catchedCR = false;
// next float will be written to next array item
valueIdx++;
}
break;
// Start the value
case '(':
if (packetProcessing) {
// write string-representation of float to the temporary buffer
strBufferPos = 0;
}
break;
// End the value
case ')':
if (packetProcessing) {
// terminate string-representation of float and convert it to real float number, which will be stored to the array
strBuffer[strBufferPos] = 0x00;
Serial.print("strBuffer: "); Serial.println(strBuffer);
values[valueIdx] = atof(strBuffer);
}
break;
// all other symbols
default:
if (!packetProcessing) {
break;
}
// all chars recieved between ( and ) will be written to the temporary buffer while its end not reached
strBuffer[strBufferPos] = inChar;
if (strBufferPos < sizeof(strBuffer)) {
strBufferPos++;
}
}
}
}
к слову сказать, пока я въезжаю в ваш код (отдельное спасибо за него Вам), решил проверить свой код со стрингами на ардуино мега, работает,считывает все параметры сразу..получается нано не справляется со стрингами в таком количестве?
Такие штуки удобней писать по-человечески, через char req[] = "..." - там же вроде как в запросе слова обычные. То, что буквы - пишете буквами, то, что не буквы - через \xHH, где HH - hex-код. У меня во фрагменте кода входящий пакет так имитирован.
вот так у меня выглядят параметры в блютуз мониторе. но это смоим кодом с кучей стрингов, на меге заработал сразу, но при внедрении в код умного дома пришлось еще потанцевать..
как разберусь с нормальным кодом, перейду на него..
можно считать что в общем то задача решена, долго я искал инфу в интернете
я передаю в OPC-сервер, и почему-то данные перестают обновлятся, счетчик видно что опрашивается, индикация на нем горит, а данные в OPC не обновляются, если рестартануть контроллер, то все норм, думал, что проблема в обработке строк, проверим
На форумах энергомеры что-то про паузы между опросами писали.
А писать в 7E1 можно посимвольно, конвертируя перед write(). Впрочем, вам виднее, как правильней - у меня счетчик просто моргает лампочкой, интерфейсов не имеет, поэтому данный вопрос неактуален.
Доброго всем дня. Подскажите, со счетчиком никаких манипуляций предварительно делать не нужно? Имею СЕ301, пытаюсь соединиться с ним уже несколько дней - безуспешно. Счетчик не отвечает ни на что. Пробовал и конвертером USB-RS485 на FTDI и самодельным шилдом для ардуины - тишина. Скорость в счетчике проверял - 9600, порт ардуины настроил на 7N1 - в терминалках проверено, все в норме, напряжение на интерфейсный модуль счетчика 13 В (Не много ли? Может он умер уже?) и никакой реакции. Осциллом наблюдаю сигнал на контактах А и В счетчика - все четко и красиво. В чем же дело?
Код пробовал. Реакции нет. До AdminTools еще правда не добрался, но пробовал OPC сервер от компании InSat - тоже безрезультатно. Сервер посылает запрос на открытие сессии и вываливается с таймаутом, т.к. ответа нет. Т.е. со счетчиком ничего делать не нужно??? Отвечать должен сразу, без манипуляций с настройками кнопками на морде?
Сомневался насчет того, что правильно будет управаляться микруха SP485, но FTDI справляется с этим без проблем. Т.е. включение передачи/приема осуществляется адекватно. Плюс пробовал свой шилд совместно с ардуиной, подключал все это дело к промышленному конвертеру rs485 - rs232 и на ПК в терминалке наблюдал правильные посылки с ардуины... Т.е. за канал RS485 я уверен, по долгу службы приходится с ним часто работать... Но счетчик молчит. (((
Настораживает малый ток потребления интерфейсным модулем счетчика. В доках указано, что источник должен отдавать ток до 100 мА, а у меня даже и 5 мА не потребляет. Может он накрылся от 13-14 вольт?
Я конечно попробую чуть позже, но думаю, что результат будет отрицательным, так как OPC сервер, что я пробовал, в своих запросах полностью копирует запросы AdminTools. Спасибо за ответы.
Вообще, если я правильно понял, то String тормозит контроллер, возможно что большое количество обработки, не дает ему нормально работать. Ну это я предполагаю всеголишь.
Со стрингами вы намутили, конечно. Попробую вам подмогнуть.
Какой у вас формат ответа устройства? Как определяется конец пакета, какие разделители строк?
Сделайте вывод с Serial.print("'"); Serial.print((char) inChar); Serial.print("' => 0x "); Serial.println((byte) inChar, HEX) для всего входящего пакета и спрячьте под коврик (как сворачивающийся код)
запрос на снятие показаний электроэнергии в ASCII выглядит так:
/EKT5CE301v7
P0(777777) ET0PE(21289.6077754)
ET0PE(13880.1965646)
ET0PE(4313.440324)
ET0PE(3095.9708868)
ET0PE(0.0)
ET0PE(0.0)
9
в HEX :
Эх... просил же со стрелочкой... Символ => код символа. Я же не компутер, чтобы прям в ASCII-кодах читать.
Но я вот вижу, что есть 0x0D 0x0A - это CRLF. А вот это 0x03, 0x02 - они постоянно лезут? Пакет всегда заканчивается одинаково?
извиняюсь
все что есть в порту
0x03, 0x02 - вроде как постоянно
а на счет заканчивается точно не знаю, возможно это <BCC>
сейчас посмотрю в протоколе
можно сократить ответ, если использовать другой режим чтения
он же только полностью
он же в ASCII полностью
ET0PE(21289.6077754)
ET0PE(13880.1965646)
ET0PE(4313.440324)
ET0PE(3095.9708868)
ET0PE(0.0)
ET0PE(0.0)
9
Т.е. я правильно понимаю, что нужно выдрать числа в ET0PE() и, в зависимости от того, каким пришел этот параметр, рассматривать его, как вольты, амперы или киловатты (например) ? Т.е. они всегда приходят в одном и том же порядке?
вот так выглядит ответ о напряжении:
VOLTA(235.158)
VOLTA(0.516)
VOLTA(0.096)
*
а вот так о мощности
POWPP(0.0)
POWPP(0.0)
POWPP(0.0)
'
ну к примеру мне нужно вытащить только то что находится в первых скобках после ETOPE, все остальное мне не нужно
Какую-то хе...ту придумали в этой энергомере.
--------------------
5.1.3.2 Формат ответа:
<STX>данные<ETX><BCC>, где данные – значения запрашиваемых параметров в формате группового чтения.
Значения параметра выдаются в скобках после имени параметра. Однотипные поля значения разделяются запятой или имеют «жесткий» формат, разнотипные – выдаются без разделителей.
Например: 0001(значение1)0020(значение1)201A(значение1)(значение2)(значение3)(значение4).
Сообщения об ошибках выдаются вместо значения параметра в формате Enn, где nn – номер ошибки. Например: 0005(E12).
-----------
Но я же вижу, что там CRLF летит. Что имеется в виду под 0001, 201A?..
это груповой опрос наверное вы смотрели?
а то что я кидал в предыдущем посте, это режим быстрого чтения
Да я вообще пытался понять по какому принципу у них пакет построен и что надо ловить, чтобы понять - принят он или нет.
Вобщем, сообразил примерно. Завтра что-нить накидаю.
а если использовать опрос в режиме програмирования
как в посте №103, то такие кодом
то я вынимаю, то что в скобках.
но может как-то оптимизировать.
спасибо, будем ждать
Да там оптимизировать надо примерно так: поймали 0x02 - начинаем читать до появления скобки, скобку задетектили - начинаем писать в буфер до появления закрывающей скобки. Скобку заловили - буфер затерминировали нулем и скормили его atof(), результат записали в массив значений. CRLF попалось - позицию в массиве значений заинкрементировали. 0x03 выловили - конец работы.
Параллельно можно контрольную сумму считать.
а для чего контрольную сумму считатть?
для проверки полученных данных?
Типа того. Решать - доверять полученным данным или нет. Вдруг вы по итогам считывания будете обесточивать дом.
Вот такой код я накидал. Особо не старался, конечно, но суть, надеюсь, передал. К RS485.read() прикрутите, думаю.
к слову сказать, пока я въезжаю в ваш код (отдельное спасибо за него Вам), решил проверить свой код со стрингами на ардуино мега, работает,считывает все параметры сразу..получается нано не справляется со стрингами в таком количестве?
Мошт, потому что у наны памяти в 4 раза меньше?
спасибо, работает
осталось в нем разобраться полностью)
спасибо, работает
осталось в нем разобраться полностью)
разобраться эт да
вы со счетчиком проверили уже?
ага, работает
проверял через быстрый запрос
{0xaf,0x3f,0x21,0x81,0xd2,0xb1,0x82,0xc5,0xd4,0x30,0x50,0xc5,0x28,0xa9,0x03,0xb7};
Такие штуки удобней писать по-человечески, через char req[] = "..." - там же вроде как в запросе слова обычные. То, что буквы - пишете буквами, то, что не буквы - через \xHH, где HH - hex-код. У меня во фрагменте кода входящий пакет так имитирован.
как разберусь с нормальным кодом, перейду на него..
можно считать что в общем то задача решена, долго я искал инфу в интернете
проблема в том, что счетчик работает в формате 7e1 а порт ардуино в 8n1
и поэтому приходится считать бит четности в ручную, в оригинале запрос выглядит примерно так:
2f 3f 21 01 52 31 02 45 54 30 50 45 28 29 03 37
я передаю в OPC-сервер, и почему-то данные перестают обновлятся, счетчик видно что опрашивается, индикация на нем горит, а данные в OPC не обновляются, если рестартануть контроллер, то все норм, думал, что проблема в обработке строк, проверим
На форумах энергомеры что-то про паузы между опросами писали.
А писать в 7E1 можно посимвольно, конвертируя перед write(). Впрочем, вам виднее, как правильней - у меня счетчик просто моргает лампочкой, интерфейсов не имеет, поэтому данный вопрос неактуален.
оно то может и можно, просто я не так хорошо разбираюсь в данном вопросе, новичок вообщем-то говоря.
Вот изучаю.
char response = RS485.read();
response &= 0x7F;// convert 8N1 to 7E1
примерно так же организовать запить с конвертированием?
Ну, как-то так: for (i=0; i < sizeof(байтовый_массив); i++) { RS485.write(байтовый_массив[i] & ...); }
Впрочем, согласен - способ спорный. Хранить данные в подготовленном виде или конвертить на лету - это уже вопрос эстетических пристрастий.
ну да, преобразовать в ручную не долго, да и код выглядит проще.
Доброго всем дня. Подскажите, со счетчиком никаких манипуляций предварительно делать не нужно? Имею СЕ301, пытаюсь соединиться с ним уже несколько дней - безуспешно. Счетчик не отвечает ни на что. Пробовал и конвертером USB-RS485 на FTDI и самодельным шилдом для ардуины - тишина. Скорость в счетчике проверял - 9600, порт ардуины настроил на 7N1 - в терминалках проверено, все в норме, напряжение на интерфейсный модуль счетчика 13 В (Не много ли? Может он умер уже?) и никакой реакции. Осциллом наблюдаю сигнал на контактах А и В счетчика - все четко и красиво. В чем же дело?
попробуйте этот код
Код пробовал. Реакции нет. До AdminTools еще правда не добрался, но пробовал OPC сервер от компании InSat - тоже безрезультатно. Сервер посылает запрос на открытие сессии и вываливается с таймаутом, т.к. ответа нет. Т.е. со счетчиком ничего делать не нужно??? Отвечать должен сразу, без манипуляций с настройками кнопками на морде?
да, ничего не нужно настраивать.
а конвертер rs485- ttl используете?
если в теримналке все работает, то и тут должно
USB-RS485, вот такой https://nazya.com/freeshipping/product/usb-20-dlya-ttl-rs485-posledovatelnij-konverter-adapter-ftdi-ft232rl-sn75176-dvojnuyu-funktsiyu-dvojnoj-zaschiti-kabel-usb_583268610.html
мне кажется, что через него не будет работать, но это не точно
если есть возможность попробуйте такой
https://www.google.com/search?q=rs485+ttl&tbm=isch&source=iu&ictx=1&fir=...
по крайней мере тот код не будет работать с этим конвертером
Сомневался насчет того, что правильно будет управаляться микруха SP485, но FTDI справляется с этим без проблем. Т.е. включение передачи/приема осуществляется адекватно. Плюс пробовал свой шилд совместно с ардуиной, подключал все это дело к промышленному конвертеру rs485 - rs232 и на ПК в терминалке наблюдал правильные посылки с ардуины... Т.е. за канал RS485 я уверен, по долгу службы приходится с ним часто работать... Но счетчик молчит. (((
Настораживает малый ток потребления интерфейсным модулем счетчика. В доках указано, что источник должен отдавать ток до 100 мА, а у меня даже и 5 мА не потребляет. Может он накрылся от 13-14 вольт?
не знаю может накрыться или нет. А через AdminTools попробуйте
Я конечно попробую чуть позже, но думаю, что результат будет отрицательным, так как OPC сервер, что я пробовал, в своих запросах полностью копирует запросы AdminTools. Спасибо за ответы.
А Вы от чего запитывали интерфейс счетчика?
А Вы от чего запитывали интерфейс счетчика?
а какой сигнал вы наблюдаете осциллом на счетчике?
лично у меня счетчик СЕ 102М, там запитывать ничего не надо..
все таки попробуйте с Admin tools, главное настройки правильные сделать
12в 1а бп
а какой сигнал вы наблюдаете осциллом на счетчике?
Ну красивый дифференциальный сигнал RS485, соответствующий посылкам с ардуины (или с конвертера USB-RS485).
А может ли кто либо поделиться быстрыми командами для чтения напряжения и тока?
А кто-нибудь отправлял данные со счётчика "энергомера 301" на сервер по GPRS?
да
А есть для примера, какие параметры, и какой интервал опроса счётчика. Можно код глянуть?