pierremolinaro / acan2515

MCP2515 CAN Controller Driver for Arduino
MIT License
77 stars 30 forks source link

Filter RTR frames #38

Closed Oulalaa closed 1 year ago

Oulalaa commented 1 year ago

Hi, Pierre

I got a question on RTR frames. I want to tell apart whether a received message is a RTR frame by the value of RTR bit. But when I sent a RTR frame with RTR bit == 1, and tried to use a filter to receive it, in the end the RTR bit of this received message becomes 0.

Then I notice that in the ACAN2515 document, section 9.2 on page 20, it says :

Filter remote and data frames. The MCP2515 filters do not handle the RTR bit: for example, you cannot specify you want to accept data frames and discard remote frames. This should be done by your code.

Does that mean a filter will set the RTR bit to 0 automatically, even I set it to 1 before sending? If that is true, to tell apart a RTR frame, do I have to manually dispatch the received messages as decribed in section 8 on page 18?

Oulalaa commented 1 year ago

Hi, looks like I have located the problem. When I set the ext bit to false, the RTR frame can be received. So It seems like the RTR bit and the EXT bit can't be true in the same message. Which means that an extended RTR frame can not be received. I don't know why but I hope it can be fixed if possible.

My question is, is there a way to receive an extended RTR frame? Here is my test code based on the loopback example.


//  ACAN2515 RTR Demo in loopback mode
//——————————————————————————————————————————————————————————————————————————————

#include <ACAN2515.h>

//——————————————————————————————————————————————————————————————————————————————
//  MCP2515 connections:
//    - standard SPI pins for SCK, MOSI and MISO
//    - a digital output for CS
//    - interrupt input pin for INT
//——————————————————————————————————————————————————————————————————————————————
// If you use CAN-BUS shield (http://wiki.seeedstudio.com/CAN-BUS_Shield_V2.0/) with Arduino Uno,
// use B connections for MISO, MOSI, SCK, #9 or #10 for CS (as you want),
// #2 or #3 for INT (as you want).
//——————————————————————————————————————————————————————————————————————————————
// Error codes and possible causes:
//    In case you see "Configuration error 0x1", the Arduino doesn't communicate
//       with the 2515. You will get this error if there is no CAN shield or if
//       the CS pin is incorrect. 
//    In case you see succes up to "Sent: 17" and from then on "Send failure":
//       There is a problem with the interrupt. Check if correct pin is configured
//——————————————————————————————————————————————————————————————————————————————

static const byte MCP2515_CS  = 10 ; // CS input of MCP2515 (adapt to your design) 
static const byte MCP2515_INT =  3 ; // INT output of MCP2515 (adapt to your design)

//——————————————————————————————————————————————————————————————————————————————
//  MCP2515 Driver object
//——————————————————————————————————————————————————————————————————————————————

ACAN2515 can (MCP2515_CS, SPI, MCP2515_INT) ;

//——————————————————————————————————————————————————————————————————————————————
//  MCP2515 Quartz: adapt to your design
//——————————————————————————————————————————————————————————————————————————————

static const uint32_t QUARTZ_FREQUENCY = 16UL * 1000UL * 1000UL ; // 16 MHz

//——————————————————————————————————————————————————————————————————————————————
//   SETUP
//——————————————————————————————————————————————————————————————————————————————

void setup () {
//--- Switch on builtin led
  pinMode (LED_BUILTIN, OUTPUT) ;
  digitalWrite (LED_BUILTIN, HIGH) ;
//--- Start serial
  Serial.begin (38400) ;
//--- Wait for serial (blink led at 10 Hz during waiting)
  while (!Serial) {
    delay (50) ;
    digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
  }
//--- Begin SPI
  SPI.begin () ;
//--- Configure ACAN2515
  Serial.println ("Configure ACAN2515") ;
  ACAN2515Settings settings (QUARTZ_FREQUENCY, 125UL * 1000UL) ; // CAN bit rate 125 kb/s
  settings.mRequestedMode = ACAN2515Settings::LoopBackMode ; // Select loopback mode
  const uint16_t errorCode = can.begin (settings, [] { can.isr () ; }) ;
  if (errorCode == 0) {
    Serial.print ("Bit Rate prescaler: ") ;
    Serial.println (settings.mBitRatePrescaler) ;
    Serial.print ("Propagation Segment: ") ;
    Serial.println (settings.mPropagationSegment) ;
    Serial.print ("Phase segment 1: ") ;
    Serial.println (settings.mPhaseSegment1) ;
    Serial.print ("Phase segment 2: ") ;
    Serial.println (settings.mPhaseSegment2) ;
    Serial.print ("SJW: ") ;
    Serial.println (settings.mSJW) ;
    Serial.print ("Triple Sampling: ") ;
    Serial.println (settings.mTripleSampling ? "yes" : "no") ;
    Serial.print ("Actual bit rate: ") ;
    Serial.print (settings.actualBitRate ()) ;
    Serial.println (" bit/s") ;
    Serial.print ("Exact bit rate ? ") ;
    Serial.println (settings.exactBitRate () ? "yes" : "no") ;
    Serial.print ("Sample point: ") ;
    Serial.print (settings.samplePointFromBitStart ()) ;
    Serial.println ("%") ;
  }else{
    Serial.print ("Configuration error 0x") ;
    Serial.println (errorCode, HEX) ;
  }
}

