rs485 Nick gammon Library

Hello guys,

My project is fairly simple. I have one arduino uno (collects data) and one arduino nano (sends data)

I am trying to make a serial rs485 connection between arduinos, however because of my lack of knowledge in programming i have difficulty understanding the code provided by nick gammon at

So the purpose is that the arduino nano has an ultrasonic sensor on it, collects its data and then trasmit those data on the arduino uno then the uno stores this value on a opc item , then the opc server(PC) collects that item via usb connection.

In order for the opc server to work i need to use softwareserial, my problem is with the example code provided by Nick Gammon, i have trouble understanding the code although the documentation is very well written.

So i altered some of the code in order to fit to my project needs and i need some guidance if possible, is this the right way to do it?

My code that is supposed to run on the nano

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance

#include <SoftwareSerial.h>

const byte ENABLE_PIN = 4;
const byte LED_PIN = 13;

SoftwareSerial rs485 (2, 3);  // receive pin, transmit pin

// callback routines
  
#include <RS485_non_blocking.h>

size_t fWrite (const byte what)
{
  return rs485.write (what);  
}

RS485 myChannel (NULL, NULL, fWrite, 0);

void setup ()
{
  Serial.begin (115200);
  myChannel.begin ();
}  // end of setup

//const byte msg [] = distance;

void loop ()
{
int distance= sonar.ping_cm();
 byte msg [] = {distance};

  
  myChannel.sendMsg (msg, sizeof (msg));
  delay (1000);   
}  // end of loop

This code compiles with a warning

warning: narrowing conversion of 'distance' from 'int' to 'byte {aka unsigned char}' inside { } [-Wnarrowing]

byte msg [] = {distance};

Is this the right way to do it?

Help would be grately appreciated.
Thanks.

Okay, several things. First, you need to read up on callback functions.

After that, the rest is easy. you need a constructor. As detailed in Nick's header,

    RS485 (ReadCallback fReadCallback, 
           AvailableCallback fAvailableCallback, 
           WriteCallback fWriteCallback,
const byte bufferSize)

You will need functions for all. NULL for the read and available callbacks means that nothing will ever be read so there will never be anything to write. In your one function,

size_t fWrite (const byte what)
{
  return rs485.write (what); 
}

get rid of the return. The function should just be what you want done when the library tries to write something. If you want some report, you can,

size_t fWrite (const byte what)
{
  int some_variable =  rs485.write (what); 
  return some_variable ;
}

some variable, if available, will often be the number of characters written (for a write function).

Anyhow, make those changes and see what happens. Better when you instantiate SoftwareSerial you use a name that's different than the constructor for RS485_non_blocking, less confusing.

BTW,

int distance= sonar.ping_cm();
byte msg [] = {distance};
myChannel.sendMsg (msg, sizeof (msg));

Is not going to give you the results you want. Read up on itoa() int the C library manual.

You know i was looking the example of the RS485_protocol.h library and he can send integer values without any itoa() conversion.

Now i am confused :S

The problem arises when distance is greater than 255. Until then, distance is a single byte. How do you want to represent 345 as a byte array? There is no automatic conversion to 3, 4, 5. 345 will be overflowed and the rest will be lost.

And Nick doesn't send integer values, he sends *data which is a pointer to the byte array. It's up to you to populate that array.

My values wont be higher than 255, i think my problem is that i am trying to implement the blocking library example and the non-blocking one,

I like the way that each slave has an adress but in the non blocking library the example is not the same, and because i have no programming experience it is really confusing me, getting a bunch of errors.

If you could give me an example how my code should look like i would take it from there, and start understanding how things work in the code.

For example i dont see any error checking on the non-blocking library , is it implemented in the mychannel class?

The function wants a byte array, so first of all it need to be NULL terminated. In this case, that means the last entry in the array must be zero. In reality, as you are also passing the sizeof the array, it's not so important but should be implemented as a matter of good coding.

As far as declaring an array array, initializing must be done with constants. You can declare the array, byte msg[2]; and the assign a value to it, msg[0] = distance, or use itoa(msg, distance) in which case msg must be declared to be large enough to carry the ASCII representation of the value distance plus 1 (for the terminator). In the case of values less than 1000, byte msg[4] will hold values up to 999.

If i do byte distance = sonar.ping_cm(); will that be ok?

Also my question still remains is there any error checking on the non-blocking library?

Do you gave a C/C++ environment where you can test code? Not necessarily Arduino code, just plain old code, like Eclipse or Code:Blocks or an editor?

Excuse me but i don't understand what you mean, i compile the code in the arduino IDE if that is what you are asking

I meant, do you have another coding environment where you can simply enter C/C++ code, compile and run it and see how it works? Without going through the process of uploading to the board. For example, take the snippet I pointed out in #2 and change it a bit so it's generic,

int distance= 123;
byte msg [] = {distance};
printf ("%i\n",msg);

compile and run it to see what happens. Quick and dirty without bothering your Arduino code or having to compile and upload. The you see straight away how the compiler will deal with your assignments.

The coding environment that i use is the arduino IDE, and using this code does compile with no errors

byte distance = sonar.ping_cm();
  byte msg [] = {distance};
  myChannel.sendMsg (msg, sizeof (msg));

So i am guessing this would work, however i still dont understand if the myChannel class does error checking.