Blynk response very slow

But I did! (and you have :+1:)

OK, admittedly I informed you in a roundabout fashion ;), primarily as I (and likely others) didnā€™t make the connection between my experienced issues and their probable timing related causes:

Resolved (sometimes) by changing BAUD rates - unsure of how direct TCP-IP would mollify the issue.

Adding Blynk.syncVirtual(Vx); resolves loss by keeping the Blynk Function attentive to the microseconds() loopā€¦

ā€¦Simular command addition thought to be required here.

Resolved by determining USB link is just not the way to go - But I (and others) may not have a choice at times :slight_smile:

Hi Gunner nice robot you have! Here is my full code, no Youtube movie yet since the robot just does what it needs since yesterday. The app now looks very dull but picture a joystick to control direction and a slider to control speed, thats it

/*******************************************funny 6 feet hexapod************************************************************************************************************************
 * 
 * This is my version of the software for "funny little six feet" hexapod robot from Thingiverse (http://www.thingiverse.com/thing:1201161).
 * Credits to gdlzsilip for his marvelous design
 * 
 * The sketch enables the hexapod to be controlled by Blynk app on your smartphone. In the Blynk app you need a Joystick widget (for direction) connected to Virual IO V1
 * and a slider (for speed) connected to virual IO V0. If Blynk does not connect within 10mS (no WiFi for example) then the robot walks around autonomously, starting forward.
 * 
 * The robot has 6 knees to lift the legfeet and 6 hips to move legs forward and back. They are divided in 2 groups. Leg connections (groups 1 and 2 mentioned in the code) : 
 * group1 = leftback+leftfront+rightmiddle legs, in short LB,LF,RM
 * group2 = leftmiddle, rightfront and rightback legs. In short LM,RF,RB.  
 * 
 * PWM channel  - group + h/k + position:
 * channel0 - group1 hip LB
 * channel1 - group1 knee LB
 * channel2 - group2 hip LM
 * channel3 - group2 knee LM
 * channel4 - group1 hip LF
 * channel5 - group1 knee LF
 * channel6 - group2 hip RF
 * channel7 - group2 knee RF
 * channel8 - group1 hip RM
 * channel9 - group1 knee RM
 * channel10 - group2 hip RB
 * channel11 - group2 knee RB
 * 
 * Good to know about the legs (hips and knees):
 * Hips left side: higher value of PWM = more backwards (lower is more forward)
 * Hips right side: higher value of PWM = more forward (lower = more backward)
 * Knees (up) is lower value of PWM and down is higher
 * 
 * A good article describing the basics of this sketch (using tripod gait method) is http://excel.fit.vutbr.cz/submissions/2015/019/19.pdf
 * 
 * My hardware consists of an ESP8266 version called Wemos d1 mini, 13 MG90 metal geared servo's (6x 2DOF leg and 1x PING sensor)and an Adafruit 
 * 16-channel Servo controller clone to control all of them.
 * I use a 7.4V lipo pack with 6V UBEC regulator controller for the servo's power. The Wemos D1 mini I power directly from a 4-battery AAA pack using its 5V pin
 * 
 * Current version  : 1.9 (19-1-2017)
 * Revision history : V1.0  - initial revision 
 *                    V1.1  - Added Blynk so the smartphone Blynk app can be used to connect a button to the system en step through all moves for easy debugging
 *                            (however with blynk it does not work yet). I changed delta to delta1 and added delta2 + delta 3, these 3 are to make deviations wrt rest positions 
 *                            regarding up/down/forward/backward
 *                    V1.2  - Basic walking works, added backward and WiFi connection is working too
 *                    V1.3  - Ticker based ping / distance measurement added (every 50mS it measures)
 *                    V1.4  - Added turn right/left
 *                    V1.5  - Added check the blynk connection: if the hexapod does not connect to my WiFi then Blynk is not connected and the robot runs autonomous
 *                    V1.6  - Now the robot in Blynk mode is controlled by the Blynk Joystick widget! We can go Right/Left/Forward/Backward via the Joystick!
 *                            Also speeded up the moves by increasing the I2C frequency 4 times to 400kHz using twi_setClock(400000); (see below in setup() )
 *                    V1.7  - Added a slider for Blynk to control the speed of the movements
 *                    V1.8  - The PING sensor values are now guarding the robot from crashing into objects: if an object is detected then using the PING and its servomotor
 *                            the robot tries to find a way out by measuring left and right sides and determining which course to take
 *                    V1.9  - Found out that the delay() function blocks the working of Blynk since in the loop() Blynk.run() gets called very few times due to all the delays between
 *                            servo position changes. I replaced delay() by a function from internet at the bottom of my sketch: Blynk_Delay();
 * 
 *                          
 * used pins:
 * Wemos D1mini D2    = Wemos I2C dataline/sda to PWM controller board sda
 * Wemos D1mini D1    = Wemos I2C clockline/scl to PWM controller board scl
 * Wemos D1mini GND   = connected to gnd of power source and to PWM servo controller board GND
 * Wemos D1mini 5V    = connected to 5V power source and to VCC of PWM servo controller board
 * 
 * NOTE: the servo's are powered from a seperate battery pack via the V+ input of the PWM servo controller board
 *                   
 *****************************************************************************************************************************************************************************************/
