CanComms.RxOpenStandard still can't accept variable bus #

Support forum for users of the M1 Build

CanComms.RxOpenStandard still can't accept variable bus #

Postby aNinjaneer on Tue Aug 15, 2017 2:29 pm

This hasn't worked since I started developing over a year ago. I'm not sure if it's a known thing, or not. If you try to get a CAN Bus number via:

Code: Select all
mcb = MyCanBus.AsInteger()


and then try to use that value to open a call to:

Code: Select all
CanComms.RxOpenStandard(mcb, 0xXX, 0x0, true)


the messages don't get received. If I hard-code the bus number to a literal UnsignedInteger value, such as:

Code: Select all
CanComms.RxOpenStandard(1, 0xXX, 0x0, true)


then it works. Is this intended? If so, how are you supposed to allow the user to select from the three CAN busses for different functions without having to hard-code it?
aNinjaneer
 
Posts: 27
Joined: Tue Apr 05, 2016 4:57 am

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby David Ferguson on Wed Aug 16, 2017 3:35 am

I'm pretty sure you use an enumerated type for the parameter. For example the ECU uses "CAN Bus Enumeration 2"

Interestingly, in ECU.Transmit.Transmit 100hz, you find code like:

local bus = CAN Bus.As Integer() -1;

...

OK = CanComms.TxStandard(h, bus, 0x640).

So, the parameter has the bus number as a 1-based, but the CanComms uses a zero-based index.
David Ferguson
Veracity Racing Data
David Ferguson
Pro User
 
Posts: 1362
Joined: Fri Nov 07, 2008 2:45 am
Location: Paso Robles, California

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby MalcolmG on Thu Aug 17, 2017 7:12 am

David Ferguson wrote:Interestingly, in ECU.Transmit.Transmit 100hz, you find code like:

local bus = CAN Bus.As Integer() -1;

...

OK = CanComms.TxStandard(h, bus, 0x640).

So, the parameter has the bus number as a 1-based, but the CanComms uses a zero-based index.

I guess this just comes down to Motec's convention of using enumerator 0 as the default/not configured setting, so the enumerator index just counts up from there, while the actual bus numbers start from 0.

I actually think this is probably the issue here, isn't it? It seems likely that MyCanBus.AsInteger() is returning a 1-3 value, and this needs to be changed into a 0-2 value for the RxOpenStandard function, otherwise you may be inadvertently looking at the wrong bus. This is a bit of an assumption since I don't know what enumerated data type you're using for MyCanBus, but I'm pretty sure this exact issue tripped me up the first time I set up a CAN receive.
MalcolmG
Pro User
 
Posts: 76
Joined: Fri Dec 18, 2015 1:34 pm
Location: Auckland, NZ

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby MalcolmG on Tue Apr 24, 2018 10:37 am

I wanted to bump this and add some info, as I've had the problem mentioned in the original post and have a better understanding of what it is doing (but not why)

Basically, this works:
Code: Select all
CanComms.RxOpenStandard(CAN Bus.AsInteger() -1 , 0xXXX, 0x000, true);


But this doesn't:
Code: Select all
local canBus = CAN Bus.AsInteger() -1;
CanComms.RxOpenStandard(canBus, 0xXXX, 0x000, true);


The same appears to be true for other arguments in the RxOpenStandard function, for instance if I have a parameter of type Unsigned Integer, named "Bus Address", this works:
Code: Select all
CanComms.RxOpenStandard(CAN Bus.AsInteger() -1 , Bus Address, 0x000, true);


but this doesn't:
Code: Select all
local canBusAddress = Bus Address;
CanComms.RxOpenStandard(CAN Bus.AsInteger() -1 , canBusAddress, 0x000, true);


Surely this is a bug.
MalcolmG
Pro User
 
Posts: 76
Joined: Fri Dec 18, 2015 1:34 pm
Location: Auckland, NZ

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby David Ferguson on Tue Apr 24, 2018 11:53 am

