Notifications
Clear all

Emergency Stop System Logic - Motor Control Board  

Page 4 / 6
  RSS

robotBuilder
(@robotbuilder)
Honorable Member
Joined: 1 year ago
Posts: 502
2020-04-29 9:43 pm  
Posted by: @dronebot-workshop

 It's expected that the intelligence driving the robot is going to have already figured out how not to drive into a wall.   An emergency stop would occur when something unexpected happens, like something suddenly blocks the robot's path.

BTW, in case you think I've abandoned everyone I haven't, I've been dividing my time between household chores and coding for DB1. I have "cleaned up the previous code and am using it to test interrupts.

 

@dronebot-workshop

Probably when you have the robot up and running any problems that require an emergency stop may become clear. My emergency stop is the application of human finger on a red button 🙂  If the robot is by itself there could always be a failure of the higher levels to recognize a problem. The signals to the human brain's higher levels might be "pain". We know from the rare cases where people do not feel pain that they tend to self harm without realizing it.  They don't feel the pain of a broken bone or a hot object burning their skin.  A failure of a bumper sensor might result in the robot trying continually to move through a wall until the motors burn out. The higher level layers would need not only to send a command but also determine if that command was being carried out as expected. If the command is to lift the arm and all the higher level has to go by is some positional feedback it might keep trying to do it forever if something has failed (like the motor has lost power or a wire from the positional sensor has broken).

So I imagine some kind of model of what should happen and when the model says, "this is taking too long to happen", it can "think again" what to do about it.

 

 

This post was modified 6 months ago 6 times by robotBuilder

ReplyQuote
starnovice
(@starnovice)
Estimable Member
Joined: 1 year ago
Posts: 169
2020-04-29 10:00 pm  

@dronebot-workshop I agree with not having to kill power.  That would be overkill 🙂  .  I have another copy of the code for the nano that I think is bullet proof for the emergency stop will post shortly when I get done with my chores.

Pat Wicker (Portland, OR, USA)


ReplyQuote
frogandtoad
(@frogandtoad)
Reputable Member
Joined: 1 year ago
Posts: 490
2020-04-30 10:43 am  
Posted by: @starnovice
Posted by: @frogandtoad

Not so fast! 🙂

A temporary class can be used as a function that wraps up the command(s)... the command object can them be destructed in the interrupt routine under emergency condition(s)... I don't see why this wouldn't work?

So, you would have to construct the class every time you wanted to use it because you couldn't be sure it still existed.  I wonder what the overhead for the construction and destruction are and if it is appropriate to use in an interrupt routine that is just one of two interrupts. Actually, ignore that last part because the other interrupt is the encoder counter and it will stop when you stop the motors. Would also have to make sure you cleaned up any global variables involved.

Yes, I would envisage each command to be a class, with an internal command id for tracking, commands (incorporated as member functions (setPwm, accelerate, etc...)).  You would also need a brain/controller class, perhaps storing an array of these commands for tracking their execution!

I wouldn't worry about overhead, as I doubt it would be a great deal more than a normal function call... the main point was to come up with an alternative idea to get something working first - You can worry about refactoring for efficiency later, should it work 🙂

Anyway, it's just an idea.

In any case, it's difficult to come up with the perfect solution when no one really understands the algorithm required.  At this stage, Bill and others have some ideas only, ,and I'm not sure if anyone really understands the algorithm to be implemented, otherwise we could see it clearly depicted in a state machine or some kind of flow chart at minimum - There doesn't appear to be an easy solution, because the problem is not really well defined yet.

Another idea would be to just introduce a clutch that can be released in an emergency... then it doesn't even matter if the last PWM completed it's command, as it wouldn't affect anything 🙂


ReplyQuote
frogandtoad
(@frogandtoad)
Reputable Member
Joined: 1 year ago
Posts: 490
2020-04-30 10:48 am  

@dronebot-workshop

Posted by: @dronebot-workshop

I think cutting the power may be a bit excessive, as long as we can immediately stop the motors we can execute an emergency stop

Likewise Bill... as per my previous reply... maybe some kind of clutch arrangement could be used? dunno!

All I know is that if I hit the brakes on my car if I want to stop quickly, I don't expect my engine to shut down 🙂


ReplyQuote
byron
(@byron)
Reputable Member
Joined: 1 year ago
Posts: 353
2020-04-30 12:38 pm  
Posted by: @frogandtoad

All I know is that if I hit the brakes on my car if I want to stop quickly, I don't expect my engine to shut down 🙂

But you do expect your wheels to stop turning 😎

Posted by: @frogandtoad

Yes, I would envisage each command to be a class, with an internal command id for tracking, commands (incorporated as member functions (setPwm, accelerate, etc...)).  You would also need a brain/controller class, perhaps storing an array of these commands for tracking their execution!

A reasoned approach from a master, so it would be a good exercise for you demonstrate the benefits by putting up your version on the program once you see what Bill does (unless he uses the same approach you propose of course).   Different coding approaches are always of interest.  Bill has indicated that programming is not the bit of the project he likes the best so your approach should be shown for the benefit of all. (if must be the full equivalent program to be of any use of course) 


