Неправильные показания датчика NPK

Я хочу прочитать этот датчик , это датчик NPK. Для этого у меня есть эта плата , и эта шапка этой платы, чтобы прочитать ссылку Mobus 485.

Для этого код происхождения , который нам дает шапка. Для считывания датчика я использую следующий туториал, и напоследок конфиг датчика NPK:

Затем, после всего этого, я сгенерировал этот код:

#define PIN_5V_EN    0
#define CAN_TX_PIN   22
#define CAN_RX_PIN   21
#define RS485_TX_PIN 19
#define RS485_RX_PIN 18
#define RS485_EN_PIN 23
#define RE 23
#define DE 0

#include <Arduino.h>
#include <HardwareSerial.h>
#include <ModbusMaster.h>
// instantiate ModbusMaster object
ModbusMaster node;
HardwareSerial Serial485(2);

// Modbus RTU requests for reading NPK values
const byte water[] = {0x01, 0x03, 0x02, 0x01, 0x00, 0x01, 0xd4, 0x72};
const byte temp[] = {0x01, 0x03, 0x02, 0x00, 0x00, 0x01, 0x85, 0xb2};
const byte ec[] = {0x01, 0x03, 0x02, 0x02, 0x00, 0x01, 0x24, 0x72};
const byte ph[] = {0x01, 0x03, 0x02, 0x03, 0x00, 0x01, 0x75, 0xb2};
const byte nitro[] = {0x01, 0x03, 0x02, 0x04, 0x00, 0x01, 0xce, 0x73};
const byte phos[]  = {0x01, 0x03, 0x02, 0x05, 0x00, 0x01, 0x95, 0xb3};
const byte pota[]  = {0x01, 0x03, 0x02, 0x06, 0x00, 0x01, 0x65, 0xb3};
const byte dev_add[]  = {0x01, 0x03, 0x10, 0x00, 0x00, 0x01, 0x80, 0xca};
const byte dev_baud[]  = {0x01, 0x03, 0x10, 0x01, 0x00, 0x01, 0xd1, 0x0A};


// A variable used to store NPK values
byte values[11];

void CANTask(void *prarm);

void setup()
{
    pinMode(RS485_EN_PIN, OUTPUT);

    pinMode(PIN_5V_EN, OUTPUT);

    Serial.begin(9600);
    Serial485.begin(9600, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN);
    delay(5);
    node.begin(2, Serial485);


}

void loop()
{
    static uint32_t i;
    uint8_t j, result;
    uint16_t data[6];

    byte val1,val2,val3,val4,val5,val6,val7,val8,val9;
    val1 = water_func();
    delay(250);
    val2 = temperature();
    delay(250);
    val3 = ec_func();
    delay(250);
    val5 = ph_func();
    delay(250);
    val5 = nitrogen();
    delay(250);
    val6 = phosphorous();
    delay(250);
    val7 = potassium();
    delay(250);
    val8 = dev_add_func();
    delay(250);
    val9 = dev_baud_func();
    delay(250);

    // Print values to the serial monitor
    Serial.print("Water: ");
    Serial.print(val1);
    Serial.println(" mg/kg");
    Serial.print("Tempetature: ");
    Serial.print(val2);
    Serial.println(" ºC");
    Serial.print("EC: ");
    Serial.print(val3);
    Serial.println(" mg/kg");
    Serial.print("PH: ");
    Serial.print(val4);
    Serial.println(" mg/kg");
    Serial.print("Nitrogen: ");
    Serial.print(val5);
    Serial.println(" mg/kg");
    Serial.print("Phosphorous: ");
    Serial.print(val6);
    Serial.println(" mg/kg");
    Serial.print("Potassium: ");
    Serial.print(val7);
    Serial.println(" mg/kg");
    Serial.print("Devive_Address: ");
    Serial.println(val8);
    Serial.print("Devive_Baud: ");
    Serial.println(val8);
    
    delay(20000);
}

