LoRa to 485

Hi ,

I'm trying to control a PTZ camera wirelessly using 2 nanos and LoRa transceivers. I have a joystick and from the a-d's with a little maths I'm able to generate the correct 7 bytes for a varity of camera actions.

I can send these commands from one nano to the other, however they seam to drop the leading zeros of any byte so for example FF 01 is transmitted as 2551. at the moment im sending the 7 bytes using a for loop however I have tried sending 1 at a time also without sucsess.

I want to be able to store the incomming bytes in an array or set of variables so I can send thes to the serial port.

Can anyone advise?

Below is my sending code ill replay on my other machine with my recieving code.

Thank you for reading

Paul

#include <SPI.h>
#include <LoRa.h>
#define joypan A1
#define joytilt A2
#define joyzoom A3

int counter = 0;
int input8 =3; //button on pin 3
int input4 =4; //button on pin 4
int input2 =5; //button on pin 5
int input1 =6; //button on pin 6
int panValue;
int tiltValue;
int zoomValue;

byte msg[7];

int panbyte4;
int tiltbyte4;
int zoombyte4;
int panSpeed;
int tiltSpeed;
//int byte4=(panbyte4+tiltbyte4+zoombyte4);

void setup() {
 pinMode(input8 , INPUT_PULLUP);
 pinMode(input4 , INPUT_PULLUP);
 pinMode(input2 , INPUT_PULLUP);
 pinMode(input1 , INPUT_PULLUP);
 Serial.begin(9600);
 
 while (!Serial);

 Serial.println("LoRa Sender");

 if (!LoRa.begin(433E6)) {
   Serial.println("Starting LoRa failed!");
   while (1);
 }
}

void sendMessage() {
 
 Serial.print("Message1");
 // send packet
 LoRa.beginPacket();

 for (byte i = 0; i<7; i++) {
   LoRa.print (msg[i],HEX);
  
 }
 
 LoRa.endPacket();

}

void movement(){
 Serial.print("moving");
 Serial.println ();
  Serial.print("panValue: ");
 Serial.println(panValue);
 if (panValue >520)
   panbyte4 = 0x04;
   panSpeed = (panValue-520)/2;
 if (panValue <480)
   panbyte4 = 0x02;
   panSpeed = (480-panValue)/2;
 
 Serial.print("tiltValue: ");
 Serial.println(tiltValue);
 if (tiltValue >520)
   tiltbyte4 =0x08;
   tiltSpeed = (tiltValue-520)/2;
 if (tiltValue <480)
   tiltbyte4 =0x10;
   tiltSpeed =  (480-tiltValue)/2;

 Serial.print("zoonValue: ");
 Serial.println(zoomValue);
 if (zoomValue >520)
   zoombyte4 =0x20;  // these values are wrong check and change
 if (zoomValue < 480)
   zoombyte4 =0x40;  // these values are wrong check and change

 msg[0] =0xFF;
 msg[1] =0x01;
 msg[2] =0x00;
 msg[3] = byte(panbyte4 + tiltbyte4 + zoombyte4);
 msg[4] = byte(panSpeed);
 msg[5] = byte(tiltSpeed);
 msg[6] = byte((msg[1] + msg[2] + msg[3] + msg[4] + msg[5])%256);

 Serial.print (msg[0]);
 Serial.println ();
 Serial.print (msg[1]);
 Serial.println ();
 Serial.print (msg[2]);
 Serial.println ();
 Serial.print (msg[3]);
 Serial.println ();
 Serial.print (msg[4]);
 Serial.println ();
 Serial.print (msg[5]);
 Serial.println ();
 Serial.print (msg[6]);
 Serial.println ();
 
 for (byte i = 0; i<7; i++) {
   Serial.print (msg[i]);
 }
 Serial.println ();

 sendMessage();


 msg[0] =0xFF;
 msg[1] =0x01;
 msg[2] =0x00;
 msg[3] =0x00;
 msg[4] =0x00;
 msg[5] =0x00;
 msg[6] =0x01;

 delay(500);

 sendMessage();


 delay(2000);
}

