Pages: [1]   Go Down
Author Topic: Watching the Dog  (Read 873 times)
0 Members and 1 Guest are viewing this topic.
Summerville, Oregon
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
I like this little thing!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Let me start by describing what I am trying to do then perhaps someone could advise me as to the best method.

The platform:
I am using an Arduino Mega

The setup:
The Mega is being used to control a 90v DC motor.  I control the speed via PWM using timer 2 and pin 10. I use the wire library to get the time of day from a DS1307, I use Serial1 to communicate with a touch screen and Serial (guess that would be 0) for debugging to the IDE and the command "attachInterrupt(0, doEncoder, CHANGE)" to keep track of the position via an optical encoder.

The mission!
I want to set up a what I used to call a watchdog timer.  I want it to make sure that a pulse from the encoder happens ever so many milli seconds. The purpose is to detect a stall condition. Something like.....

watcher code:
if( I don't hear from Mr. encoder)
{
     raise a fit and stop the motor;
}

encoder code;
{
    I am here and counting so sent note to watcher
}

Summary:
So! Any ideas folks, seems I need some combination of timer, interrupt or something.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12283
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Fair warning: the code below may not compile.

Your application has three states...

  Motor On
  Motor Off
  Motor Stalled

There are three transitions...

  Motor Off --> Motor On
  Motor On --> Motor Off
  Motor On --> Motor Stalled

I would define an enum for the states...

Code:
typedef enum ( MotorInit, MotorOff, MotorOn, MotorStalled ) tMotorState;
tMotorState CurrentMotorState;

Then in loop do something roughly like this...

Code:
void loop( void )
{
  switch ( CurrentMotorState )
  {
    case MotorInit:
      // This stuff could also be done in setup
      // Ensure the pin for the motor is off
      digitalWrite( MotorPin, 0 );
      // Ensure the motor shaft is not rotating (save the state of the encoder, delay, check the state of the encoder)
      // Say hello to the human or display a fault message
      // If everything looks good, transition to MotorOff
      CurrentMotorState = MotorOff;
      break;

    case MotorOff:
      // When the conditions are right, turn the motor on
      if ( WhateverIsTrue )
      {
        digitalWrite( MotorPin, 1 );
        CurrentMotorState = MotorOn;
      }
      break;

    case MotorOn:
      // When the conditions are right, turn the motor off
      if ( WhateverElseIsTrue )
      {
        digitalWrite( MotorPin, 0 );
        CurrentMotorState = MotorOff;
      }
      // Otherwise, check for a stall
      else
      {
        ThisMillis = millis();
        // If the encoder changed, the motor is not stalled
        if ( EncoderChanged )
        {
          LastEncoderMillis = ThisMillis;
        }
        // If the encoder hasn't changed in 50ms, something is wrong
        if ( ThisMillis - LastEncoderMillis >= 50 )
        {
          digitalWrite( MotorPin, 0 );
          CurrentMotorState = MotorStalled;
          // Inform the human
        }
      }
      break;

    case MotorStalled:
      // We need the human's assitance to get out of this state
      break;
  }
}

I hope that makes sense.
Logged

Summerville, Oregon
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
I like this little thing!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for the replay CB but because of the complexity of code running I would prefer not to use a polling method.  I have found some code that looks promising but would like to see what you and the others think. I have not figured out how to enable/disable the timer interrupt call yet. help?

Keshka
Code:
#include <avr/interrupt.h>

ISR(TIMER3_OVF_vect)
{
    call motor power off and notify user.
}

void doEncoder()
{
    update my encoder count;
    
    //reset timer so it does not cause interrupt
    TCNT3 = My_beginning timer_count;
}



void setup()
{
   // watch for encoder movement
   attachInterrupt(0, doEncoder, CHANGE);
}

void loop()
{
    enable the ISR(TIMER3_OVF_vect) function
    move_motor()
  
// lots of other code to follow

// stuff
// stuff
// stuff

   stop_motor()
   disable the ISR(TIMER3_OVF_vect) function

}

Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12283
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm afraid I won't be able to help.  I don't have any low-level experience with the counters.
Logged

Summerville, Oregon
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
I like this little thing!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Any one used timer3 on the Mega?

Keshka
Logged

Summerville, Oregon
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
I like this little thing!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, when all else fails read the book and do it yourself.  I modified Timer1 created by Jesse Tane and created Timer3.  You can find my notes and the files here: http://www.arduino.cc/playground/Code/Timer1

Keshka
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12283
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for following-up and thank you for publishing the fruits of your labor!
Logged

Pages: [1]   Go Up
Jump to: