Go Down

Topic: Help with Serial Communication between arduinos (Read 293 times) previous topic - next topic

Evincou

Basically i have two arduinos, One reading the value of joysticks (potentiometers) and another that will write to servos, they have to be seperate for reasons i won't get into but i am wondering what's the best approach for this.

Also i need to send an analog read from the 'servo arduino' to the 'joystick arduino', so there will be communication going both ways.

Any help is very much appreciated, just a few pointers in the right direction thats all.


PaulS

Quote
they have to be seperate for reasons i won't get into but i am wondering what's the best approach for this.
Wired or wireless?
Close or far side of the moon or somewhere in between?
How critical is it that information be communicated?
How much information? How often?

You've given practically nothing to go on.
The art of getting good answers lies in asking good questions.

terryking228

Hi,
If it's within 100 feet or so, try the example here:

https://arduinoinfo.mywikis.net/wiki/SoftwareSerialRemoteExample

If it's LONG way away, send data through RS485 transceivers like in this example:

http://arduinoinfo.mywikis.net/wiki/SoftwareSerialRS485Example
Regards, Terry King terry@yourduino.com  - Check great prices, devices and Arduino-related boards at http://YourDuino.com
HOW-TO: http://ArduinoInfo.Info

Idahowalker

#3
Feb 11, 2019, 09:07 pm Last Edit: Feb 11, 2019, 09:09 pm by Idahowalker
Adding to what was written above, the data sent could be sent as sentences with a character representing the beginning of a sentence, a character at the end of the sentence and a word separator.

Something like <DoThis,1,7,9>, where you have an instruction and instruction info.
<!,62,1,549,345,77,9><@,4,3,7><$,3,44,55,66>. That way if one Uno gets 22,77>, you know to discard that data stream.
 The below code reads from the serial port and collects the data to send to a parser.
Code: [Select]
void fReceiveSerial_LIDAR( void * parameters  )
{
  bool BeginSentence = false;
  sSerial.reserve ( StringBufferSize300 );
  char OneChar;
  for ( ;; )
  {
    EventBits_t xbit = xEventGroupWaitBits (eg, evtReceiveSerial_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY);
    if ( LIDARSerial.available() >= 1 )
    {
      while ( LIDARSerial.available() )
      {
        OneChar = LIDARSerial.read();
        if ( BeginSentence )
        {
          if ( OneChar == '>')
          {
            if ( xSemaphoreTake( sema_ParseLIDAR_ReceivedSerial, xTicksToWait0 ) == pdTRUE ) // no wait on semaphore
            {
              xQueueOverwrite( xQ_LIDAR_Display_INFO, ( void * ) &sSerial );
              xEventGroupSetBits( eg, evtParseLIDAR_ReceivedSerial );
              //
            }
            BeginSentence = false;
            break;
          }
          sSerial.concat ( OneChar );
        }
        else
        {
          if ( OneChar == '<' )
          {
            sSerial = ""; // clear string buffer
            BeginSentence = true; // found begining of sentence
          }
        }
      } //  while ( LIDARSerial.available() )
    } //if ( LIDARSerial.available() >= 1 )
    xSemaphoreGive( sema_ReceiveSerial_LIDAR );
  }
  vTaskDelete( NULL );
} //void fParseSerial( void * parameters  )


This code parses out the received data and send it to the proper functions:
Code: [Select]

