How to modify message data in CAPL if message is generated by Interactive generator block? - can-bus

I am using CANalyzer.
I am transmitting CAN message using Interactive Generator block. I use IG to modify signals in transmitted message by hand.
I need to automaticaly calculate checksum (the last byte in the message) every time the message is sent. Checksum is calculated from all previous data bytes in the message (message is always 8 bytes long). There is no option in IG to do that.
I need:
Set signals by hand using IG.
Automatically calculate value of the last data byte according to values of preceding data bytes.
I tried to write simple code in CAPL but without success.
I put CAPL Program node after the IG node in the Configuration window and wrote on message event in CAPL script:
on message FooMsg
{
message FooMsg msg1; // FooMsg is name of message in database
msg1 = this; // copy message from IG to temporary variable
// this.byte(7) = 0x11; // not posibble, compiler warning
msg1.byte(7) = 0x11; // constant value just for test
output(msg1); // send message
}
The message is transmitting but the Tx period set in IG is not respected (message is transmitted as fast as possible).
I thought I catch the message generated from IG, modify it and send to CAN bus.

Finally, I redesigned the whole stuff as VioletVynil recommended.
I created panels, add system variables and hooked them to controls on panels, wrote some code in CAPL for calculating checksum and periodic transmit of the message and it runs! Without any problems! And yes additional CRC on the payload is used for additional safety (railway application). I didn't designed communication protocol, I just got it.

Related

CAPL: Why am I not receiving the data bytes of a CAN message in CAPL?

