Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.04.2019, 12:33   #1
PTyTb32
Форумчанин
 
Регистрация: 06.10.2013
Сообщений: 216
Лампочка Опрос электросчетчика - Меркурий 206 RN на борту он имеет RS-485 и свой протокол обмена

Привет, делюсь опытом. прикупил счетчик Меркурий 206 RN на борту он имеет RS-485 и свой протокол обмена. В угоду моей лени не долго думая приобрел преобразователь интерфейса RS-485 - USB, в итоге все получилось, программа запрашивает показания, расшифровывает и отображает на форме, ниже код запросов и обработки ответов

Запрос состояния сети:
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  bb: uint64;
  s, ss, mes, nmes: string;
  I: Integer;
begin
  nmes := '';
  commanda := 1; //Глобальная переменная для того что бы знали что ожидать
  mes := '0000000000'; // серийный адрес устройства я свой просто заменил 0х00 и код команды в соответствии с протоколом
  for I := Length(mes) div 2 downto 1 do
    nmes := nmes + mes[I * 2 - 1] + mes[I * 2]; // преобразовываем адрес для отправки
  s := IntToHex(GetModbusCRC16(mes)); //получаем контрольную сумму
  ss := s[3] + s[4] + s[1] + s[2]; // преобразовываем контрольную сумму
  bb := HexToInt(ss + nmes); // готовим пакет к отправке
  CommPortDriver1.SendData(@bb, Length(mes) div 2 + 2); // отправляем пакет
end;
после этого счетчик отвечает и срабатывает событие событие CommPortDriver1ReceiveData

Код:
procedure TForm1.CommPortDriver1ReceiveData(Sender: TObject; DataPtr: Pointer;
  DataSize: Cardinal);
var
  s, s1, s2, s3: string;
  I: Integer;
begin
  try
    s := '';
    I := 0;
    while I < 500000 do
      inc(I);                   //это костыль ы качестве маленькой паузы
    for I := 0 to 21 do
      s := s + StrToHex(pWidechar(DataPtr)[I]); //заполняем переменную S ответом счетчика
    case commanda of  // смотрим какую команду мы дали, у нас она равна 1 идем сразу туда
      0:
        begin
          s1 := s[11] + s[12] + s[13] + s[14] + ',' + s[15] + s[16] +
            s[17] + s[18];
          try
            s1 := floattostr(strtofloat(s1) * 100);
          except
            s1 := '0';
          end;
          s2 := s[19] + s[20] + s[21] + s[22] + ',' + s[23] + s[24] +
            s[25] + s[26];
          try
            s2 := floattostr(strtofloat(s2) * 100);
          except
            s2 := '0';
          end;
          Label5.Caption := 'День: ' + s1 + ' кВт';
          Label6.Caption := 'Ночь: ' + s2 + ' кВт';
          Label7.Caption := 'Общие показания: ' +
            floattostr(strtofloat(s1) + strtofloat(s2)) + ' кВт';
          label1.Caption:='Стоимость Т1: '+floattostr((strtofloat(s1) + strtofloat(s2))*5.38) + ' Руб.'; //однотарифный расчет
          label8.Caption:='Стоимость Т2: '+floattostr(strtofloat(s1)*2.29 + strtofloat(s2)*6.18) + ' Руб.'; //двухтарифный расчет
          label9.Caption:='Разница: '+floattostr(((strtofloat(s1) + strtofloat(s2))*5.38)-(strtofloat(s1)*2.29 + strtofloat(s2)*6.18))+ ' Руб.'; // разница однотарифного и двухтарифного расчета
          if (s1='0') or (s2='0')  or (s3='0') then
          Button2Click(self);
        end;
      1:
        begin
          s1 := s[11] + s[12] + ',' + s[13] + s[14]; //забираем показатель напряжения
          try
            s1 := floattostr(strtofloat(s1) * 10);
          except
            s1 := '0';
          end;
          s2 := s[15] + s[16] + ',' + s[17] + s[18];//забираем показатель силы тока
          try
            s2 := floattostr(strtofloat(s2));
          except
            s2 := '0';
          end;
          s3 := s[19] + s[20] + s[21] + s[22] + s[23] + s[24];//забираем показатель мощности 
          try
            s3 := floattostr(strtofloat(s3));
          except
            s3 := '0';
          end;
          Label2.Caption := 'Напряжение: ' + s1 + ' В';
          Label3.Caption := 'Ток: ' + s2 + ' А';
          Label4.Caption := 'Мощность: ' + s3 + ' Вт/ч';
          if (strtofloat(s1) < 180) or (strtofloat(s1) > 300) then //проверяем правильно ли пришел пакет (если параметр напряжения ниже 180 или более 300 вольт, на мой взгляд таких параметров в розетке не будет)
          Button1Click(self);  //если нет то запрашиваем еще раз
        end;
    end;
  except

  end;
end;
так же есть таймер для автоматического опроса и планирую прикрутить БД для ведения статистики

Последний раз редактировалось PTyTb32; 25.04.2019 в 12:35.
PTyTb32 вне форума Ответить с цитированием
Старый 25.04.2019, 15:35   #2
WorldMaster
Старожил
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Сообщений: 2,841
По умолчанию

Это вы от радости чтоли решили похвастаться??
Мы все несказанно рады что у вас все получается... ))))))))))))
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
WorldMaster вне форума Ответить с цитированием
Старый 25.04.2019, 15:52   #3
IliaIT
Форумчанин
 
