There's two basic things wrong with what you are doing there:
pulseIn()
isn't good for very accurate measurements
- The signal is still happening while you're doing other things, such as printing the high/low times.
You're not actually measuring the duty cycle of one single cycle, but the HIGH time of one cycle followed by the low cycle of a later one. If you want to do it properly you will have to ditch pulseIn()
and instead get your head around interrupts and timestamps.
The basic method is to present the signal to one of the INT pins, and attach an interrupt to that pin with the trigger set to CHANGE. The interrupt routine you specify will then be triggered every time the signal changes from HIGH to LOW or from LOW to HIGH.
Then the interrupt routine does very little. It basically records the time the interrupt happened (that must be the very first thing you do), then looks to see if it's a HIGH or a LOW signal on the pin. You then use the previous timestamp from the last time the interrupt was triggered to work out how long the previous phase lasted and set either a HIGH or a LOW variable depending on the current level of the state (if it's low set a high variable since that was the previous phase level, and if it's high set a low variable) with the time that phase lasted.
Then in your main loop you interrogate those variables periodically to display the duty cycle.
If that still isn't accurate enough then you should look at the hardware Input Capture module built into the MCU. That uses a hardware timer in much the same way as the interrupt but is able to capture a much more accurate time stamp for you since the time stamp is grabbed the moment the signal changes, rather than after a short delay once the interrupt routine has been called. Details can be found in the datasheet for the MCU on your Arduino.