DORJ-FSCK Driver

Simple, copy the three bytes into an array (in the correct order for Big Endian) and do:

  Serial.write(array, 3);

I wanted to move most of the code into a function. Other applications using that function(s) wont necessarily use serial to interact with a user. Say for example an automated radio beacon.

Can functions return more than one data type?
If not, am I down to using text strings to interact with that function?

You seem to be wandering all over the place with your design and not providing a lot of details or clarity for people to help you.

Yes, amongst other things, functions can return a struct. They can also modify data structures in the function that called them via C++ References or pointers.

Unfortunately that in large part is how my head works. It should be much clearer if I re-post the code with all the changes I made over the last day or so. But I wanted to try to fix some other things first.

It sounds like having the function return a data structure is the right way to do things.

You are making this much more complicated than it needs to be.
There are only two commands, read and write, each is just an array of bytes.
You either send ten bytes of data or receive ten bytes of data.

That's why your head hurts. Keep it simple.

That will only give you the ASCII character associated with the value of each byte.

Something more like this

uint32_t  frequency = (uint32_t)dorj_response[3]<<16 + dorj_response[4]<<8  + dorj_response[5];

Guess we're talking about different things. I was describing how to start with the frequency stored in a 32-bit unsigned variable (Little Endian) and send it, in binary, from a Print object as a 24-bit unsigned value, in Big Endian order.

  uint8_t array[3];
  uint32_t frequency;

  frequency = 2000;
  auto ptr = reinterpret_cast<uint8_t *>(&frequency) + 2;
  for (size_t i = 0; i < 3; i++) {
    array[i] = *ptr--;
  }
  Serial.write(array, 3);

Doesn't work either.

Here's where I'm at presently. I haven't tested it on hardware. But at least it compiles I guess. :face_with_bags_under_eyes:


// Arduino driver for DORJ-FSK Transmitter/Reciever modules.

// Set labels for each Pin.
int SetA = 40;
int TXD = 18;
int RXD = 19;
int AUX = 42;
int SetB = 41;

struct parameters
{
  bool valid;
  unsigned long frequency;
  String parity;
  byte speed, baud, power;
};

void setup()
{
pinMode(SetA, OUTPUT);      // Make SETA Pin Output.
pinMode(SetB, OUTPUT);      // Make SetB Pin Output.
pinMode(AUX, INPUT_PULLUP); // Make AUX Pin Input.
Serial.begin(9600);         // Instantiate communication over USB.
Serial1.begin(9600);        // Instantiate communication over RX/TX pins.
}

void loop()
{
Serial.print("Getting module settings... ");
parameters data = read_settings();

if (data.valid = true)
{
  Serial.println("Response Valid");
  char strBuf[80];
  Serial.println("Frequency \t Speed \t Baud \t Power \t Parity");
  sprintf(strBuf,"%u Khz \t %u Kbps \t %u Kbps \t %u Dbm \t %s",data.frequency,data.speed,data.baud,data.power,data.parity);
  Serial.println(strBuf);
}
else
{
  Serial.println("Response Invalid");
}
delay(5000);
}

