1

Topic: Trouble with RemoteXY_Handler Communication

We are using RemoteXY to build an app GUI for our senior design project that controls a robot. Our configuration is using an Audrino MEGA 2560 with an ESP2866 and the Audrino IDE. Our GUI works for the most part as we can use the master switch to run the robot along with inputting two parameters for our code. However, we are not able to use the same master switch to stop our robots movement. Additionally, there is another switch in the GUI that does nothing when pressed even though we believe our program logic is fine. We believe we have some confusion on how RemoteXY_Handler actually communicates with the wifi board and audrino. Every time the Handler function is called, is there a data transfer or do we only need it once in the loop? Any help is appreciated. Our code is listed below: (Granted its not super efficient haha)

RemoteXY.switch_1 controls the master switch
RemoteXY.feed_switch controls our other switch (that doesn't work)


/*******************************************************************************
   MOTOR DRIVER SETUP

   THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTY AND SUPPORT
   IS APPLICABLE TO THIS SOFTWARE IN ANY FORM. CYTRON TECHNOLOGIES SHALL NOT,
   IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL
   DAMAGES, FOR ANY REASON WHATSOEVER.
********************************************************************************
   DESCRIPTION:

   This example shows how to drive a motor using the PWM and DIR pins.
   This example only shows how to drive a single motor for simplicity.
   For dual channel motor driver, both channel work the same way.


   CONNECTIONS:

   Arduino D9  - Motor Driver PWM Input
   Arduino D8  - Motor Driver DIR Input
   Arduino GND - Motor Driver GND


   AUTHOR   : Kong Wai Weng
   COMPANY  : Cytron Technologies Sdn Bhd
   WEBSITE  : www.cytron.io
   EMAIL    : support@cytron.io

*******************************************************************************/
#include <SoftwareSerial.h>
#include <Servo.h>
#include "CytronMotorDriver.h"
#define ENCA1 20
#define ENCB1 21
#define ENCA2 11
#define ENCB2 3
#define ENCA3 18
#define ENCB3 19
#define Lswitch 2

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
//   avoid using pins with LEDs attached

SoftwareSerial MyBlue(0, 1); // RX | TX
Servo myservo;

float pi = 3.14;

int firstclip = 1;
float T1 = 0;
float T2 = 0;
float T3 = 0;


float revTicks = 8245.92; // ticks per rev
float revWheel = pi; // inches traveled by one rev of wheel
float revTrack = 3 * pi; // inch
float revFeeder = 2 * pi; // inch
int clip_count = -1;
int total_clips = 0;
int Percent = 0;

float tpi = 440;

int pos1 = 0;
long prevT1 = 0;
float eprev1 = 0;
float eintegral1 = 0;
float target1 = 0;
int kp1 = 1.2;
int ki1 = 0;
int kd1 = 0;
int pwr1 = 0;

int pos2 = 0;
long prevT2 = 0;
float eprev2 = 0;
float eintegral2 = 0;
float target2 = 0;
int kp2 = 1;
int ki2 = 0;
int kd2 = 0;
int pwr2 = 0;

int pos3 = 0;
long prevT3 = 0;
float eprev3 = 0;
float eintegral3 = 0;
float target3 = 0;
int kp3 = 1.2;
int ki3 = 0;
int kd3 = 0;
int pwr3 = 0;


// Configure the motor driver.

CytronMD motor1(PWM_DIR, 9, 8);  // PWM 1 = Pin 9, DIR 1 = Pin 8. wheel
CytronMD motor2(PWM_DIR, 5, 4); // PWM 2 = Pin 5, DIR 2 = Pin 4. feeder
CytronMD motor3(PWM_DIR, 6, 7); // PWM 2 = Pin 6, DIR 2 = Pin 7. tread

/******************************************************************************************
   -- Jollybot GUI --

   This source code of graphical user interface
   has been generated automatically by RemoteXY editor.
   To compile this code using RemoteXY library 3.1.8 or later version
   download by link http://remotexy.com/en/library/
   To connect using RemoteXY mobile app by link http://remotexy.com/en/download/
     - for ANDROID 4.11.1 or later version;
     - for iOS 1.9.1 or later version;

   This source code is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
*/

//////////////////////////////////////////////
//        RemoteXY include library          //
//////////////////////////////////////////////

// RemoteXY select connection mode and include library
#define REMOTEXY_MODE__ESP8266_HARDSERIAL_POINT

#include <RemoteXY.h>


// RemoteXY connection settings
#define REMOTEXY_SERIAL Serial
#define REMOTEXY_SERIAL_SPEED 115200
#define REMOTEXY_WIFI_SSID "JollyBot"
#define REMOTEXY_WIFI_PASSWORD "HolidaySolutions"
#define REMOTEXY_SERVER_PORT 6377


// RemoteXY configurate
#pragma pack(push, 1)
uint8_t RemoteXY_CONF[] =   // 282 bytes
  { 255,6,0,2,0,19,1,16,31,1,7,52,8,28,22,6,132,26,1,2,
  1,8,10,22,11,132,26,31,31,83,84,65,82,84,0,83,84,79,80,0,
  7,52,8,45,22,6,132,26,1,129,0,8,6,21,3,24,77,97,115,116,
  101,114,32,67,111,110,116,114,111,108,0,129,0,8,41,23,3,8,76,101,
  110,103,116,104,32,111,102,32,76,105,103,104,116,115,0,129,0,8,24,18,
  3,8,67,108,105,112,32,83,112,97,99,105,110,103,0,129,0,42,6,10,
  3,0,70,101,101,100,101,114,0,129,0,21,35,9,3,0,105,110,99,104,
  101,115,0,129,0,25,52,5,3,0,102,101,101,116,0,130,1,7,59,48,
  32,16,129,0,9,62,36,6,1,84,104,101,32,74,111,108,108,121,98,111,
  116,0,129,0,22,71,7,6,0,98,121,0,129,0,20,80,33,4,12,72,
  111,108,105,100,97,121,32,83,111,108,117,116,105,111,110,115,0,71,56,35,
  29,24,24,16,12,24,75,0,0,0,0,0,0,200,66,0,0,200,65,0,
  0,160,64,0,0,0,0,24,80,101,114,99,101,110,116,32,67,111,109,112,
  108,101,116,101,0,2,1,36,10,22,11,12,26,31,31,79,78,0,79,70,
  70,0 };

// this structure defines all the variables and events of your control interface
struct {

  // input variables
  int16_t Clip_Spacing ;  // 32767.. +32767
  uint8_t switch_1 ; // =1 if switch ON and =0 if OFF
  int16_t Light_Length ;  // 32767.. +32767
  uint8_t test; // =1 if button pressed, else =0
  uint8_t feed_switch ; // =1 if switch ON and =0 if OFF

  // output variables
  int16_t Percent_Complete;  // from 0 to 100

  // other variable
  uint8_t connect_flag;  // =1 if wire connected, else =0

} RemoteXY;
#pragma pack(pop)

/////////////////////////////////////////////
//           END RemoteXY include          //
/////////////////////////////////////////////

#define PIN_TEST 13

// The setup routine runs once when you press reset.
void setup()
{
  // MOTOR Setups
  Serial.begin(9600);
  MyBlue.begin(9600);
  Serial.println("Ready to connect\nDefualt password is 1234 or 000");
  pinMode(ENCA1, INPUT);
  pinMode(ENCB1, INPUT);
  pinMode(ENCA2, INPUT);
  pinMode(ENCB2, INPUT);
  pinMode(ENCA3, INPUT);
  pinMode(ENCB3, INPUT);
  pinMode(Lswitch, INPUT);
  myservo.write(5);
  myservo.attach(12);
  attachInterrupt(digitalPinToInterrupt(ENCA1), readEncoder1, RISING); // continously updates encoder count
  attachInterrupt(digitalPinToInterrupt(ENCA2), readEncoder2, RISING); // what is tick (revolution per tick)
  attachInterrupt(digitalPinToInterrupt(ENCA3), readEncoder3, RISING);


  // Bluetooth Set Up
  RemoteXY_Init ();
  pinMode (PIN_TEST, OUTPUT);


  // TODO you setup code ? (left by RemoteXY)


}
// The loop routine runs over and over again forever.
void loop()
{

  RemoteXY_Handler ();

  ticksTOinches(RemoteXY.Clip_Spacing, revTicks, revWheel, revTrack, revFeeder, &target1, &target2, &target3);


  // TODO you loop code
  // use the RemoteXY structure for data transfer
  // do not call delay()

  calcPID(target1, kp1, ki1, kd1, &prevT1, &eprev1, &pwr1, &pos1, &eintegral1);
  calcPID(target2, kp2, ki2, kd2, &prevT2, &eprev2, &pwr2, &pos2, &eintegral2);
  calcPID(target3, kp3, ki3, kd3, &prevT3, &eprev3, &pwr3, &pos3, &eintegral3);


  if (RemoteXY.switch_1 == 1)
  {
    if (Percent == 100)  // ends movement if all clips placed
    {
      RemoteXY.switch_1 = 0;
      RemoteXY_Handler ();
      motor1.setSpeed(0);
      motor2.setSpeed(0);
      motor3.setSpeed(0);
      Percent = 0;
      clip_count = 0;
    }
    else if ((eprev3 >50) && (firstclip < 1))  // might need to refine this
    {

      motor2.setSpeed(255);
      RemoteXY_delay(500);
      motor1.setSpeed(-pwr1);
      motor3.setSpeed(-pwr3);
      myservo.write(1);
      RemoteXY_Handler ();
    }
    else if ((digitalRead(Lswitch) == HIGH))
    {
      eprev3 =eprev2 =eprev1 = 0;
      motor1.setSpeed(-200);
      motor3.setSpeed(-200);
      motor2.setSpeed(255);
      myservo.write(1);
      RemoteXY_Handler ();
    }
    else if (RemoteXY.Clip_Spacing > 0)
    {
      motor1.setSpeed(0);
      motor2.setSpeed(0);
      motor3.setSpeed(0);
      motor2.setSpeed(255);
      RemoteXY_delay(250);
      myservo.write(110);
      RemoteXY_delay(500);
      RemoteXY_delay(500);
      myservo.write(5);
      RemoteXY_delay(250);

      pos1 = pos2 = pos3 = 0;
      clip_count++;
      firstclip =0;

      total_clips = RemoteXY.Light_Length * 12 / RemoteXY.Clip_Spacing;
      Percent = clip_count / total_clips * 100;
      RemoteXY.Percent_Complete = Percent;
      RemoteXY_Handler ();
    }
    else
    {
      motor1.setSpeed(0);
      motor2.setSpeed(0);
      motor3.setSpeed(0);
      myservo.write(5);
      RemoteXY_Handler ();
    }

  }
  else if (RemoteXY.feed_switch == 1)
  {
   motor2.setSpeed(255);
   RemoteXY_delay(5000);
   motor2.setSpeed(0);
   RemoteXY.feed_switch = 0;
   RemoteXY_Handler ();
  }
  else
  {
    motor1.setSpeed(0);
    motor2.setSpeed(0);
    motor3.setSpeed(0);
    RemoteXY_Handler ();
  }
 
  RemoteXY_delay(2);
}


void readEncoder1()
{ int  b = digitalRead(ENCB1);
  if (b > 0)
  {
    pos1--;
  }
  else
  {
    pos1++;
  }
}

void readEncoder2()
{ int  b = digitalRead(ENCB2);
  if (b > 0)
  {
    pos2++;
  }
  else
  {
    pos2--;
  }
}

void readEncoder3()
{ int  b = digitalRead(ENCB3);
  if (b > 0)
  {
    pos3++;
  }
  else
  {
    pos3--;
  }
}

void ticksTOinches(int Target, float revTicks, float revWheel, float revTrack, float revFeeder, float *T1, float *T2, float *T3)
{
  *T1 = float(Target) * tpi;
  *T2 = float(Target) * tpi;
  *T3 = float(Target) * tpi;


}

void calcPID (int target, float kp, float ki, float kd, long *prevT, float *eprev, int *pwr, int *pos, float *eintegral)
{
  long currT = micros();
  float deltaT = ((float)(currT - *prevT)) / 1.0e6;
  *prevT = currT;
  int e = target - *pos;

  float dedt = (e - *eprev) / (deltaT);
  *eintegral = *eintegral + e * deltaT;
  float u = kp * e + kd * dedt + ki * *eintegral;
  *pwr = u;
  if (*pwr > 255)
  {
    *pwr = 255;
  }
  else if (*pwr < -255)
  {
    *pwr = -255;
  }
  *eprev = e;
  if ((e > 10) || (e < -10))
  {
    *pwr = *pwr;
  }
  else
  {
    *pwr = 0;
  }
}

2

Re: Trouble with RemoteXY_Handler Communication

The Handler() function listens for messages from the ESP, which may arrive at different times. The function may do nothing if no data has been received from the ESP. The function also listens for data from the application, listens for requests from the application for data transfer. If a data transfer request comes in, the function sends a response.
If you don't call the Handler() function in time, the receive buffer will overflow and data will be lost, no response will be sent to the application, and the connection will break.