ReplyQuote
frogandtoad
(@frogandtoad)
Reputable Member
Joined: 1 year ago
Posts: 490
2020-04-30 1:04 pm  

@byron

Posted by: @byron

But you do expect your wheels to stop turning 😎 

Of course... I would add some calipers 🙂

Posted by: @byron

A reasoned approach from a master, so it would be a good exercise for you demonstrate the benefits by putting up your version on the program once you see what Bill does (unless he uses the same approach you propose of course).   Different coding approaches are always of interest.  Bill has indicated that programming is not the bit of the project he likes the best so your approach should be shown for the benefit of all. (if must be the full equivalent program to be of any use of course)

I am not a master, and it was just an idea to add to the current ideas flying around.  Have you found a flaw with my idea that you would like to expand on?

If you have, then great... an idea needs to be researched well before being accepted, and certainly well before any development can (or should), begin.

I'm not sure what Bill's like or dislike of programming has to do with an idea?


ReplyQuote
DroneBot Workshop
(@dronebot-workshop)
Workshop Guru Admin
Joined: 1 year ago
Posts: 628
2020-04-30 1:19 pm  

OK, I have some code on GitHub for you.

Essentially this is an improved version of the original test code, and it has a basic Emergency Stop interrupt running.

There are a few demo statements in the Loop, just to move the motor back and forth. If, at any time, you generate an interrupt everything in the Loop will stop.

What has actually happened is that you have set the "motorStatus" variable to a value of "9", which is Emergency Stop. Nothing will run until something sets that to another value.

This is a simple demo, and I'm going to modify it now to check to see which of the six lines caused the Emergency Stop, and to prevent "false alarms". But I wanted to get it out to you this morning so I could spend the rest of the day playing in the workshop!

The Interrupt Service Routine is very simple:

void isr_emstop() {
// Set motor speed to zero
motorPwm = 0;
// Stop Motor by sending PWM signal low
digitalWrite(MD10C_PWM, 0);

// Set Status
motorStatus = 9;

}

 

We set the motorPwm speed variable to zero and stop the motor by sending a digital zero to the PWM pin. Then the motorStatus variable is set to 9.

The key to getting this to work is to replace all uses of the "analogWrite" statement with a call to a function called motorMove.

 

void motorMove(int mtrspeed) {
// Check motor status
if (motorStatus == 9) {
digitalWrite(MD10C_PWM, 0);
} else {
analogWrite(MD10C_PWM, mtrspeed);
}

}

As you can see, what this does is first check the motorStatus. If it is a 9 (Emergency Stop) then it stops the motor, as opposed to moving it.

So look at some functions like motorAccel, motorDecel, or movePWM, and you'll see the "analogWrite" statements replaced by calls to motorMove.

 

Now that this is on GitHub you can clone or fork it and improve upon it. Please note the "Function Status" list starting on line 116, it shows the current status of all the functions in the code, as there are still several incomplete functions.  I will update this list as I publish code updates.

Again, please remember that this is test code and that it is due to change periodically, I'll keep posting the latest version to GitHub.

😎

Bill

 

"Never trust a computer you can’t throw out a window." — Steve Wozniak


truckmen liked
ReplyQuote
frogandtoad
(@frogandtoad)
Reputable Member
Joined: 1 year ago
Posts: 490
2020-04-30 1:29 pm  

@dronebot-workshop

Hi Bill,

Not sure if this is meant for me, someone else, or the group in general?

Nevertheless, I will have a look at it 🙂

Cheers!


ReplyQuote
byron
(@byron)
Reputable Member
Joined: 1 year ago
Posts: 353
2020-04-30 2:40 pm  
Posted by: @frogandtoad

Not sure if this is meant for me

I was meant for you for sure.

Posted by: @frogandtoad

Have you found a flaw with my idea that you would like to expand on?

Nope, I thought is was a well considered idea, I hope you follow up with your version.

Posted by: @frogandtoad

I'm not sure what Bill's like or dislike of programming has to do with an idea?

Nothing I suppose.  I was really meaning to allude that Bill appreciates folk suggesting improvements to his code and he does not appear to think this is his main expertise (excellent though his code is).   C++ examples with classes coming up ??

Posted by: @frogandtoad

Nevertheless, I will have a look at it 🙂

Thats the spirit 😀 

This post was modified 6 months ago by byron

ReplyQuote
starnovice
(@starnovice)
Estimable Member
Joined: 1 year ago
Posts: 169
2020-04-30 2:55 pm  

@dronebot-workshop

My solution is similiar to yours, but in yours you can still have the e-stop occur after the "if (motorStatus == 9) " and before the "analogWrite(MD10C_PWM, mtrspeed);", in which case the speed would be changed to mtrspeed even though you set it to 0 in the interrupt handler. To cover that case I put a second check after the "analogWrite(MD10C_PWM, mtrspeed);" to set it back to 0. But you are right in that this is the only place allowed to change the motor speed (except for the interrupt handler of course).

void motorMove(int mtrspeed){ 
if (motorStatus == 9) {
digitalWrite(MD10C_PWM, 0);
} else {
analogWrite(MD10C_PWM, mtrspeed);
}
if (motorStatus ==9) {
analogWrite(MD10C_PWM, 0)
}

Pat Wicker (Portland, OR, USA)


ReplyQuote
byron
(@byron)
Reputable Member
Joined: 1 year ago
Posts: 353
2020-04-30 3:26 pm  

@dronebot-workshop

The flag check does the trick 👍 .  

I did notice a couple of bits of code along the following line:

 // Set Status to Ready
  if (motorStatus == 9) {
    motorStatus = 9;
  } else {
    motorStatus = 1;
  } 

Which I though may be better as
if (motorStatus != 9) {
motorStatus = 1;




ReplyQuote
DroneBot Workshop
(@dronebot-workshop)
Workshop Guru Admin
Joined: 1 year ago
Posts: 628
2020-04-30 3:34 pm  

@frogandtoad

It's meant for everyone. I'm hoping it can be turned into something useful!

@byron

Yes, I agree, that does look better!  I'm changing it.

😎

Bill

"Never trust a computer you can’t throw out a window." — Steve Wozniak


ReplyQuote
DroneBot Workshop
(@dronebot-workshop)
Workshop Guru Admin
Joined: 1 year ago
Posts: 628
2020-04-30 3:42 pm  
Posted by: @starnovice

void motorMove(int mtrspeed){
if (motorStatus == 9) {
digitalWrite(MD10C_PWM, 0);
} else {
analogWrite(MD10C_PWM, mtrspeed);
}
if (motorStatus ==9) {
analogWrite(MD10C_PWM, mtrspeed)
}

Sorry, I have some brain fog here. Shouldn't the last line be analogWrite(MD10C_PWM, 0); ? Or have I missed something?

You do make a good point about the interrupt occurring at exactly the wrong moment!

"Never trust a computer you can’t throw out a window." — Steve Wozniak


ReplyQuote
starnovice
(@starnovice)
Estimable Member
Joined: 1 year ago
Posts: 169
2020-04-30 3:46 pm  
Posted by: @dronebot-workshop
Posted by: @starnovice

void motorMove(int mtrspeed){
if (motorStatus == 9) {
digitalWrite(MD10C_PWM, 0);
} else {
analogWrite(MD10C_PWM, mtrspeed);
}
if (motorStatus ==9) {
analogWrite(MD10C_PWM, mtrspeed)
}

Sorry, I have some brain fog here. Shouldn't the last line be analogWrite(MD10C_PWM, 0); ? Or have I missed something?

You do make a good point about the interrupt occurring at exactly the wrong moment!

You are right, I edited the message.

Pat Wicker (Portland, OR, USA)


ReplyQuote
frogandtoad
(@frogandtoad)
Reputable Member
Joined: 1 year ago
Posts: 490
2020-04-30 3:54 pm  

@dronebot-workshop

Hi Bill,

No problem... I didn't see the @ symbol, so just checking as I've been away for a while and come in on this pretty late 🙂

Anyway, I did have a quick look, but not through the whole code yet, because I found a few areas of improvement that may end up changing your thinking and design anyway 🙂

Here is an example of what I mean for the first function I looked at:

enum {BUSY, AWAITING_COMMAND, STOP = 8, EMERGENCY_STOP = 9};

int motorStatus = STOP;

void movePWM(int spp, int dr, long tm, long acl, long dcl)
 {
  if(motorStatus == EMERGENCY_STOP /*STOP or STOP or both?*/) {
    Serial.println("Emergency stop initiated - Aborting move...");
    motorStatus = AWAITING_COMMAND; // STANDBY?
    return;
   } else {
    // You can remove all of the if statements too...
    constrain(spp, 0, 255);   // Keep PWM speed between 0 and 255
    constrain(dr,  0, 1);     // Keep Direction between 0 and 1
    constrain(tm,  0, 60000); // Keep run time between 0 and 1 minute
    constrain(acl, 0, 60000); // Keep acceleration between 0 and 1 minute
    constrain(dcl, 0, 60000); // Keep deceleration between 0 and 1 minute
  }

  // Removed other code for brevity

  Serial.println("End of movePwm function");
  motorStatus = AWAITING_COMMAND;
 }

void setup() {
 Serial.begin(9600);
 
 motorStatus = EMERGENCY_STOP;
 movePWM(10, 1, 0, 0, 0);
 Serial.println("Motor status: " + String(motorStatus) + String(" - Ready for a new command\n"));
 
 motorStatus = BUSY;
 movePWM(10, 1, 0, 0, 0);
 Serial.println("Motor status: " + String(motorStatus) + String(" - Ready for a new command\n")); 
 }

void loop() {

 }

I've basically just simplified all those if statements and incorporated the (IMO), highly under utilised constraint function, but, the most important part of the code is just returning the function at the right spot.

Also note that an integer is too small in Arduino for that range, so changed to long data type.  These parameters of the function also raise another question, as in your code you pass them by value, and then in places access their global names anyway, so I think you need to settle on a standard there.

Anyway, give it a test... just some ideas to get you thinking 😉


ReplyQuote
Page 4 / 6