//----------------------------------------------------------------------------------------------------------------------

static uint32_t gBlinkLedDate = 0 ;
static uint32_t gReceivedFrameCount = 0 ;
static uint32_t gSentFrameCount = 0 ;

//——————————————————————————————————————————————————————————————————————————————

void loop () {
  CANMessage frame ;
    CANMessage inmsg ;
  frame.rtr = true;
  frame.ext = true;//commented to print the received frame RTR
  frame.id = 0x112;
  if (gBlinkLedDate < millis ()) {
    gBlinkLedDate += 2000 ;
    digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
    const bool ok = can.tryToSend (frame) ;
    if (ok) {
      gSentFrameCount += 1 ;
      Serial.print ("Sent: ") ;
      Serial.println (gSentFrameCount) ;
      Serial.print ("Sent RTR bit: ") ;
    Serial.println (frame.rtr) ;
    }else{
      Serial.println ("Send failure") ;
    }
  }
  if (can.available ()) {
    can.receive (inmsg) ;
    gReceivedFrameCount ++ ;
    Serial.print ("Received ID: ") ;
    Serial.println (inmsg.id) ;
        Serial.print ("Received RTR bit: ") ;
    Serial.println (inmsg.rtr) ;
  }
}

//——————————————————————————————————————————————————————————————————————————————```
pierremolinaro commented 1 year ago

Hello,

An extended remote frame is valid and should be received. Extended / Standard and data / remote are orthogonal, all 4 combinations are valid.

So if your code does not work with an extended remote frame, it is a library bug that should be fixed.

Give me some time to examine the problem.

Pierre

Le 29 nov. 2022 à 07:43, Achilles @.***> a écrit :

Hi, looks like I have located the problem. When I set the ext bit to false, the RTR frame can be received. So It seems like the RTR bit and the EXT bit can't be true in the same message. Which means that an extended RTR frame can not be received. I don't know why but I hope it can be fixed if possible.

My question is, is there a way to receive an extended RTR frame? Here is my test code based on the loopback example.

// ACAN2515 RTR Demo in loopback mode //——————————————————————————————————————————————————————————————————————————————

include

//—————————————————————————————————————————————————————————————————————————————— // MCP2515 connections: // - standard SPI pins for SCK, MOSI and MISO // - a digital output for CS // - interrupt input pin for INT //—————————————————————————————————————————————————————————————————————————————— // If you use CAN-BUS shield (http://wiki.seeedstudio.com/CAN-BUS_Shield_V2.0/) with Arduino Uno, // use B connections for MISO, MOSI, SCK, #9 or #10 for CS (as you want), // #2 or #3 for INT (as you want). //—————————————————————————————————————————————————————————————————————————————— // Error codes and possible causes: // In case you see "Configuration error 0x1", the Arduino doesn't communicate // with the 2515. You will get this error if there is no CAN shield or if // the CS pin is incorrect. // In case you see succes up to "Sent: 17" and from then on "Send failure": // There is a problem with the interrupt. Check if correct pin is configured //——————————————————————————————————————————————————————————————————————————————

static const byte MCP2515_CS = 10 ; // CS input of MCP2515 (adapt to your design) static const byte MCP2515_INT = 3 ; // INT output of MCP2515 (adapt to your design)

//—————————————————————————————————————————————————————————————————————————————— // MCP2515 Driver object //——————————————————————————————————————————————————————————————————————————————

ACAN2515 can (MCP2515_CS, SPI, MCP2515_INT) ;

//—————————————————————————————————————————————————————————————————————————————— // MCP2515 Quartz: adapt to your design //——————————————————————————————————————————————————————————————————————————————

static const uint32_t QUARTZ_FREQUENCY = 16UL 1000UL 1000UL ; // 16 MHz

//—————————————————————————————————————————————————————————————————————————————— // SETUP //——————————————————————————————————————————————————————————————————————————————

