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;
}
}