void loop() {


 msg[0] =0x00;
 msg[1] =0x00;
 msg[2] =0x00;
 msg[3] =0x00;
 msg[4] =0x00;
 msg[5] =0x00;
 msg[6] =0x00;
 //msg[7] =0x00;
 //for (byte i = 0; i<7; i++) {
 //  Serial.print (msg[i]);
 //}
 Serial.println ();
 Serial.print("looping: ");
 Serial.println(counter);
 panValue = analogRead(joypan);
 tiltValue = analogRead(joytilt);
 zoomValue = analogRead(joyzoom);
 if (panValue >520)
   movement();
 if (panValue <480)
   movement();
 if (tiltValue >520)
   movement();
 if (tiltValue <480)
   movement();
 if (zoomValue >520)
   movement();
 if (zoomValue <480)
   movement();
 

   

 

 //Serial.println (msg[1]);
 
 delay(2000);
 




 

 
 
 
 if ((digitalRead(input8)== LOW )&&  (digitalRead(input4)== LOW )&& (digitalRead(input2)== LOW )&&  (digitalRead(input1)== LOW )) {// this line checks for 1111 or F
   sendMessage();
   
 }
 
 
 




 counter++;

 delay(250);
}

here is my other code

#include <SPI.h>
#include <LoRa.h>
#include <SoftwareSerial.h>

#define SSerialRX        7  //Serial Receive pin
#define SSerialTX        8  //Serial Transmit pin

#define SSerialTxControl 3   //RS485 Direction control

#define RS485Transmit    HIGH
#define RS485Receive     LOW

SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX

int ptz;
int byteReceived;
int byteSend;
byte msg[7];

void setup() {
 Serial.begin(9600);
 pinMode(SSerialTxControl, OUTPUT);

 digitalWrite(SSerialTxControl, RS485Receive);
 
 while (!Serial);

 RS485Serial.begin(4800);

 Serial.println("LoRa Receiver");

 if (!LoRa.begin(433E6)) {
   Serial.println("Starting LoRa failed!");
   while (1);
 }
}


void send485(){

 digitalWrite(SSerialTxControl, RS485Transmit);
 
 RS485Serial.write(0xFF);//,0x01,0x00,0x52,0x31,0x57); 
 RS485Serial.write(0x01);
 RS485Serial.write(0x01);
 RS485Serial.write(0x52);
 RS485Serial.write(0x31);
 RS485Serial.write(0x57);

 digitalWrite(SSerialTxControl, RS485Receive); 

 Serial.print ("in the loop");
 
}

void loop() {
 msg[0] = 0x00;
 msg[1] = 0x00;
 msg[2] = 0x00;
 msg[3] = 0x00;
 msg[4] = 0x00;
 msg[5] = 0x00;
 msg[6] = 0x00;
 
 // try to parse packet
 int packetSize = LoRa.parsePacket();
 if (packetSize) {
   // received a packet
   Serial.print("Received packet '");
   Serial.println();

   // read packet
   while (LoRa.available()) {
     Serial.print((byte)LoRa.read());
     //ptz = ((char)LoRa.read());
     //Serial.print(ptz);

     //for ( char i =0; i<7; i++) {
       //msg[i] = (char(LoRa.read()));
     //}
   }
  
   Serial.println();

   //delay (500);

   send485();

 
 }
}

Please edit your posts to add code tags, as described in the "How to use this forum" post.

If you want to install a different LoRa library, it includes worked examples for using a joystick to remote control servos, see here;

Example programs 35 and 36.

The example even adjusts itself to stay within 10% required for most ISM bands use.

The version for the 2.4Ghz LoRa device (SX1280) runs at as high a duty cycle that it can.

True that example is for 1 XY joystick and 1 button, but the code should be easy enough to expand to two joysticks and up to 8 buttons.

Hi

jremington noted and added.

srnet thank you. that's definitely worth a look at read Ill see if i can use that as it could save me lots of time and research. If so this will really help with my project and ill post my code here for others after.

If not I think I have some ideas for some of the issues when I was thinking last night

