Sending serial data back and forth.

Hello,
I have been learning programming language and working with Arduino on my own, but I have come to a standstill with my project. I have started building a tethered UUV. The idea is to use a "control case" with 2 joysticks and a switch to fully control the UUV's movement, some LCD's to show a few values, a screen for video monitoring etc.
As far as controlling the UUV goes, using a serial connection (to limit the amount of cables in the tether and reduce interference) it works well because that is just in one direction.
But now I want to return some sensor data such as current depth (and later on compass heading as well) from the UUV back to the control case for monitoring. And this is something I can't wrap my head around. Can anyone point me in the right direction?

My (working) code so far: (attachements)
I've left the return send and recieve text which I came up with in the program, but obviously that part does not work at all.

UUV_2.0_SENDER.ino (7.84 KB)

UUV_2.0_RECIEVER.ino (1.47 KB)

As your code is quite small please post it here rather than attaching it

Please follow the advice on posting code given in posting code

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless

Sender:

#include <Servo.h>
#include <LiquidCrystal.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <stdlib.h>

LiquidCrystal_I2C lcd1(0x27,16,2);
LiquidCrystal_I2C lcd2(0x21,16,2);

const int joy1yPin = 0;
const int joy1xPin = 1;
const int joy2yPin = 2;
const int led = 13;
const int button1 = 2;
const int button2 = 9;
int SS1 = LOW;
int SS2 = LOW;

int start = 0;
int end = 0;
int BB = 0;
int SB = 0;
int Rear = 0;
int RearT =0;
int Dive = 0;
int Light = 0;
int Depth = 0;
int Compass = 0;
int BBTmp = 0;
int SBTmp = 0;
int RearTmp = 0;
int DiveTmp = 0;
int LightTmp = 0;
int LCDBB = 0;
int LCDSB = 0;
int LCDRear = 0;



void setup()
{
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(led,OUTPUT);
  pinMode(button1,INPUT);
  pinMode(button2,INPUT);
    
  Serial.begin(9600);
 
 lcd1.begin();                  
 lcd1.print("UUV v2.0"); 
 lcd1.setCursor(0,1);        
 lcd1.print("INITIALIZING...");
 lcd2.begin();                  
 lcd2.print("UUV v2.0"); 
 lcd2.setCursor(0,1);       
 lcd2.print("INITIALIZING...");
 delay(1000);
}

void loop(){
  Calculations();
  Signalsend();
  Signalrecieve();
  Displays();
}

void Calculations(){

//
// FORWARD REVERSE
//
  
 int joy1y = analogRead(joy1yPin);         // variable joystick 1 y value
 if (joy1y < 511){                         // joystick down
  BB = map(joy1y, 0, 511, 10, 90);         // scale forward signal to BB ESC/SERVO with 
  SB = map(joy1y, 0, 511, 10, 90);         // scale forward signal to SB ESC/SERVO with
 }
 else if (joy1y > 515){                    // joystick up
  BB = map(joy1y, 1023, 511, 170, 90);     // scale reverse signal to BB ESC/SERVO with
  SB = map(joy1y, 1023, 511, 170, 90);     // scale reverse signal to SB ESC/SERVO with
 }
 else if (joy1y < 515 && joy1y > 511){
  BB = 90;                                 // no motor movement
  SB = 90;                                 // no motor movement
 }

//  
// LEFT RIGHT
//
  
 int joy1x = analogRead(joy1xPin);         // variable joystick 1 x value
 if (joy1x < 511) {                        // joystick left
  int xMapped=map(joy1x,0,511,90,0);       // map movement
  BB = BB - xMapped;                       // slow down BB with mapped value
  SB = SB + xMapped;                       // speed up SB with mapped value
  if (BB < 10) {                           // set max speed limit reverse
    BB = 10;
  }
  if (SB > 170) {                          // set max speed limit forward
    SB = 170;
  }                             
 }
 if (joy1x > 511) {                        // joystick right
  int xMapped=map(joy1x,1023,511,90,0);    // map movement with safety limit
  BB = BB + xMapped;                       // speed up BB with mapped value
  SB = SB - xMapped;                       // slow down SB with mapped value
  if (SB < 10) {                           // set max speed limit reverse
    SB = 10;
  }                              
  if (BB > 170) {                          // set max speed limit forward 
    BB = 170;
  }                             
 }

//  
// DEPTH CONTROL
//
  // READ BUTTON 
 
  if(digitalRead(button1)== HIGH){              
    SS1 = 1;
    digitalWrite(led, LOW);
  }
  if(digitalRead(button1)==LOW){
    SS1 = 0;
    digitalWrite(led, HIGH);
  }
    
  // READ JOY  
  
int joy2y = analogRead(joy2yPin);
 if (joy2y< 511){                           // joystick down
  RearT = map(joy2y, 0, 511, 10, 90);       // scale reverse signal to depth ESC/SERVO
 }
 else if (joy2y > 511){                     // joystick up
  RearT = map(joy2y, 1023, 511, 170, 90);   // scale reverse signal to depth ESC/SERVO
 }  
 if (RearT < 10) {                        // set speed limit dive
    RearT = 10;
 }                              
 if (RearT > 170) {                         // set speed limit surface 
    RearT = 170;
 }
  if (SS1 == 1){
    Rear = RearT;
    Dive = 90;
  }
  else{
    Dive = RearT;
    Rear = 90;
  }
  
//
// LIGHT  
//
// 
//  if(digitalRead(button2)== HIGH){              
//    Light = 1;
//    digitalWrite(led, LOW);
//  }
//  if(digitalRead(button2)==LOW){
//    Light = 0;
//    digitalWrite(led, HIGH);
//  }
}    

