Электросчетчики Энергомеры

Serzh251
Offline
Зарегистрирован: 15.11.2017

да, пробовал и на 3 и на 1, на 1 исправно работает GSM шилд

пробовал и в формате 7E1, тоже тишина

фидимо надо смотреть всетаки на софт сериал и способы вытаскивания переменной. и хард сериал не занимает в итоге

MaksVV
Offline
Зарегистрирован: 06.08.2015

однажды устанавливая связь с блоком управления двигаталем. Связи небыло из-за того, что при отправке сообщений на блок байты летели один за другим сразу. А блоку нужна была задержка в 1 мс между байтами. Может есть различия в таймингах при отправке байт на софт и хард, поэтому на  одном работает, на другом нет. Так же на хард на Тх Rx должны стоять резисторы около 1кОм, может они влияют

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

Serzh251
Offline
Зарегистрирован: 15.11.2017

может быть, но времени лишнего гадать нет)

нужно возвращаться к переменным

кстати когда тестировал нано и USB-TTL, RS-485 повесил на Тх и Rx ардуино, на мониторе ардуино были данные, на USB и терминальной проге нет

Serzh251
Offline
Зарегистрирован: 15.11.2017

харды рабочие, первый и второй точно

MaksVV
Offline
Зарегистрирован: 06.08.2015

надо было убрать при этом RS485  и напрямую Tx и Rx

MaksVV
Offline
Зарегистрирован: 06.08.2015

короче надо убедиться до RS485, что с харда данные вылетают. Если да, то копать дальше. Может всё таки в коде где нибудь ошиблись. 

Serzh251
Offline
Зарегистрирован: 15.11.2017

так, что я сейчас сделал:

подключил RS-485 k Rx Tx ардуино нано, в мониторе порта кракозябры (такие же если выводить данные с соф сериал и без конвертации)

запускал нард сериал на 7Е1, все тоже самое

MaksVV
Offline
Зарегистрирован: 06.08.2015

соедините мегу и нану без rs485 добейтесь правильных байтов

MaksVV
Offline
Зарегистрирован: 06.08.2015

и еще, монитор порта IDE показывает только в ASCII, а у вас просто байты , надеюсь вы про это в курсе

Serzh251
Offline
Зарегистрирован: 15.11.2017

я вернулся к исходному коду, все данные отображаются вот так:

ищу путь как вытащить цифры в переменные

z/EKT5CE102Mv01
P0(001)gET0PE(5573.34)
(3455.40)
(2117.94)
(0.00)
(0.00)
(0.00)
=VOLTA(220.69)
"CURRE(9.472)
pPOWEP(1.998953)
FREQU(49.96)
x
Serzh251
Offline
Зарегистрирован: 15.11.2017

вообще уровень моих познаний крайне не высок

вот такие мысли есть:

char response нужно сделать строкой

а потом функцией atof вытащить числа

inspectorcot
Offline
Зарегистрирован: 21.02.2018

http://bigbarrel.ru/%D0%BA%D0%BE%D0%BD%D0%B2%D0%B5%D1%80%D1%82%D0%B0%D1%...

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

Serzh251
Offline
Зарегистрирован: 15.11.2017

да, смотрел, исходя из этого сделал вот так

    char response = RS485.read();
    response &= 0x7F;// convert 8N1 to 7E1
    
    String str(response);//convert char to string
    
    str.toCharArray(floatbufVar,sizeof(floatbufVar));
    floatVar=atof(floatbufVar);
    Serial.print(floatVar);
проскакивают кое какие цифры, но в основном нули
есть мысли как из char response сделать строку? а лучше наверное несколько строк?
в мониторе порта каждый параметр начинается с новой строчки, может нужно отследить символ возрата строки..короче уже не знаю
b707
Offline
Зарегистрирован: 26.05.2017

Serzh251 пишет:

да, смотрел, исходя из этого сделал вот так

так работать не будет. У вас в коде сплошные несуразицы...

Смотрите: Начать с того, что у вас в response один единственный символ. То есть никаких чисел с числом цифр больше одной вы из него в принципе не получите. Но вы еще и обрабатываете его неверно. Сначала переводите в строку, потом зачем-то обратно в char.  и потом в число функцией atof(). При этом совершенно не заботитесь о том, что для этой функции строка должна кончаться на терминатор '\0'. В лучшем случае вы так сможете получить, например, первый символ "8" из числа  8823.33 - но чаще вообще ничего не получите.

Вам надо сначала собрать полную строку из отдельных символов. Потом добавить в конце терминатор. Потом в этой строке найти, где начинается число. И только потом извлекать числа функцией atof().