//Blynk debugging (to work it must be at the first lines in the sketch)
//#define BLYNK_DEBUG // Optional, this enables lots of prints
//#define BLYNK_PRINT Serial

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

//For Blynk app to control this via Android phone
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

//for PING sensor
#include <Ticker.h> //to do PING measurements every x mS (similar to irq based method)
#include <NewPing.h>

// called this way, it uses the addres you add as an argument, my chinese clone board has 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);

//not used right now but they are safe values for my system
#define SERVOMIN  325 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  500 // this is the 'maximum' pulse length count (out of 4096)

//I2C speeds to let the Servo controller work faster if required
#define _100KHZ  100000
#define _200KHZ  200000
#define _300KHZ  300000
#define _400KHZ  400000


//local wifi
#define SSID1  "SSIDNAME"
#define PASS1  "PASSWORD"
#define WIFI_TIMEOUT  30 //divided by 2 is the time in seconds we give the WiFi to connect before giving up


//variable to control the robots moving speed (it is a delay between the moves the legs do and is controlled using Blynk slider)
int DELAY_BETWEEN_MOVES = 5;  //take  large value to debug the legs by slowing down its movements

//To this pin(s) a virtual BLynk button on Android app is assigned to
const int buttonPin = D3;
char auth[] = "yourtoken"; // You should get Auth Token in the Blynk App, go to the Project Settings (nut icon).
int joy_x = 512; //to control the robot via Blynk's Joystick widget. These 2 start values correspond with moving forward
int joy_y = 1023;

//Ping pins and max distance
#define TRIGGER_PIN  D8  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     D7  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

//instantiate 1 ping 
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

int staticpos = 375; //these are the midpositions for all servos
int delta1 = 120; //controls how deep the robot goes down w.r.t "staticpos"
int delta2 = 50; //controls how high the robot rises w.r.t "staticpos"
int delta3 = 38; //controls deviation of hips w.r.t "staticpos"

//instantiate the ticker and define a function to run using the ticker
Ticker measure_distance; //measure with ping periodically
int distance = 0; //global variable to store measured distance, ticker wants void functions as argument so cannot return values
int previousdistance = 0; //because the PING can give sometimes a ghost value due to a glitch I use 2 variables as a failsafe

boolean autonomous = true;

