[SOLVED] SYSTEM MODE MANUAL messes up PWM based motor-speed control

Hey folks,

I’ve got a setup with the Spark Core, that runs 3 different motors (2 DC motors using the Pololu DRV8801 driver and 1 stepper motor using the Pololu DRV8825 driver). I’m using the AccelStepper library to handle the stepper motor. In a previous thread (Spark Core + AccelStepper Library problems) I was told that the permanent to the Cloud drains a huge amount of the performance. So I used SYSTEM_MODE(MANUAL); and that solved most of the problems.

Now I have a PWM based speed control of all of my motors. When I’m using the AUTOMATIC system mode, the DC motors can be controlled perfectly fine and the stepper motor is running slow as hell. When I put in the MANUAL mode, the stepper motor is just fine, and can be controlled with my potentiometers perfectly … BUT there is a problem with the DC motors. When I turn the potentiometer for the DC motors, It only takes a few degrees of turning the potentiometer to enable the full speed on the DC motor. So it does NOT use the full range of motion of the potentiometer. So maybe after 10% of turning the potentiometer the DC motor has its full speed, and the rest of the turning of the potentiometer the speed stays the same.

And this is somehow related to the MANUAL system mode.

Here you can find my code:
http://pastebin.com/AMNVGEUJ

Hope you can understand my description. I can provide videos and pictures if you need them.

Thank you very much!

When I press my button (connected to D0) that fires the connect() function and fires up Spark.connect(); the speed control with my potentiometer for my DC motor is behaving normally again.

I also note that all my motors are running counterclockwise, even though they are wired correctly and have the correct polarity.

Before looking into your code, could you just give a try to one thought?

If you emulate the cloud lag by only reading the pot every 10ms or so.

e.g.

  ...
  if(millis() - msLastRead > 10)
  {
    pot = analogRead(potPin);
    msLastRead = millis();
  }
  ...

Does this change anything?

Hi,

I’ve read around and learned that if the loop’s are calculated too fast the accuracy of the potentiometers will suffer. Therefore I’ve inserted a delay(100) at the end of the getPot() function and the controls of the DC motors with SYSTEM_MODE(MANUAL) will work just fine.

BUT, as a result, the stepper motor will step extremely slow. Only When I remove the delay, the stepper motor will turn just fine, even though the control with the potentiometer is just fine … but just not with the DC motor … how can this be?

My delay(100) and your code @ScruffR will result in the same behavior…

Have you tested this or are you just assuming.

A delay(100) does block and hence will slow down the iteration speed of your loop() while what I’ve done with my code is called a non-blocking or “soft” delay whicht will not impact the frequency with which loop() will be serviced, allowing for the time critical tasks - as your other motors - to be run more frequently than the non-critical or even speed-limited tasks.

So if you haven’t tested it, do.
And if you have tested it, can you show your updated code, to see if you’ve used my excerpt at the “proper” position.

Hey, I tried it out.

I have tried to increase the duration in your if statement up top 10.000 and nothing really changes regarding my problem. :confused:

I’m freaking out …

SYSTEM_MODE(MANUAL);
#include "AccelStepperSpark/AccelStepperSpark.h"



// Button
const int buttonPin = D0;
const int ledPin = D7;
int buttonState = 0;

// Pot 1
const int pot1Pin = A0;
int pot1Val = 0;

// Motor 1
const int motor1Speed = A1;  
const int motor1Dir = D1;
int motor1Val = 0;

// Pot 2
const int pot2Pin = A4;
int pot2Val = 0;

// Motor 2
const int motor2Speed = A5;  
const int motor2Dir = D5;
int motor2Val = 0;

// Pot 3
const int pot3Pin = A6;
int pot3Val = 0;

// Stepper Motor
AccelStepper motor3(AccelStepper::DRIVER, D3, D2);
const int motor3mode = D4;
int motor3Val = 0;

int msLastRead = 0;



// Setup

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  pinMode(pot1Pin, INPUT);
  pinMode(motor1Speed, OUTPUT);
  pinMode(motor1Dir, OUTPUT);

  pinMode(pot2Pin, INPUT);
  pinMode(motor2Speed, OUTPUT);
  pinMode(motor2Dir, OUTPUT);
  
  pinMode(pot3Pin, INPUT);
  pinMode(motor3mode, OUTPUT);
  digitalWrite(motor3mode, HIGH);
  motor3.setMaxSpeed(15000);
}


// Loop

void loop()
{
  getPot();
  run();
  connect();
}


// Functions

