09-19-2011 12:03 AM
Using WindowsCVI version 8.5, trying to set the time interval ( between 20 to 25sec.) in an ascynchronous timer. IT DOES NOT WORK!
The following code snippet is from asynctmr.c:
case ASYNC_ATTR_INTERVAL :
{
double doubleInterval = va_arg(parmInfo,double);
if (doubleInterval >= 0)
{
double doubleResolution = GetResolution ();
CVIUSTEtime interval;
if (doubleInterval < doubleResolution)
doubleInterval = doubleResolution;
ConvertDoubleToTime (doubleInterval, &interval);
if (CVIUSTEsettimer (asyncTimerPtr->timer, &interval)) <---this function call always returns a {0}. Causing...
asyncTimerPtr->interval = interval;
else
error = ASYNC_TIMER_FAIL_ERR; <-----this error to be returned to the caller.
}
else
error = ASYNC_INVALID_PARAMETER_ERR;
break;
}
The timer is created with an interval of 10.0seconds, which works just fine. But any attempt to change the original value will not work!
Solved! Go to Solution.
09-19-2011 04:16 AM
Do you receive the same error when running the asynchronous timer demo (samples\toolbox\asyncdem.prj)? I have tried it on my machine (CVI 8.5.0; async timer loaded as a library) without any error with intervals from 10 to 500 msec.
09-19-2011 08:18 AM
The demo project works just fine on my system also. The demo project has the asynctmr.fp linked in on the project worksheet. On my project I have the actual (c) module {asynctmr.c} along with its header {asynctmr.h} in the project file listing. That was how I was able to step intro the source shown in my original message. I cannot do that on the demo project.
09-19-2011 08:35 AM
Actually you can: once the async timer is loaded as an instrument, you can go to Instrument >> Edit menu, select the instrument in the list of elements loaded and then click on Attach and edit source button: with this you are able to use the source code, step trace into it, place breakpoints and examine variables.
09-19-2011 10:09 AM
I really appreciate the tip you gave above. Didn't know that you could step and trace into Instuments that way. Sure wish National would provide the type of documentation that they use to ( I've been an occasional user since version 5.0).
Noticed one difference between my program and the demo. The demo progam has the timer running (ENABLED) when the interval attribute is changed. In my program I have an instance of the timer created, which of course gave me the Timer_ID, but it is not running (IT IS DISABLED) when I am trying to change it's interval. Could that be the problem? I am trying to first change the interval attruibute and then enabling the timer.
09-19-2011 04:16 PM
I cannot answer at the moment 'cause I don't have CVI installed on this machine.
If it can fit with your application, you could simplify the code and have a single NewAsyncTimer with the correct interval instead of creating the timer disabled and setting the interval after this moment.
09-19-2011 05:05 PM
I could not reproduce this even if the timer was disabled when created. Do you have a small piece of code that will reproduce this?
09-20-2011 01:59 PM
Thanks again for your help. I used your suggestion to just create the async timer(s) only as needed, embedding the current interval time in the parameter NewAsyncTimer() call. This seems to work. Attached is a code snippet of the Timer creation and Callback. Notice that the instance of the timer self destructs when its timeout event occurs. I hope this is OK to do this.
if ( ( action == OUTPUT ) || ( action == BOTH ) )
{
LaunchOutputTerminals( sys.channel[cidx].output );
NewTimerID = NewAsyncTimer( TimerPeriod, -1, 0, Output_Timer, NULL );
sys.channel[cidx].tmr_id = NewTimerID;
SetAsyncTimerAttribute( NewTimerID, ASYNC_ATTR_ENABLED, TRUE );
}
}
sys.channel[cidx].saved_state = PresentInputState; //..save new state
}
return( 0 );
}
int CVICALLBACK Output_Timer( int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
i32 cidx = 1;
DebugPrintf( "Output_Timer Callback\n" );
do
{
if ( control == sys.channel[cidx].tmr_id ) break;
}
while( ++cidx < 17 );
switch (event)
{
SetAsyncTimerAttribute( control, ASYNC_ATTR_ENABLED, FALSE );
case EVENT_DISCARD:
sys.channel[cidx].tmr_id = 0;
break;
case EVENT_TIMER_TICK:
KillOutputTerminals( sys.channel[cidx].output );
DiscardAsyncTimer( control );
break;
}
return( 0 );
}