void setup() 
{
  Serial.begin(9600);
  
  pwm.begin();
  
  /*DVEDEBUG the next piece of code only works for Arduino compatible boards not for ESP8266
  //next command is to make the PWM controller work 4 times as fast (default I2C clock is 100kHz)
  TWBR = ((F_CPU /(_200KHZ+1)) - 16) / 2; // Change the i2c clock to 200KHz
  */

  //this line changes the I2C frequency for esp8266, this is done to speedup the Servo controller moves
  twi_setClock(_200KHZ);
  pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates

  
  //DVEDEBUG not used right now, was for blynk first test
  //pinMode(buttonPin, INPUT);

  /**************************the following is to use the robot independent from blynk connection, it prevents that the ESP keeps trying to connect to blynk while there is no wifi******/
  //connection to blynk now managed by first trying to connect to wifi, skip blynk if no wifi is connected
  WiFi.begin(SSID1, PASS1);
  int counter = 0;
  while (WiFi.status() != WL_CONNECTED && (counter <= WIFI_TIMEOUT)) 
  {
delay(500);
Serial.print(".");
counter++;
  }
  Blynk.config(auth);  // in place of Blynk.begin(auth, ssid, pass);
  Blynk.connect(3333);  // timeout set to 10 seconds and then continue without Blynk
  /****************************end Blynk connection code*********************************************************************************************************************************/
  
  //setup the ticker controlled function to do PINGs
  measure_distance.attach_ms(50,do_ping); //do a ping measurement every x mS using ticker 
  
  //The resting position
  zeropoz();
  delay(3000);

  //check if the robot is connected to blynk, if not then run in the loop() the autonomous program version instead of the remote controlled version via Blynk app
  if(!Blynk.connected())
autonomous=true;
  else
autonomous=false; 
}


//this process is running constantly it does not need to be called in the loop()
//V1 is virtual pin 1 so it does not take a pin resource
BLYNK_WRITE(V1) 
{
  joy_x = param[0].asInt();
  joy_y = param[1].asInt();
}

//this process is running constantly too and on V0 (virtual pin 0) it gets the slider position from my Blynk app, here it is assigned to a variable and used in the code 
//to control the robots speed
BLYNK_WRITE(V0)
{
  DELAY_BETWEEN_MOVES = param.asInt();
}

void loop() 
{ 
  if (distance < 20 && (abs(distance - previousdistance) < 10)) //something close in range of the robot, also check difference of 2 measurements to prevent acting on glitches of the PING
  {
measure_distance.detach(); //disable auto pinging
zeropoz();
delay(1000);

//check if left is more space to continue?
pwm.setPWM(12, 0, 500);
delay(300);
int left = sonar.ping_cm();
delay(500);

//same for right
pwm.setPWM(12, 0, 250);
delay(300);
int right = sonar.ping_cm();
delay(500);

//determine the new course (forward = f, backward = b, left = l, right = r, t = turn)
unsigned char direction;
if ((left >= (distance + 10)) && (left >= (right + 10)))
  direction = 'l'; 
else if ((right >= (distance + 10)) && (right >= (left + 10)))
  direction = 'r'; 
else
  direction = 't'; //turn 180 degrees

//set PING sensor back to midposition and do evasive maneuvre
pwm.setPWM(12, 0, 375);
switch(direction)
{
  case 'l' :
    for(int i=0; i < 4; i++)
      turnleft();
    break;

  case 'r' :
    for(int i=0; i < 4; i++)
      turnright();
    break;
    
  case 't' :
    for(int i=0; i < 2; i++)
      backward();
    for(int i=0; i < 6; i++)
      turnright();
    break;
}
measure_distance.attach_ms(50,do_ping); //re-enable auto ping measuring and then resume normal course
distance = 100; //the loop without blynk is so fast that there is no new measurement before re-entering so this assignment is to get it out of the loop
  }
  
  else if (autonomous == true)
  {
forward(); //keep going forward, the PING is guarding the robot from crashing
  }
  
  else //we control the robot via Blynk remote control app
  {
Blynk.run();

//go in the direction of the joystick, the PING is guarding the robot from crashing
if(joy_y > 1015) 
  forward();
else if(joy_x > 1015) 
  turnleft();
else if(joy_y <= 10) 
  backward();
else if(joy_x <= 10) 
  turnright();
else
  forward();
  }  
}



void zeropoz()
{
  pwm.setPWM(0, 0, 375);
  pwm.setPWM(1, 0, 375);
  pwm.setPWM(2, 0, 375);
  pwm.setPWM(3, 0, 375);
  pwm.setPWM(4, 0, 375);
  pwm.setPWM(5, 0, 375);
  pwm.setPWM(6, 0, 375);
  pwm.setPWM(7, 0, 375);
  pwm.setPWM(8, 0, 375);
  pwm.setPWM(9, 0, 375);
  pwm.setPWM(10, 0, 375);
  pwm.setPWM(11, 0, 375);
  pwm.setPWM(12, 0, 375); //the servo which controls the scanning of the PING sensor
}

void walkpoz()
{
  int pdelta1 = 60;

  pwm.setPWM(0, 0, 375);
  pwm.setPWM(1, 0, 375);
  pwm.setPWM(2, 0, 375-pdelta1);
  pwm.setPWM(3, 0, 375);
  pwm.setPWM(4, 0, 375+pdelta1);
  pwm.setPWM(5, 0, 375);
  pwm.setPWM(6, 0, 375);
  pwm.setPWM(7, 0, 375);
  pwm.setPWM(8, 0, 375-pdelta1);
  pwm.setPWM(9, 0, 375);
  pwm.setPWM(10, 0, 375+pdelta1);
  pwm.setPWM(11, 0, 375);
}

void forward()
{
  Group1Up();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Bw();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Fw();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Down();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Up();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Bw();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Fw();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Down();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
}

void backward()
{
  Group1Up();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Fw();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Bw();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Down();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Up();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Fw();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Bw();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Down();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
}

void turnright(void)
{
  Group1Up();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Right();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Left(); 
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Down();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Up();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Right();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Left(); 
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Down();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
}

void turnleft(void)
{
  Group1Up();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Left();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Right();            
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Down();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Up();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group1Left();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Right();              
  Blynk_Delay(DELAY_BETWEEN_MOVES);
  Group2Down();
  Blynk_Delay(DELAY_BETWEEN_MOVES);
}

//groups down dept is arranged by delta1 value and rise hight by delta12 value
void Group1Up()
{
  for(int jk=375+delta2; jk>=375-delta1; jk--)
  {
pwm.setPWM(1, 0, jk); //knee left back
pwm.setPWM(5, 0, jk); //knee left front
pwm.setPWM(9, 0, jk); //knee right middle
  }
}

void Group2Up()
{
  for(int jk=375+delta2; jk>=375-delta1; jk--)
  {
pwm.setPWM(3, 0, jk); //knee left middle
pwm.setPWM(7, 0, jk); //knee right front
pwm.setPWM(11, 0, jk); //knee righ back
  }
}

void Group1Down()
{
  for(int jk=375-delta1; jk<=375+delta2; jk++)
  {
pwm.setPWM(1, 0, jk); //knee left back
pwm.setPWM(5, 0, jk); //knee left front
pwm.setPWM(9, 0, jk); //knee right middle
  }
}

void Group2Down()
{
  for(int jk=375-delta1; jk<=375+delta2; jk++)
  {
pwm.setPWM(3, 0, jk); //knee left middle
pwm.setPWM(7, 0, jk); //knee right front
pwm.setPWM(11, 0, jk); //knee right back
  }
}

void Group1Fw() 
{
  //pwm.setPWM(0, 0, (staticpos - (delta3-10))); //hip left back //DVE this was finetuned: endvalue needs to be slightly higher so it goes less forward, prevent it from slamming to the hip left middle
  pwm.setPWM(0, 0, (staticpos - delta3)); //hip left back 
  pwm.setPWM(4, 0, (staticpos - delta3)); //hip left front (was 500)
  pwm.setPWM(8, 0, (staticpos + delta3)); //hip right middle 
}

//this one was not worked out, I derived it from Group1Fw()
void Group2Fw()
{
  pwm.setPWM(2, 0, (staticpos - delta3)); //hip left middle
  pwm.setPWM(6, 0, (staticpos + delta3)); //hip right front
  pwm.setPWM(10, 0, (staticpos + delta3)); //hip right back
}

