Juerg
August 23, 2024, 3:14pm
1
I am trying to get CAN-Bus running on FEZ-Pico Can1 using the sample code but get a lot of System.NotSupportedExceptions when accessing the Filter methods and/or Enable method.
The same code works well on FEZ-Stick / Dev.board (using Can2).
Hardware is the same (FEZ + SN65HVD230) and USB-CAN-Adapter on the PC-side.
Any idea is welcome!
Regards, Juergen
FEZ stick uses SC20xxx support CANFD
FEZ pico uses SC13xx does not support CANFD.
Show us your code so we know what wrong there. First check should remove “SetDataBitTiming” which is not supported on SC13xxx
Juerg
August 23, 2024, 7:50pm
3
Haven’t found another way to upload…
// -------------------------------------------------------------------------------------
// Project: TCLR_CAN_Test
// File: Program.cs
//
// Created: 2024-08-22
// Author: JBranscheid
// Updated: 2024-08-22
//
// (c) 2024 Branscheid Industrie Automation GmbH - All rights reserved.
// --------------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Threading;
using GHIElectronics.TinyCLR.Devices.Can;
using GHIElectronics.TinyCLR.Pins;
namespace TCLR_CAN_Test
{
internal class Program
{
private static void Main()
{
Debug.WriteLine("TCLR_CAN_Test started..");
// var can = CanController.FromName(SC20100.CanBus.Can2); // FEZ-Stick
var can = CanController.FromName(SC13048.CanBus.Can1); // FEZ-Pico
var propagationPhase1 = 13;
var phase2 = 2;
var baudratePrescaler = 6;
var synchronizationJumpWidth = 1;
var useMultiBitSampling = false;
can.SetNominalBitTiming(new CanBitTiming(propagationPhase1, phase2, baudratePrescaler,
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
synchronizationJumpWidth, useMultiBitSampling));
var message = new CanMessage()
{
Data = new byte[] { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2E, 0x20, 0x20 },
ArbitrationId = 0x12,
Length = 8,
RemoteTransmissionRequest = false,
ExtendedId = false,
FdCan = false,
BitRateSwitch = false
};
byte cntr = 0;
//The following filter will accept arbitration IDs from 0x12 to 0x20 inclusive.
can.Filter.AddRangeFilter(Filter.IdType.Standard, 0x12, 0x20);
//The following filter will accept arbitration IDs from 0x500 to 0x1000 inclusive.
can.Filter.AddRangeFilter(Filter.IdType.Standard, 0x500, 0x1000);
//The following filter will accept arbitration IDs of 0x11 and 0x13.
can.Filter.AddMaskFilter(Filter.IdType.Standard, 0x11, 0xFD);
//The following filter will accept arbitration IDs of 5678 only.
can.Filter.AddMaskFilter(Filter.IdType.Standard, 0x5678, 0xFFFF);
can.MessageReceived += Can_MessageReceived;
can.ErrorReceived += Can_ErrorReceived;
can.Enable();
while (true)
{
message.Data[7] = cntr++;
can.WriteMessage(message);
Thread.Sleep(100);
}
}
private static void Can_MessageReceived(CanController sender, MessageReceivedEventArgs e)
{
sender.ReadMessage(out var message);
Debug.WriteLine("Arbitration ID: 0x" + message.ArbitrationId.ToString("X8"));
Debug.WriteLine("Is extended ID: " + message.ExtendedId.ToString());
Debug.WriteLine("Is remote transmission request: "
+ message.RemoteTransmissionRequest.ToString());
Debug.WriteLine("Time stamp: " + message.Timestamp.ToString());
var data = "";
for (var i = 0; i < message.Length; i++) data += Convert.ToChar(message.Data[i]);
Debug.WriteLine("Data: " + data);
}
private static void Can_ErrorReceived(CanController sender, ErrorReceivedEventArgs e)
=> Debug.WriteLine("Error " + e.Error.ToString());
}
}
Juerg:
can.Filter.AddRangeF
SC13xxx also doesn’t support AddRange filter, remove it.
Juerg
August 23, 2024, 8:42pm
5
I tried that before by commenting out all ‘Filter’ calls.
Some result, can.Enable() throws an NotSupportedException.
I just ran on my SC13xxx dev board, no problem on v2.3.0.1000
Below is setup for 500Kb.
On Pico there is no CAN hardware but it should not say “NotSupportedException” if you you run my code below.
static void Main()
{
Debug.WriteLine("TCLR_CAN_Test started..");
var can = CanController.FromName(SC13048.CanBus.Can1); // FEZ-Pico
can.SetNominalBitTiming(new GHIElectronics.TinyCLR.Devices.Can.CanBitTiming(5, 4, 8, 1, false)); // 500Kb at 40MHz
var counter = 0;
can.MessageReceived += Can_MessageReceived;
can.ErrorReceived += Can_ErrorReceived;
can.Enable();
while (true)
{
Thread.Sleep(1000);
Debug.WriteLine("CAN Enabled " + counter++);
}
}
private static void Can_MessageReceived(CanController sender, MessageReceivedEventArgs e)
{
sender.ReadMessage(out var message);
Debug.WriteLine("Arbitration ID: 0x" + message.ArbitrationId.ToString("X8"));
Debug.WriteLine("Is extended ID: " + message.ExtendedId.ToString());
Debug.WriteLine("Is remote transmission request: "
+ message.RemoteTransmissionRequest.ToString());
Debug.WriteLine("Time stamp: " + message.Timestamp.ToString());
var data = "";
for (var i = 0; i < message.Length; i++) data += Convert.ToChar(message.Data[i]);
Debug.WriteLine("Data: " + data);
}
private static void Can_ErrorReceived(CanController sender, ErrorReceivedEventArgs e)
=> Debug.WriteLine("Error " + e.Error.ToString());
Juerg
August 26, 2024, 2:20pm
7
I tried your example and it enables the CAN. But when sending first message, it throws an exception:
The thread ‘’ (2) has exited with code 0 (0x0).
TCLR_CAN_Test started…
#### Exception System.InvalidOperationException - CLR_E_INVALID_OPERATION (1) ####
#### Message:
#### GHIElectronics.TinyCLR.Devices.Can.Provider.CanControllerApiWrapper::WriteMessages [IP: 0000] ####
#### GHIElectronics.TinyCLR.Devices.Can.CanController::WriteMessages [IP: 001c] ####
#### GHIElectronics.TinyCLR.Devices.Can.CanController::WriteMessage [IP: 000e] ####
#### TCLR_CAN_Test.Program::Main [IP: 0143] ####
Exception thrown: ‘System.InvalidOperationException’ in GHIElectronics.TinyCLR.Devices.Can.dll
Same code works on SC20100 (FEZ-Stick) using the same Hardware (.SN65HVD230).
Regards JBranscheid
My code:
/
using System;
using System.Diagnostics;
using System.Threading;
using GHIElectronics.TinyCLR.Devices.Can;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Pins;
namespace TCLR_CAN_Test
{
internal class Program
{
private static void Main()
{
Debug.WriteLine("TCLR_CAN_Test started..");
GpioPin ldrButton;
CanController can;
int baudratePrescaler;
if (true)
{
// FEZ-Pico
baudratePrescaler = 8; // 16 = 250k, 8 = 500k for SC13048
ldrButton = GpioController.GetDefault().OpenPin(SC13048.GpioPin.PC13);
can = CanController.FromName(SC13048.CanBus.Can1);
}
else
{
// FEZ-Stick
baudratePrescaler = 6; // 12 = 250k, 6 = 500k for SC20100
ldrButton = GpioController.GetDefault().OpenPin(SC20100.GpioPin.PE3);
can = CanController.FromName(SC20100.CanBus.Can2);
}
ldrButton.SetDriveMode(GpioPinDriveMode.InputPullUp);
var propagationPhase1 = 13;
var phase2 = 2;
var synchronizationJumpWidth = 1;
var useMultiBitSampling = false;
can.SetNominalBitTiming(new CanBitTiming(propagationPhase1, phase2, baudratePrescaler,
synchronizationJumpWidth, useMultiBitSampling));
var message = new CanMessage()
{
Data = new byte[] { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2E, 0x20, 0x20 },
ArbitrationId = 0x16,
Length = 8,
RemoteTransmissionRequest = false,
ExtendedId = false,
FdCan = false,
BitRateSwitch = false,
Timestamp = DateTime.Now
};
byte cntr = 0;
can.Filter.AddMaskFilter(Filter.IdType.Standard, 0x10, 0xFF);
can.MessageReceived += Can_MessageReceived;
can.ErrorReceived += Can_ErrorReceived;
can.Enable();
while (true)
{
message.Data[7] = cntr++;
try
{
if (ldrButton.Read() == GpioPinValue.Low)
can.WriteMessage(message);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
Thread.Sleep(100);
}
}
// ---------------------------------------------------------------------------------------------------
// <summary>
// Can message received.
// </summary>
//
// <param name="sender"> The sender. </param>
// <param name="e"> Message received event information. </param>
// ---------------------------------------------------------------------------------------------------
private static void Can_MessageReceived(CanController sender, MessageReceivedEventArgs e)
{
sender.ReadMessage(out var message);
Debug.WriteLine("Arbitration ID: 0x" + message.ArbitrationId.ToString("X8"));
Debug.WriteLine("Is extended ID: " + message.ExtendedId.ToString());
Debug.WriteLine("Is remote transmission request: "
+ message.RemoteTransmissionRequest.ToString());
Debug.WriteLine("Time stamp: " + message.Timestamp.ToString());
Debug.WriteLine("Length: " + message.Length.ToString());
var data = BitConverter.ToString(message.Data);
Debug.WriteLine("Data: " + data);
}
// ---------------------------------------------------------------------------------------------------
// <summary>
// Can error received.
// </summary>
//
// <param name="sender"> The sender. </param>
// <param name="e"> Error received event information. </param>
// ---------------------------------------------------------------------------------------------------
private static void Can_ErrorReceived(CanController sender, ErrorReceivedEventArgs e)
=> Debug.WriteLine("Error " + e.Error.ToString());
}
}
It doesn’t work because you are setting wrong speed.
As I see FEZ Stick set for 500Kb, mean SN65HVD23 set 500Kb.
But FEZ Pico you are setting 312.5Kb. One side is 500Kb and other side is 312.5Kb of course not work
Change to below to get 500Kb on pico.
var propagationPhase1 = 5; // GHI changed to 5, it was 13
var phase2 = 4; // GHI changed to 4, it was 2
Juerg
August 26, 2024, 7:51pm
9
Thank you, works so far.
But, …where do I get this magic numbers for the SC13048?
Not magic numbers. Our docs explains it. But if you want shorter, here it is.
SC13 CAN clock 40MHz.
Prescal = 8.
40 / 8 = 5MHz
5/ 0.5 = 10.
10 is (T1 + T2 + 1)
I set T1 = 5,
T2 = 4
=> 5 + 4 + 1 = 10.
5/0.25 = 20 = (T1+ T2 + 1)
so you can set T1 = 10, T2 = 9 => T1 + T2 + 1 = 10 + 9 + 1 = 20…
Same for SC20xxx but SC2xx Clock is 48MHz.
…
But T1 or T2 can not be zero or too large (32, 64 or 128 max), I don’t remember exactly, depend on the device. At that time you need to adjust prescaler.