Работа с вакуумметром ВМЦ по ModBus

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015

Посмотрите как реализованы мастеры в примерах к библиотеке и сделайте также. Там применяется автомат состояний через использование case'ов.

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1: 
    telegram.u8id = 1; // slave address
    telegram.u8fct = 3; // function code (this one is registers read)
    telegram.u16RegAdd = 1; // start address in slave
    telegram.u16CoilsNo = 4; // number of elements (coils or registers) to read
    telegram.au16reg = au16data; // pointer to a memory array in the Arduino

    master.query( telegram ); // send query (only once)
    u8state++;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 100; 
    }
    break;
  }
}

Для нескольких запросов там есть расширенный пример.

RizONE
Offline
Зарегистрирован: 22.03.2018

uni пишет:

Там применяется автомат состояний через использование case'ов.

а смысл этого? По шагам:1 - ждем нужное время 2 - делаем запрос на чтение 3- смотрим что там пришло

Т.е. фактически через равные промежутки времени делаем запрос и читаем ответ.

Если помните первые мои образцы скетчов так и строились. Может чего не понимаю, но логика от этого не меняется

RizONE
Offline
Зарегистрирован: 22.03.2018

uni пишет:

Для нескольких запросов там есть расширенный пример.

сейчас гляну...

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015

Насколько я понял master.poll() является асинхронной операцией, поэтому важно делать так, как написано в примерах. Асинхронность означает, что функция возвращает управление сразу, а не ожидает завершения какой-то операции.

RizONE
Offline
Зарегистрирован: 22.03.2018

про несколько запросов - логика вроде такая:

case 0 ждем 1000мс

case 1 шлем запрос telegram[0]

case 2 обрабатываем ответ

case 0 ждем 1000мс

case 1 шлем запрос telegram[1]

case 2 обрабатываем ответ

и т.д.

У меня вроде тоже самое, нет?

RizONE
Offline
Зарегистрирован: 22.03.2018

uni пишет:

Насколько я понял master.poll() является асинхронной операцией, поэтому важно делать так, как написано в примерах. Асинхронность означает, что функция возвращает управление сразу, а не ожидает завершения какой-то операции.

может и асинхронна, не знаю, ок, попробую и строго по примерам. Спасибо

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015

RizONE пишет:

У меня вроде тоже самое, нет?

Судя по всему не так. У вас получается случайная каша, на которую я не обратил внимания, т.к. не видел примеров использования класса в режиме мастера. Метод poll() должен вызываться постоянно, а не однократно. И каждый раз нужно следить за переменной внутреннего состояния. Т.е. нужно дать задание и потом непрерывно "дергать" объект, проверяя не пришло ли чего. В вашем случае звёзды совпали только частично.

Ну и не обязательно делать 2 запроса. Вполне можно обойтись и одним, запрашивая 2 регистра, но также как в примерах.

RizONE
Offline
Зарегистрирован: 22.03.2018

uni пишет:

Т.е. нужно дать задание и потом непрерывно "дергать" объект, проверяя не пришло ли чего.

идею понял, ща переделаю

RizONE
Offline
Зарегистрирован: 22.03.2018

Переделал, вот что вышло:

#include <ModbusRtu.h>
#include <LiquidCrystal.h>

#define TXEN 10
#define ID 10

uint16_t au16data[16];
uint8_t u8state;
uint16_t flag = 1;
union Data
{
  struct REG
  {
    uint16_t LOWORD;
    uint16_t HIWORD;
  } reg;

  float fvalue;
};
Data data;
Modbus master(0,0,TXEN);
modbus_t telegram;
unsigned long u32wait;

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

void setup() {
  master.begin(19200);
  master.setTimeOut(1000);
  u32wait = millis() + 3000;
  u8state = 0;
  lcd.begin(16, 2);
  lcd.print("hello, world!"); 
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++;
    break;
  case 1: 
    telegram.u8id = ID;
    telegram.u8fct = 4;
    telegram.u16RegAdd = 1000;
    telegram.u16CoilsNo = 2;
    telegram.au16reg = au16data;

    master.query(telegram); 
    u8state++;
    break;
  case 2:
    master.poll();
    if (master.getState() == COM_IDLE) {
      //data.reg.LOWORD = au16data[0];
      //data.reg.HIWORD = au16data[1];
      data.reg.HIWORD = 0x38a0;
      data.reg.LOWORD = 0x93b1;
      lcd.setCursor(0, 1);
      lcd.print(data.fvalue);
      u8state = 0;
      u32wait = millis() + 3000;
    }
    break;
  }
}

Проверил на установке - данные шлем и получаем! Ура!

Теперь беда с отображением полученных данных на экране. Для этого в 56 и 57 явно подставил значения и надеялся получить на экране что нить типа 0.00007656 или 7.656е-005 но дает 0.00

Вариант lcd.print(data.fvalue*100000); единственный для получения результата или можно без умножения?

RizONE
Offline
Зарегистрирован: 22.03.2018

Очень хотелось бы видеть на экране не только 2 знака после запятой

PS

Разобрался!