Но это потом. Для начала стоит потратить некоторое время на изучение основ языка Си. Я бы советовал отложить этот код, найти хороший учебник и прорешать в нем примеры от начала и до конца. Потратите пару месяцев, зато потом этот код напишете за 1 вечер. Вы там выше писали "мой уровень невысок". Простите, но это вы еще себе польстили. Ваш уровень практически нулевой.

inspectorcot
Offline
Зарегистрирован: 21.02.2018

ну как успехи? получилось?

Serzh251
Offline
Зарегистрирован: 15.11.2017

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

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

inspectorcot
Offline
Зарегистрирован: 21.02.2018

вас понял, хорошее дело, успехов!

Serzh251
Offline
Зарегистрирован: 15.11.2017

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

inspectorcot
Offline
Зарегистрирован: 21.02.2018

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

#include <SoftwareSerial.h>
int i = 0;
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 = 15; 
String inString;
String inString2;
char x [50];
// открываем сессию
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,0x50,0xcf,0xd7,0xc5,0x50,0x28,0xa9,0x03,0xe4};
// частота  
byte cmd6[] = {0x81,0xd2,0xb1,0x82,0xc6,0xd2,0xc5,0xd1,0x55,0x28,0xa9,0x03,0x5c};


#define DIR 8 
 
SoftwareSerial RS485 (7, 6); // RX, TX

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
    

      char inChar = response;

      inString += inChar;
      if (inString.lastIndexOf('/')>0) {
      int first = inString.indexOf('(');
      int second  = inString.indexOf('(', first + 1 );
       second = second + 1; 
      int first_2 = inString.indexOf(')');
      int second_2 = inString.indexOf(')', first_2 + 1 );
      inString2 = inString.substring(second,second_2);
      
      
       inString2.toCharArray(x, sizeof(x));
        float f = atof(x);
        
          
          Serial.print(inString2);   //формат string
          Serial.print("------>");
          Serial.print(f);           //формат float
          Serial.print('\n');
          
      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)
       {
        
         val = 0;
         
         
       }
 
  }

}
   

 

Serzh251
Offline
Зарегистрирован: 15.11.2017

у вас работает?

жаль проверить пока не могу

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

      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 = ""; //обнуляем строку?

 

inspectorcot
Offline
Зарегистрирован: 21.02.2018

да, у меня работает

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 = ""; //обнуляем строку

 

Serzh251
Offline
Зарегистрирован: 15.11.2017

че т я совсем запутался

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

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

#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 = ""; //обнуляем строку
               }
}}

 

Serzh251
Offline
Зарегистрирован: 15.11.2017
в этом коде все работает нормально
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() {




}

 

inspectorcot
Offline
Зарегистрирован: 21.02.2018

  //  response &= 0x7F;// convert 8N1 to 7E1047

раскоментируйте строку

Serzh251
Offline
Зарегистрирован: 15.11.2017

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

inspectorcot
Offline
Зарегистрирован: 21.02.2018

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

inspectorcot
Offline
Зарегистрирован: 21.02.2018

удалось найти причину по которой не работало?

Serzh251
Offline
Зарегистрирован: 15.11.2017
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 = ""; //обнуляем строку

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

inspectorcot
Offline
Зарегистрирован: 21.02.2018

ненмого сократить можно если использовать быстрое чтение вместо оыбчного способа

то есть мы уберем из строки ответы на первые 2 опроса

//сумма
byte fast1[] = {0xaf,0x3f,0x21,0x81,0xd2,0xb1,0x82,0xc5,0xd4,0x30,0x50,0xc5,0x28,0xa9,0x03,0xb7};
//мощность
byte fast2[] = {0xaf,0x3f,0x21,0x81,0xd2,0xb1,0x82,0x50,0xcf,0xd7,0x50,0x50,0x28,0xa9,0x03,0x6f};

не очень много конечно, но все же меньше будет.

 

inspectorcot
Offline
Зарегистрирован: 21.02.2018

если я вас правильно понял, то если вы будете так собирать

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 вот такое число

Serzh251
Offline
Зарегистрирован: 15.11.2017

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

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

inspectorcot
Offline
Зарегистрирован: 21.02.2018

да, позволяет без открытия сессии

я пробовал, работает

есть еще метод групового чтения, но с ним я пока е знаком

Serzh251
Offline
Зарегистрирован: 15.11.2017

на коментарии на обращайте внимания, я их не менял..

речь идет об этом. описание

Serial.available()

