Hi zusammen,
Ich brauche Mal euren Rat.
Ich bin dabei einen kleinen CANFD Logger zu bauen. Dazu nutze ich einen MCP2518fd CAN Controller welcher per SPI am Arduino hängt.
Im Moment nutze ich diese Longan Lib mit entsprechendem Programm. Womit die Kommunikation auch wunderbar klappt. LonganLIB
Nun habe ich aber das Problem das einige Frames von meinem Arduino nicht gefangen werden.
Im Bild kann man gut erkennen das frames mit einem extrem kurzen Abstand ( <1ms ) es nicht in die logdatei schaffen.
Zeilenumbrüche in Logdatei zur Übersicht manuell eingefügt.
Das bsp. aus der Lib nutzt eine einfache wiederholende abfrage des CAN Controllers und holt sich dann die daten daraus. Eine andere Variante per Interrupt gibt es auch, jeodoch hängt sich dann ab einem bestimmten Punkt alles auf. Eventuell weil mehr Interrupts kommen als verarbeite werden können?
Somit fehlen mir in bestimmten Situationen also frames.
Ich bin mir sicher das der CAN Controller die Daten hat nur ich es aber nicht schaffe sie schnell genug abzurufen.
Habt ihr eventuell Vorschläge wie ich das ganze lösen kann? Muss ich irgendwie den Speicher besser nutzen und die Daten nicht im Interrupt verarbeiten? Oder ist hier ein Arduino UNO einfach unterdimensioniert?
Wenn ich richtig recherchiert habe, beträgt der kleinste Abstand zwischen den Frames 15 Bit-Zeiten. Was bei einem 500kbit/s Bus etwa 30 Mikrosekunden entspricht.
Anbei mein Code:
/* MCP2517/8 receive a CAN-FD frame with interrupt
can-fd baud rate:
CAN_125K_500K
CAN_250K_500K
CAN_250K_750K
CAN_250K_1M
CAN_250K_1M5
CAN_250K_2M
CAN_250K_3M
CAN_250K_4M
CAN_500K_1M
CAN_500K_2M
CAN_500K_3M
CAN_500K_4M
CAN_1000K_4M
v2 - einbau SD karte über die selbe SPI schnitstelle
v3 - nutzung Software SPI mit SDfat lib
v4 - import RTC modul & Datumsformatierte Dateinbenamung
v5 - zu schriebende daten aus dem buffer auch ohne Close schrieben "flush()"
+ 5sec timer zum wegschreiben
+ einbau delta t der einzelnen frames zueinander
v6 - ausgabe anpassung für großtest
+ wiederholte flush mit SaveDataTimerStatus jetzt vehindert
V7 - anpassung ausgab, beim flush()
+ RTC steup bei Compilevorgang, schaltbar!
v8 - performancetests bzgl. frames <1ms
v9 - performanstests flush nur nach 90ms ohne frame- so sollte der FIFO des MCP frei sein
v9_1 - cleaned for forum
v10 - umbau auf ISR
+auswertung des RX FIFO
+nutzung von tab formatierung
*/
#include <Arduino.h>
#include <SPI.h>
#include "mcp2518fd_can.h"
#include <ThreeWire.h>
#include <RtcDS1302.h>
ThreeWire myWire(7,5,8); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);
#include <SdFat.h>
#if SPI_DRIVER_SELECT == 2
#define SD_FAT_TYPE 1
#define MAX_DATA_SIZE 64
// pin for CAN-FD Shield
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
//anpassung für SD Karte
int count = 0 ;
bool SaveDataTimerStatus = true;
static unsigned long Zeitscheibe_0 = 0;
unsigned long vorher_ms = 0;
// Chip select may be constant or RAM variable. (Software SPI aus SDfat LIB)
const uint8_t SD_CS_PIN = 10;
const uint8_t SOFT_MISO_PIN = 6;
const uint8_t SOFT_MOSI_PIN = 3;
const uint8_t SOFT_SCK_PIN = 4;
#if SD_FAT_TYPE == 0
SdFat sd;
File file;
#elif SD_FAT_TYPE == 1
SdFat32 sd;
File32 file;
#elif SD_FAT_TYPE == 2
SdExFat sd;
ExFile file;
#elif SD_FAT_TYPE == 3
SdFs sd;
FsFile file;
#else // SD_FAT_TYPE
#error Invalid SD_FAT_TYPE
#endif // SD_FAT_TYPE
// SdFat software SPI template
SoftSpiDriver<SOFT_MISO_PIN, SOFT_MOSI_PIN, SOFT_SCK_PIN> softSpi;
// Speed argument is ignored for software SPI.
#if ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(25), &softSpi)
#else // ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(0), &softSpi)
#endif // ENABLE_DEDICATED_SPI
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
unsigned char flagRecv = 0;
unsigned char len = 0;
unsigned char buf[MAX_DATA_SIZE];
void setup() {
delay(4000); //kurze wartezeit um nach dem hochladen das Terminal verbinden zu können
Serial.begin(115200);
while (!Serial);
//+++++++++++++++++++++++++++ RTC ++++++++++++++++++++++++++++++++++++++++++++++++++++
Rtc.Begin();
//setzen der RTC über compiler (einmal auf true gesetzt hochladen)
if(false){
Serial.print("compiled: ");
Serial.print(__DATE__);
Serial.println(__TIME__);
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
//printDateTime(compiled);
Serial.println();
Serial.println("setze neue Zeit aus Compilevorgang");
Rtc.SetDateTime(compiled);
}
RtcDateTime now = Rtc.GetDateTime();
if (!now.IsValid()){
// Common Causes:
// 1) the battery on the device is low or even missing and the power line was disconnected
Serial.println("RTC lost confidence in the DateTime!");
}else{
Serial.println("RTC init ok! - ");
}
//+++++++++++++++++++++++++++ SD ++++++++++++++++++++++++++++++++++++++++++++++++++++
//timestamp als Dateiname erstellen
String timestamp = (String(now.Hour())+"_"+String(now.Minute())+"_"+String(now.Second())+".txt");
vorher_ms = millis();
char newFilename[20];
timestamp.toCharArray(newFilename, 20);
// SD Karte initialisierung
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt();
}
Serial.println("SD init ok!");
//SD Dateivorbereitung
if (!file.open(newFilename, O_RDWR | O_CREAT)) {
sd.errorHalt(F("open failed!!"));
}
Serial.print("Create logifle: ");
Serial.print(newFilename);
Serial.print(" ... ");
file.println(F("Logged by rudikx6"));
Serial.println("done.");
//+++++++++++++++++++++++++++ CAN ++++++++++++++++++++++++++++++++++++++++++++++++++++
//attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), CAN_ISR, FALLING); // start interrupt
CAN.setMode(CAN_NORMAL_MODE);
//CAN.setMode(CAN_LISTEN_ONLY_MODE);
// init can bus : arbitration bitrate = 500k, data bitrate = 2M
while (0 != CAN.begin(CAN_500K_2M)) {
Serial.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN init ok!");
}
void loop() {
if (CAN_MSGAVAIL == CAN.checkReceive()) {
// unsigned long dauer = millis();
CAN.readMsgBuf(&len, buf); // You should call readMsgBuff before getCanId
unsigned long id = CAN.getCanId();
unsigned long now_ms = millis(); //ermittle zeitabstand der frames
unsigned long dt_Frame = now_ms - vorher_ms;
vorher_ms = now_ms;
Serial.print(CAN.readRxTxStatus()); //Rx FIFO status
/* CAN_RX_FIFO_NO_EVENT = 0,
CAN_RX_FIFO_ALL_EVENTS = 0x0F,
CAN_RX_FIFO_NOT_EMPTY_EVENT = 0x01,
CAN_RX_FIFO_HALF_FULL_EVENT = 0x02,
CAN_RX_FIFO_FULL_EVENT = 0x04,
CAN_RX_FIFO_OVERFLOW_EVENT = 0x08 */
// Serial.print(dt_Frame);
file.print(dt_Frame);
// Serial.print("ms - id: ");
// file.print("ms - id: ");
file.print("\t");
// Serial.print(id, HEX);
file.print(id, HEX);
// Serial.print("x - Data: ");
// file.print("x - Data: ");
file.print("\t");
// file.write(buf, HEX);
for (int i = 0; i < len; i++) {
// Serial.print(buf[i], HEX);
// Serial.print(" ");
file.print(buf[i], HEX);
file.print(" ");
// data [i] = (buf[i], HEX);
// data.append(" ");
}
// Serial.println();
file.println();
Zeitscheibe_0 = millis();
SaveDataTimerStatus = true; //weil ein neuer Frame reinkam, aktieviere wieder den SaveDataTimerStatus
}
if (millis() - Zeitscheibe_0 > 90 & SaveDataTimerStatus) { // Zeitscheibe_0 zur Datensicheurng wenn seit 90ms kein daten mehr gekommen sind
Zeitscheibe_0 = millis();
file.flush();
Serial.println("flush"); //("flush SaveDataTimerStatus");
SaveDataTimerStatus = false; //deaktiviere den SaveDataTimerStatus damit nicht unnötig flush() ausgeführt wird
}
}
#else // SPI_DRIVER_SELECT
#error SPI_DRIVER_SELECT must be two in SdFat/SdFatConfig.h
#endif // SPI_DRIVER_SELECT
// END FILE
Hier auch der Teil der Ausgabe bis es schief geht :
RTC init ok! -
SD init ok!
Create logifle: 23_53_33.txt ... done.
CAN init ok!
flush
00000flush
00flush
00000flush
00flush
000000000flush
00000flush
0000000000000000flush
0000000flush
0000flush
0000000000110flush
0000000flush
0000000flush
00000flush
00000000flush
001110flush
0flush
01115111111111111111111111199999998flush
9998flush
8flush
811151111111511111111111111111199999998flush
811151111111111111111111111111199999998flush
8flush
9111511111111111111111111111111111199999998flush
915111111111111111111111111111111119999999888flush
811111115111111111111111111111111999999988flush
811151511111111111511111111111111111111999999998888flush
88888flush
888888898888988888888888flush
889999999999999988888999998998888899998888899988889999888flush
888888888flush
99999999999999999999899988888888889899988888998889989989999999988898999988889999998flush
888888898888988898888888888899888988988898898888999998898888flush
8899988998flush
und die entsprechende Logdatei die dabei erstellt wurde.
(habe die ersten fehlenden Stellen gekennzeichnet)
23_53_33.txt (91.9 KB)
Vielleicht hat jemand hier ja schon Erfahrung damit gemacht ![]()