This feels like a type casting issue. What happens if you declare your locals with an explicit type such as

Code: Select all
local <Integer> canBus = CAN Bus.AsInteger() - 1;

and

local <Unsigned Integer> canBusAddress = Bus Address;
David Ferguson
Veracity Racing Data
David Ferguson
Pro User
 
Posts: 1362
Joined: Fri Nov 07, 2008 2:45 am
Location: Paso Robles, California

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby MalcolmG on Tue Apr 24, 2018 12:15 pm

I tried that and it made no difference.
MalcolmG
Pro User
 
Posts: 76
Joined: Fri Dec 18, 2015 1:34 pm
Location: Auckland, NZ

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby rntechnologies on Wed Aug 15, 2018 11:01 pm

Just to add to this, i'm not sure if you guys have noticed, but this issue only occurs in the RX messaging, and not TX.
I'm definitely thinking there is something up, but only in the RxOpenStandard function.
Regards,
Ryan
User avatar
rntechnologies
Pro User
 
Posts: 90
Joined: Tue Aug 07, 2018 9:45 am
Location: Australia

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby DarrenR on Thu Aug 16, 2018 12:12 pm

Hi Guys,

Firstly, I apologize for this taking a year to get a real answer...
This is one little quirk with the way Build compiles the code that I don't believe we have documented well... So I'll document here.

The CanComms.RxOpenStandard() function is used by Build in two ways. The line of code is extracted from your scheduled method and used at ECU startup to configure the CAN driver and receive buffer. So where you have written -
Code: Select all
local canBus = CAN Bus.AsInteger() -1;
CanComms.RxOpenStandard(canBus, 0xXXX, 0x000, true);

Only the CanComms line is extracted and used at startup, the canBus local variable does not exist and so 'canBus' in the function returns 0 when this line is processed at startup. The same applies for the other variables used in the function.
This means only parameters or hard coded values can be used within the function. I did some testing a long time ago and I think flash backed channels may also work, but the ECU still requires a reset to update the details of messages sent to the buffer by the system, so it's not possible to set the CAN ID dynamically as the ECU is running. If we did allow some sort of reset of the Rx details, it can get quite messy in terms of change over time and what messages make it through. There is a better way to handle this.

The code that is actually used periodically is only a link to retrieve the handle for the receive buffer in question. The data passed there periodically is never used.

It works this way so that immediately after startup the system can start receiving CAN messages and pushes them off to the receive buffer (with matching bus, ID and mask). You don't have to read the data as the RxMessage() function can be called conditionally, the data will wait there. Up to 32 CAN messages can be buffered before the oldest message is over written and lost if you don't call RxMessage() soon enough.

The ideal way to code the bus number to the function is like this -
Code: Select all
CanComms.RxOpenStandard(CAN Bus eq CAN Bus.Not in Use ? 0 : CAN Bus.AsInteger() -1, 0xXXX, 0x000, true);

The reason for the ternary operator usage is because if we just use CAN Bus.As Interger() - 1, if the CAN Bus parameter is set to Not in Use (0) then -1 is passed to RxOpenStandard() which gives an error condition to the system and a debug message is written. We are locked to using Not in Use as 0 so that the object hiding in Tune functions correctly. It ends up a bit messy, but no strain on the CPU since all of this is only used at startup.

This assumes using our standard enumeration with Not in Use, CAN Bus 1, 2 and 3. If you don't want to take advantage of the object hiding in Tune, an enumeration of CAN Bus 1, 2 and 3 with integer values of 0, 1 and 2 respectively can be used also and the parameter with .AsInteger() can be used without the - 1 or ternary operator.

The functions that have this dual usage are -
- CanComms.RxOpenStandard()
- CanComms.RxOpenExtended()
- CanComms.RxOpenStandardBuffered()
- CanComms.RxOpenExtendedBuffered()
- CanComms.TxOpen()
- J1939.Open()
- J1939.DTC()
- J1939.RxParameterGroup()
- J1939.TxParameterGroup()

