Hi all - this is maybe a boneheaded question regarding RS485, but I’ve got an Argon hooked up to a ALMOCN TTL to RS485 Adapter Module, trying to get data from a Signineer 6000w solar inverter via RS485.
Argon rx/tx are connected to the above module - per the q/a - rx<->rx, tx<->tx (not crossed), using a short section of cat5 twisted pair going to what should be the A/+ : B/- pins on the rj45…I’m using the Modbus-particle lib, and at least per the code, all seems right except I’m getting 226 timeouts - no answer.
I put a scope on the a/b lines, and see what looks to be (to me) a healthy signal on the line, but no replies coming back - I’m not an EE and there might be a subtlety here that I’m just not seeing:
CH1 is A/+, CH2 is B/-.
Does this look right? Should I have a terminating resistor? Any other pointers? Are the docs just lying about what pins are the right a/b pins?
…
/*
* Project inverter_monitor
* Description:
* Author:
* Date:
*/
#include <ModbusMaster-Particle.h>
#include "PublishQueuePosixRK.h" //background cloud publishing
SYSTEM_THREAD(ENABLED); //enable threads
ModbusMaster slave;
unsigned long interval = 0;
unsigned long base_T = 1000;
SerialLogHandler logHandler(LOG_LEVEL_INFO);
void preTransmission() {
// set interface to TX
}
void postTransmission() {
// set interface to RX
}
void idle() {
delay(10); // in case slave only replies after 10ms
Particle.process(); // avoids letting the connection close if open
}
void setup() {
slave.begin(1,Serial1); // slaveID=1, serial=Serial1
slave.setSpeed(9600,SERIAL_8N1);
//slave.enableDebug(); // to catch the logs
slave.preTransmission(preTransmission);
slave.postTransmission(postTransmission);
slave.idle(idle);
Log.info("Starting Modbus Transaction");
// start async cloud-publish thread
PublishQueuePosix::instance().setup();
PublishQueuePosix::instance().withRamQueueSize(10); // hold 10 messages in memory before going to flash
}
void loop() {
uint8_t j, result;
uint16_t data[10];
if (millis() - interval > base_T) {
interval = millis();
result = slave.readHoldingRegisters(0,1);
// do something with data if read is successful
if (result == slave.ku8MBSuccess) {
Log.info("Success, Received data...");
for (j = 0; j < 2; j++) {
data[j] = slave.getResponseBuffer(j);
Log.info("%i", data[j]);
log_to_cloud(result);
}
base_T = 1000;
} else {
Log.info("Failed, Response Code: %i", result);
base_T = 5000; //if failed, wait for bit longer, before retrying!
//log_to_cloud(result);
}
}
PublishQueuePosix::instance().loop(); // let the system publish
}
void log_to_cloud(int i) {
char buf[256];
JSONBufferWriter writer(buf, sizeof(buf));
writer.beginObject();
writer.name("error_code");
writer.beginObject();
writer.name("value").value(i);
writer.endObject();
writer.endObject();
// I think this is a terminator for the buffer - not sure
writer.buffer()[std::min(writer.bufferSize(), writer.dataSize())] = 0;
// en-queue the message, and the "Ubidots" event name will trigger the
// webhook over to ubidots on the particle end
PublishQueuePosix::instance().publish("Ubidots", buf, PRIVATE | NO_ACK);
}