Firstly I don't need to send all 7 bytes as the first three never change so i could store those on the receiver.
The last byte is a checksum this could also be worked out on the receiver.

To stop the dropping of leading 0 i could add 100 before sending and then remove after receiving.

This would only leave the how to store the recieved data

Thank you once again I will update once I have progressed hopefully with good news.

Thanks

Paul

Hi,

Thank you for your advice earlier srnet, I had a look at the git hub you pointed to but found it too complex to follow.

So i have worked more on with my own code removing unnecessary things and have made some progress.

The sender code now only sends 3 messages, using 3 digit number for each. These are being sent and i can read them on the receiver using the Serial.print command.

However I just cant save the data when i receive it. im adding both my send and recieve code below could anyone have a look and point me in the direction. i have spent all day on it. Is it something to do with casting? i think the LoRa has to end data as a char.

thank you for reading.

Paul

Transmit code

#include <SPI.h>
#include <LoRa.h>
#define joypan A1
#define joytilt A2
#define joyzoom A3

int counter = 0;
int input8 =3; //button on pin 3
int input4 =4; //button on pin 4
int input2 =5; //button on pin 5
int input1 =6; //button on pin 6  for later use
int panValue;
int tiltValue;
int zoomValue;

int msgone;
int msgtwo;
int msgthree;

int panbit;
int tiltbit;
int zoombit;
int panSpeed;
int tiltSpeed;

int partone;
int parttwo;
int partthree;

//----------------------------------------------------------------

void sendMessage(){


  LoRa.beginPacket();
  LoRa.print (int(partone));
  LoRa.print (int(parttwo));
  LoRa.print (int(partthree));
  Serial.println ("messagesent");

  LoRa.endPacket();
  
}




//----------------------------------------------------------------