Аватар для IliaIT
 
Регистрация: 17.03.2009
Сообщений: 979
По умолчанию

непонятно где CRC проверяется. далее на некоторых компах программа работать не будет из за разных десятичных знаков по умолчанию. Ну и интересный расчёт в рублях, это сумма с момента установки, а вот сколько заплатить надо это риторический вопрос, который без баз данных не решить (или хотя бы лог файла). там ещё многое по мелочи, что не позволит использовать код в автономном режиме.
Хотя всё замечательно, для первого раза, когда то сам так писал лет 10 назад, когда только начинал делать скада систему на дельфи.
Интуитивно понятный интерфейс - это такой интерфейс, для работы с которым нужна недюжинная интуиция.
IliaIT вне форума Ответить с цитированием
Старый 25.04.2019, 16:24   #4
PTyTb32
Форумчанин
 
Регистрация: 06.10.2013
Сообщений: 216
По умолчанию

Цитата:
Сообщение от WorldMaster Посмотреть сообщение
Это вы от радости чтоли решили похвастаться??
Мы все несказанно рады что у вас все получается... ))))))))))))
не то что бы похвастаться, эту программу я писал с поддержкой этого форума. в процессе написания возникали вопросы, ответ на которые было найти затруднительно, по этому и решил выложить, что бы другие искатели находили что то полезное

Цитата:
Сообщение от IliaIT Посмотреть сообщение
непонятно где CRC проверяется. далее на некоторых компах программа работать не будет из за разных десятичных знаков по умолчанию. Ну и интересный расчёт в рублях, это сумма с момента установки, а вот сколько заплатить надо это риторический вопрос, который без баз данных не решить (или хотя бы лог файла). там ещё многое по мелочи, что не позволит использовать код в автономном режиме.
Хотя всё замечательно, для первого раза, когда то сам так писал лет 10 назад, когда только начинал делать скада систему на дельфи.
расчет действительно с момента установки и еще в нем фиксированные тарифы, что тоже не верно, однако данный расчет призван показать какой тариф наиболее выгодный, а не для проверки управляшек (они иначе дурят население), на счет запятой не совсем понял, если вы об этом s1 := s[11] + s[12] + ',' + s[13] + s[14]; //забираем показатель напряжения, то это особенность протокола, я сравнивал показания программы с показаниями на экране прибора учета, они сошлись
и зачем проверять CRC?
PTyTb32 вне форума Ответить с цитированием
Старый 25.04.2019, 16:52   #5
IliaIT
Форумчанин
 
Аватар для IliaIT
 
Регистрация: 17.03.2009
Сообщений: 979
По умолчанию

Фиксированные тарифы меняются через конфигуратор этого счётчика. (Конфигуратор (v.1.7.81) универсальный для Меркурий 200, 201.8 TLO, 203.2T, 206, 230, 231, 233, 234, 236).

тут всё нормально, нет претензий работать будет везде. точнее не нормально, надо целое, а потом делить на коэфицент
Код:
s1 := s[11] + s[12] + s[13] + s[14] + ',' + s[15] + s[16] +s[17] + s[18];
а вдруг в системе десятичный знак "."? будет всегда 0.
Код:
strtofloat(s1)
а можно было всего 1 раз вычислить
Код:
d_par.DecimalSeparator:=',';
TryStrToFloat(s1,s_d,d_par);
где
s_d:Single;
d_par:TFormatSettings;

CRC проверяют для верности пакета, если провод немного болтается или наводка есть то будут помехи на линии, и непонятно как тогда программа поведёт себя. хотя это проявится обычно при масштабировании опросов (по-русски раз на раз не приходится).
ладно не буду больше писать всё равно офтоп получается... вдруг искру программиста чем испорчу и вдохновение пропадёт.
Интуитивно понятный интерфейс - это такой интерфейс, для работы с которым нужна недюжинная интуиция.
IliaIT вне форума Ответить с цитированием
Старый 25.04.2019, 17:15   #6
PTyTb32
Форумчанин
 
Регистрация: 06.10.2013
Сообщений: 216
По умолчанию

Цитата:
Сообщение от IliaIT Посмотреть сообщение
Фиксированные тарифы меняются через конфигуратор этого счётчика. (Конфигуратор (v.1.7.81) универсальный для Меркурий 200, 201.8 TLO, 203.2T, 206, 230, 231, 233, 234, 236).

тут всё нормально, нет претензий работать будет везде. точнее не нормально, надо целое, а потом делить на коэфицент
Код:
s1 := s[11] + s[12] + s[13] + s[14] + ',' + s[15] + s[16] +s[17] + s[18];
а вдруг в системе десятичный знак "."? будет всегда 0.
Код:
strtofloat(s1)
а можно было всего 1 раз вычислить
Код:
d_par.DecimalSeparator:=',';
TryStrToFloat(s1,s_d,d_par);
где
s_d:Single;
d_par:TFormatSettings;

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


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Каждая игра имеет свой ИД Niko777 PHP 2 31.10.2016 21:08
Выдернуть протокол обмена по СОМ-порту из утилиты one_man_show Фриланс 7 31.10.2016 18:43
HEX помощь - протокол обмена данными с прибором acid26sk Помощь студентам 18 17.11.2014 11:25
Свой простейший протокол vovken1997 Общие вопросы Delphi 17 06.07.2013 22:57
Свой протокол Alex_Gordon Общие вопросы Delphi 8 07.01.2012 00:13