void setup () { //--- Switch on builtin led pinMode (LED_BUILTIN, OUTPUT) ; digitalWrite (LED_BUILTIN, HIGH) ; //--- Start serial Serial.begin (38400) ; //--- Wait for serial (blink led at 10 Hz during waiting) while (!Serial) { delay (50) ; digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ; } //--- Begin SPI SPI.begin () ; //--- Configure ACAN2515 Serial.println ("Configure ACAN2515") ; ACAN2515Settings settings (QUARTZ_FREQUENCY, 125UL * 1000UL) ; // CAN bit rate 125 kb/s settings.mRequestedMode = ACAN2515Settings::LoopBackMode ; // Select loopback mode const uint16_t errorCode = can.begin (settings, [] { can.isr () ; }) ; if (errorCode == 0) { Serial.print ("Bit Rate prescaler: ") ; Serial.println (settings.mBitRatePrescaler) ; Serial.print ("Propagation Segment: ") ; Serial.println (settings.mPropagationSegment) ; Serial.print ("Phase segment 1: ") ; Serial.println (settings.mPhaseSegment1) ; Serial.print ("Phase segment 2: ") ; Serial.println (settings.mPhaseSegment2) ; Serial.print ("SJW: ") ; Serial.println (settings.mSJW) ; Serial.print ("Triple Sampling: ") ; Serial.println (settings.mTripleSampling ? "yes" : "no") ; Serial.print ("Actual bit rate: ") ; Serial.print (settings.actualBitRate ()) ; Serial.println (" bit/s") ; Serial.print ("Exact bit rate ? ") ; Serial.println (settings.exactBitRate () ? "yes" : "no") ; Serial.print ("Sample point: ") ; Serial.print (settings.samplePointFromBitStart ()) ; Serial.println ("%") ; }else{ Serial.print ("Configuration error 0x") ; Serial.println (errorCode, HEX) ; } }

//----------------------------------------------------------------------------------------------------------------------

static uint32_t gBlinkLedDate = 0 ; static uint32_t gReceivedFrameCount = 0 ; static uint32_t gSentFrameCount = 0 ;

//——————————————————————————————————————————————————————————————————————————————

void loop () { CANMessage frame ; CANMessage inmsg ; frame.rtr = true; frame.ext = true;//commented to print the received frame RTR frame.id = 0x112; if (gBlinkLedDate < millis ()) { gBlinkLedDate += 2000 ; digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ; const bool ok = can.tryToSend (frame) ; if (ok) { gSentFrameCount += 1 ; Serial.print ("Sent: ") ; Serial.println (gSentFrameCount) ; Serial.print ("Sent RTR bit: ") ; Serial.println (frame.rtr) ; }else{ Serial.println ("Send failure") ; } } if (can.available ()) { can.receive (inmsg) ; gReceivedFrameCount ++ ; Serial.print ("Received ID: ") ; Serial.println (inmsg.id) ; Serial.print ("Received RTR bit: ") ; Serial.println (inmsg.rtr) ; } }

//——————————————————————————————————————————————————————————————————————————————``` — Reply to this email directly, view it on GitHub https://github.com/pierremolinaro/acan2515/issues/38#issuecomment-1330157245, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEWKZVG5DQEZLKP7SB73VBDWKWQ23ANCNFSM6AAAAAASNQTUHE. You are receiving this because you are subscribed to this thread.

pierremolinaro commented 1 year ago

Hi, the bug is fixed, it is a ACAN2515 library error.

On frame receive, I was always testing the SRR bit (see MCP2515 datasheet DS20001801H, register 4.5, page 30), but this bit is only valid for standard frame. For extended frame, the RTR bit should be tested instead (register 4.8, page 32).

I will publish a new release in a few hours.

Thanks for reporting this bug!

Best Regards,

Pierre

Le 29 nov. 2022 à 07:43, Achilles @.***> a écrit :

Hi, looks like I have located the problem. When I set the ext bit to false, the RTR frame can be received. So It seems like the RTR bit and the EXT bit can't be true in the same message. Which means that an extended RTR frame can not be received. I don't know why but I hope it can be fixed if possible.

My question is, is there a way to receive an extended RTR frame? Here is my test code based on the loopback example.

// ACAN2515 RTR Demo in loopback mode //——————————————————————————————————————————————————————————————————————————————

include

//—————————————————————————————————————————————————————————————————————————————— // MCP2515 connections: // - standard SPI pins for SCK, MOSI and MISO // - a digital output for CS // - interrupt input pin for INT //—————————————————————————————————————————————————————————————————————————————— // If you use CAN-BUS shield (http://wiki.seeedstudio.com/CAN-BUS_Shield_V2.0/) with Arduino Uno, // use B connections for MISO, MOSI, SCK, #9 or #10 for CS (as you want), // #2 or #3 for INT (as you want). //—————————————————————————————————————————————————————————————————————————————— // Error codes and possible causes: // In case you see "Configuration error 0x1", the Arduino doesn't communicate // with the 2515. You will get this error if there is no CAN shield or if // the CS pin is incorrect. // In case you see succes up to "Sent: 17" and from then on "Send failure": // There is a problem with the interrupt. Check if correct pin is configured //——————————————————————————————————————————————————————————————————————————————

static const byte MCP2515_CS = 10 ; // CS input of MCP2515 (adapt to your design) static const byte MCP2515_INT = 3 ; // INT output of MCP2515 (adapt to your design)

//—————————————————————————————————————————————————————————————————————————————— // MCP2515 Driver object //——————————————————————————————————————————————————————————————————————————————

ACAN2515 can (MCP2515_CS, SPI, MCP2515_INT) ;

//—————————————————————————————————————————————————————————————————————————————— // MCP2515 Quartz: adapt to your design //——————————————————————————————————————————————————————————————————————————————

static const uint32_t QUARTZ_FREQUENCY = 16UL 1000UL 1000UL ; // 16 MHz

//—————————————————————————————————————————————————————————————————————————————— // SETUP //——————————————————————————————————————————————————————————————————————————————

void setup () { //--- Switch on builtin led pinMode (LED_BUILTIN, OUTPUT) ; digitalWrite (LED_BUILTIN, HIGH) ; //--- Start serial Serial.begin (38400) ; //--- Wait for serial (blink led at 10 Hz during waiting) while (!Serial) { delay (50) ; digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ; } //--- Begin SPI SPI.begin () ; //--- Configure ACAN2515 Serial.println ("Configure ACAN2515") ; ACAN2515Settings settings (QUARTZ_FREQUENCY, 125UL * 1000UL) ; // CAN bit rate 125 kb/s settings.mRequestedMode = ACAN2515Settings::LoopBackMode ; // Select loopback mode const uint16_t errorCode = can.begin (settings, [] { can.isr () ; }) ; if (errorCode == 0) { Serial.print ("Bit Rate prescaler: ") ; Serial.println (settings.mBitRatePrescaler) ; Serial.print ("Propagation Segment: ") ; Serial.println (settings.mPropagationSegment) ; Serial.print ("Phase segment 1: ") ; Serial.println (settings.mPhaseSegment1) ; Serial.print ("Phase segment 2: ") ; Serial.println (settings.mPhaseSegment2) ; Serial.print ("SJW: ") ; Serial.println (settings.mSJW) ; Serial.print ("Triple Sampling: ") ; Serial.println (settings.mTripleSampling ? "yes" : "no") ; Serial.print ("Actual bit rate: ") ; Serial.print (settings.actualBitRate ()) ; Serial.println (" bit/s") ; Serial.print ("Exact bit rate ? ") ; Serial.println (settings.exactBitRate () ? "yes" : "no") ; Serial.print ("Sample point: ") ; Serial.print (settings.samplePointFromBitStart ()) ; Serial.println ("%") ; }else{ Serial.print ("Configuration error 0x") ; Serial.println (errorCode, HEX) ; } }

//----------------------------------------------------------------------------------------------------------------------

static uint32_t gBlinkLedDate = 0 ; static uint32_t gReceivedFrameCount = 0 ; static uint32_t gSentFrameCount = 0 ;

//——————————————————————————————————————————————————————————————————————————————

void loop () { CANMessage frame ; CANMessage inmsg ; frame.rtr = true; frame.ext = true;//commented to print the received frame RTR frame.id = 0x112; if (gBlinkLedDate < millis ()) { gBlinkLedDate += 2000 ; digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ; const bool ok = can.tryToSend (frame) ; if (ok) { gSentFrameCount += 1 ; Serial.print ("Sent: ") ; Serial.println (gSentFrameCount) ; Serial.print ("Sent RTR bit: ") ; Serial.println (frame.rtr) ; }else{ Serial.println ("Send failure") ; } } if (can.available ()) { can.receive (inmsg) ; gReceivedFrameCount ++ ; Serial.print ("Received ID: ") ; Serial.println (inmsg.id) ; Serial.print ("Received RTR bit: ") ; Serial.println (inmsg.rtr) ; } }

//——————————————————————————————————————————————————————————————————————————————``` — Reply to this email directly, view it on GitHub https://github.com/pierremolinaro/acan2515/issues/38#issuecomment-1330157245, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEWKZVG5DQEZLKP7SB73VBDWKWQ23ANCNFSM6AAAAAASNQTUHE. You are receiving this because you are subscribed to this thread.

Oulalaa commented 1 year ago

Amazing! Thank you so much for this wonderful library!