void setup() {
  pinMode(input8 , INPUT_PULLUP);
  pinMode(input4 , INPUT_PULLUP);
  pinMode(input2 , INPUT_PULLUP);
  pinMode(input1 , INPUT_PULLUP);
  
  Serial.begin(9600);
  
  while (!Serial);

  Serial.println("LoRa Sender");

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

//----------------------------------------------------------------------



//----------------------------------------------------------------------

void makePackets() {

  partone = (msgone +100);
  parttwo = (msgtwo + 100);
  partthree = (msgthree +100);

  Serial.print("partone: ");
  Serial.println(partone);
  Serial.print("parttwo: ");
  Serial.println(parttwo);
  Serial.print("partthree: ");
  Serial.println(partthree);

  sendMessage();

  
}
//----------------------------------------------------------------------

void movement() {

  msgone = 0;
  msgtwo = 0;
  msgthree =0;

  //Serial.print("panValue: ");
  //Serial.println(panValue);
  
  if (panValue >520) {
    panbit = 4;
    panSpeed = (panValue - 520)/2;}
  if (panValue <480){
    panbit = 2;
    panSpeed = (480 - panValue)/2;}
  if ((panValue <520) && (panValue >480)){
    panSpeed = 0;
    panbit = 0;}
   
  //Serial.print("panSpeed: ");
  //Serial.println(panSpeed);
  //Serial.print("panbit: ");
  //Serial.println(panbit);
  //Serial.print("tiltValue: ");
  //Serial.println(tiltValue);
  
  if (tiltValue >520){
    tiltbit =8;
    tiltSpeed = (tiltValue-520)/2;}
  if (tiltValue <480){
    tiltbit =16;
    tiltSpeed =  (480-tiltValue)/2;}
  if ((tiltValue <520) && (tiltValue >480)){
    tiltSpeed = 0;
    tiltbit = 0;}

  //Serial.print("tiltSpeed: ");
  //Serial.println(tiltSpeed);
  //Serial.print("tiltbit: ");
  //Serial.println(tiltbit);
  //Serial.print("zoonValue: ");
  //Serial.println(zoomValue);
  
  if (zoomValue >520) {
    zoombit =32;  }
  if (zoomValue < 480){
    zoombit =64;  }
  if ((zoomValue <520) && (zoomValue >480)){
    zoombit = 0;}

  //Serial.print("zoombit: ");
  //Serial.println(zoombit);
  //Serial.println ();

  msgone = (panbit + tiltbit + zoombit);
  msgtwo = panSpeed;
  msgthree = tiltSpeed;
  
  Serial.print("msgone: ");
  Serial.println(msgone);
  Serial.print("msgtwo: ");
  Serial.println(msgtwo);
  Serial.print("msgthree: ");
  Serial.println(msgthree);

  makePackets();
  

  
}



//-----------------------------------------------------------------------

void loop() {
  

  Serial.println ();
  Serial.print("looping: ");
  Serial.println ();
  panValue = analogRead(joypan);
  tiltValue = analogRead(joytilt);
  zoomValue = analogRead(joyzoom);
  if (panValue >520)
    movement();
  if (panValue <480)
    movement();
  if (tiltValue >520)
    movement();
  if (tiltValue <480)
    movement();
  if (zoomValue >520)
    movement();
  if (zoomValue <480)
    movement();
  delay(2300);
}
//---------------------------------------------------------------------

Receive code

#include <SPI.h>
#include <LoRa.h>
#include <SoftwareSerial.h>

#define SSerialRX        7  //Serial Receive pin
#define SSerialTX        8  //Serial Transmit pin

#define SSerialTxControl 3   //RS485 Direction control

#define RS485Transmit    HIGH
#define RS485Receive     LOW

SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX


int byteReceived;
int byteSend;
byte msg[7];
char bob;
char ctest;
int itest;



//---------------------------------------------------------------------------------------------

void setup() {
  Serial.begin(9600);
  pinMode(SSerialTxControl, OUTPUT);

  digitalWrite(SSerialTxControl, RS485Receive);
  
  while (!Serial);

  RS485Serial.begin(4800);

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

//----------------------------------------------------------------------------------
void send485(){

  digitalWrite(SSerialTxControl, RS485Transmit);
  
  RS485Serial.write(0xFF);//,0x01,0x00,0x52,0x31,0x57); 
  RS485Serial.write(0x01);
  RS485Serial.write(0x01);
  RS485Serial.write(0x52);
  RS485Serial.write(0x31);
  RS485Serial.write(0x57);

  digitalWrite(SSerialTxControl, RS485Receive); 

  //Serial.print ("in the loop");
  
}


//--------------------------------------------------------------------------------------------------

void read() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    //Serial.println(packetSize);
    // received a packet
    //Serial.print("Received packet size '" + packetSize);

    // read packet
    
    while (LoRa.available()) {
      Serial.println();
      Serial.print((char)LoRa.read());
     // bob =((char)LoRa.read());
      //for( int i =0; i<8; i++) {
        //bob[i] = (char(LoRa.read()));}
        //Serial.print(bob[i]);}
      Serial.print(bob);
      
     
    }

   
  }

  
}

//--------------------------------------------------------------------------------------------------
void loop() {
  //msg[0] = 0x00;
  //msg[1] = 0x00;
  //msg[2] = 0x00;
  //msg[3] = 0x00;
  //msg[4] = 0x00;
  //msg[5] = 0x00;
  //msg[6] = 0x00;

  read();
  

  //Serial.print(bob);
  
  // try to parse packet
 // int packetSize = LoRa.parsePacket();
  //if (packetSize) {
    // received a packet
    //Serial.print("Received packet '");
    //Serial.println();

    // read packet
    //while (LoRa.available()) {
      //bob =((char)LoRa.read());
      //Serial.println (bob);
      //ptz = ((char)LoRa.read());
      //Serial.print(ptz);

      //for ( char i =0; i<8; i++) {
        //bob[i] = (char(LoRa.read()));
        //Serial.print(bob[i]);
        
      //}

    //delay(200);
    //for ( char i =0; i<8; i++) {
      //Serial.print(bob[i]);
    //}
    //for ( char i =0; i<8; i++) {
      //Serial.print(bob[i]);    
     // }      
    //Serial.println();
    //Serial.println(bob[0]);
    //Serial.println(bob[0]);
        
        
      
    //}
   
    //Serial.println();

    delay (500);

    //send485();

  
  //}
}