Функция получает количество байт(символов) доступных для чтения из последовательного интерфейса связи. Это те байты которые уже поступили и записаны в буфер последовательного порта. Буфер может хранить до 64 байт.

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

/EKT5CE102Mv01
P0(001)gET0PE(5933.21)
(3685.94)
(2247.27)

(0.00)
(0.00)
(0.00)
GVOLTA(215.35)
CURRE(0.473)
hPOWEP(0.094839)
FREQU(49.99)

кракозябры такие выходят после копирования

 

 

inspectorcot
Offline
Зарегистрирован: 21.02.2018

 

в режиме быстрого чтения этого не будет:

 

/EKT5CE102Mv01

	P0(001)g

 

 

 

inspectorcot
Offline
Зарегистрирован: 21.02.2018

так вы отправляете строку всю целиком?

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

inspectorcot
Offline
Зарегистрирован: 21.02.2018

а куда вы потом будете слать всю информацию?

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

Serzh251
Offline
Зарегистрирован: 15.11.2017

да, я отправляю целиком

счетчик шлет посимвольно, с задержками между строк-правильно?

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

Serzh251
Offline
Зарегистрирован: 15.11.2017

inspectorcot пишет:

а куда вы потом будете слать всю информацию?

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

да, умный дом..

там уже много всего у меня насобиралось

еще есть мониторинг АКБ на базе монитора батарей BMV-700 от виктрон, у него свой фирменный протокол, пример его считывания нашел на зарубежных форумах, там вроде как все работает 

inspectorcot
Offline
Зарегистрирован: 21.02.2018

да, посимвольно с задержками.

у меня в коде есть вот такая строка:

if (inString.lastIndexOf('/')>0)

я выбрал символ "/" как знак конца строки. на этом символе у меня заканчивается формирование строки.

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

строка формируется так

E
ET
ETO
ETOP
ETOPE

ETOPE(

и так далее

до знака / (у меня)

после этого знака у меня заканчивается формирование строки и я начинаю ее разбор

 

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

inspectorcot
Offline
Зарегистрирован: 21.02.2018

и опять же мне кажется с этими запросами могут быть пролемы

int first = inString.indexOf("VOLTA"); //  находим первую скобку "(" в строке и сохраняем в int ее порядковый номер для того что бы можно было найти вторую

	 

	 

	    int first1 = first + 6; //пришлось добавить +1 т.к. захватывало с собой скобку

	 

	    int first_2 = first+13;

	 

	    inString2 = inString.substring(first1,first_2);//присваиваем inString2

 

Serzh251
Offline
Зарегистрирован: 15.11.2017

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

но если в цикле собирания строки вместо if использовать while? счетчик отправил строку, если там появилось что то нужное, разобрали, если нет, ждем следующую строку символов, ее разобрали, обнулили. но в моем случае могут возникать накладки, если к примеру в порт будет продолжать что то валиться и мы потом сразу две строки обнулим..

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

Serzh251
Offline
Зарегистрирован: 15.11.2017

если собрать правильно строку и потом правильно ее обнулить, то какие могут быть проблемы с такими запросами типа VOLTA? если ориентироваться на скобки, например, их слишком много

inspectorcot
Offline
Зарегистрирован: 21.02.2018

ну допустим у этой строки

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?

 

Serzh251
Offline
Зарегистрирован: 15.11.2017

в общем да, об этом тоже думал, и вроде как проблемы возникают только когда ток 10А и больше, остальное кол-во цифр вроде как не изменно..

в таком случае добавить еще одно условие на поиск скобки после VOLTA

вообще из описания функции atof я полагал что для нее в строке могут быть не только числа, а и другие символы, она же вытаскивает из нее только числа, а на деле функция не работает, даже если одна скобка попала в данные

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

#13

inspectorcot
Offline
Зарегистрирован: 21.02.2018

 

интересно, спасибо.

попробуем-с

Serzh251
Offline
Зарегистрирован: 15.11.2017

намутил я вот такой код:

#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 у меня почему то не заработал
вы на каком ардуино тестируете? есть возможность попробовать все параметры сразу на чем то большем, чем нано?

 

 

inspectorcot
Offline
Зарегистрирован: 21.02.2018

под скетч в 80 посте нужно писать отдельную обработку.

а если раскоментироваь, то все влезет?

Serzh251
Offline
Зарегистрирован: 15.11.2017

inspectorcot пишет:

под скетч в 80 посте нужно писать отдельную обработку.

а если раскоментироваь, то все влезет?

влезать влезает, но сразу же все параметры по нулям, начиная от строк типа VOLTAinString2, они пустые становятся, соответственно и флоат по нулям

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