Я хочу прочитать этот датчик , это датчик 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];
}
Но когда я запустил его, это вывод:
Я думаю, что у меня есть некоторые проблемы с тем, как передать сообщение и прочитать его, есть идеи?
Спасибо!!!
На вашей шапке RS485 нет контакта DE, а RE находится на контакте 32. Вы должны удалить код, относящийся к #define DE 0
, и все, что связано с digitalWrite(DE,HIGH/LOW);
.
У меня нет этого датчика, поэтому имейте в виду, что здесь я угадываю, но я могу дать вам пару советов, которые могут помочь.
Прежде всего, в техпаспорте на датчик упоминается следующее:
Скорость передачи данных по умолчанию составляет 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, вы знаете какой-нибудь учебник для него? Спасибо!!!
Привет, Франциско, я могу добавить к своему ответу пару скриншотов, чтобы показать вам, как использовать QModMaster. Я предполагаю, что вы уже подключили свой USB-адаптер, верно? В противном случае добавьте ссылку на его марку и модель.
Привет, Маркос, да, у меня есть такой, как на картинке. Спасибо!!! Действительно ценю это!!!
Сделанный. Это должно быть прямо сейчас.
Добро пожаловать и удачи в вашем проекте.
вам нужно сначала понять карту контактов вашей платы, в Arduino IDE, какую плату вы выбираете для своей конфигурации? как вы на самом деле подключили свою плату к приемопередатчику rs486, который подключается к датчику? Ваш код использует контакт 0 как контакт DE и PIN_5V_EN, это точно не сработает.