byte water_func(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(water,sizeof(water))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte temperature(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(temp,sizeof(temp))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte ec_func(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(ec,sizeof(ec))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte ph_func(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(ph,sizeof(ph))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}


byte nitrogen(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(nitro,sizeof(nitro))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}
 
byte phosphorous(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(phos,sizeof(phos))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}
 
byte potassium(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(pota,sizeof(pota))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte dev_add_func(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(dev_add,sizeof(dev_add))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte dev_baud_func(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if (Serial485.write(dev_baud,sizeof(dev_baud))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    Serial.print(Serial485.read(),HEX);
    values[i] = Serial485.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}

Но когда я запустил его, это вывод:

Я думаю, что у меня есть некоторые проблемы с тем, как передать сообщение и прочитать его, есть идеи?

Спасибо!!!

вам нужно сначала понять карту контактов вашей платы, в Arduino IDE, какую плату вы выбираете для своей конфигурации? как вы на самом деле подключили свою плату к приемопередатчику rs486, который подключается к датчику? Ваш код использует контакт 0 как контакт DE и PIN_5V_EN, это точно не сработает.

hcheung 13.02.2023 07:51

На вашей шапке RS485 нет контакта DE, а RE находится на контакте 32. Вы должны удалить код, относящийся к #define DE 0, и все, что связано с digitalWrite(DE,HIGH/LOW);.

hcheung 13.02.2023 07:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Прежде всего, в техпаспорте на датчик упоминается следующее:

Скорость передачи данных по умолчанию составляет 4800 бит/с, а значение по умолчанию адрес 0x01

Итак, первое, что нужно попробовать, это выбрать скорость передачи данных:

Serial485.begin(4800, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN);

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

Следующее, что вам нужно понять, это то, что вы делаете некоторые вещи в своем коде, которые являются избыточными. Вы загружаете библиотеку ModbusMaster.h, но не используете ее. Вместо этого вы отправляете и получаете кадры Modbus вручную.

Проще всего просто удалить библиотеку, удалив эти строки:

#include <ModbusMaster.h>
// instantiate ModbusMaster object
ModbusMaster node;

....
node.begin(2, Serial485);

Но моим предпочтительным решением было бы использовать библиотеку (не изобретайте велосипед , верно?).

Это краткий пример считывания значений температуры с вашего датчика с помощью ModbusMaster.h:

#define PIN_5V_EN    0
#define CAN_TX_PIN   22
#define CAN_RX_PIN   21
#define RS485_TX_PIN 19
#define RS485_RX_PIN 18
#define RS485_EN_PIN 23
#define RE 23
#define DE 0

#include <Arduino.h>
#include <HardwareSerial.h>
#include <ModbusMaster.h>
// instantiate ModbusMaster object
ModbusMaster node;
HardwareSerial Serial485(2);

// Modbus RTU requests for reading NPK values
// These are not needed, the library will do its magic


// A variable used to store NPK values
byte values[11];

void setup()
{
    pinMode(RS485_EN_PIN, OUTPUT);

    pinMode(PIN_5V_EN, OUTPUT);

    Serial.begin(9600);
    Serial485.begin(4800, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN); // Changed to 4800, default value
    delay(5);
    node.begin(1, Serial485); // Changed to ID=1, default value


}

void loop()
{
    uint8_t result;
    uint16_t data_temperature;
    
    result = node.readHoldingRegisters(0x0200, 1); // use library to read holding register 0x0200, just 1 register that contains the temperature
    
    // do something with data if read is successful-->store
    if (result == node.ku8MBSuccess) {
        data_temperature = node.getResponseBuffer(0);
    }

    // Print values to the serial monitor
    Serial.print("Tempetature: ");
    Serial.print(data_temperature/100); //scale divinding by 100
    Serial.println(" ºC");
    
    
    delay(20000);

}

Как видите, я изменил скорость передачи данных и идентификатор подчиненного устройства Modbus на 1 с помощью node.begin(1, Serial485);, чтобы сохранить значения по умолчанию в соответствии с таблицей.

Если вы используете библиотеку, вам не нужно заботиться о построении, отправке и получении кадров. Кроме того, для вас рассчитываются и проверяются CRC.

Наконец, пара вещей, которые действительно полезны, когда вы отлаживаете такой проект, как ваш:

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

-Загрузите, распакуйте и запустите QModMaster (qModMaster.exe). Возможно, вам придется запустить от имени администратора.

-Настройте свой порт, выбрав Modbus RTU из меню Options:

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

-Сохраните настройки, нажав OK. Теперь в главном окне измените Function Code на Read Holding Registers (0x03) и выберите значение 512 (0x0200) для Start Address , вы должны увидеть что-то вроде этого:

-Наконец, перейдите к Connect в меню Commands или нажмите на третий значок, начиная слева. Значение вашей температуры (умноженное на 100) должно появиться в первом регистре (поле, показывающее -/- непосредственно перед подключением).

Если вы не получили значение, единственная проблема может заключаться либо в неисправности вашего датчика (питание или что-то другое), либо в проблемах с проводкой. Для моего USB-адаптера мне пришлось бы подключить A+, B- и GND (не забудьте об этом):

У меня есть один адаптер USB RS485, вы знаете какой-нибудь учебник для него? Спасибо!!!

Francisco Gonzalez 13.02.2023 21:32

Привет, Франциско, я могу добавить к своему ответу пару скриншотов, чтобы показать вам, как использовать QModMaster. Я предполагаю, что вы уже подключили свой USB-адаптер, верно? В противном случае добавьте ссылку на его марку и модель.

Marcos G. 14.02.2023 17:28

Привет, Маркос, да, у меня есть такой, как на картинке. Спасибо!!! Действительно ценю это!!!

Francisco Gonzalez 14.02.2023 17:50

Сделанный. Это должно быть прямо сейчас.

Marcos G. 14.02.2023 18:33

Добро пожаловать и удачи в вашем проекте.

Marcos G. 15.02.2023 18:04

Другие вопросы по теме