Particle, Blynk, and PWM

Hello, everyone!

I am working on setting up a robot that is track-driven, with a really neat feature called “flip-treads” (a second set of treads that run along the ground parallel to the others, but can be flipped to a different orientation via a metal gear servo to enable climbing, bridging small gaps, and the like).

I am attempting to run it off of Blynk (because my ability to code an app or a webpage that will do the trick is just not strong). When I start it up, the the servo slider works fine (slide it left to right to write to the servo “arms” a value from 0 to 180.

Unfortunately, once I press any button to control the direction the robot travels (see code posted below), the servo slider stops responding until I reset the Photon. Troubleshooting methods have included:

  • Creating a Blynk button that writes to a static angle when pressed and 0 when released (also stops functioning after I use the motor buttons)
  • Creating an IFTTT hook to run forward for 1 second on pressing the DO button (also stops the servo slider)
  • Attempted to bypass PWM requirements for the move() function by writing that pin HIGH for full speed and LOW for off. (Also stops the slider).

A gentleman over in the Blynk community suggested that the hardware timers used by my various PWM commands may be exceeding the number available on the Photon.

As promised, here is the code:

BLYNK_WRITE(V1) { //forward
    while (param.asInt() == 1) {
        digitalWrite(STBY, HIGH);
        move(0,255,0);
        move(1,255,1);
    }
    move(0,0,0);
    move(1,0,0);
    digitalWrite(STBY, LOW);
}

BLYNK_WRITE(V2) { //backward
    if (param.asInt() == 1) {
        digitalWrite(STBY, HIGH);
        move(0,255,1);
        move(1,255,0);
    }
    else {
        move(0,0,0);
        move(1,0,0);
    }
}

BLYNK_WRITE(V3) { //left
    if (param.asInt() == 1) {
        digitalWrite(STBY, HIGH);
        move(0,255,0);
        move(1,255,0);
    }
    else {
        move(0,0,0);
        move(1,0,0);
        digitalWrite(STBY, LOW);
    }
}

BLYNK_WRITE(V4) { //right
    if (param.asInt() == 1) {
        digitalWrite(STBY, HIGH);
        move(0,255,1);
        move(1,255,1);
    }
    else {
        move(0,0,0);
        move(1,0,0);
        digitalWrite(STBY, LOW);
    }
}

void loop() {
  Blynk.run();
}

void move(int motor, int speed, int direction){
//Move specific motor at speed and direction
//motor: 0 for B 1 for A
//speed: 0 is off, and 255 is full speed
//direction: 0 clockwise, 1 counter-clockwise

  boolean inPin1 = LOW;
  boolean inPin2 = HIGH;

  if(direction == 1){
    inPin1 = HIGH;
    inPin2 = LOW;
  }

  if(motor == 1){
    digitalWrite(AIN1, inPin1);
    digitalWrite(AIN2, inPin2);
    analogWrite(PWMA, speed);
  }
  else{
    digitalWrite(BIN1, inPin1);
    digitalWrite(BIN2, inPin2);
    analogWrite(PWMB, speed);
  }
}

I apologize if this is a fairly newbie question, but any help would be welcome. :smiley: Thanks!

Edit: I came across the part of the particle documentation that stated that D0 and D1 are on one timer group, almost everything else is on another timer group, and A7/WKP is on a third by itself. Thinking this may be the problem, I rerouted the servo to A7, and ensured that my motors were still on D0 and D3, which puts all three PWM devices on a different timer. This, however, changed nothing. Still worth noting for troubleshooting.

Edit, part two: Definitely not a hardware limitation! I commented out the Blynk portion and replaced it with the following:

arms.write(45);
digitalWrite(STBY, HIGH);
move(0,255,0);
move(1,255,1);
delay(500);
move(0,0,0);
move(1,0,0);
digitalWrite(STBY, LOW);
arms.write(0);
delay(500);

As soon as it kicked on, it behaved exactly as expected, writing to the arms and tracks interchangibly. This tells me that the issue appears to be with Blynk. So, I think I need to write the motor controls completely outside the Blynk controls and just call them. Crossing fingers.

And the answer: Apparently, Blynk does not like to do work, it just likes to call stuff. So, I moved any and all motor code into a single function with a single parameter. When I set Blynk up to call the function with a variable and do almost nothing else, it ran like a dream.

Thanks, community, for letting me puzzle this one out!