void getPot() 
{
  if(millis() - msLastRead > 10)
  {
    pot1Val = analogRead(pot1Pin);
    motor1Val = map(pot1Val, 0, 4095, 0, 255);
  
    pot2Val = analogRead(pot2Pin);
    motor2Val = map(pot2Val, 0, 4095, 0, 255);
  
    pot3Val = analogRead(pot3Pin);
    motor3Val = map(pot3Val, 0, 4095, 0, 12800);

    msLastRead = millis();
  }
}


void run() 
{
  analogWrite(motor1Speed, motor1Val);
  analogWrite(motor2Speed, motor2Val);
  motor3.setSpeed(motor3Val);
  motor3.runSpeed();
}


void connect() 
{
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {     
    digitalWrite(ledPin, LOW);  
  } else {
    digitalWrite(ledPin, HIGH);
    if (!Spark.connected()) {
      Spark.connect();
    } else {
      Spark.process();
    }
  }
}

Did I understand correctly: With the delay (blocking or soft) in place your motor 3 behaves correctly but the two others don’t and without delay M1 & M2 do behave correctly but M3 not?

If this sounds right, then I’d suggest to try this instead

void getPot() 
{
  pot1Val = analogRead(pot1Pin);
  motor1Val = map(pot1Val, 0, 4095, 0, 255);

  pot2Val = analogRead(pot2Pin);
  motor2Val = map(pot2Val, 0, 4095, 0, 255);

  if(millis() - msLastRead > 10)
  {  // only slow down pot 3 reading
    pot3Val = analogRead(pot3Pin);
    motor3Val = map(pot3Val, 0, 4095, 0, 12800);

    msLastRead = millis();
  }
}

void run() 
{
  analogWrite(motor1Speed, motor1Val);
  analogWrite(motor2Speed, motor2Val);

  if(millis() - msLastSetSpeed > 10)
  {  // only slow down pot 3 reading
    motor3.setSpeed(motor3Val);
    motor3.runSpeed();
    msLastSetSpeed = millis();
  }
}

And you could even do something similar with your run().

On the Photon there was a PWM glitch at some point, where each time you set the PWM value anew, the current PWM cycle was stopped, not fullfilling the puls-gap-ratio and restarting immediately a new cycle, causing a way too high puls-gap-ratio, since the gap keept getting cut short.

This would also explain your M3 problem.

To verify this theory, could you please try out all three combinations:

  • soft delay only around pot 3 reading
  • soft delay around pot 3 and motor3.setSpeed()
  • soft delay only around motor3.setSpeed()

I tried every suggestion but none of them worked…
Further I’ve experienced a few thermal shutdowns of my Stepper motor driver… it gets insanely hot and the soft blocking of the motor3.setSpeed won’t reduce the the heat.

I’m so fucking annoyed by this project, so I will just get rid of the damn stepper motor and get another simple DC motor…

But thanks for your advices and help. I really appreciate it.

Pitty that nothing helped :weary:

I’d still like to understand what the issue is.
When it works one way and not the other that just cries for being solved :stuck_out_tongue_closed_eyes:

BTW: Are you using firmwarw 0.4.5 already or still 0.3.4?
Does using the other change anything?

Hey,

made a quick video describing my problem: https://www.youtube.com/watch?v=2g3FzseYr6s

Yes, I’m using 0.4.5 firmware. The soft blocking that you’ve mentioned in any of the described places, for the stepper motor and I’ve tried it even for the DC motors reading and running speeds, but I didn’t worked. :frowning:

Can’t watch this video since it’s private

Sorry for the rough time you have with this, but any chance to try it with 0.3.4? :wink:

Sorry, @ScruffR, you should now be able to see it!

Hm yes, I can try it later with 0.3.4

OK, now after watching your video my understanding of the problem just got flipped round.
Obviously I’ve not read/understood your written description right :blush:

And this was obviously wrong

Since I got it wrong then, try everything I said for M3 with M1 & M2 instead :wink:

If I’m not wrong again :flushed: then I guess M3 needs to be serviced as often as possible while M1 & M2 want some breathing time in between.
Most likely I’d think soft-delaying the analogWrite() part should do the trick and applying a moving average to the pot readings might help too.

You sir, @ScruffR, freaking made my day.

It works now as it should be. I cannot thank you enough for your help!!!
Thanks for your patience and your advices! :)))))

3 Likes

Thank you for sticking with me, despite me sending you off the wrong direction, just because I can’t read :flushed:

:+1: glad to hear that you’ve got it working now.

Happy to help :sunglasses:

2 Likes