06-30-2015 10:28 AM
Hi all,
I'm trying to generate 100% "NI PCI-CAN/2 Serie 2" card, but I'm only able to reach 60% with 8byte CAN frames and 35% with 1byte CAN frames. I'm using the "CAN Transmit Multiple" example:
loop:
//write the frames to the board
Status = ncWriteMult (TxHandle0, sizeof(Transmit0), Transmit0);
//wait until the last frame is send out
Status = ncWaitForState (TxHandle0, NC_ST_WRITE_SUCCESS, 2000, 0);
//This is faster than using ncWaitForState (TxHandle0, NC_ST_WRITE_MULT, 200, 0)
However there is always a ~85uS gap between the CAN frames. (I'm looping back to the second CAN channel of the card.)
Does anyone have an idea how to fix this?
Regards,
mskr
06-30-2015 11:33 AM
A real 100% bus load is not something you can really do. There is priority in messaging and as a result your buffer will be filled with messages that can't go out and it will return errors, which will probably prevent new messages from going out.
That being said if you want to fille the transmission why are you relying on software timing? Just throw 100 new messages on the buffer every millisecond and you'll have 100%.
Unofficial Forum Rules and Guidelines
Get going with G! - LabVIEW Wiki.
17 Part Blog on Automotive CAN bus. - Hooovahh - LabVIEW Overlord
07-01-2015 11:39 AM
Thanks for your answer. However, I think I do not rely on SW timing. I throw in 128/256 messages every time the buffer has been transmitted or tells me that there are free slots. Nevertheless I have the behaviour I described above (gaps between each and every frame). (At a baudrate of 50kBit I can reach a bus load of 98% which drops continually if a increase the baudrate...)
07-01-2015 11:44 AM
Where does it say in your sudo code you are putting in 128 messages? I see one write taking place, then a wait until that message has been sent out. Posting actual code (preferable in the form of a VI) is more helpful.
Unofficial Forum Rules and Guidelines
Get going with G! - LabVIEW Wiki.
17 Part Blog on Automotive CAN bus. - Hooovahh - LabVIEW Overlord
07-01-2015 11:11 PM
Sorry for not posting the whole code but only the loop fragment - but here it is:
/* CAN Transmit multiple.c Demonstrates how to transmit multiple CAN Frames in one Burst via the Network Interface. Time Difference is related to the first frame which always has to have a timestamp of zero. In Timestamp Mode, these frames will be sent out using the specified time differences. In Immediate Mode all frames will be send out back to back in one burst. */ #include <stdio.h> // Include file for printf #include <stdlib.h> // Include file for strtol #include <windows.h> // Include file for Win32 time functions #include <conio.h> // Include file for _getch/_kbhit #include <string.h> #include "Nican.h" // Include file for NI-CAN functions and constants #define NUM_TX_CNT 256 /* NI-CAN handles */ NCTYPE_OBJH TxHandle=0; /* Print a description of an NI-CAN error/warning. */ void PrintStat(NCTYPE_STATUS status, char *source) { char statusString[1024]; if (status != 0) { ncStatusToString(status, sizeof(statusString), statusString); printf("\n%s\nSource = %s\n", statusString, source); // close object handle, then exit. ncCloseObject(TxHandle); exit(1); } } int getch_noblock() { if (_kbhit()) return _getch(); else return -1; } int main () { NCTYPE_CAN_STRUCT Transmit[NUM_TX_CNT]; NCTYPE_UINT32 TXMode = 0; NCTYPE_ATTRID AttrIdList[8]; NCTYPE_UINT32 AttrValueList[8]; NCTYPE_UINT32 Baudrate = 1000000; NCTYPE_STATUS Status; char Interface[7] = "CAN0"; int NumFrames = NUM_TX_CNT; int iDataLoop, iLoop; int ch; int frame_id_curr, frame_id_cnt; unsigned int packet_cnt = 0; /* Configure the CAN Network Interface Object */ AttrIdList[0] = NC_ATTR_BAUD_RATE; AttrValueList[0] = Baudrate; AttrIdList[1] = NC_ATTR_START_ON_OPEN; AttrValueList[1] = NC_FALSE; AttrIdList[2] = NC_ATTR_READ_Q_LEN; AttrValueList[2] = 0; AttrIdList[3] = NC_ATTR_WRITE_Q_LEN; AttrValueList[3] = NumFrames; AttrIdList[4] = NC_ATTR_CAN_COMP_STD; AttrValueList[4] = 0; AttrIdList[5] = NC_ATTR_CAN_MASK_STD; AttrValueList[5] = NC_CAN_MASK_STD_DONTCARE; AttrIdList[6] = NC_ATTR_CAN_COMP_XTD; AttrValueList[6] = 0; AttrIdList[7] = NC_ATTR_CAN_MASK_XTD; AttrValueList[7] = NC_CAN_MASK_XTD_DONTCARE; Status = ncConfig(Interface, 8, AttrIdList, AttrValueList); if (Status < 0) { PrintStat(Status, "ncConfig"); } /* open the CAN Network Interface Object */ Status = ncOpenObject(Interface, &TxHandle); if (Status < 0) { PrintStat(Status, "ncOpenObject"); } for(iLoop = 0; iLoop < NUM_TX_CNT; iLoop++) { Transmit[iLoop].ArbitrationId = iLoop; Transmit[iLoop].DataLength = 8; Transmit[iLoop].FrameType = NC_FRMTYPE_DATA; //Transmit[iLoop].Timestamp.HighPart = 0; /* The Timestamp resolution is ms, so only the low part is needed as multiple of 100ns */ //Transmit[iLoop].Timestamp.LowPart = time_dff[iLoop]*10000; } /* print out the instructions to the I/O window */ printf("\nRunning on CAN0 ...\n\nPress 't' to transmit the frames timestamped (PXI/PCI/PCMCIA only)"); printf("\n\nPress 'n' to transmit the frames back to back\n\nPress 'q' to quit\n\n"); /*Transmit frames each time the user selects to*/ frame_id_curr = 0; do { ch = _getch(); if (ch == 'n') { int ch1; //Start Communication with ncAction Status = ncAction (TxHandle, NC_OP_START, 0); if (Status < 0) { PrintStat(Status, "ncAction"); } frame_id_curr = 0; frame_id_cnt = 0; packet_cnt = 1; do { ch1 = getch_noblock(); for (iLoop = 0; iLoop < NUM_TX_CNT; iLoop++) { Transmit[iLoop].ArbitrationId = frame_id_curr++; memset(Transmit[iLoop].Data, 0, 8); *((unsigned int *)(Transmit[iLoop].Data)) = packet_cnt++; if (frame_id_curr == 0x800) { frame_id_curr = 0; frame_id_cnt++; } } //write the frames to the board Status = ncWriteMult (TxHandle, sizeof(Transmit), Transmit); if (Status < 0) { PrintStat(Status, "ncWrite"); } //wait until the last frame is send out Status = ncWaitForState (TxHandle, NC_ST_WRITE_SUCCESS, 2000, 0); if (Status < 0) { PrintStat(Status, "ncWaitForState1"); } //wait until there is free space //do { // Status = ncWaitForState (TxHandle, NC_ST_WRITE_MULT, 200, 0); //} while (Status < 0); } while (ch1 == -1); //wait until the last frame is send out Status = ncWaitForState (TxHandle, NC_ST_WRITE_SUCCESS, 2000,0); if (Status < 0) { PrintStat(Status, "ncWaitForState"); } //stop communication to set the TXMode for the next write Status = ncAction (TxHandle, NC_OP_STOP, 0); if (Status < 0) { PrintStat(Status, "ncAction"); } } Sleep(100); } while (ch != 'q'); /* Close the Network Interface Object */ Status = ncCloseObject(TxHandle); if (Status < 0) { PrintStat(Status, "ncCloseObject"); } return 0; }