I have an ECU sending a CAN message with 2 bytes of data. I want to take those 2 data bytes in CAPL and put them into 2 environment variables. I am developing a canoe simulation and I want to use those 2 environment variables to display their value in a panel.
I am seeing the CAN message with the data bytes on trace being received correctly, but when I try using those data bytes in CAPL, they are 0.
I have the following code:
message CAN1.SWversion SWversion;
on message SWversion
{
putValue(ev_MainSW, SWversion.MainSW);
putValue(ev_SecSW, SWversion.SecSW);
}
SWversion.MainSW is byte(0), SWversion.SecSW is byte(1). I see their values on trace, but in CAPL they are 0.
Any hints as to why?
Here's my trace window with the data bytes
Here's my message & signals definition in the database
Here's one of my variable definitions
In your event handler it seems that you should access the received message, not a global (obviously uninitialized) variable:
on message CAN1.SWversion
{
putValue(ev_MainSW, this.MainSW);
putValue(ev_SecSW, this.SecSW);
}
I figured it out:
message CAN1.SWversion SWversion;
on message SWversion
{
putValue(ev_MainSW, SWversion.MainSW);
putValue(ev_SecSW, SWversion.SecSW);
}
needed to be changed to
message CAN1.SWversion SWversion;
on message SWversion
{
putValue(ev_MainSW, this.byte(0));
putValue(ev_SecSW, this.byte(1);
}
Apparently, you cannot use predefined signals to access the data in a CAN message in CAPL.

Driver error 11 in TransmitCANFrame XL_ERR_QUEUE_IS_FULL

I am using a CANCase VN1640A between 2 ECUs in order to falsify a CAN message. Below the bridge simulation setup:
In my CAPL Code, the received messages from channel 1 will be redirected to channel 3 and vice-versa. (So far I am not falsifying any message)
variables{
message can1. msgCAN1;
message can3. msgCAN3;
}
on message can1.{
msgCAN3=this;
if(this.dir == rx)
output(msgCAN3);
}
on message can3.{
msgCAN1 = this;
if(this.dir == rx)
output(msgCAN1);
}
But when I start CANoe I get this Error message:
This error means that CANoe tries to send more as it could. The transmit buffer is overflowed. I have changed the hardware configuration of Transmit Queue size to the max 32768 messages, also the Receive Latency to very fast but unfortunately the error occur again.
Does anyone have any hints that could help to solve this problem and thanks in advance.
The error message can mean, that CANoe tries to send more as it could. The transmit buffer is overflowed. This can have several causes:
the bus is full of high prior messages and therefore CAN hardware cannot send
You have a program which writes messages very quick to the buffer, so that the card can´t send (while loops for).
Error frames occur when sending and thus the card cannot send.
Vector tool provides a loop test:
Send messages from CH1 to CH3. If this is working fine, it looks like the problem is caused by your CANoe configuration.
The necessary test programs are part of the Vector Driver Setup Files and located in the folder Common. You can download the Driver Setup File from www.vector.com/driver-setup.
CAN Highspeed Looptest: http://kb.vector.com/entry/589/
CAN Low-speed Looptest: http://kb.vector.com/entry/590/
If the loop test works fine, you can see the time, the busload etc. If not, you will get a failed message.
Note:
Reduce the number of channels used in CANoe/CANalyzer under:
Configuration | Options | Measurement | General | Channel usage.
Are there more selected channels in the CANoe configuration than assigned CANcabs in the Vector Hardware Config?
(Start | Control Panel | Hardware and Sound | Vector Hardware)
Please check the channel and application assignment in the Vector Hardware Config.
Kindly check the hardware mapping in CANoe. This error mostly arises when the mapping is not correct or disturbed.
Go to Hardware-> Network Hardware configuration -> Driver -> Select proper channel for the vector hardware
I hope this helps !
So this error does NOT mean that CANoe tries to send more as it could.
It means instead:
We have (many) error frames on the CAN bus. CANoe tries to send messages which does not work (for whatever reason) -> error frames are the result. The CAN controller will retry to send the frame which might again lead to an error frame. Now over time the Send Requests accumulate and lead to further error frames. At some point the buffer for the error frames does overflow which leads to the message you see in the write window.
Solution:
We have to check the Trace Window and check what kind of error frames we get there (and then take suitable measures to prevent them).

Sending cyclic message using CANoe - IL DLL

I have a configuration setup with two CAN nodes and an attached database. I have added a CANOEILNLVECTOR.dll to both the nodes. By adding this Dll file all my messages are sent cyclic as I see in trace window.
Now I set some value for a signal in a message, For Eg:
variables
{
message Battery_Traction Batt_msg;
}
on start
{
Batt_msg.Isolation_Signal = 0x02; //0x02:On
output(Batt_msg);
}
What I see on trace is: The message is cyclic but only for the first instance the value set by me above appears in trace. For all of the rest times the signal value in the message in set to default.
As seen in the image value 0x02 is sent only once.
I am not sure what could be the problem, as seen in image attached value set by me is only sent once.
When using output you are putting the message directly onto the CAN bus, but you are not changing the value inside of your (simulated) node, so the interaction layer is still sending the old value.
You can change the signal value in the interaction layer by just putting a $ in front of the signal name and set the value.
In your case most likely $Isolation_Signal = 0x02
Outputting the message on the CAN bus at the right time, with the right cycle time and so on will be handled by the interaction layer.
You have two ways to influence dynamically the value of your message: IL DLLs and custom message sending.
Custom message sending is the basic way, where
you define the message ex.: message Battery_Traction Batt_msg;
you trigger its sending(output function)
you set up cyclic sending on timer Cycletimemsg1 {output(msg1);}
and so on.
IL DLLs are doing this all for you, without much coding effort from your side, but they rely heavily on the dbc settings and attributes you have linked as database to your CAN Channel.
Unfortunately, they don't play well together, meaning you need advanced CANoe know-how of them to use both in the same environment. You basically bypassed your CANOEILNLVECTOR.dlls working by sending explicit message.
So your code if you are accessing your signal through IL, should look like this:
variables
{
/*no need to define custom message object, they are already "known" to IL by dbc*/
}
on start
{
$Batt_msg::Isolation_Signal = 0x02; //0x02:On
/*NO need for output either (IF YOUR MESSAGE IS defined Cyclic in dbc), */
}
If your signal is not identified at $Batt_msg::Isolation_Signal, just dragndrop the signal from the CAPL browsers Symbols panel, and add the $ sign before it.
Through dollar($) sign, you access the dbsignal class objects signal value attribute.

QNX MsgReceive Pulse

I have a problem because I don't know how _pulse receiving works. If I have my data struct
typedef struct _my_data {
msg_header_t hdr;
int data;
} my_data_t;
and I am receiving only my msg I cant tell if it is a pulse
my_data_t msg;
...
rcvid = MsgReceive(g_Attach->chid, &msg, sizeof(msg), NULL);
when rcvid = 0 BUT how a program knows that it need to send _pulse in a form of msg (struct that I defined) or else how does it work. In addition is _IO_CONNECT a pulse? If yes why doesn't it have rcvid==0? - according to http://www.qnx.com/developers/docs/6.3.2/neutrino/lib_ref/n/name_attach.html
1 - _IO_CONNECT is not used for pulse. Its used for connect system call to resource managers. Example system calls are open(), close(), etc.
2 - You need to know whether the server or client is waiting on pulse message or not. For pulse message the blocking function in the resource manager will be MsgReceivePulse() and the client will use MsgSendPulse().
MsgSend() is used for normal message and MsgSendPulse() is for sending pulse message.
Similarly MsgReceive() is used for receiving normal message and MsgReceivePulse() is used for receiving pulse messages. Please refer to the QNX documents for more detailed description.
Both variants have different parameters like the functions for pulse messages do not have any parameter for return data because pulses are non blocking small messages which do not block for any reply but functions for normal messages have parameters for receive data.
You need to create channel and connection, for example
chid=ChannelCreate(0);
int pid=getpid();
coid=ConnectAttach(0, pid, chid, 0, 0);
and attach channel to connection.............
Then if you have two threads...............from one thread you can to call MsgSend function, for example MsgSend(coid, &(message), sizeof(message), &rmsg, sizeof(rmsg)); and in the other thread rcvid=MsgReceive(chid, (void*)&message, sizeof(message),NULL);

How to write data to socket in BlackBerry?

I am sending data to the server twice. First, I send "Hello world" and then I send "Server".
But the server received the data at 1 read. But the server have to read the data in a two-read operation.
Also, I write the data. Then read data from server and then I write the data.
In this case, the server can read the first data. But server can not read the second data.
The server uses read, write, read.
So how to overcome this issue? How do I write data to socket in BlackBerry?
What you describe is how TCP is supposed to work by default. What you are seeing is the Nagle algorithm (RFC 896) at work, reducing the number of outbound packets being sent so they are processed as efficiently as possible. You may be sending 2 packets in your code, but they are being transmitted together as 1 packet. Since TCP is a byte stream, the receiver should not be making any assumptions about how many packets it gets. You have to delimit your packet data in a higher-level protocol, and the receiver has to process data according to that protocol. It has to handle cases where multiple packets arrive in a single read, a single pakcet arriving in multiple reads, and everything in between, only processing packet data when they have been received in full, caching whatever is left over for subsequent reads to process when needed.
Hard to say without a little more detail, but it sounds like you're using 1-directional communication in the first case - i.e. the client writes, then writes again. There are any number of reasons that the server would receive the 2 writes as 1 read. Buffering on the client, somewhere in the wireless stack (or in the BES), buffering on the server side. All of those are legal with TCP/IP.
Without knowing anything more about your solution, have you thought about defining a small protocol - i.e. the client writes a known byte or bytes (like a 0 byte?) before sending the second write? Then the server can read, then recognize the delimiting byte, and say 'aha, this is now a different write from the client'?
As previously said this is an expected TCP behavior to save bandwidth. Note that to deliver your package TCP adds lot of data (e.g. destination port,sequence number, checksums...).
Instead of flushing the data I´ll recommend you to put more work in your protocol. For example you can define a header that contains the number of bytes to read and then the payload (the actual data).
The following code is a protocol encoded in an string with the structure [length];[data]
StringBuffer headerStr = new StringBuffer();
StringBuffer data = new StringBuffer();
//read header
char headerByte = dataInputStream.readChar();
while (headerByte != ';') {
headerStr.append(headerByte);
headerByte = dataInputStream.readChar();
}
//header has the number of character to read
int header= Integer.parseInt(headerStr.toString());
int bytesReaded = 1;
char dataByte = dataInputStream.readChar();
//we should read the number of characters indicated in the header
while (bytesReaded < header) {
data.append(dataByte);
dataByte = dataInputStream.readChar();
bytesReaded++;
}
For the first query, I guess you are using TCP. If you use UDP, then the server will read the packets in the order you want.
Can you be more clear/elaborative on the second query ?
I would try explicitly telling Connector.open to open up the stream as read_write. Then I would ensure that I flush my connections after each time I talked to the server.
SocketConnection connection = (SocketConnection) Connector.open(url, Connector.READ_WRITE);
OutputStream out = connection.openOutputStream();
// ... write to server
out.flush()
I got a solution to overcome to extract both the string
On sender device
Create a header which contains details of that data eg the data
length, datatype etc.
Add this header to the actual data and send it
On recipient device
read the header
retrieve the actual data length from the header
read the next data upto the data length as specified by the header

Resources