I was wondering how to measure duty cycle, in this case button pressed/released ratio.
My goal is/was to find a function which gives me duty cycle for linear actuator 'cos manufacturer's data sheet says that duty cycle shouldn't exceed 25%. This example measures duty cycle by 10 second periods but if someone has an idea how to measure it by last 10 seconds, I'll be grateful. I mean that the function which returns last 10 second duty cycle for example every second or so..
Someone might find this example useful.
int inPin = 2;
boolean inPinState = false;
int debouncing_time = 15;
volatile unsigned long lastMicros;
unsigned long previousMillis = 0;
const long interval = 2000;
long pressedWhileInterval = 0;
void setup()
{
Serial.begin(115200);
pinMode(inPin, INPUT_PULLUP);
digitalWrite(inPin, HIGH);
attachInterrupt(0, interrupt, CHANGE);
}
void loop()
{
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval)
{
previousMillis = currentMillis;
float dutyCycle = (float)pressedWhileInterval / interval;
dutyCycle = dutyCycle * 100;
Serial.print("dutyCycle: ");
Serial.print(dutyCycle,0);
Serial.println(" %");
pressedWhileInterval = 0;
}
}
void interrupt()
{
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
// wait a while for stabilizing button pin
delay(50);
// read pin state, was pressed or released
inPinState = digitalRead(inPin);
// If interrupts come faster than 50ms, assume it's a bounce and ignore
if (interrupt_time - last_interrupt_time > 50)
{
switch (inPinState)
{
case 0:
//Serial.println("PRESSED ");
break;
case 1:
long pressedDuration = (long)interrupt_time - last_interrupt_time;
pressedWhileInterval += pressedDuration;
//Serial.print("RELEASED, Was pressed: ");
//Serial.println(pressedDuration);
break;
}
}
last_interrupt_time = interrupt_time;
}
void loop() {
// put your main code here, to run repeatedly:
if (Change) {
Serial.print("Pin 2 Went "); Serial.print(PinState);
Serial.print("\t Time "); Serial.println(DeltaTime);
Serial.println();
Change = 0;
}
}
Thanks! Wasn't exactly what I've in mind but thanks!
Edit: What I'm planning is like history from last 10 seconds.. Like oscilloscopes will show measured voltage also in the past, this would be duty cycle percentage history for last 10 seconds (or some other reasonable time).
The duty cycle for a motor is a thermal restriction, the timescales involved are usually minutes, hours,
not 10 seconds (that would be for a very small thermal mass).
I'd suggest finding the datasheet for clarification of the thermal time constant, and then just
low-pass filter your measurements of duty cycle using a first order digital filter of about the
same time constant. That then provides a proxy for the temperature rise in the actuator.
MarkT:
The duty cycle for a motor is a thermal restriction, the timescales involved are usually minutes, hours,
not 10 seconds (that would be for a very small thermal mass).
Yes, 10 seconds was just an example for time period I wish to measure it..
That zhomeslice's example could be exactly what I was looking for if I'll choose to calculate duty cycle ratio each time when the actuator is switched off, by dividing those two times together.. ..the time how long it was turned on last time divided by the time how long it was switched off before that..
MarkT:
I'd suggest finding the datasheet for clarification of the thermal time constant, and then just
low-pass filter your measurements of duty cycle using a first order digital filter of about the
same time constant. That then provides a proxy for the temperature rise in the actuator.
Datasheet says: "Duty cycle:25% or 1 min continuous operation in 4 min."
Could you explain more this chapter, please?
Then you just need to digitally low pass filter the on/off state of the motor with a time constant of 240 seconds
or so and raise the alarm if it creeps up to 0.25.
To digitally filter you'll need to sample the state of the motor often enough to get a reasonable accurate
measure (10 times faster than the minimum mark or space times you use ought to be good).
There will be various websites that can generate you a 1st order digital filter got a given sample rate and
cutoff-frequency (which is the reciprocal of time-constant).
MarkT:
Then you just need to digitally low pass filter the on/off state of the motor with a time constant of 240 seconds
or so and raise the alarm if it creeps up to 0.25.
To digitally filter you'll need to sample the state of the motor often enough to get a reasonable accurate
measure (10 times faster than the minimum mark or space times you use ought to be good).
There will be various websites that can generate you a 1st order digital filter got a given sample rate and
cutoff-frequency (which is the reciprocal of time-constant).
Thanks! I've used filter like this to smooth for example potentiometer reading of the actuator
OUTPUT =(INPUT + OUTPUTlast * k - 1) / k
In this case k-factor would be much higher than 8 which I've used with pot values, right?
If motor driving state is 1 (which means actuator is on) it will slightly increase OUTPUT-value and vice versa if it's 0 it will slightly decrease OUTPUT-value.
All I have to do is to find right value for k-factor or did you mean something else ?
MarkT:
That's the sort of thing. The numerically stable form is:
OUTPUT += (INPUT - OUTPUTlast) / k ;
There is only only k, which is used to scale the error term. Your form integrates the input so
its not quite the same anyway.
TommiP:
I'll have to do some testing. Thanks for helping me out
TommiP
int PinState, PinStateWas;
int k = 1000;
float dutyCycle;
void setup()
{
}
void loop()
{
switch (digitalRead(2)^1)
{
case 0:
PinState = -1;
break;
case 1:
PinState = 1;
break;
}
dutyCycle += (float)(PinState + PinStateWas) / k;
dutyCycle = constrain(dutyCycle, 0, 1);
PinStateWas = PinState;
}
This seems to work like you mean right? The k-factor is now 1000 for testing purposes but it should be more and I was wondering that should it's correct value be the value which raises dutyCycle to 0.25 in one minute ?