Hello,
I have been working on a project and I recently started noticing some very strange behavior. My project entails using a homemade linear actuator as a braking mechanism on a winch. The specific area I am having trouble with is measuring the velocity that the winch is lowering a mass at. I am currently using a rotary encoder to measure pulses, which I then translate to linear action using the arc length. I am using a single interrupt pin on only one signal of the encoder because I only care about velocity, not direction. After I count pulses and translate this to linear motion (~36 PPR encoder), (linear distance = NumberPulse/362pi*radius), I calculate velocity by counting the time it takes to traverse this number of pulses using millis(). I am having the very strange behavior that the time interval I calculate using millis is always coming out to be zero (code attached below). I have spent some time checking this, I tried a few things - maybe there is something I dont understand about how arduino uses clocks on interrupt pins - maybe its something with how I store my values? Any help will be appreciated.
The area I am concerned about is the function doEncoderA(), but I included all my code
//.............Encoder and Servo..............// //H = 187
#define encoder0PinA 2 //encoder writes to pin 2
#define reset 6
#define DistancePin 3
// board writes to pin 9 for servo
#include <Servo.h>
float PulseIn = 50.0;
//................Other Values...............//
const float pi = 3.1415;
volatile int encoder0Pos = 0;
unsigned long TimeNow; unsigned long PreviousTime;
unsigned long Interval;
float distance1 = PulseIn / 36.0 * 2 * pi * 2.54 / 4.0; //[cm]
float distance; float analog;
float Velocity;
int VSetPt; float Error; int SetPos = 150;
//...........Values for Stall Check...........//
int CheckTime1;
int CheckTime2 = 0;
int CheckServo1;
int CheckServo2 = -1; //servo will never be at this angle, will always be reset in the loop
int inittime;
int currenttime;
Servo myservo;
int a;
void setup() {
inittime = millis();
delay(1000);
Serial.begin(9600);
Serial.println("setup");
Serial.println(distance1, DEC);
myservo.attach(9); // attaches the servo on pin 9 to the servo object
//......................Encoder Stuff..................//
pinMode(encoder0PinA, INPUT);
pinMode(reset, INPUT);
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(digitalPinToInterrupt(encoder0PinA), doEncoderA, RISING);
//attachInterrupt(digitalPinToInterrupt(reset), doreset,RISING);
// encode r pin on interrupt 1 (pin 3)
//attachInterrupt(digitalPinToInterrupt(encoder0PinB), doEncoderB, CHANGE);
}
void loop() {
//..........Read Distance..........//
distance = pulseIn(3, HIGH);
a = digitalRead(reset);
//Serial.print("Is the reset high? | ");Serial.println(a);
if (distance > 45) {
// Serial.print("Value from distance pin | ");Serial.println(distance);
//........Check to see if stall..........//
CheckTime1 = millis();
CheckServo1 = myservo.read();
if (CheckServo1 == CheckServo2) {
if (CheckTime1 - CheckTime2 > 5) {
myservo.write(CheckServo1 + 20);
}
} else {
CheckServo2 = CheckServo1;
CheckTime2 = CheckTime1;
}
}
if (a == 1) {
SetPos = 150;
myservo.write(SetPos);
inittime = millis();
Serial.print("reset position | "); Serial.println(a);
}
}
void doEncoderA() {
encoder0Pos++;
Serial.print("encoder position | "); Serial.println(encoder0Pos);
if (encoder0Pos % (int)PulseIn == 0) {
TimeNow = millis();
Interval = TimeNow - PreviousTime;
Velocity = distance1 / ((float)Interval / 1000);
Serial.print("TimeNow | "); Serial.println(TimeNow);
Serial.print("Previous Time | "); Serial.println(PreviousTime);
PreviousTime = TimeNow;
SetServo();
Serial.print("velocity | "); Serial.println(Velocity);//Serial.println(encoder0Pos);
Serial.print("interval | "); Serial.println(Interval);
}
}
void SetServo() {
//calculate error
currenttime = millis();
if (distance < 70 && (currenttime - inittime) > 3000) {
VSetPt = 80.0 / 20.0 * distance - 80.0 / 120.0 * 20.0;
}
else {
VSetPt = 5; //HIGH: 150, LOW: 100? original: 130
}
Error = Velocity - VSetPt;
if (Error >= 1) { //this is our range
SetPos = SetPos - 1;
if (SetPos < 0) {
SetPos = 0;
}
myservo.write(SetPos);
}
else if (Error < -1) {
SetPos = SetPos + 1;
if (SetPos > 130) {
SetPos = 130;
}
myservo.write(SetPos);
}
//...........Switch to rest to 150 degrees.............//
Serial.print("Set Postiion = "); Serial.println(SetPos);
//Serial.print("reset position | ");Serial.println(a);
}
Again, the value "Interval" I calculate comes out to be zero very often, which causes my velocity to drive to infinity. The interval seems to go to zero more often when the winch shaft is rotating faster as opposed to slower.
Thank you