parameters read_settings()                                          // Get parameters from the module and return that data.
{
byte dorj_status_cmd[7] = {0xff,0x56,0xAE,0x35,0xA9,0x55,0xF0};     // Command used to read from module.
digitalWrite(SetA, HIGH);                                           // Ask module to enter setup/sleep mode.
if (digitalRead(AUX)==HIGH) {Serial1.write(dorj_status_cmd,7);}     // Monitor AUX Pin, then send status request when ready.
byte dorj_response[10];                                             // Array for module response.
Serial1.readBytes(dorj_response,10);                                // Aquire response from module.
digitalWrite(SetA, LOW);                                            // Return module to normal opperation.
parameters data_out;                                                // Instantiate structure for data return.

if (dorj_response[0] == 0x24 && dorj_response[1] == 0x24 && dorj_response[2] == 0x24) // Check for valid preamble.
  {
    data_out.valid = true;
    data_out.frequency = dorj_response[3] + dorj_response[4] + dorj_response[5];
    data_out.parity = dorj_response[9];
    data_out.power = (dorj_response[7] + 1) * 3;
    
    switch (dorj_response[6])
    {
      case 0x00:
      data_out.speed = 1;
      break;
      case 0x01:
      data_out.speed = 2;
      break;
      case 0x02:
      data_out.speed = 5;
      break;
      case 0x03:
      data_out.speed = 10;
      break;
      case 0x04:
      data_out.speed = 20;
      break;
      case 0x05:
      data_out.speed = 40;
      break;
    }
    
    switch (dorj_response[8])
    {
      case 0x00:
      data_out.baud = 1200;
      break;
      case 0x01:
      data_out.baud = 2400;
      break;
      case 0x02:
      data_out.baud = 4800;
      break;
      case 0x03:
      data_out.baud = 9600;
      break;
      case 0x04:
      data_out.baud = 19200;
      break;
      case 0x05:
      data_out.baud = 38400;
      break;
      case 0x06:
      data_out.baud = 57600;
      break;
    }
    
    switch (dorj_response[9])
    {
      case 0:
      data_out.parity = "None";
      break;
      case 1:
      data_out.parity = "Even";
      break;
      case 2:
      data_out.parity = "Odd";
    }
  }
else 
  {
     data_out.valid = false;
  }
return data_out;
}

What is this?

Of course I realize there's still a ton of things wrong. I'm stuck playing catch up.
The post was just to make sure we were at least looking at the same thing.

Probably something that doesn't work at all.
But the idea was to define a variable as 'unsigned long'. Giving me 32 Bits to store the frequency extracted from the byte array.

I'm ultimately aiming to have two functions. One to inquire upon the module parameters, and one to tell the module which parameters are to be used.
I wanted to reuse the same data structure for both functions. So the unsigned long variable evolved into being defined within a structure I called 'data_out'.

Which probably should have been called 'data_in'.

No, not quite. Unless I'm reading the data sheet wrong.
Both command responses are 10 bytes. But the command to tell the module to provide it's current parameters, is 7 Bytes. While the command to set those parameters is 14 Bytes.

I find it a little bit lumpy. Which is why I wanted to abstract it out a bit.

That's what I meant

To get the frequency you need to left shift the bytes

  byte Fdata[3] = {0x06, 0x9F, 0x00}; // LSByte is in Fdata[2]

  unsigned long frequency = (unsigned long) Fdata[0] << 16 | (unsigned long) Fdata[1] << 8 | Fdata[2];

I understand what is happening here. But the syntax has me a little lost.
what does the parenthesis around '(unsigned long)' signify?

The byte value is being cast to unsigned long. The compiler will default to 16-bit integers when using the Mega, in order to do a 16-bit shift you have to explicitly tell the compiler to use a 32-bit data type.

what does the parenthesis around '(unsigned long)' signify?

The byte value is being changed into an unsigned long.

I see you have ignored my advice about reading the Arduino Reference.

I decided to take a sabbatical. Hopefully that will help me to write code with much more clarity and focus. I then re-wrote what I had, more or less from scratch. In so doing I think I managed to fix most of the smaller issues. As of right now, what I have compiles, and seems to behave. Except for the minor inconvenience of not reporting any of the correct values.

Getting module settings... Response Valid
Frequency 	 FSK-DR 	 Baud 		 Power 		 Parity
0 Khz 		 0 Kbps 	 0 Kbps 	 0 Dbm 

The code I am currently running:

// Arduino driver for DORJ-FSK Transmitter/Reciever modules.

int SetA = 40;                  // Set labels for each pin.
int TXD = 18;
int RXD = 19;
int AUX = 42;
int SetB = 41;

void setup()
{
pinMode(SetA, OUTPUT);          // Make SETA Pin Output.
pinMode(SetB, OUTPUT);          // Make SetB Pin Output.
pinMode(AUX, INPUT_PULLUP);     // Make AUX Pin Input.
Serial.begin(9600);             // Instantiate communication over USB.
Serial1.begin(9600);            // Instantiate communication over RX/TX pins.

int drfsk;
int baud;
int power;
String parity;
bool valid_message = false;
unsigned long frequency;

Serial.print("Getting module settings... ");
read_settings(frequency, drfsk, baud, power, parity, valid_message);
if (valid_message = true)
  {
    Serial.println("Response Valid");
    char strBuf[80];
    Serial.println("Frequency \t FSK-DR \t Baud \t\t Power \t\t Parity");
    sprintf(strBuf,"%u Khz \t\t %u Kbps \t %u Kbps \t %u Dbm \t\t\ %s",frequency,drfsk,baud,power,parity);
    Serial.print(strBuf);
  }
else
  {
    Serial.println("Response Invalid");
  }
}

void read_settings(unsigned long frequency, int drfsk, int baud, int power, String parity, bool valid_message)           // Get parameters from the module and send to terminal.
{
byte dorj_status_cmd[7] = {0xff,0x56,0xAE,0x35,0xA9,0x55,0xF0};                                                       // Command used to read from module.
digitalWrite(SetA, HIGH);                                                                                             // Ask module to enter setup/sleep mode.
if (digitalRead(AUX)==HIGH) {Serial1.write(dorj_status_cmd,7);}                                                       // Monitor AUX Pin, then send status request when ready.
byte dorj_response[10];                                                                                               // Array for module response.
Serial1.readBytes(dorj_response,10);                                                                                  // Aquire response from module.
digitalWrite(SetA, LOW);                                                                                              // Return module to normal opperation.
digitalWrite(SetB, HIGH);

if (dorj_response[0] == 0x24 && dorj_response[1] == 0x24 && dorj_response[2] == 0x24)                                 // Check for valid preamble.
  {
    valid_message = true;
    frequency = ((unsigned long) dorj_response[3] << 16 | (unsigned long) dorj_response[4] << 8 | dorj_response[5]);
    power = (dorj_response[7] + 1) * 3;                                                                               // Dorj Module represents signal power as 7 steps of 3-Dbm.
                                                                                                                      // Add one so that each step is no longer 0 Indexed.
                                                                                                                      // Multiply by 3 to get signal power in Dbm.
    switch (dorj_response[6])
      {
      case 0x00:
      drfsk = 1;
      break;
      case 0x01:
      drfsk = 2;
      break;
      case 0x02:
      drfsk = 5;
      break;
      case 0x03:
      drfsk = 10;
      break;
      case 0x04:
      drfsk = 20;
      break;
      case 0x05:
      drfsk = 40;
      break;
      }
    
    switch (dorj_response[8])
      {
      case 0x00:
      baud = 1200;
      break;
      case 0x01:
      baud = 2400;
      break;
      case 0x02:
      baud = 4800;
      break;
      case 0x03:
      baud = 9600;
      break;
      case 0x04:
      baud = 19200;
      break;
      case 0x05:
      baud = 38400;
      break;
      case 0x06:
      baud = 57600;
      break;
      }
     
    switch (dorj_response[9])
      {
        case 0x00:
        parity = "None";
        break;
        case 0x01:
        parity = "Even";
        break;
        case 0x02:
        parity = "Odd";
        break;
      }
  }
else 
  {
      valid_message = false;
  }
return 0;
}

void loop()
{
}

I get quite a few Warnings when I compile you sketch.

This one is a very common newbie mistake and will make the code non-fuctional

C:\Temp\arduino_modified_sketch_848539\sketch_sep13a.ino:26:21: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
   if (valid_message = true)
       ~~~~~~~~~~~~~~^~~~~~
should be ==