04-01-2009 09:41 AM
Rick,
flex_load_circular_arc() is just a special case of the spherical arc but you only set the start angle and travel angle and the rest of data parameters are set to 0 (like pitch and yaw).
flex_wait_reference() is your own function that is built on top of flex_read_reference_status_rtn() so you can implement it how ever you want.
flex_check_reference() is another high leve function you can make yourself. Again it leverages flex_read_reference_status_rtn(). Here is a code snipet that shows what you might do:
FLEXFUNC flex_check_reference(BOARD, u8 axisOrVectorSpace, u16 axisOrVSMap, u16 *found, u16 *finding) {
i32 ret = NIMC_noError;
ret = flex_read_reference_status_rtn(BOARDID, axisOrVectorSpace, axisOrVSMap, NIMC_FINDING_REFERENCE, finding);
if (ret == NIMC_noError)
ret = flex_read_reference_status_rtn(BOARDID, axisOrVectorSpace, axisOrVSMap, NIMC_REFERENCE_FOUND, found);
//return status
return (ret);
}
flex_insert_program_label() is
cmdID = 344
word cnt = 4
data = label number (1 - 255 I think, 0 is not allowed)
nimcResetController() is not a command but a special sequence of data sent to the board at offset 0x0C
_busRegisterPtr->writeU16(0x0C, 0x0430);
_busRegisterPtr->writeU16(0x0C, 0x01D0);
_busRegisterPtr->writeU16(0x0C, 0x02B0);
_busRegisterPtr->writeU16(0x0C, 0x0470);
Rodger
04-07-2009 01:51 AM
Hi Rodger,
Many Thanks for your description of these functions. I have successfully accomplished the driver project. Without your assistance, I could hardly write the driver out.
Sincerely Thanks!
Rick
MSP
04-07-2009 07:05 AM
Rick,
Glad I could help and I'm very glad you were successful.
Would you be able to post your solution for others to use?
Thanks,
Rodger
04-09-2009 01:02 AM
Hi Rodger,
I have attached the codes of some difficult functions in the func.c file. Whoever would like to develop the customized driver for NI-Motion boards could take it for reference.
My driver is all written in RTX ( Real Time eXtension ). The meaning of the RtAPIs can be very easily guessed, for example, RtGetClockTime() is the time &clock read function in RTX.
The msp_motion_sendcommand() is another name for SendCommand(), which can be found in Natmotion.c.
The general process to develop the NI-Motion custom driver is:
First, the engineer must get familiar with and rewrite the SendCommand(). The original SendCommand() is for Linux platform. One must realize this function on his specific OS.
Then, every control commands in Motion DDK document need to be write out in almost the same format, like
int mmc_insert_program_label( HANDLE hmmc, USHORT labelNumber);
int mmc_load_circular_arc( HANDLE hmmc, UCHAR vectorSpace, ULONG radius, double startAngle, double travelAngle, UCHAR inputVector);
The only thing one should care is that the data conversion. The engineer must exactly follow the format mentioned in DDK to deliver commands and data to the controller.
If anybody has some questions about the driver, please feel free to ask me or mail to me. I will be very glad to communicate with others and write mails to you when I am not in the project 🙂
Regards,
Rick
MSP
06-01-2009 02:47 AM
Hi Rodger,
Thanking for your valuable information and suggestions, I have successfully finished the project. But the customer found there was a little problem during using the driver.
If I just installed the NI Windows driver for NI-7358 first but use my own driver APIs in RTX environment, everything goes quite well. However, if I uninstalled the Windows driver and directly use my driver APIs, the NI-7358 will return very strange error information by flex_read_error_msg_rtn() when I execute the initialize function:
//returned information
command ID = 52428
resource ID = 52428
error code = -858993460
I think the strange numbers appear because the FPGA and DSP are initialized incorrectly. Maybe Windows driver has done some additional initialize steps for the FPGA and DSP, which is not included in flex_initialize_controller().
My initialize function is:
int mmc_initialize_controller( HANDLE hmmc )
{
mmc_flush_rdb( hmmc );
mmc_read_csr( hmmc, &Temp);
if ( (Temp&0X40) != 0 ) {
mmc_read_error_msg( hmmc, &CommandID, &ResourceID, &ErrorCode);
if ( CommandID != 0) {
RtPrintf("Error occurs in mmc_initialize_controller()\n");
RtPrintf("command ID = %d\n",CommandID);
RtPrintf("resource ID = %d\n",ResourceID);
RtPrintf("error code = %d\n\n",ErrorCode);
RtPrintf("Please check for error code for solution\n");
}
}
mmc_read_csr(hmmc, &Temp);
if ( (Temp&0X40) != 0 ) {
mmc_read_error_msg( hmmc, &CommandID, &ResourceID, &ErrorCode);
if ( CommandID != 0) {
RtPrintf("Error occurs in mmc_initialize_controller()\n");
RtPrintf("command ID = %d\n",CommandID);
RtPrintf("resource ID = %d\n",ResourceID);
RtPrintf("error code = %d\n\n",ErrorCode);
RtPrintf("Please check for error code for solution\n");
}
}
mmc_read_csr(hmmc, &Temp);
mmc_clear_pu_status(hmmc);
mmc_read_csr( hmmc, &Temp);
while ( (Temp&0X20) != 0 ) {
mmc_read_csr( hmmc, &Temp );
}
mmc_stop_motion( hmmc, NIMC_AXIS_CTRL, NIMC_KILL_STOP, 0X01FE);
mmc_enable_axis( hmmc, 3, 0X0000);
mmc_config_axis(hmmc, NIMC_AXIS1, NIMC_ENCODER1, 0, NIMC_DAC1, 0);
mmc_enable_axis( hmmc,3, 0X01FE);
// Add additional functions here for your applications
//Enable ADCs if Necessary
//Set the Axes Modes
//Set the Limits
//Load PID Parameters
//Load the Velocity Settings
//Load the Motion Profile
//Set Up the Gearing
//Set Up the Encoders
//Set up I/O
//Set up the PWM
return 0;
}
I have exactly followed the instruction of DDK. Is there any additional steps I need to do or maybe there is mistake in my initialize function?
My customer has written some tests for NI-7358 in Linux. He found that without the official NI Linux driver, his own initialize function also met the some problem.
Could you please help me on this problem?
Many Thanks!
Rick
MSP
06-01-2009 08:02 AM
Rick,
Do you have the code that initializes the miniMITE chip on the motion board. Without this code, the communication via the PCI bus with the board is not set up and will not work. My guess is that this is the problem. Our motion driver will do this when the system discovers the board. So it happens without the user calling anything. I believe the DDK tells you how to set up the miniMITE, please make sure this is being done.
Also the return information numbers you included in your message are interesting. If looked at them in hex, they become 0xCCCC, 0xCCCC, and 0xCCCCCCCC. This is a common value you see on Windows if you are looking at uninitialized memory.
Let me know if this solves our problem.
Thanks,
Rodger
06-21-2009 10:17 PM
Hi Rodger,
Once again, you have provide me the exactly perfect answer!
It is the MiniMite initialization that causes my problem.
Now with the code in motion-DDK, the motion board can be easily initialized in RTX. Thank you!!
Best Regards,
Rick
MSP
09-24-2009 10:14 PM
Hi Rodger,
Sorry to trouble you once again...
I found the followed 3 arc functions have some problems. After these functions are executed, the motors do not work at all.
flex_load_circular_arc()
flex_load_helical_arc()
flex_load_spherical_arc()
I write in the same format for all the flex_ functions. Only these 3 functions could not driver the motors. All other functions work well as I expect.
I am afraid that maybe there is something wrong for the command format of these functions. I checked the motion DDK. The command format for flex_load_helical_arc() and flex_load_spherical_arc() are:
Load Helical Arc
Using This Function
startAngle = (u32)((startAnglef64 * 0x10000) / 45)
where: 0 <= startAnglef64 <= 359.999313
travelAngle = (u32)((travelAnglef64 * 0x10000) / 45)
where: 0 <= travelAnglef64 <= 359.999313
CommandID: 375
Valid Resource Type(s): Coordinate
Vector Type(s): Input
Packet Data (Send)
Word Count: 8
Data Passed In
u32 radius
u32 startAngle
u32 travelAngle
i32 linearTravel
Load Spherical Arc
Using This Function
The following formulas convert floating point parameters into
their integer representations, which are passed to the motion controller:
pitch = (f64planePitch * 0x10000) / 45.
If yaw == 360, then yaw = 0. Else yaw = (f64planeYaw * 0x10000) / 45.
If startAngle == 360, then startAngle = 0. Else startAngle =
(f64startAngle * 0x10000) / 45.
travelAngle = (f64travelAngle * 0x10000) / 45.
CommandID: 290
Valid Resource Type(s): Coordinate
Vector Type(s): Input
Packet Data (Send)
Word Count: 10
Data Passed In
u32 radius
u32 pitch
u32 yaw
u32 startAngle
i32 travelAngle
Could you please do me a favor to have a check on whether there is an error on the below command format?
Thank you in advance!
Regards,
Rick
MSP
09-25-2009 08:05 AM
Rick,
I double checked and the command packet information seems to be correct. Things to consider are:
1. Big endian vs. little endian. Since the value is crossing over the 16 bit word boundry, make sure the data is being packed correctly. The most significant word should be sent first. And the CPU on the board is using big endian so you may need to do some translation if your host CPU uses little endian.
2. The notes for several of the parameters show a conversion from float to fixed point. This is important to do correctly.
If that does not help, send me your code snippet and I will take a look at it for you.
Thanks,
Rodger