The CanComms.TxStandard() function does not suffer from the same issue as the variables passed to the function are used periodically.
Darren Reynolds
MoTeC Research Centre - Melbourne, Australia.
DarrenR
MoTeC
 
Posts: 176
Joined: Thu May 01, 2008 2:15 pm
Location: Melbourne, Australia

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby DarrenR on Thu Aug 16, 2018 1:26 pm

I mentioned there is a better way to receive CAN messages with a dynamic ID, and I also mentioned functions called CanComms.RxOpenStandard/ExtendedBuffered() which you may not have seen since they only became available in SDK 01.04.00.0061 (currently the latest SDK version).

The most basic usage for CanComms.RxOpenStandardBuffered() is like this -
Code: Select all
local h = CanComms.RxOpenStandardBuffered(0, 0x100, 0x0, true);
if (CanComms.RxFindMessage(h, 0, 0, 0, 0))        //finds the newest message with id 0x100 (set in RxOpen).
{
                Channel = CanComm.GetUnsignedInteger(h, 16, 16);
}


This will work in the same way as the original RxOpenStandard() and RxMessage() functions, except it will get the newest available message matching the Rx details rather than the oldest message. This means if more than one message arrived since the last call of RxOpenStandardBuffered(), only the newest can be read and the older ones are thrown out. This is effectively the same as doing the double call of RxMessage(), but the newer method uses more memory and is slightly slower so the older method is preferred for standard cyclic messages.

The arguments passed to the RxFindMessage() function are -
- handle
- Find CAN ID. Ignored if 0.
- Find Bit Offset (data section).
- Find Bit Length (data section). Ignored if 0.
- Find value (data section).

To use these functions for dynamically updated CAN IDs works because of the extra information passed to the RxFindMessage() function. This is designed to receive messages with compound Ids in the data section (multiplexed messages) using the Find offset, length and value, but works for the ID also.
Code: Select all
local h = CanComms.RxOpenStandardBuffered(0, 0x100, 0xF, true);

local canID = 0x105;

if (CanComms.RxFindMessage(h, canID, 0, 0, 0))        //finds the newest message with id 0x105 (set in by the local).
{
                Channel = CanComm.GetUnsignedInteger(h, 16, 16);
}


In this case the system will fill the receive buffer with any message from 0x100 to 0x10F (due to the mask of 0xF). Again the receive buffer is 32 messages long. The RxFindMessge() function searches through the buffer looking for a match to the details passed to it, in this case a CAN ID of 0x105. If it finds a match it will return True and the GetUnsignedInteger() will return data based on the message found.

Another message can also be searched for by repeating the 'if' statement section with a different CAN ID used. The important part is that when RxOpenStandardBuffered() is called, all messages are transferred from the CAN receive buffer to a second searchable buffer and all necessary searching is done at this time. The buffer is cleared after this.

The mask passed to the system can be widened, even to 0x7FF which will pass all standard IDs received to the receive buffer. However this will use more CPU time and the user needs to make sure that the buffer doesn't fill up. For example, if RxOpenStandardBuffered() is called on a 100Hz cycle, only up to 32 message can be received in each 10ms block (up to 3200 messages per second). If more are received the oldest messages will be overwritten and lost.
Darren Reynolds
MoTeC Research Centre - Melbourne, Australia.
DarrenR
MoTeC
 
Posts: 176
Joined: Thu May 01, 2008 2:15 pm
Location: Melbourne, Australia

Re: CanComms.RxOpenStandard still can't accept variable bus

Postby rntechnologies on Fri Aug 17, 2018 8:34 am

Thanks for clarifying all of that Darren, appreciate it!
Regards,
Ryan
User avatar
rntechnologies
Pro User
 
Posts: 90
Joined: Tue Aug 07, 2018 9:45 am
Location: Australia

Next

Return to M1 Build

Who is online

Users browsing this forum: No registered users and 4 guests