однажды устанавливая связь с блоком управления двигаталем. Связи небыло из-за того, что при отправке сообщений на блок байты летели один за другим сразу. А блоку нужна была задержка в 1 мс между байтами. Может есть различия в таймингах при отправке байт на софт и хард, поэтому на одном работает, на другом нет. Так же на хард на Тх Rx должны стоять резисторы около 1кОм, может они влияют
так работать не будет. У вас в коде сплошные несуразицы...
Смотрите: Начать с того, что у вас в response один единственный символ. То есть никаких чисел с числом цифр больше одной вы из него в принципе не получите. Но вы еще и обрабатываете его неверно. Сначала переводите в строку, потом зачем-то обратно в char. и потом в число функцией atof(). При этом совершенно не заботитесь о том, что для этой функции строка должна кончаться на терминатор '\0'. В лучшем случае вы так сможете получить, например, первый символ "8" из числа 8823.33 - но чаще вообще ничего не получите.
Вам надо сначала собрать полную строку из отдельных символов. Потом добавить в конце терминатор. Потом в этой строке найти, где начинается число. И только потом извлекать числа функцией atof().
Но это потом. Для начала стоит потратить некоторое время на изучение основ языка Си. Я бы советовал отложить этот код, найти хороший учебник и прорешать в нем примеры от начала и до конца. Потратите пару месяцев, зато потом этот код напишете за 1 вечер. Вы там выше писали "мой уровень невысок". Простите, но это вы еще себе польстили. Ваш уровень практически нулевой.
по правильному совету b707 я пока отложил этот код, он прав, моих познаний не достаточно чтобы самому справиться с этим, поэтому читаю книжки) к тому же это интересно и давно собирался это сделать..
до этого я изучал программирование только на ардуино, в чем так же опыта у меня не много
попытался разобраться, указал коменты. поправьте если не так
char inChar = response; //переменной inChar присваиваем считанное и конвертированное полученное значение ( один символ)
inString += inChar; //складываем символы в одну строку
if (inString.lastIndexOf('/')>0) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); //присваиваем переменной first значение после скобки (
int second = inString.indexOf('(', first + 1 ); //присваиваем переменной second значение после второй скобки (
second = second + 1; //увеличиваем значение переменной second на единицу
int first_2 = inString.indexOf(')'); //присваиваем переменной first_2 значение после скобки )
int second_2 = inString.indexOf(')', first_2 + 1 ); //присваиваем переменной second_2 значение после второй скобки )
inString2 = inString.substring(second,second_2);//присваиваем inString2 подстроку, second-начальный индекс, second_2-конечный индекс
inString2.toCharArray(x, sizeof(x));// копируем строку в буфер типа char
float f = atof(x); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.print('\n');
inString = ""; //обнуляем строку?
char inChar = response; //переменной inChar присваиваем считанное и конвертированное полученное значение ( один символ)
inString += inChar; //складываем символы в одну строку
if (inString.lastIndexOf('/')>0) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
second = second + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(second,second_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(x, sizeof(x));// копируем строку в буфер типа char
float f = atof(x); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.print('\n');
inString = ""; //обнуляем строку
ваш код работает, сейчас доступа к счетчику нет, тренируюсь отсылкой скопированной строки в монитор порта, сделал код, не работает..
если слать всю строку, или частями в сериал порт получаестя ерунда по этому коду;
#include <SoftwareSerial.h>
long Previous = 0;
int val = 0;
int Time_1 = 1;
int Time_2 = 2;
int Time_3 = 3;
int Time_4 = 4;
int Time_5 = 5;
int Time_6 = 6;
int Time_7 = 7;
int Time_8 = 15;
byte cmd1[] = {0xaF,0x3F,0x21,0x8D,0x0A};// открываем сессию
byte cmd2[] = {0x06,0x30,0x35,0xb1,0x8d,0x0a};// читаем тип счетчика
byte cmd3[] = {0x81,0xd2,0xb1,0x82,0xc5,0xd4,0x30,0x50,0xc5,0x28,0xa9,0x03,0xb7};// снимаем показания
byte cmd4[] = {0x81,0xd2,0xb1,0x82,0x56,0xcf,0xcc,0xd4,0x41,0x28,0xa9,0x03,0x5f};// напряжения на фазах
byte cmd5[] = {0x81,0xd2,0xb1,0x82,0xc3,0x55,0xd2,0xd2,0xc5,0x28,0xa9,0x03,0x5a};// ток на фазах
byte cmd6[] = {0x81,0xd2,0xb1,0x82,0x50,0xcf,0xd7,0xc5,0x50,0x28,0xa9,0x03,0xe4}; //мощность
byte cmd7[] = {0x81,0xd2,0xb1,0x82,0xc6,0xd2,0xc5,0xd1,0x55,0x28,0xa9,0x03,0x5c}; //частота
#define DIR 5 // пин управления прием/передача
SoftwareSerial RS485 (7, 6); // RX, TX
String inString;
String inString2;
char x [50];
char power [50];
char current [50];
char freq [50];
void setup()
{
RS485.begin(9600);
Serial.begin(9600);
pinMode(DIR, OUTPUT);
digitalWrite(DIR, HIGH);
}
void loop()
{
if (Serial.available())
{
char response = Serial.read();
// response &= 0x7F;// convert 8N1 to 7E1
char inChar = response;
inString += inChar;
if (inString.lastIndexOf("ET0PE")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
second = second + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(second,second_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(x, sizeof(x));// копируем строку в буфер типа char
float f = atof(x); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.print('\n');
// inString = ""; //обнуляем строку
}
if (inString.indexOf("VOLTA")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
// int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
first = first + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
// int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(first,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(power, sizeof(power));// копируем строку в буфер типа char
float f = atof(power); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.println("Volt");
// inString = ""; //обнуляем строку
}
if (inString.indexOf("CURRE")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
// int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
first = first + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
// int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(first,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(current, sizeof(current));// копируем строку в буфер типа char
float f = atof(current); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.println("amper");
// inString = ""; //обнуляем строку
}
if (inString.indexOf("pPOWEP")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
// int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
first = first + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
// int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(first,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(power, sizeof(power));// копируем строку в буфер типа char
float f = atof(power); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.println("watt");
// inString = ""; //обнуляем строку
}
if (inString.indexOf("FREQU")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
// int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
first = first + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
// int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(first,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(freq, sizeof(freq));// копируем строку в буфер типа char
float f = atof(freq); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.println("Hz");
inString = ""; //обнуляем строку
}
}}
в этом коде все работает нормально
String inString;
String inString2;
char x [50];
char y [50];
char power [50];
char volt [50];
char current [50];
char freq [50];
void setup() {
Serial.begin(9600);
String inString = "z/EKT5CE102Mv01P0(001)gET0PE(5573.34)(3455.40)(2117.94)(0.00)(0.00)(0.00)";
if (inString.lastIndexOf("ET0PE")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
second = second + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(second,second_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(x, sizeof(x));// копируем строку в буфер типа char
float f = atof(x); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.println("Total");
}
inString = "=VOLTA(220.69)";
if (inString.lastIndexOf("VOLTA")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
// int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
first = first + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
// int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(first,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(volt, sizeof(volt));// копируем строку в буфер типа char
float f = atof(volt); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.println(" Volt");
inString = ""; //обнуляем строку
}
inString = "CURRE(9.472)";
if (inString.lastIndexOf("CURRE")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти в
// int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
first = first + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
// int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(first,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(current, sizeof(current));// копируем строку в буфер типа char
float f = atof(current); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.println("amper");
inString = ""; //обнуляем строку
}
inString = "pPOWEP(1.598953)";
if (inString.lastIndexOf("pPOWEP")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
// int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
first = first + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
// int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(first,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(power, sizeof(power));// копируем строку в буфер типа char
float f = atof(power); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f*1000); //формат float
Serial.println("watt");
inString = ""; //обнуляем строку
}
inString = "FREQU(49.96)x";
if (inString.indexOf("FREQU")>-1) { //если найден символ "/" с конца строки
int first = inString.indexOf('('); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
// int second = inString.indexOf('(', first + 1 ); //находим вторую по порядку скобку "(" в строке, с нее начинаются данные
first = first + 1; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = inString.indexOf(')'); //находим первую скобку ")" сохраняем в int
// int second_2 = inString.indexOf(')', first_2 + 1 ); //находим вторую скобку ")" на ней кончаются данные
inString2 = inString.substring(first,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(freq, sizeof(freq));// копируем строку в буфер типа char
float f = atof(freq); //извлекаем из буфера переменную типа float
Serial.print(inString2); //формат string
Serial.print("------>");
Serial.print(f); //формат float
Serial.println("Hz");
inString = ""; //обнуляем строку
}
}
void loop() {
}
Зачем? Если я шлю данные через монитор порта, а не от счётчика получаю. И это тоже не помогало. Ещё сделал скетч, где просто приём данных и собирание в строку и печать строки, так вот, несколько символов с начала строки пропадает, в собранной строки их нет. Т.е. Если в строку закинуть данные, все норм, какая-то проблема у меня с собирание строки
if(Serial.available()) //если модуль что-то послал
{
char ch = ' ';
String val = "";
while(Serial.available()){
ch = Serial.read();
val += char(ch); //собираем принятые символы в строку
delay(3);}
Serial.print("Sim send> "); Serial.println(val); //печатаем собранную строку
использовал этот код, для того чтобы потестировать как собирается строка. шлю разное кол-во символов, строка собирается не сразу, начало строки терятеся в итоге..
сейчас переделываю код вот на такой вариант, чтобы не от скобок шел поиск, а от фразы, которая соответствует каждому параметру. но еще вопрос, буфер порта имеет размер в 64 байта, если отправить все символы что выдает счетчик, часть не влезает
int first = inString.indexOf("VOLTA"); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
int first1 = first + 6; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = first+13;
inString2 = inString.substring(first1,first_2);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(volt, sizeof(volt));// копируем строку в буфер типа char
float f = atof(volt); //извлекаем из буфера переменную типа float
Serial.print("Volt=");
Serial.println(f); //формат float
int first3 = inString.indexOf("CURRE"); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
int first4 = first3 + 6; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_3 = first3+13;
inString2 = inString.substring(first4,first_3);//присваиваем inString2 подстроку, вытаскиваем строку между этимизначениями
inString2.toCharArray(current, sizeof(current));// копируем строку в буфер типа char
float cu = atof(current); //извлекаем из буфера переменную типа float
Serial.print("amper");
Serial.println(cu); //формат float
inString = ""; //обнуляем строку
т.е. с разбором строки все в порядке, главное правильно посчитать символы. проблема в собирании строки целиком. завтра буду рядом со счетчиком, займусь плотнее этим вопросом
если я вас правильно понял, то если вы будете так собирать
int first = inString.indexOf("VOLTA"); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
int first1 = first + 6; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = first+13;
inString2 = inString.substring(first1,first_2);//присваиваем inString2
то если число в скобках станет больше 7-ми значного, то у вас будет не то, что вы ожидаете
у меня в этих скоках 21288.2567602 вот такое число
на коментарии на обращайте внимания, я их не менял..
речь идет об этом. описание
Serial.available()
Функция получает количество байт(символов) доступных для чтения из последовательного интерфейса связи. Это те байты которые уже поступили и записаны в буфер последовательного порта. Буфер может хранить до 64 байт.
следовательно, я шлю в монитор порта ( счетчика сейчас нет под рукой) то, что прилетает от счетчика, скопированное когда был рядом у счетчика, и разбираю эти символы. если отправить целиком, часть в конце теряется, потому что уже не влезает в буфер порта
счетчик шлет посимвольно, с задержками между строк-правильно?
думаю все таки лучше рассматривать разбор всей строки целиком. например если код большой и где то задержки, то в буфере уже будет вся строка, если я правильно понимаю, если она туда не влезет, что то потеряется. если построчно, то надо работать отдельно с каждой строкой информации, определять новую строку, например по символу возврата каретки..
еще есть мониторинг АКБ на базе монитора батарей BMV-700 от виктрон, у него свой фирменный протокол, пример его считывания нашел на зарубежных форумах, там вроде как все работает
я выбрал символ "/" как знак конца строки. на этом символе у меня заканчивается формирование строки.
когда будете опрашивать счетчик, могут возникнуть проблемы, так как у вас я не увидел индикатора конца в коде, и ардуино не поймет когда заканчивать формирование строки.
строка формируется так
E
ET
ETO
ETOP
ETOPE
ETOPE(
и так далее
до знака / (у меня)
после этого знака у меня заканчивается формирование строки и я начинаю ее разбор
а что у вас выступает в роли верхнего уровня, для приема данных?
и опять же мне кажется с этими запросами могут быть пролемы
int first = inString.indexOf("VOLTA"); // находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую
int first1 = first + 6; //пришлось добавить +1 т.к. захватывало с собой скобку
int first_2 = first+13;
inString2 = inString.substring(first1,first_2);//присваиваем inString2
у меня задумка такая, от счетчика идет строка, как только в ней появилось что то нужное, я начинаю разбор, а после разбора обнуляю строку, но видимо нужное не появится у меня, т.к. как только сработал if с каким то параметром, данные в строку еще на набрались, а я ее обнуляю
но если в цикле собирания строки вместо if использовать while? счетчик отправил строку, если там появилось что то нужное, разобрали, если нет, ждем следующую строку символов, ее разобрали, обнулили. но в моем случае могут возникать накладки, если к примеру в порт будет продолжать что то валиться и мы потом сразу две строки обнулим..
так что ваш метод надежнее, я его не разобрал изначально, не допонял сути символа /
если собрать правильно строку и потом правильно ее обнулить, то какие могут быть проблемы с такими запросами типа VOLTA? если ориентироваться на скобки, например, их слишком много
в общем да, об этом тоже думал, и вроде как проблемы возникают только когда ток 10А и больше, остальное кол-во цифр вроде как не изменно..
в таком случае добавить еще одно условие на поиск скобки после VOLTA
вообще из описания функции atof я полагал что для нее в строке могут быть не только числа, а и другие символы, она же вытаскивает из нее только числа, а на деле функция не работает, даже если одна скобка попала в данные
#include <SoftwareSerial.h>
#define DIR 8 // пин управления прием/передача
SoftwareSerial RS485 (7, 6); // RX, TX
long Previous = 0;
int val = 0;
int Time_1 = 1;
int Time_2 = 2;
int Time_3 = 3;
int Time_4 = 4;
int Time_5 = 5;
int Time_6 = 6;
int Time_7 = 7;
int Time_8 = 15;
byte cmd1[] = {0xaF,0x3F,0x21,0x8D,0x0A};// открываем сессию
byte cmd2[] = {0x06,0x30,0x35,0xb1,0x8d,0x0a};// читаем тип счетчика
byte cmd3[] = {0x81,0xd2,0xb1,0x82,0xc5,0xd4,0x30,0x50,0xc5,0x28,0xa9,0x03,0xb7};// снимаем показания
byte cmd4[] = {0x81,0xd2,0xb1,0x82,0x56,0xcf,0xcc,0xd4,0x41,0x28,0xa9,0x03,0x5f};// напряжения на фазах
byte cmd5[] = {0x81,0xd2,0xb1,0x82,0xc3,0x55,0xd2,0xd2,0xc5,0x28,0xa9,0x03,0x5a};// ток на фазах
byte cmd6[] = {0x81,0xd2,0xb1,0x82,0x50,0xcf,0xd7,0xc5,0x50,0x28,0xa9,0x03,0xe4}; //мощность
byte cmd7[] = {0x81,0xd2,0xb1,0x82,0xc6,0xd2,0xc5,0xd1,0x55,0x28,0xa9,0x03,0x5c}; //частота
String inString;
void setup()
{
Serial.begin(9600);
RS485.begin(9600);
pinMode(DIR, OUTPUT);
digitalWrite(DIR, HIGH);
}
void loop()
{
if (RS485.available())
{
char response = RS485.read();
response &= 0x7F;// convert 8N1 to 7E1
// Serial.print(response);
char inChar = response;
inString += inChar;
if (inString.lastIndexOf('/')>0) {
/* uint8_t TOTALfirst = inString.indexOf('(');
uint8_t TOTALsecond = inString.indexOf('(', TOTALfirst + 1 );
TOTALsecond = TOTALsecond + 1;
uint8_t TOTALfirst_2 = inString.indexOf(')');
uint8_t TOTALsecond_2 = inString.indexOf(')', TOTALfirst_2 + 1 );
String TOTALinString2 = inString.substring(TOTALsecond,TOTALsecond_2);
char TOTAL [50];
TOTALinString2.toCharArray(TOTAL, sizeof(TOTAL));
float f = atof(TOTAL);
Serial.print(f); //формат float
Serial.println("=TOTAL");
uint8_t T1first = inString.indexOf('(', TOTALsecond + 1 );
T1first=T1first+1;
uint8_t T1first_2 = inString.indexOf(')', TOTALsecond_2 + 1 );
String T1inString2 = inString.substring(T1first,T1first_2);
char T1 [50];
T1inString2.toCharArray(T1, sizeof(T1));
float t1 = atof(T1);
Serial.print(t1); //формат float
Serial.println("=T1");
float t2 =f-t1;
Serial.print(t2); //формат float
Serial.println("=T2");
*/
uint8_t VOLTAfirst = inString.indexOf("VOLTA");
VOLTAfirst=VOLTAfirst+6;
uint8_t VOLTAfirst_2=VOLTAfirst+6;
String VOLTAinString2 = inString.substring(VOLTAfirst,VOLTAfirst_2);
char VOLTA [50];
VOLTAinString2.toCharArray(VOLTA, sizeof(VOLTA));
float V = atof(VOLTA);
Serial.print(V); //формат float
Serial.println("=V");
/* uint8_t CURREfirst = inString.indexOf("CURRE");
CURREfirst=CURREfirst+6;
uint8_t CURREfirst_2=CURREfirst+5;
String CURREinString2 = inString.substring(CURREfirst,CURREfirst_2);
char CURRE [50];
CURREinString2.toCharArray(CURRE, sizeof(CURRE));
float I = atof(CURRE);
Serial.print(I); //формат float
Serial.println("=I");
*/
/* uint8_t POWERfirst = inString.indexOf("POWEP");
POWERfirst=POWERfirst+6;
uint8_t POWERfirst_2=POWERfirst+8;
String POWERinString2 = inString.substring(POWERfirst,POWERfirst_2);
char POWER [50];
POWERinString2.toCharArray(POWER, sizeof(POWER));
float W = atof(POWER);
Serial.print(W*1000); //формат float
Serial.println("=Wt");
*/
uint8_t FREQfirst = inString.indexOf("FREQU");
FREQfirst=FREQfirst+6;
uint8_t FREQfirst_2=FREQfirst+8;
String FREQinString2 = inString.substring(FREQfirst,FREQfirst_2);
char FREQ [50];
FREQinString2.toCharArray(FREQ, sizeof(FREQ));
float F = atof(FREQ);
Serial.print(F); //формат float
Serial.println("=Hz");
Serial.print("inString=");
Serial.println(inString); //формат float
inString = "";
}
}
if (millis() - Previous > 1000)
{
Previous = millis();
val ++;
if (val == Time_1)
{
digitalWrite(DIR, HIGH);
RS485.write (cmd1,5);
digitalWrite(DIR, LOW);
}
if (val == Time_2)
{
digitalWrite(DIR, HIGH);
RS485.write (cmd2,6);
digitalWrite(DIR, LOW);
}
if (val == Time_3)
{
digitalWrite(DIR, HIGH);
RS485.write (cmd3,13);
digitalWrite(DIR, LOW);
}
if (val == Time_4)
{
digitalWrite(DIR, HIGH);
RS485.write (cmd4,13);
digitalWrite(DIR, LOW);
}
if (val == Time_5)
{
digitalWrite(DIR, HIGH);
RS485.write (cmd5,13);
digitalWrite(DIR, LOW);
}
if (val == Time_6)
{
digitalWrite(DIR, HIGH);
RS485.write (cmd6,13);
digitalWrite(DIR, LOW);
}
if (val == Time_7)
{
digitalWrite(DIR, HIGH);
RS485.write (cmd7,13);
digitalWrite(DIR, LOW);
}
if (val == Time_8)
{ val = 0;}
}
}
все работает, но, только если закомментировать часть из параметров, вместе работает не более двух параметров, в любом сочетании.
для тестов использую ардуино нано. может его ресурсов недостаточно? но с двумя параметрами
Скетч использует 8 258 байт (57%) памяти устройства. Всего доступно 14 336 байт.
Глобальные переменные используют 489 байт (47%) динамической памяти, оставляя 535 байт для локальных переменных. Максимум: 1 024 байт.
по замечаниям в постах №91,94 пока проблем в работе не обнаружил. Если я правильно понимаю, я в худшем случае потеряю последнюю цифру после запятой, мне это не критично, точности предостаточно
пост №80 у меня почему то не заработал
вы на каком ардуино тестируете? есть возможность попробовать все параметры сразу на чем то большем, чем нано?
да, пробовал и на 3 и на 1, на 1 исправно работает GSM шилд
пробовал и в формате 7E1, тоже тишина
фидимо надо смотреть всетаки на софт сериал и способы вытаскивания переменной. и хард сериал не занимает в итоге
однажды устанавливая связь с блоком управления двигаталем. Связи небыло из-за того, что при отправке сообщений на блок байты летели один за другим сразу. А блоку нужна была задержка в 1 мс между байтами. Может есть различия в таймингах при отправке байт на софт и хард, поэтому на одном работает, на другом нет. Так же на хард на Тх Rx должны стоять резисторы около 1кОм, может они влияют
проверьте харды, подключив их друг на друга и выводите инфу в монитор порта.
может быть, но времени лишнего гадать нет)
нужно возвращаться к переменным
кстати когда тестировал нано и USB-TTL, RS-485 повесил на Тх и Rx ардуино, на мониторе ардуино были данные, на USB и терминальной проге нет
харды рабочие, первый и второй точно
надо было убрать при этом RS485 и напрямую Tx и Rx
короче надо убедиться до RS485, что с харда данные вылетают. Если да, то копать дальше. Может всё таки в коде где нибудь ошиблись.
так, что я сейчас сделал:
подключил RS-485 k Rx Tx ардуино нано, в мониторе порта кракозябры (такие же если выводить данные с соф сериал и без конвертации)
запускал нард сериал на 7Е1, все тоже самое
соедините мегу и нану без rs485 добейтесь правильных байтов
и еще, монитор порта IDE показывает только в ASCII, а у вас просто байты , надеюсь вы про это в курсе
я вернулся к исходному коду, все данные отображаются вот так:
ищу путь как вытащить цифры в переменные
вообще уровень моих познаний крайне не высок
вот такие мысли есть:
char response нужно сделать строкой
а потом функцией atof вытащить числа
http://bigbarrel.ru/%D0%BA%D0%BE%D0%BD%D0%B2%D0%B5%D1%80%D1%82%D0%B0%D1%...
я вроде кидал, не знаю смотрели или нет, может поможет в преобразовании
да, смотрел, исходя из этого сделал вот так
да, смотрел, исходя из этого сделал вот так
так работать не будет. У вас в коде сплошные несуразицы...
Смотрите: Начать с того, что у вас в response один единственный символ. То есть никаких чисел с числом цифр больше одной вы из него в принципе не получите. Но вы еще и обрабатываете его неверно. Сначала переводите в строку, потом зачем-то обратно в char. и потом в число функцией atof(). При этом совершенно не заботитесь о том, что для этой функции строка должна кончаться на терминатор '\0'. В лучшем случае вы так сможете получить, например, первый символ "8" из числа 8823.33 - но чаще вообще ничего не получите.
Вам надо сначала собрать полную строку из отдельных символов. Потом добавить в конце терминатор. Потом в этой строке найти, где начинается число. И только потом извлекать числа функцией atof().
Но это потом. Для начала стоит потратить некоторое время на изучение основ языка Си. Я бы советовал отложить этот код, найти хороший учебник и прорешать в нем примеры от начала и до конца. Потратите пару месяцев, зато потом этот код напишете за 1 вечер. Вы там выше писали "мой уровень невысок". Простите, но это вы еще себе польстили. Ваш уровень практически нулевой.
ну как успехи? получилось?
по правильному совету b707 я пока отложил этот код, он прав, моих познаний не достаточно чтобы самому справиться с этим, поэтому читаю книжки) к тому же это интересно и давно собирался это сделать..
до этого я изучал программирование только на ардуино, в чем так же опыта у меня не много
вас понял, хорошее дело, успехов!
спасибо, как только получится, а я на это надеюсь, выложу код тут, если кто то не опередит меня
у вас работает?
жаль проверить пока не могу
попытался разобраться, указал коменты. поправьте если не так
да, у меня работает
че т я совсем запутался
ваш код работает, сейчас доступа к счетчику нет, тренируюсь отсылкой скопированной строки в монитор порта, сделал код, не работает..
если слать всю строку, или частями в сериал порт получаестя ерунда по этому коду;
// response &= 0x7F;// convert 8N1 to 7E1
047
раскоментируйте строку
Зачем? Если я шлю данные через монитор порта, а не от счётчика получаю. И это тоже не помогало. Ещё сделал скетч, где просто приём данных и собирание в строку и печать строки, так вот, несколько символов с начала строки пропадает, в собранной строки их нет. Т.е. Если в строку закинуть данные, все норм, какая-то проблема у меня с собирание строки
ааа, я думал от счетчика, извиняюсь, я немного занят пока, потом гляну, может помогу чем
удалось найти причину по которой не работало?
использовал этот код, для того чтобы потестировать как собирается строка. шлю разное кол-во символов, строка собирается не сразу, начало строки терятеся в итоге..
сейчас переделываю код вот на такой вариант, чтобы не от скобок шел поиск, а от фразы, которая соответствует каждому параметру. но еще вопрос, буфер порта имеет размер в 64 байта, если отправить все символы что выдает счетчик, часть не влезает
т.е. с разбором строки все в порядке, главное правильно посчитать символы. проблема в собирании строки целиком. завтра буду рядом со счетчиком, займусь плотнее этим вопросом
ненмого сократить можно если использовать быстрое чтение вместо оыбчного способа
то есть мы уберем из строки ответы на первые 2 опроса
не очень много конечно, но все же меньше будет.
если я вас правильно понял, то если вы будете так собирать
то если число в скобках станет больше 7-ми значного, то у вас будет не то, что вы ожидаете
у меня в этих скоках 21288.2567602 вот такое число
т.е. быстрое чтение позволяет получить информацию, отправив только такой запрос? без открытия сессии, что в начальном коде?
я мельком был у счетчика, убрал запрос на модель счетчика, данных вообще не стало..
да, позволяет без открытия сессии
я пробовал, работает
есть еще метод групового чтения, но с ним я пока е знаком
на коментарии на обращайте внимания, я их не менял..
речь идет об этом. описание
Serial.available()
Функция получает количество байт(символов) доступных для чтения из последовательного интерфейса связи. Это те байты которые уже поступили и записаны в буфер последовательного порта. Буфер может хранить до 64 байт.
следовательно, я шлю в монитор порта ( счетчика сейчас нет под рукой) то, что прилетает от счетчика, скопированное когда был рядом у счетчика, и разбираю эти символы. если отправить целиком, часть в конце теряется, потому что уже не влезает в буфер порта
кракозябры такие выходят после копирования
в режиме быстрого чтения этого не будет:
так вы отправляете строку всю целиком?
если так, то счетчик же слать вам будет по частям, поэтому проблем не должно быть
а куда вы потом будете слать всю информацию?
вы кажется говорили, что для умного дом?
да, я отправляю целиком
счетчик шлет посимвольно, с задержками между строк-правильно?
думаю все таки лучше рассматривать разбор всей строки целиком. например если код большой и где то задержки, то в буфере уже будет вся строка, если я правильно понимаю, если она туда не влезет, что то потеряется. если построчно, то надо работать отдельно с каждой строкой информации, определять новую строку, например по символу возврата каретки..
а куда вы потом будете слать всю информацию?
вы кажется говорили, что для умного дом?
да, умный дом..
там уже много всего у меня насобиралось
еще есть мониторинг АКБ на базе монитора батарей BMV-700 от виктрон, у него свой фирменный протокол, пример его считывания нашел на зарубежных форумах, там вроде как все работает
да, посимвольно с задержками.
у меня в коде есть вот такая строка:
if
(inString.lastIndexOf(
'/'
)>0)
я выбрал символ "/" как знак конца строки. на этом символе у меня заканчивается формирование строки.
когда будете опрашивать счетчик, могут возникнуть проблемы, так как у вас я не увидел индикатора конца в коде, и ардуино не поймет когда заканчивать формирование строки.
строка формируется так
E
ET
ETO
ETOP
ETOPE
ETOPE(
и так далее
до знака / (у меня)
после этого знака у меня заканчивается формирование строки и я начинаю ее разбор
а что у вас выступает в роли верхнего уровня, для приема данных?
и опять же мне кажется с этими запросами могут быть пролемы
у меня задумка такая, от счетчика идет строка, как только в ней появилось что то нужное, я начинаю разбор, а после разбора обнуляю строку, но видимо нужное не появится у меня, т.к. как только сработал if с каким то параметром, данные в строку еще на набрались, а я ее обнуляю
но если в цикле собирания строки вместо if использовать while? счетчик отправил строку, если там появилось что то нужное, разобрали, если нет, ждем следующую строку символов, ее разобрали, обнулили. но в моем случае могут возникать накладки, если к примеру в порт будет продолжать что то валиться и мы потом сразу две строки обнулим..
так что ваш метод надежнее, я его не разобрал изначально, не допонял сути символа /
если собрать правильно строку и потом правильно ее обнулить, то какие могут быть проблемы с такими запросами типа VOLTA? если ориентироваться на скобки, например, их слишком много
ну допустим у этой строки
int
first = inString.indexOf(
"VOLTA"
);
int будет = 10(к примеру)
значит:
int
first1 = first + 6;
int
first_2 = first+13;
first1 = 16 а first2 = 23
inString2 = inString.substring(first1,first_2);
вытаскиваем значит 7 значений межуд этими переменными
а если цифр у вас будет больше чем 7?
в общем да, об этом тоже думал, и вроде как проблемы возникают только когда ток 10А и больше, остальное кол-во цифр вроде как не изменно..
в таком случае добавить еще одно условие на поиск скобки после VOLTA
вообще из описания функции atof я полагал что для нее в строке могут быть не только числа, а и другие символы, она же вытаскивает из нее только числа, а на деле функция не работает, даже если одна скобка попала в данные
#13
интересно, спасибо.
попробуем-с
намутил я вот такой код:
для тестов использую ардуино нано. может его ресурсов недостаточно? но с двумя параметрами
под скетч в 80 посте нужно писать отдельную обработку.
а если раскоментироваь, то все влезет?
под скетч в 80 посте нужно писать отдельную обработку.
а если раскоментироваь, то все влезет?
влезать влезает, но сразу же все параметры по нулям, начиная от строк типа VOLTAinString2, они пустые становятся, соответственно и флоат по нулям
данная ерунда наблюдается если пытаться разобрать более двух любых параметров одновременно. отдельно все параметры работают.