Hi,
I create C# software to measure periode of pulse.
Here is Config code for timer setup :
LJUD.eTCConfig(JackU3.ljhandle, aEnableTimers, aEnableCounters, tcpInOffset,
(int)timerClockBaseIndex, timerClockDivisor, aTimerModes, adblTimerValues, 0, 0);
And here is how to read timer :
LJUD.eTCValues(JackU3.ljhandle, aReadTimers, aUpdateResetTimers, aReadCounters,
aResetCounters, adblTimerValues, adblCounterValues, 0, 0);
but with my software i reading pulse periode is constant at 16,xx ms but at osiciloscope actual periode is constant at 19.xx.
Could you help me what is i missing here ?
Thanks
Here is my complete code for counter periode measurement.
Thank you.
private void Labjack_ReadTimerCounter(emTimermode timMode)
{
LJUD.TIMERCLOCKS timerClockBaseIndex;
int tcpInOffset;
int timerClockDivisor;
int[] aEnableTimers = new int[2];
int[] aEnableCounters = new int[2];
int[] aTimerModes = new int[2];
int[] aReadTimers = new int[2];
int[] aUpdateResetTimers = new int[2];
int[] aReadCounters = new int[2];
int[] aResetCounters = new int[2];
double[] adblTimerValues = new double[2];
double[] adblCounterValues = { 0, 0 };
timerClockBaseIndex = LJUD.TIMERCLOCKS.MHZ48; // Base clock is 48 MHz, so Counter0 is Available.
timerClockDivisor = 0; // No divisor
try
{
if (timMode == emTimermode.TiConInit)
{
// using by eTCConfig.
tcpInOffset = 8; // Offset is 8, so timers/counters start at EIO0.
aEnableTimers[0] = 0; // Enable Timer0 (uses EIO0). 0=OFF 1=ON
aEnableTimers[1] = 0; // Enable Timer1 (uses EIO1). 0=OFF 1=ON
aEnableCounters[0] = 0; // Enable Counter0 (uses EIO2). 0=OFF 1=ON
aEnableCounters[1] = 0; // Enable Counter1 (uses EIO3). 0=OFF 1=ON
aTimerModes[0] = (int)LJUD.TIMERMODE.DUTYCYCLE;
aTimerModes[1] = (int)LJUD.TIMERMODE.DUTYCYCLE;
//----------------------------------------------------------------------------
if (EdTimClock.Text == "12 MHZ") timerClockBaseIndex = LJUD.TIMERCLOCKS.MHZ12;
tcpInOffset = Decimal.ToUInt16(EdTimOffset.Value);
if (EdTimEnable.Value == 1) { aEnableTimers[0] = 1; aEnableTimers[1] = 0; }
else { aEnableTimers[0] = 1; aEnableTimers[1] = 1; }
if (EdCntEn00.Checked) aEnableCounters[0] = 1;
if (EdCntEn11.Checked) aEnableCounters[1] = 1;
if (CbTimMode00.SelectedIndex == 1) aTimerModes[0] = (int)LJUD.TIMERMODE.RISINGEDGES32; // Timer0 is duty cyle input.
if (CbTimMode11.SelectedIndex == 1) aTimerModes[1] = (int)LJUD.TIMERMODE.RISINGEDGES32; // Timer1 is duty cyle input.
//----------------------------------------------------------------------------
adblTimerValues[0] = 16384; // Set PWM8 duty-cycle to 16384=75%, 32768=50%.
adblTimerValues[1] = 16384; // Set PWM8 duty-cycle to 16384=75%, 32768=50%.
LJUD.eTCConfig(JackU3.ljhandle, aEnableTimers, aEnableCounters, tcpInOffset,
(int)timerClockBaseIndex, timerClockDivisor, aTimerModes, adblTimerValues, 0, 0);
}
//------------- must be delay 1000 mS between init and Read for easy measurement
else if (timMode == emTimermode.TiConRead)
{
// using by eTCValues.
aReadTimers[0] = 0; // Read Timer0; 0-> Dont Read
aReadTimers[1] = 0; // Read Timer1;
aUpdateResetTimers[0] = 0; // Update Timer0;
aUpdateResetTimers[1] = 0; // Reset Timer1;
aReadCounters[0] = 0; // Read Counter0;
aReadCounters[1] = 0; // Read Counter1;
aResetCounters[0] = 0; // Reset Counter0.
aResetCounters[1] = 0; // Reset Counter1.
//adblTimerValues[1] = 0;
//----------------------------------------------------------------------------
if (EdTimEnable.Value == 1) { aReadTimers[0] = 1; aUpdateResetTimers[0] = 1;
aReadTimers[1] = 0; aUpdateResetTimers[1] = 0; }
else { aReadTimers[0] = 1; aUpdateResetTimers[0] = 1;
aReadTimers[1] = 1; aUpdateResetTimers[1] = 1; }
if (EdCntEn00.Checked) { aReadCounters[0] = 1; aResetCounters[0] = 1; }
if (EdCntEn11.Checked) { aReadCounters[1] = 1; aResetCounters[1] = 1; }
//----------------------------------------------------------------------------
adblTimerValues[0] = 32768; // Change Timer0 duty-cycle to 50%.
adblTimerValues[1] = 32768; // Change Timer0 duty-cycle to 50%.
LJUD.eTCValues(JackU3.ljhandle, aReadTimers, aUpdateResetTimers, aReadCounters,
aResetCounters, adblTimerValues, adblCounterValues, 0, 0);
//??? LJUD.AddRequest(JackU3.ljhandle, LJUD.IO.PUT_TIMER_MODE, 0, (double)LJUD.TIMERMODE.RISINGEDGES32, 0, 0);
// https://labjack.com/forums/ccc/precision-wait-non-rtos
/*
LJUD.AddRequest(d.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.TIMER_COUNTER_PIN_OFFSET, 6 ,0 ,0);
LJUD.AddRequest(d.ljhandle, LJUD.IO.PUT_CONFIG, LJUD.CHANNEL.NUMBER_TIMERS_ENABLED, 1,0,0);
LJUD.AddRequest(d.ljhandle, LJUD.IO.PUT_COUNTER_ENABLE, 1,1,0,0);
LJUD.AddRequest(d.ljhandle, LJUD.IO.PUT_TIMER_MODE, 0 ,(double)LJUD.TIMERMODE.RISINGEDGE32,0,0)
*/
//----------------------------------------------------------------------------
LabTimer00.Text = adblTimerValues[0].ToString(); // string.Format("{0:0.000}", adblTimerValues[0]);
LabTimer11.Text = adblTimerValues[1].ToString(); // string.Format("{0:0.000}", adblTimerValues[1]);
LabCounter00.Text = adblCounterValues[0].ToString(); // string.Format("{0:0.000}", adblCounterValues[0]);
LabCounter11.Text = adblCounterValues[1].ToString(); // string.Format("{0:0.000}", adblCounterValues[1]);
//--------------------------------------------------------------------
double valPer00=0, valPer11=0;
if (adblCounterValues[0] > 0) valPer00 = adblCounterValues[0] / (timTiCon.Interval);
if (adblCounterValues[1] > 0) valPer11 = adblCounterValues[1] / (timTiCon.Interval);
if (valPer00 > 10) valPer00 += decimal.ToInt32(EdOffset.Value);
if (valPer11 > 10) valPer11 += decimal.ToInt32(EdOffset.Value);
LabPeriode00.Text = string.Format("{0:0.00}", valPer00);
LabPeriode11.Text = string.Format("{0:0.00}", valPer11);
//--------------------------------------------------------------------
double HiTim0 = 0, LoTim0 = 0, DutyTim0 = 0;
HiTim0 = (double)(((ulong)adblTimerValues[0]) % (65536)); // High time is LSW
LoTim0 = (double)(((ulong)adblTimerValues[0]) / (65536)); // Low time is MSW
DutyTim0 = 100 * HiTim0 / (HiTim0 + LoTim0); // Calculate the duty cycle percentage.
LabTiHigh00.Text = string.Format("{0:0.0}", HiTim0);
LabTiLow00.Text = string.Format("{0:0.0}", LoTim0);
LabDuty00.Text = string.Format("{0:0.0}", DutyTim0);
//--------------------------------------------------------------------
double HiTim1 = 0, LoTim1 = 0, DutyTim1 = 0;
HiTim1 = (double)(((ulong)adblTimerValues[1]) % (65536)); // High time is LSW
LoTim1 = (double)(((ulong)adblTimerValues[1]) / (65536)); // Low time is MSW
DutyTim1 = 100 * HiTim1 / (HiTim1 + LoTim1); // Calculate the duty cycle percentage.
LabTiHigh11.Text = string.Format("{0:0.0}", HiTim1);
LabTiLow11.Text = string.Format("{0:0.0}", LoTim1);
LabDuty11.Text = string.Format("{0:0.0}", DutyTim1);
//--------------------------------------------------------------------
//Disable all timers and counters.
//aEnableTimers[0] = 0;
//aEnableTimers[1] = 0;
//aEnableCounters[0] = 0;
//aEnableCounters[1] = 0;
//LJUD.eTCConfig(JackU3.ljhandle, aEnableTimers, aEnableCounters, 4, (int)timerClockBaseIndex, timerClockDivisor, aTimerModes, adblTimerValues, 0, 0);
}
}
catch (LabJackUDException ERR)
{
LabJack_MessageLog(ERR.ToString(), emMessage.emError);
}
}
The 48MHz clock is not suitable to measure a signal with 16ms period, the maximum measurable period is 65535/48000000 ≈ 1.37ms. Any value bigger than 1.37ms will cause an overflow. The timer counts should be saved as unsigned integers, so the overflow should just roll the value and cause invalid measurements.
Additionally, your calculations are off. The value returned for the duty cycle feature is the number of clock ticks and should be interpreted as integers. If the least significant word from the return value (corresponding to the high time) is 60000, the high time is equal to 60000 ticks/48000000(ticks/s) = 1.25ms.
I would recommend doing any initial timer/counter configuration in our LJControlPanel software. This should be faster to configure and troubleshoot, plus it helps limit the possibility of minor software errors affecting the setup. We have some good guides for timer/counter setups:
https://labjack.com/support/software/applications/ud-series/ljcontrolpan...
Hi labJack Team
Actually i already do test with LJControl panel.
And now i try to create same application with same function with LJControl panel.
Please see picture attached.
As you can see, LJControl panel can measure reach to 0.019108 Sec (19.108 mS).
but my software always range 14.xx mS ~ 16.xx mS and can not reach to 19 mS.
Need your input or advice on this.
Thank you.
FYI :
Configuration i already try for 48 MHz, 12 MHz.
Mode timer Duty Cycle, RisingEdge32 FallingEdge, etc any possibilities already try.
But can not reach event 17.xx mS
Regards,
Toopayz.
If you are using the duty cycle feature, the 12MHz clock is not very appropriate for a signal with 19ms period as given by our previous response about timer overflow/roll. You need to use a bigger clock divisor. 65535/0.019 ≈ 3.5MHz; the biggest clock frequency you should use with the duty cycle feature is 3MHz, which could be set up with the 48MHz clock and a divisor of 16.
It is expected that the period input feature is working correctly in LJControlPanel with your setup. The duty cycle feature needs to track both high time and low time, so the 32-bit timer register is split in two 16-bit registers, and that limits the measurable period. The period input feature can use the full 32-bit register to track the period. The maximum period measurable with the 48MHz clock and the period input feature is (232 - 1)/48000000 ≈ 89.47 seconds.
The value returned from the period input feature is also different from the duty cycle feature; it returns the period in seconds rather than clock ticks (the return of the duty cycle feature). Your code appears to be set up to read duty cycle only (and with errors in calculations as previously stated) so the period input readings would not work correctly under your current code.