However I just cant save the data when i receive it.

What does this mean? Please explain what you expect to happen and what happens instead.

The lines below are a bit of a mess, and is where some of the problems lie.
What do you expect to happen when you print "bob", which is declared a single character, and undefined?
The following line won't work unless the result of LoRa.read() is a zero terminated C-string.

      Serial.print((char)LoRa.read());
     // bob =((char)LoRa.read());
      //for( int i =0; i<8; i++) {
        //bob[i] = (char(LoRa.read()));}
        //Serial.print(bob[i]);}
      Serial.print(bob);

Hi jremington,

Thank you for your reply,

It is a bit of a mess i keep commenting out and in as I try different things.

so if i do the following in the while loop:

 while (LoRa.available()) {
      Serial.println();
      Serial.print((char)LoRa.read());

I get the data printed in the serial monitor one character per line as i would expect.

If I comment out the second line and have:

 while (LoRa.available()) {
      //Serial.println();
      Serial.print((char)LoRa.read());

I get the data printed on the same line. If I move the second line above the while loop i get each packet on a separate line so this all works right, I can see the data I'm receiving is the same as what I'm sending. The problem comes when i try to save the data so I can work on it.

So i have tried some different ways to save the data, if i define bob (char bob;) and change the while loop to:

 while (LoRa.available()) {
     bob =((char)LoRa.read());
      Serial.print(bob);

I also here get the correct data printed on individual lines so it looks like the data has been saved correctly.

however if i send the the data to a new function and try to manipulate it as so:

Serial.println();
    while (LoRa.available()) {
      bob =((char)LoRa.read());
      Serial.print(bob);
      math();



void math(){
  ctest = (bob -100);
  Serial.print(ctest);
}

I get the following out put the reversed ? being what i think the math() function is printing.

1⸮1⸮0⸮1⸮4⸮5⸮1⸮5⸮5

Now if I print bob from the math function that prints correctly. So I think it to do with the data type I can't perform maths on it.So I think Ineed to change the data type and also if possible save each piece in an array.

If any one can help it would be amazing i will share my code and try and help others as this is something I'm going to be working on more and more in the future

Thanks

Paul

If you want to save (and later do something with) an entire line of characters, you need to declare a character array and store each incoming character in it. For use with the string handling routines, the array must be terminated with a zero byte.

This is the same problem as input from serial, so start by studying this tutorial: Serial input basics.

Hi,

Success!!

Thank you jremington for your pointers in the right direction

I used a variable count to count through the iterations of the read from the LoRa radio and stored these in an array as suggested.

each digit was stored as a char so when I copied them to an array the values where out by 48 so i simply deducted 48 from there value.

From there using simple maths I was able to pull the correct parts of the array and build my 485 commands. These were then sent to the software 485 where I was able to see them on a protocol analyser and they look correct.

The code below is the finished receiver code, the sender code was already correct after reducing the number of bytes sent.

#include <SPI.h>
#include <LoRa.h>
#include <SoftwareSerial.h>

#define SSerialRX        7  //Serial Receive pin
#define SSerialTX        8  //Serial Transmit pin

#define SSerialTxControl 3   //RS485 Direction control

#define RS485Transmit    HIGH
#define RS485Receive     LOW

SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX



char incomming;

int part[9];

int byteReceived;
int byteSend;      
int count;           //used to count posistion in array
int comBOne;         //used to store first command
int comBTwo;         //used to store second command
int comBThree;       //used to store third command
int comBFour;        //used to store fourth command
int comBFive;        //used to store fifth command
int comBSix;         //used to store sixth command
int comBSeven;       //used to store seven command

int haltOne =255;
int haltTwo =1;
int haltThree =0;
int haltFour =0;
int haltFive =0;
int haltSix =0;
int haltSeven =1;
//--------------------------------------------------------------------------------------------

void command() { // this funtion create the decimal equivelents of all the camera controls from the we dont use the first and every third digit as they were used 
                // to keep the inegrity of leading zeros and all zero commands as the LoRa sender dros leading zeros off data sent

  comBOne =255;
  Serial.println(comBOne);
  comBTwo =1;
  Serial.println(comBTwo);
  comBThree = 0;
  Serial.println(comBThree);
  comBFour = ((10*part[1])+part[2]);
  Serial.println(comBFour);
  comBFive = ((10*part[4])+part[5]);
  Serial.println(comBFive);
  comBSix = ((10*part[7])+part[8]);
  Serial.println(comBSix);
  comBSeven =((comBTwo + comBThree + comBFour + comBFive + comBSix)%256);
  Serial.println(comBSeven);
  
}

//---------------------------------------------------------------------------------------------

void store(){
   
  part[count] =incomming;// adds each incomming digit to the int array part
    
}

//---------------------------------------------------------------------------------------------

void setup() {
  Serial.begin(9600);                                         //sets up serial port
  pinMode(SSerialTxControl, OUTPUT);                          //sets up output

  digitalWrite(SSerialTxControl, RS485Receive);               //sets up input 
  
  while (!Serial);                                            

  RS485Serial.begin(4800);                                    // sets up software serial port

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(433E6)) {                                   //runs lines below if and whilever LoRa not up
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

//----------------------------------------------------------------------------------------------
void send485(){ // this funtion sends the data out the soft RS485

  digitalWrite(SSerialTxControl, RS485Transmit);
  
  RS485Serial.write(comBOne); 
  RS485Serial.write(comBTwo);
  RS485Serial.write(comBThree);
  RS485Serial.write(comBFour);
  RS485Serial.write(comBFive);
  RS485Serial.write(comBSix);
  RS485Serial.write(comBSeven);

  digitalWrite(SSerialTxControl, RS485Receive); 


  delay(200);  // delay before stop comand will have to be adjusted so that camera action looks smooth to human eye


  digitalWrite(SSerialTxControl, RS485Transmit);  //this section ise used for the stop comand otherwise the camera continues the action forever.
  
  RS485Serial.write(haltOne); 
  RS485Serial.write(haltTwo);
  RS485Serial.write(haltThree);
  RS485Serial.write(haltFour);
  RS485Serial.write(haltFive);
  RS485Serial.write(haltSix);
  RS485Serial.write(haltSeven);

  digitalWrite(SSerialTxControl, RS485Receive); 

  
  
}

//------------------------------------------------------------------------------------------------

void read() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
        
    Serial.println();
    count = 0;      // sets variable to zero before reading packet
    while (LoRa.available()) {
      
      incomming =((char)LoRa.read()); // as a digit is recieved it is placed in the incomming char variable
            
      store();  // this funtion store the variables in an array
      count = (count + 1); // this counter is used to change the posistion that of the aray the variable incomming is stored in
             
    }

    for(int i =0; i<9; i++) {
      part[i] =(part[i]-48);    // this loops deducts 48 from every number in the part array as they were just changed to int format and assci and ints have a difference of 48
    }
    
    //Serial.print(part[1]);  // used for testing
    //Serial.print(part[2]);  // used for testing
    
    //Serial.print(part[4]);  // used for testing
    //Serial.print(part[5]);  // used for testing
    
    //Serial.print(part[7]);  // used for testing
    //Serial.print(part[8]);  // used for testing
    Serial.println();
    command();

    send485();
   
  }
  
}

//-----------------------------------------------------------------------------------------------------
void loop() {
  
  read(); //calls funtion to monitor LoRa radio incomming mssages

    

    
}

Thank you again while no one did this for me I was pointed in the right direction and that help was massive in this outcome.

I will come on here each week and try and repay the help.

Paul

Glad you got it to work!

This bit of code can be compacted greatly by defining a single character array and sending it all in one line:

  RS485Serial.write(comBOne);
  RS485Serial.write(comBTwo);
  RS485Serial.write(comBThree);
  RS485Serial.write(comBFour);
  RS485Serial.write(comBFive);
  RS485Serial.write(comBSix);
  RS485Serial.write(comBSeven);