I haven’t finished with my previous G400 CAN issue, and ran in another one… In short: if there’s some traffic on the bus and I want to send a message, sometimes it is lost (about 5 in 1000). It is simply not sent, although sending function is called.
Here’s a source code that illustrates the problem. Comments inside the code.
public class Program {
//It works as follows. LDR1 turns on/off continuous broadcasting (~100 messages per second).
//Clicking LDR0 sends 1000 messages and then stops.
//I have two G400's, connected through CAN: a custom board and a G400HDR one. The code on both is
//basically the same: I just change CAN message Id depending on board, so I could see which messages
//comes from which board.
//The experiment:
//1. I reset both boards and attach debug output readers.
//2. If I click LDR0 on both boards, all messages are sent and all of them are received.
//3. I click LDR1 on both boards; this adds some traffic as both boards are then transmitting something all the time.
//4. I click LDR0 (can be on one board), 1000 messages are sent, but very often, some messages are not actually sent to CAN.
//the sending board outputs "Sent 1000 messages, received xxx messages", and receiving board outputs "Sent xxx messages, received 967".
static readonly InputPort buttonforBroadcasts = new InterruptPort((Cpu.Pin)(4), false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
static InputPort _buttonforSending = new InterruptPort((Cpu.Pin)(24), false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
static OutputPort led = new OutputPort((Cpu.Pin)(3 * 32 + 3), true); // led pd3
// static OutputPort led = new OutputPort((Cpu.Pin)(3 * 32 + 18), true); // led pd18 <--this is for my custom G400 board
static CAN.Message[] sendList;
static CAN.Message[] receiveList;
public static void Main() {
//Create a message list of 1000 messages
sendList = new CAN.Message[1000];
for (int i = 0; i < sendList.Length; i++) {
sendList[i] = new CAN.Message();
sendList[i].ArbID = 100;
sendList[i].DLC = 8;
sendList[i].Data[1] = (byte)(i & 0xFF);
}
receiveList = new CAN.Message[1000];
for (int i = 0; i < receiveList.Length; i++) {
receiveList[i] = new CAN.Message();
}
//configuring CAN
var brp = 6;
var sjw = 1;
var propag = 1;
var phase1 = 7;
var phase2 = 7;
CAN can = new CAN(CAN.Channel.Channel_1, (uint)((brp << 16) + (sjw << 12) + (propag << 8) + (phase1 << 4) + (phase2 << 0)), 1000); //1Mbit
// Subscribe to events
can.DataReceivedEvent += new CANDataReceivedEventHandler(can_DataReceivedEvent);
can.ErrorReceivedEvent += new CANErrorReceivedEventHandler(can_ErrorReceivedEvent);
var isBroadcasting = false;
buttonforBroadcasts.OnInterrupt += (data1, data2, data3) => {
isBroadcasting = !isBroadcasting;
};
new Thread(() => {
var y = 0;
var messageToBroadcast = new CAN.Message() { DLC = 8, ArbID = 10 };
messageToBroadcast.Data[0] = 1;
var messagesToBroadcast = new CAN.Message[] { messageToBroadcast };
while (true) {
if (isBroadcasting) {
//Adding some traffic to the bus
can.PostMessages(messagesToBroadcast, 0, 1);
}
Thread.Sleep(10);
}
}).Start();
var isSending = false;
_buttonforSending.OnInterrupt += (data1, data2, data3) => {
isSending = true;
};
var sentCounter = 0;
new Thread(() => {
while (true) {
if (isSending) {
Debug.Print("Sending");
for (int i = 0; i < 1000; i++) {
//==== This is my manual send implementation — seems messages are not lost
//SendCanMessage(sendList[i].ArbID, sendList[i].Data);
//Thread.Sleep(1);
//=======================================================
//==== This is GHI implementation — messages are lost even with additional Thread.Sleep(1)
can.PostMessages(sendList, i, 1);
while (can.PostedMessagesSent == false) {
Thread.Sleep(1);
}
Thread.Sleep(1); //<-- if I remove this loss rate is higher
//=========================================================
sentCounter++;
}
isSending = false;
}
Thread.Sleep(10);
}
}).Start();
Thread.Sleep(5000);
while (true) {
Debug.Print("Sent " + sentCounter + " messages, received " + receivedCounter);
Thread.Sleep(1000);
}
}
static int receivedCounter = 0;
private static int totalReceived = 0;
static Boolean error = false;
static void can_DataReceivedEvent(CAN sender, CANDataReceivedEventArgs args) {
// Blink LED every 50ms if r
led.Write((totalReceived % 100 >= 50) && (error == false));
var received = sender.GetMessages(receiveList, 0, receiveList.Length);
totalReceived += received;
for (int i = 0; i < received; i++) {
//receivedCounter only counts messages that are sent from other board after pressing LDR0
if (receiveList[i].ArbID > 99) receivedCounter++;
}
if (error == false && totalReceived % 1000 == 0) {
Debug.Print("Still running " + totalReceived);
}
}
static void can_ErrorReceivedEvent(CAN sender, CANErrorReceivedEventArgs args) {
error = true;
switch (args.Error) {
case CAN.Error.Overrun:
Debug.Print("Overrun error. Message lost");
break;
case CAN.Error.RXOver:
Debug.Print("RXOver error. Internal buffer is full. Message lost");
break;
case CAN.Error.BusOff:
Debug.Print("BusOff error. Reset CAN controller.");
sender.Reset();
break;
}
}
private static readonly Register Mailbox7ModeRegister = new Register(0xF80002E0);
private static readonly Register Mailbox7StatusRegister = new Register(0xF80002F0);
private static readonly Register Mailbox7IdRegister = new Register(0xF80002E8);
private static readonly Register Mailbox7DataLowRegister = new Register(0xF80002F4);
private static readonly Register Mailbox7DataHighRegister = new Register(0xF80002F8);
private static readonly Register Mailbox7ControlRegister = new Register(0xF80002FC);
private static readonly Register Mailbox7AcceptanceMaskRegister = new Register(0xF80002E4);
public static void SendCanMessage(UInt32 id, byte[] data) {
//Disabling M7
Mailbox7ModeRegister.Write((0 << 24) | (0 << 16));
//Writing ID
Mailbox7IdRegister.Write((uint)((0 << 29) | (id << 18)));
//Writing DLC?..
//mailbox7ControlRegister.SetBits(7 << 16);
//Writing data
Mailbox7DataLowRegister.Write((uint)(data[0] + data[1] * 256 + data[2] * 256 * 256 + data[3] * 256 * 256 * 256));
Mailbox7DataHighRegister.Write((uint)(data[4] + data[5] * 256 + data[6] * 256 * 256 + data[7] * 256 * 256 * 256));
//Setting filter
// Mailbox7AcceptanceMaskRegister.Write(0x1FFFFFFF);
//Enabling M7
Mailbox7ModeRegister.Write((3 << 24) | (1 << 16));
//Sending M7
Mailbox7ControlRegister.Write((1 << 23) | (8 << 16));
}
}