void Signalsend(){

// 
// SENDING SIGNALS
//

  if(BB != BBTmp || SB != SBTmp || Rear != RearTmp || Dive != DiveTmp || Light != LightTmp)
  {
    BBTmp = BB;
    SBTmp = SB;
    RearTmp = Rear;
    DiveTmp = Dive;
    LightTmp = Light;
  
    Serial.write(9);
    Serial.write(BB);
    Serial.write(SB);
    Serial.write(Rear);
    Serial.write(Dive);
    Serial.write(Light);
    Serial.write(9);
    Serial.flush();
    
   }
  }

void Signalrecieve(){
//
// RECIEVE SIGNALS
//
//
//    start = Serial.read();
//  
//    Serial.println("Start: ");
//    Serial.print(start, DEC);
//    if(start == 8){
//      int Depth = Serial.read();
//      int Compass = Serial.read();
//      
//    end = Serial.read();
//    Serial.println("End: ");
//    Serial.print(end, DEC);
//    if(end == 8)
//  {
//     
//    lcd2.setCursor(9,0);
//    lcd2.print("Compass");
//    lcd2.setCursor(9,1);
//   lcd2.print("Depth");
//  
//  }
// }
}

void Displays(){

//
// WRITE DISPLAY 1
//
  
 if (BB > 90){                             
   LCDBB = map(BB, 90, 170, 0, 10);        // scale forward speed in percentage
 }
 if (BB < 90){
   LCDBB = map(BB, 90, 10, 0, 10);         // scale reverse speed in percentage
 }
 if (SB > 90){
   LCDSB = map(SB, 90, 170, 0, 10);        // scale forward speed in percentage
 }
 if (SB < 90){
   LCDSB = map(SB, 90, 10, 0, 10);         // scale reverse speed in percentage
 }
 if (RearT > 90){
   LCDRear = map(RearT, 90, 170, 0, 10);   // scale dive speed in percentage
 }
 if (RearT < 90){
   LCDRear = map(RearT, 90, 10, 0, 10);    // scale surface speed in percentage
 }

 lcd1.clear();                // clear display
 lcd1.setCursor(8, 0);                      // place cursor row 1, collumn 1
 lcd1.print("DIVE");                    // write text
 lcd1.setCursor(13, 0);
  if ((LCDRear) < 100) {
    lcd1.print(" ");            // this writes a space to shove the number over one place if the number is 2 digits
    if ((LCDRear) < 10) {
      lcd1.print(" ");
    }
  }
 lcd1.print(LCDRear);             // now write the number
 
 lcd1.setCursor(0, 0);
  if (SS1 == HIGH){
    lcd1.print("STATIC");
  }
  else{
    lcd1.print("DYNAMIC");
  }
 
 lcd1.setCursor(0, 1);                      // place cursor row 2, collumn 1
 lcd1.print("BB");                          // write text
 lcd1.setCursor(4, 1);                      // place cursor row 2, collumn 3
  if ((LCDBB) < 100){ 
    lcd1.print(" ");            // this writes a space to shove the number over one place if the number is 2 digits
    if ((LCDBB) < 10) {
      lcd1.print(" ");            // this writes another space to shove the number over a total of 2 spaces if less than 2 digits
    }
  }
 lcd1.print(LCDBB);                         // write BB engine speed percentage

 lcd1.setCursor(8, 1);                      // place cursor row 2, collumn 7
 lcd1.print("SB");                          // write text
 lcd1.setCursor(13, 1);                     // place cursor row 2, collumn 9
  if ((LCDSB) < 100) {
    lcd1.print(" ");            // this writes a space to shove the number over one place if the number is 2 digits
    if ((LCDSB) < 10) {
      lcd1.print(" ");                // this writes another space to shove the number over a total of 2 spaces if less than 2 digits
    }
  }
 lcd1.print(LCDSB);                               // write SB engine speed percentage                                    // refresh in .5 seconds

// WRITE DISPLAY 2
  
 lcd2.clear();
 lcd2.setCursor(0,0);
 lcd2.print("Heading:");
 lcd2.setCursor(0,1);
 lcd2.print("Depth:");

}

