Measuring Duty Cycle in conjunction with frequency

Hello,

I have started writing some very rough code to measure frequency, and convert that into a % of ethanol. The sensor i am using to measure that uses 50-150hz to display ethanol % and the duty cycle to display temp where 1 millisecond indicates -40* and 5 milliseconds indicates 257*.

The code i have written uses frequency measure library and it seems to do its job fairly well. I currently am simulating the frequency using one of the digital pins to turn on and off and feeding that back into pin 8 for it to be read out as a frequency. it seems to work fairly well for testing since im dealing with really low hz.

What i need to know is how can i add in the duty cycle calculation to determine tempurature? Does the library i am using allow for those calculations? Im very new to programming so most of this code is copy and paste from different examples, so im sure its not very efficient code.

#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  FreqMeasure.begin();
  pinMode(13, OUTPUT);
}

double sum=0;
int count=0;
float ethanol = 0;

void loop() {
  if (FreqMeasure.available()) {
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 100) {
      float frequency = FreqMeasure.countToFrequency(sum / count);
      Serial.print(frequency);
      Serial.println("hz");
      sum = 0;
      count = 0;
    if (frequency > 50)
    {ethanol = frequency-50.00;}
    else
    {ethanol = 0;}
    if (ethanol > 99)
    {ethanol = 99;}
    Serial.print(ethanol);
    Serial.println("%");
    }
  }
  {
  digitalWrite(13, HIGH);
  delay(10);
  digitalWrite(13, LOW);
  delay(10);
  }
}

You aren't measuring duty-cycle. You are measuring pulse width. There is a pulseIn() function which measures a pulse in microseconds.

Thanks for that clarification. The code that i was basing this off of was converting the pulse width into a duty cycle, so that's probably where i was getting confused. When i was reading up on pulsein() when i was beginning this project, i was only seeing examples of it being used with the analog inputs, but i am using a digital input. But, after reading the arduino page on pulsein, it looks like it can be used on a digital input. Would i run into any issues with processing latency that would cause errors in either calculation?

i just tried to implement pulsein, and it screwed with the frequency measurement. How can i implement pulsein? Would i use interrupts?

I use pulseIn without interrupts. something like...

int Frq = pulseIn(frqPin, HIGH);

int Frq being the variable you store results from pulseIn into.

frqPin is the physical pin you are connectes to on Arduino.

HIGH checks the time in microseconds the signal is HIGH. Alternatively you can use LOW as well.

Also, you can add a timeout period, although I've had mixed results using it so I leave it alone. You add a third element to the mix like so.

int Frq = pulseIn(frqPin, HIGH,1000);

Using pulseIn you can calculate the duty cycle, frequency, etc.

Bill

ironmanisanemic:
i just tried to implement pulsein, and it screwed with the frequency measurement. How can i implement pulsein? Would i use interrupts?

pulseIn() is blocking code… so be aware of that.

I think with frequencies and duty cycle you may want to look at interrupts as a simple way to keep the value updated.

here is an idea (that is untested) that you may want to play with:

struct SquareWave{
  volatile unsigned long pulseStart = 0;
  volatile unsigned long duration;
  volatile unsigned long timeOn;
  int frequency;
  int dutyCycle;
  void update() {this->frequency = 1.0 / float(duration); this->dutyCycle = float(timeOn) / float(duration);};
};

SquareWave myWave;

unsigned long lastUpdate = 0;

void setup() 
{
  Serial.begin(9600);
  attachInterrupt(0, signalRising, RISING);
  attachInterrupt(0, signalFalling, FALLING);
}

void loop() 
{
  myWave.update();
  if(millis() - lastUpdate > 5000UL)
  {
    lastUpdate = millis();
    Serial.print(F("Frequency:"));
    Serial.println(myWave.frequency);
    Serial.print(F("Duty Cycle:"));
    Serial.println(myWave.dutyCycle);
  }
}

void signalRising()
{
  unsigned long riseTime = micros();
  myWave.duration = riseTime - myWave.pulseStart;
  myWave.pulseStart = riseTime;
}

void signalFalling()
{
  myWave.timeOn = myWave.pulseStart - micros();
}

just a little struct that you use update() method to keep your variables up to date. You could apply a smoothing method as well if you care to.

It needs boundary checking as well (i.e. what it measures if no pulse or 100% duty cycle).

Of course you can't use pulseIn() with your existing code because you can't wait for an input and generate the input at the same time. You should generate the test signal on a separate device.

I would use interrupts and note the time intervals between rising edges for frequency and rising-then-falling edges for pulse length. Set a flag for each completed calculation and process the data in loop().