void Group1Bw()
{
  pwm.setPWM(0, 0, (staticpos + delta3)); //hip left back
  //pwm.setPWM(4, 0, (staticpos + (delta3+10))); //hip left front //finetuned: goes slightly more backward then the others
  pwm.setPWM(4, 0, (staticpos + delta3)); //hip left front 
  pwm.setPWM(8, 0, (staticpos - delta3)); //hip right middle
}

void Group2Bw()
{
  //pwm.setPWM(2, 0, (staticpos + (delta3-10))); //hip left middle. //slightly finetuned to solve slamming into leg Left back by slightly making end value lower, makes it go less backward
  pwm.setPWM(2, 0, (staticpos + delta3)); //hip left middle.
  pwm.setPWM(6, 0, (staticpos - delta3)); //original was 375 (hip right front) 
  pwm.setPWM(10, 0, (staticpos - delta3));//original was 285 (hip right back)
}

void Group1Right() //go right is acomplished by moving the left 2 legs forward while the middle right leg goes backward
{
  pwm.setPWM(0, 0, (staticpos - delta3)); //hip left back
  pwm.setPWM(4, 0, (staticpos - delta3)); //hip left front (was 500)
  pwm.setPWM(8, 0, (staticpos - delta3)); //hip right middle //to make the right middle leg go backward we need - delta3
}

void Group2Right() //to go right with group2 the 2 right legs of the group need to move backward and the 1 left needs to move forward
{
  pwm.setPWM(2, 0, (staticpos - delta3)); //hip left middle //going forward now
  pwm.setPWM(6, 0, (staticpos - delta3)); //original was 375 (hip right front)
  pwm.setPWM(10, 0, (staticpos - delta3));//original was 285 (hip right back)
}


void Group1Left() //go left is acomplished by moving the left 2 legs backward while the middle right leg goes forward
{
  pwm.setPWM(0, 0, (staticpos + delta3)); //hip left back
  pwm.setPWM(4, 0, (staticpos + delta3)); //hip left front
  pwm.setPWM(8, 0, (staticpos + delta3)); //hip right middle now going forward to make going left possible
}

void Group2Left() //to go right with group2 the 2 right legs of the group need to move forward and the 1 left needs to move backward
{
  pwm.setPWM(2, 0, (staticpos + delta3)); //hip left middle, now moving backward ( + delta instead of -) so that the robot can go left
  pwm.setPWM(6, 0, (staticpos + delta3)); //hip right front
  pwm.setPWM(10, 0, (staticpos + delta3)); //hip right back
}


void do_ping(void)
{
  previousdistance = distance; //as a failsafe, used in loop() to check that the 2 do not differ too much from eachother, the robot is not that fast so they should not differ a lot
  distance = sonar.ping_cm();
}

//delay function to replace delay() of arduino, this function takes care that Blynk keeps working properly and up to speed
void Blynk_Delay(int milli)
{
  int end_time = millis() + milli;
  while (millis() < end_time)
  {
if (Blynk.connected())
{
  Blynk.run();
}
yield();
  }
}

A hexapod! Impressive! ā€¦ OK, I guess I am not porting anything over to my comparatively simplistic differential drive :laughing:

But I will have fun digging into it anyhowā€¦ for pointers and all. Thanks!

Welcome! mech design is from somebody at thingiverse and starting point of the code was as well but the rest I put around it. It works decently!

By the way the hexapod sounds difficult with its 6 legs but they are controlled in 2 groups of 3 legs each so apart from having knees and joints its comparable in difficulty to differential drive :slight_smile:

Hi, you must use myServo.writeMicroseconds(uS) instead of myServo.write() in order to achieve a good control of the servos, because of delays in myServo.write(), it seems that myServo.writeMicroseconds just update once the servo value, then goes to high :slight_smile:

@Snakee Thanks for the additional infoā€¦ I found more details about it here - https://www.arduino.cc/en/Reference/ServoWriteMicroseconds

FYI, you are responding to a 5 month old topic :wink: Please take note of the date/time stamp before posting.

A post was split to a new topic: Want to control robot using Blynk