void fParseLIDAR_ReceivedSerial ( void * parameters )
{
  // distribute received LIDAR info
  String sTmp = "";
  sTmp.reserve ( 20 );
  String sMessage = "";
  sMessage.reserve ( StringBufferSize300 );
  for ( ;; )
  {
    EventBits_t xbit = xEventGroupWaitBits (eg, evtParseLIDAR_ReceivedSerial, pdTRUE, pdTRUE, portMAX_DELAY) ;
    //  Display info from LIDAR
    xQueueReceive ( xQ_LIDAR_Display_INFO, &sMessage, QueueReceiveDelayTime );
    int commaIndex = sMessage.indexOf(',');
    sTmp.concat ( sMessage.substring(0, commaIndex) );
    sMessage.remove( 0, (commaIndex + 1) ); // chop off begining of message
    if ( sTmp == "!" )
    {
      sLIDAR_Display_Info = sMessage;
      // reset watchdog variables upon receipt of LIDAR info
      xSemaphoreTake ( sema_LIDAR_Watchdog_Counter, xSemaphoreTicksToWait );
      LIDAR_Watchdog_Counter = 1;
      xSemaphoreGive ( sema_LIDAR_Watchdog_Counter );
      xSemaphoreTake ( sema_LIDAR_OK, xSemaphoreTicksToWait );
      bLIDAR_OK = true;
      xSemaphoreGive ( sema_LIDAR_OK );
    }
    if ( sTmp == "@" )
    {
         // xSemaphoreTake ( sema_Vbatt, xSemaphoreTicksToWait );
         // sVbatt = sMessage;
         // xSemaphoreGive( sema_Vbatt );
    }
    if ( sTmp == "#")
    {
      xSemaphoreTake( sema_LIDAR_Alarm, xSemaphoreTicksToWait );
      sLIDAR_Alarm_info = sMessage;
      xSemaphoreGive( sema_LIDAR_Alarm );
      xEventGroupSetBits( eg, evtfLIDAR_Alarm );
    }
    sTmp = "";
    sMessage = "";
    xSemaphoreGive( sema_ParseLIDAR_ReceivedSerial );
  }
  vTaskDelete( NULL );

Evincou

#4
Feb 11, 2019, 09:50 pm Last Edit: Feb 11, 2019, 10:02 pm by Evincou
Thanks for the help guys, sorry for being vague, it gonna be a wired connection and i need information sent as quickly as possible, basically think of a wired model plane, it has servos joysticks and you don't want lagg in the transmission, so there would be very frequent updates of the servos, but not a huge amount of information required for that,

PaulS

Next question. What kind of Arduinos? Arduinos with multiple hardware serial ports, such as the Mega, Due, Leonardo, and some others, would make the job easy. SoftwareSerial, AltSoftSerial, and NewSWSerial can be used if you only have one hardware serial port, with various tradeoffs (slow, high processor load, limited to specific pins, etc.)

If you are just sending servo position data, that can be sent in binary, instead of converting to ASCII and back.
The art of getting good answers lies in asking good questions.

Evincou

Yah so i have an arduino due as the main computer, incharge of the joystick potentiometers and a nano onboard controlling the servos, will those libraries work for both or only for due?

PaulS

You shouldn't need software serial on the Due. It has 4 hardware serial ports.

The Nano has only one serial port. A Teensy is about the same size, can be programmed using the Arduino IDE, and has 2 hardware serial ports.
The art of getting good answers lies in asking good questions.

Evincou

I see, thanks for the help anyway, im gonna play around with the two boards for a while and see if i can make heads or tails of this, i'm sure it will come to me in time

PaulS

I see, thanks for the help anyway, im gonna play around with the two boards for a while and see if i can make heads or tails of this, i'm sure it will come to me in time
The SoftwareSerial library comes with examples, showing how to connect the other device to the required pins. So do the other options.

Connecting one of the hardware serial ports on the Due is a matter of using matching N values for RXN, TXN, and SerialN.
The art of getting good answers lies in asking good questions.

GolamMostafa

#10
Feb 12, 2019, 09:22 am Last Edit: Feb 12, 2019, 04:38 pm by GolamMostafa
@OP
Communication between DUE and NANO over Hardware UART Port (UART) of DUE and Software UART Port (SUART) of NANO.

1.  Connect wiper point of the Joystick Potentiometer at A0-pin of DUE and set the wiper voltage at approx. 2.35V (test volt).

2.  Connect TX1-pin with DPin-2/D2 (SRX-pin of NANO) of NANO.

3.  Connect RX1-pin with DPin-3/D3 (STX-pin of NANO) of NANO.

4.   Connect GND-pin of DUE with GND-pin of NANO.

5.   Read the wiper voltage (say, 2.35) from A0-pin and send it as float number (2.35) to NANO over the UART1 Port of DUE.
Code: [Select]
unsigned x = analogRead(A0); //x = 0x02D9 = 729  //for DUE Vref = 3.3V only choice
float y = (float)((3.3/1023.0)*x); // y ~= 2.35
Serial1.print(y, 2);  //DUE sends four UART frames/ASCII Codes to NANO for symbols: 2, ., 3, 5


6.  Check that digit 2 has arrived to NANO; if it has arrived, save it in a variable.
(When 2 (UART Frame/ASCII Code = 0011 0010) arrives to NANO via its Software UART Port (SUART), the NANO is interrupted and the received ASCII code is immediately saved in a FIFO type Buffer. The SUART Port is created by including these two lines in the sketch of NANO: #include<SoftwareSerial.h; and SoftwareSerial(2, 3);.)
Code: [Select]
byte x1 = SUART.available();  // X1 ==0 means that no character has arrived
if(x1 != 0)
{
    byte x2 = SUART.read(); //charcater/symbol/digit has arrived and it is in buffer; read it from Buffer.
    Serial.write(x2);             //Serial Monitor of NANO show show 2; it verifies that you have got 2
}


7.   Hope that you have got the principles of UART communication. Write full codes to reconstruct 2.35 from the received frames and then use it to control the position of the shaft of Servo. Post your codes, we will try to help you; we have all the hardware resources to test your sketch.

8.  Sketch for DUE
Code: [Select]
void setup()
{
  Serial.begin(9600); //hardware UART0 of DUE
  Serial1.begin(9600); //hardware UART1 of DUE
  analogReadResolution(10);
  analogReference(AR_DEFAULT); //3.3V for DUE (only option)
}

void loop()
{
  unsigned int x2 = analogRead(A0); //testing 3.30/2 = 1.65V
  Serial1.print('<');
  float x3 = (float)((5 / 1023.0) * x2); // x3 = 1.65V
  Serial.println(x3, 2);
  Serial1.print(x3, 2); //ASCII codes of 3, ., 3, 0 are sent
  Serial1.print('>');
  delay(1000);  //transmission intervavl
}


9.  Sketch for UNO/NANO
Code: [Select]
#include<SoftwareSerial.h>
SoftwareSerial SUART(2, 3);//SRX, STX
char ascArray[20] = "";
int i = 0;
bool flag1 = false;

void setup()
{
  Serial.begin(9600);
  SUART.begin(9600);
}

void loop()
{
  if (SUART.available() > 0)
  {
    if (flag1 == false)
    {
      char x1 = SUART.read();
      if (x1 == '<')
      {
        flag1 = true;
      }
    }
    else
    {
      char x2 = SUART.read();
      if (x2 != '>')
      {
        ascArray[i] = x2;
        i++;
      }
      else
      {
        float x3 = atof(ascArray);
        Serial.println(x3, 2);   //or drive Servo; myervo.write(arg);
        i = 0;
        flag1 = false;
      }
    }
  }
}

Robin2

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

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

You can send data in a compatible format with code like this (or the equivalent in any other programming language)
Code: [Select]
Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker


...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up