0

I've written a program which allows me to use my Arduino Uno to send a PWM to an Electronic Speed Controller. 5 seconds after startup the ESC is sent a config via PWM to signal the low to high PWM range to be used by the ESC. Then I can type into the Serial Monitor a single digit 0-9 to pick the PWM I want to send to my ESC. (n*2 = pwm)

This works great when running code for one ESC, but adding code for a second ESC causes significant issues (I only have one ESC plugged in). When I send a serial command to specify PWM rate, my ESC only receives the PWM change sometimes. About 2/3 times it ignores the PWM change and keeps spinning at the same rate it was already at.

What's going on here?

Code

WorkingESCSoftware (main file of .eno)

#include <SoftwareServo.h>
#include "TestClass.h"

int val;    // variable to read the value from the analog pin
int stage = 0;

TestClass t, t2;

void setup()
{
  Serial.begin(115200);

  t = TestClass();
  t.setPin(3);
  t2 = TestClass();
  t2.setPin(5);
}

void loop()
{
  t.loop();
  t2.loop();
}

TestClass.h

class TestClass {
  private:
    SoftwareServo servo;
    bool _initialized = false;

    int PWM_MAX = 180;
    int PWM_HIGH = 170;
    int PWM_MEDIUM = 80;
    int PWM_LOW = 40;
    int PWM_OFF = 25; // has to be between esc config off (stop) and low (slow spin)
  public:
    TestClass();
    void setPin(int);
    void loop();
};

TestClass::TestClass() {
  Serial.println("cycle lipo power to esc");
}

void TestClass::setPin(int pin) {
  this->servo.attach(pin);
}

void TestClass::loop() {
  //  Serial.println("loop");

  // 5 seconds after power, send PWM range to ESC
  if(millis() > 5000 && this->_initialized == false) {
    this->_initialized = true;

    Serial.println("esc setup");
    this->servo.write(PWM_MAX);
    delay(5);
    this->servo.write(PWM_OFF);
    delay(5);
    Serial.println("esc ready");
  }

  char r = Serial.read();
  String inStr = String(r);
  if(r > -1) {
    Serial.print("serial in: ");
    Serial.println(inStr);
  }

  use h, m, l, o, or 0-9 to control PWM of ESC
  if(r <= -1) {
    // void
  } else if(inStr == "h") { // high
    Serial.print("HIGH: ");
    Serial.println(PWM_HIGH);
    this->servo.write(PWM_HIGH); // highest spinning (same as 160?)
  } else if(inStr == "m") { // medium
    Serial.print("MED: ");
    Serial.println(PWM_MEDIUM);
    this->servo.write(PWM_MEDIUM);
  } else if (inStr == "l") { // low
    Serial.print("LOW: ");
    Serial.println(PWM_LOW);
    this->servo.write(PWM_LOW);
  } else if (inStr == "o") {
    Serial.println("OFF");
    this->servo.write(PWM_OFF);
  } else if (inStr.toInt() >= 0 && inStr.toInt() <= 9) {
    int val = inStr.toInt() * 20;
    Serial.println(val);
    this->servo.write(val);
  }

//  SoftwareServo::refresh();
  this->servo.refresh();
}
  • You cannot do this simply by creating two instances of the class - you have to have a single instance of code which reads the serial port and dispatches complete commands to them. – Chris Stratton Aug 11 '16 at 2:05
1

You have two copies of your program sharing one physical resource, the serial port input to the Arduino. It is by chance which of the two copies will receive and process the input data. So this approach will not work dependably.

Semiphoras are often used when sharing hardware among several programs. However you are not only sharing hardware, but also the data being sent to the Arduino. And the data will only be sent once.

In this case, you need to handle the data once in code that is separate from the 2 instantiations of the ESP class. That is, you need to process the received data once and pass that processed data to the appropriate instantiation of the ESP class.

  • Ah, so it's strictly an issue with how I'm handling Serial input? That makes sense. I'll move the serial read out to the main program loop and see how things go. – Jacksonkr Aug 11 '16 at 15:47
  • It may not be the only issue with your code. But it is the most obvious and explains the undependable behavior. I believe you will want to keep the serial read in the main loop. Basically, you will want to read the serial port, then pass the read data to the correct ESP instance. Then, I assume, you will keep repeating this pattern infinity. So all this code would remain in the Arduino's loop() method. – st2000 Aug 12 '16 at 1:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.