Your receiver is reading stuff that may not be there.

Robin2 has an excellent serial handling tutorial.

Take a look at Serial input basics - updated

Reciever:

#include <Servo.h>
#include <LiquidCrystal.h>

Servo BBPin;
Servo SBPin;
Servo RearPin;
Servo DivePin;

int start = 0;
int end = 0;
int LightPin = 13;
int Depth = 0;
int Compass = 0;
int DepthTmp = 0;
int CompassTmp = 0;


void setup()
{
  BBPin.attach(2);
  SBPin.attach(3);
  RearPin.attach(4);
  DivePin.attach(5);
  Serial.begin(9600);
  
}

void loop()
{
  //
  // Read sensor values
  //
  
  Depth = analogRead(0);
  Compass = 180;
  
  //
  // RECIEVE SIGNALS
  //
  
     start = Serial.read();
  
//    Serial.println("Start: ");
    Serial.println(start, DEC);
    if(start == 9)
    {
      int BB = Serial.read();
      int SB = Serial.read();
        int Rear = Serial.read();
      int Dive = Serial.read();
        int Light = Serial.read();
        Serial.println(Light);
      
    end = Serial.read();
    Serial.println("End: ");
    Serial.print(end, DEC);
    if(end == 9)
  {
     
     BBPin.write(BB);
     SBPin.write(SB);
     RearPin.write(Rear);
     DivePin.write(Dive);
      if(Light == 1){
        digitalWrite(LightPin, HIGH);
      }
      else{
        digitalWrite(LightPin, LOW);
      }
    }
  }

// 
// SENDING SIGNALS
//
//  
//  if(Depth != DepthTmp || Compass != CompassTmp)
//  {
//    DepthTmp = Depth;
//    CompassTmp = Compass;
//      
//    Serial.write(8);
//    Serial.write(Depth);
//    Serial.write(Compass);
//    Serial.write(8);
//    Serial.flush();
//   }
  }

Still having the "5 minute waiting period"...
And I have read the the "Serial input basics" , but I don't quite understand the logic or structure behind it. So far I mostly programmed "by example". Seeing written code from a specific example, understanding the situation and function then modify and implement in my own project.

Without diving into your code, I'm guessing from your description that UUV = Unmanned Underwater Vehicle? AKA an ROV (Remotely Operated Vehicle).

I guess you need to decide if your system is going to be a command-response system or an ad-hoc system. With the command-response system, the remote device only sends back data when asked to by the controlling device. With the ad-hoc system, the remote device sends data whenever it wants to and you don't have to think about scheduling data request messages to send to the remote device.

According to the datasheet, the 328p micro has a full duplex hardware UART so you can send and receive at the same time.

A 9600 baud (960 chars/sec ish!) serial link would probably be fine for sending a few packets of data between the controller and the remote device.

Unmanned Underwater Vehicle indeed...

For the moment I am using 2 arduino uno's and was aiming at an ad-hoc system so I would have a constant visual of the depth and heading of the UUV.

chinookel:
Still having the "5 minute waiting period"...

only another 96 posts to go

And I have read the the "Serial input basics" , but I don't quite understand the logic or structure behind it.

Read it again.
Remember that serial is slow, and the microcontroller is very fast.

Example 5 of the serial input basics is probably a good starting point for you. The use of start and end markers lets the receiving device correctly determine the order of the data received.

EDIT: I should have also said that you would benefit more by understanding serial input basics from the start rather than just jumping in with example 5.

For example if you send a motor speed from -128 (full reverse) through 0 (stop) to +127 (full forward), then if your UUV receives a sequence of the data such as: 50, -50, 50, -50, 50, -50 etc, then which number belongs to which motor?

If you use start and end markers such as [ & ], then it becomes obvious to the UUV when the data is sent as [-50,50][-50,50] etc.

The technique in the 3rd example in Serial Input Basics
will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

...R

The first thing I suggest you do is document, in comments, the format of the messages you are sending in both directions.
Comma separated newline terminated i.e. CSV is a common format.
You could send the data in binary format. However sending as text is easier to debug, but requires text to number conversions in the receiver.

For an example of reading and parsing CSV data, without blocking the rest of your code from running, see my tutorial on Text I/O for the Real World which avoids low level byte handling and the associated coding errors.

Since you are trying to do more than one thing (task) 'at the same time', I suggest you look at my tutorial on Multi-tasking in Arduino

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.