## Measuring duty cycle

FunkyAP
Posts: 3
Joined: Fri Apr 08, 2016 10:29 am

### Measuring duty cycle

Hi,

I have a project going on that requires me to measure duty cycle of a 100 Hz square wave signal. The duty cycle changes but the frequency stays constant. The amplitude of the signal is 15 volts and I have used a resistor and zener to get it down to 3 volts so I can use one of the GPIO pins to measure the duty cycle.

For some reason once in a while when the duty cycle changes there is a huge error in the measurement. For example when it changes from 50 % to 55 % raspberry might show that it is 3 % or 87 % or something else. I'm guessing that the problem comes from the fact when the duty cycle changes it sometimes screws up the timing calculations for the next pulse. Since I'm fairly new to raspberry and python I don't know how to solve this.

I tried to do the same with arduino and it works perfectly when I'm using the pulseIn function and the exact same circuit. The signal is generated from my function generator and I have check it with my scope that it is correct. But if I connect arduino to pi and send the data over tx and rx or over usb there is some weird error on the measurement that I don't get with my pc.

Here is the code that I have used with my Pi and the resistor and zener circuit (basic overvoltage circuit).

Code: Select all

``````import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

while True:
try:
GPIO.wait_for_edge(25, GPIO.RISING)
startTime = time.time()
GPIO.wait_for_edge(25, GPIO.FALLING)
print "%.1f" % ((time.time() - startTime) * 10000)
except KeyboardInterrupt:
GPIO.cleanup()
GPIO.cleanup()``````
I also tried this code but I get the same problem

Code: Select all

``````import time
import RPi.GPIO as GPIO

dutyPin = 25
GPIO.setmode(GPIO.BCM)
GPIO.setup(dutyPin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

while True:
try:
while GPIO.input(dutyPin)
pass
start = time.time()
while not GPIO.input(dutyPin)
pass
width = time.time() - start

print "%.1f" % (width * 10000)
except KeyboardInterrupt:
GPIO.cleanup()
GPIO.cleanup()``````

joan
Posts: 14934
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

### Re: Measuring duty cycle

boyoh
Posts: 1468
Joined: Fri Nov 23, 2012 3:30 pm
Location: Selby. North Yorkshire .UK

### Re: Measuring duty cycle

The problem of eratic duty cycles might be due the the timing of the duty cycles
Starting and stopping, If the timing is random you will , you might get problem
Try starting and stopping the duty cycles at the rising and falling edge of the pulses
This will give you some synchronization between the pulse generator and the pulse
Modulater
BoyOh ( Selby, North Yorkshire.UK)
Some Times Right Some Times Wrong

liudr
Posts: 687
Joined: Sat Jun 01, 2013 12:11 am
Location: Central MN, USA
Contact: Website

### Re: Measuring duty cycle

1% of the 100Hz duty is 0.1 millisecond accuracy. Use an arduino for that and return average duty cycle via USB serial port. How often do you need to measure?
Arduino data loggers, user interface, printed circuit board designer since 2009, RPI 3B 2B 2B Zero Jessie, assembly/C/C++/java/python programmer since the 80's

FunkyAP
Posts: 3
Joined: Fri Apr 08, 2016 10:29 am

### Re: Measuring duty cycle

boyoh wrote:The problem of eratic duty cycles might be due the the timing of the duty cycles
Starting and stopping, If the timing is random you will , you might get problem
Try starting and stopping the duty cycles at the rising and falling edge of the pulses
This will give you some synchronization between the pulse generator and the pulse
Modulater
I was trying to do something like that with my code. Just reading the positive pulse of the PWM signal and calculating the duty cycle since it is a fixed frequency, but for some reason since the duty cycle is changing it gives a few bad readings from time to time (1/10 - 1/20 is bad). This is a control circuit so it would be good the ged rid of the bad readings and since I don't need to read every pulse, every other is just fine I was wondering if there is an accurate delay function on python that I could use and skip one or two pulses and then read one again or is there a better way to skip every other pulse so I get more time to process the readings / timing wont be such an issue?
liudr wrote:1% of the 100Hz duty is 0.1 millisecond accuracy. Use an arduino for that and return average duty cycle via USB serial port. How often do you need to measure?
I tried to read it with arduino and it works perfectly if the arduino is connected to my PC and I send the data over serial, but when I connect it to raspberry I get a really odd error on the readings, 50% duty cycle will be 44% and it is linear error. The lower the duty cycle, bigger the error about 10 - 12 units and higher the duty cycle the lower the error is about 0 - 1 units.

Avarage readings work on raspberry alone but since this is a control circuit the reading can't be an avarage or the behaviour will change and it won't control the system correctly. I don't need to read every pulse, it can skip few pulses to get the timing correct for the one it actually read. So if it reads one pulse it can skip the next four pulses and then read one again.

rurwin
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

### Re: Measuring duty cycle

Python is not fast enough to get the speed you require and it will show systematic and random errors due to the Python interpreter and other processes and interrupts that Linux is executing.

It is possible to do this on the Pi, but you need to get much closer to the hardware to do it. Joan has a library that does it and has pointed it out to you above.

liudr
Posts: 687
Joined: Sat Jun 01, 2013 12:11 am
Location: Central MN, USA
Contact: Website

### Re: Measuring duty cycle

What data do you send from arduino to PC, the duty cycle or raw data?
Arduino data loggers, user interface, printed circuit board designer since 2009, RPI 3B 2B 2B Zero Jessie, assembly/C/C++/java/python programmer since the 80's

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

### Re: Measuring duty cycle

rurwin wrote:Python is not fast enough to get the speed you require and it will show systematic and random errors due to the Python interpreter and other processes and interrupts that Linux is executing.
I have a comparable problem as OP. I want to sent a AM-signal (via 433MHz) with a frequency around 10kHz using the "typical" 433-transmitter (GPIO connected to DATA pin gets me this AM 433-signal). I am struggling with python and just came through your post. Do I understand it correctly that using simple python is a very bad idea to achieve this?

I also tried an arduino but was also not lucky. But this might be due to the fact that I programmed it badly (arrays instead of straightforward writing down the short pulse train, complicated if-then-else etc). I am new to arduino - would you still recommend to dug deeper into it?
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

rurwin
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

### Re: Measuring duty cycle

Using the Pi to generate a radio signal is a subject that will be closed down fast on this forum. It is illegal to do this unless one is an expert on radio engineering because the signal coming out of the Pi is not just 433MHz but has many strong harmonics. The primary user of the 433MHz band is the UK military.

I strongly suggest that you look for the many cheap radio transmitter and receiver modules that are available. They are ready to use and legal. They simply accept a digital pulse-train, transmit it to the receiver and output it there.

A 10kHz signal would be difficult to receive using Python, but you could use the UART to send and receive through a pair of radio modules, probably faster than that.