pierremolinaro / acan2517

Arduino CAN driver for MCP2517FD CAN Controller (in CAN 2.0B mode)
MIT License
22 stars 10 forks source link

Using acan2517 without INT #2

Open thomasfla opened 5 years ago

thomasfla commented 5 years ago

Hi @pierremolinaro, nice work on your lib, and his doc!

I was wondering if it was possible to use this library without using the INT interrupt signal. Indeed I plan to connect 8 MCP2517FD, without enough interrupt input available. In my application, I was thinking of pooling each module through SPI to check for the presence of one (or more) CAN frames ready to be read.

Thanks for your work.

pierremolinaro commented 5 years ago

Hi,

8 MCP2517FD, nice project ! What kind of Arduino do you plan to use ?

The current version (1.1.0) of ACAN2517 is not intended to operate without the interruption signal.

however, it is possible to circumvent this obligation:

Please find in the attached file the implementation of this solution.

If you are interested, I think it would be possible for several MCP2517FD to share the same interrupt line.

Best regards,

Pierre Molinaro

Le 31 janv. 2019 à 16:11, thomasfla notifications@github.com a écrit :

Hi @pierremolinaro https://github.com/pierremolinaro, nice work on your lib, and his doc!

I was wondering if it was possible to use this library without using the INT interrupt signal. Indeed I plan to connect 8 MCP2517FD, without enough interrupt input available. In my application, I was thinking of pooling each module through SPI to check for the presence of one (or more) CAN frames ready to be read.

Thanks for your work.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pierremolinaro/acan2517/issues/2, or mute the thread https://github.com/notifications/unsubscribe-auth/ASys1NPyZ7l4op8Em-qO7PxSbGAwGmfbks5vIweLgaJpZM4acgn_.

pierremolinaro commented 5 years ago

I have just released ACAN2517 1.1.1, that can works with no interrupt pin.

Best regards,

Pierre

Le 31 janv. 2019 à 16:11, thomasfla notifications@github.com a écrit :

Hi @pierremolinaro https://github.com/pierremolinaro, nice work on your lib, and his doc!

I was wondering if it was possible to use this library without using the INT interrupt signal. Indeed I plan to connect 8 MCP2517FD, without enough interrupt input available. In my application, I was thinking of pooling each module through SPI to check for the presence of one (or more) CAN frames ready to be read.

Thanks for your work.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pierremolinaro/acan2517/issues/2, or mute the thread https://github.com/notifications/unsubscribe-auth/ASys1NPyZ7l4op8Em-qO7PxSbGAwGmfbks5vIweLgaJpZM4acgn_.

thomasfla commented 5 years ago

Great, thank you very much!

I plan to use a Maple Mini (STM32F103RCBT6) with this core https://github.com/stm32duino. If it doesn't work, I think I'll switch to a Teensy.

For the moment I'm waiting for some components to assemble my board. As soon as I can test your library with it, I'll let you know and report here.

By the way, the PCB I'm designing will be open source. It will be used to control a mobile robot.

img_20190204_100556

pierremolinaro commented 5 years ago

Nice ! I do not known Maple Mini, but I use Teensy 3.x for years.

Best Regards,

Pierre

Le 4 févr. 2019 à 10:17, thomasfla notifications@github.com a écrit :

Great, thank you very much!

I plan to use a Maple Mini (STM32F103RCBT6) with this core https://github.com/stm32duino https://github.com/stm32duino. If it doesn't work, I think I'll switch to a Teensy.

For the moment I'm waiting for some components to assemble my board. As soon as I can test your library with it, I'll let you know and report here.

By the way, the PCB I'm designing will be open source. It will be used to control a mobile robot.

https://user-images.githubusercontent.com/11156435/52199186-a4035300-2865-11e9-966c-d481faa35096.jpg — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pierremolinaro/acan2517/issues/2#issuecomment-460177338, or mute the thread https://github.com/notifications/unsubscribe-auth/ASys1E9-Vhx2v6I1wHnID57RyLXW7IAIks5vJ_qVgaJpZM4acgn_.

thomasfla commented 5 years ago

Hi pierre,

The lib works out of the box for SMT32 arduino core! (With my setup, I can only tested the polling version..)

I realized that MODIF bit of CiINT register was always active, and I do not understand why... This makes the polling time slower because this register is cleared at each poll call.

Looking with an oscilloscope on CLK line I can see that signe byte SPI transfers are quite far appart from each other. Maybe this is just a STM32 core problem?

Using one buffered SPI transfer for both command and data exchange, i got quite good improvment:

Here are my results with 9Mhz SPI: Polling 8 MCP2517FD in a loop with

Polling time is critical in my application, but this should also improve CAN frame transfer..

The drawback is that it breaks your 'LEVEL FUNCTION'

Here is the modified functions:

uint32_t ACAN2517::readWordSPI (void) {

  #ifndef OPTIMIZED_SPI
    uint32_t result = mSPI.transfer (0) ;
    result |= ((uint32_t) mSPI.transfer (0)) <<  8 ;
    result |= ((uint32_t) mSPI.transfer (0)) << 16 ;
    result |= ((uint32_t) mSPI.transfer (0)) << 24 ;
  #else
    uint32_t result  = 0;
    unsigned char buff[4]={0};
    mSPI.transfer(buff,4);
    result |= ((uint32_t)buff[0]) << 0;
    result |= ((uint32_t)buff[1]) << 8;
    result |= ((uint32_t)buff[2]) << 16;
    result |= ((uint32_t)buff[3]) << 24;
  #endif
  return result ;
}
void ACAN2517::writeByteRegisterSPI (const uint16_t inRegisterAddress, const uint8_t inValue) {
  assertCS () ;
  #ifndef OPTIMIZED_SPI
    writeCommandSPI (inRegisterAddress) ; // Command
    mSPI.transfer (inValue) ; // Data  
  #else  
    unsigned char buff[3]={0};  
    const uint16_t writeCommand = (inRegisterAddress & 0x0FFF) | (0b0010 << 12) ;
    buff[0] = writeCommand >> 8;
    buff[1] = writeCommand & 0xFF;
    buff[2] = inValue;
    mSPI.transfer(buff,3);  
  #endif
  deassertCS () ;
}
uint32_t ACAN2517::readRegisterSPI (const uint16_t inRegisterAddress) {
  assertCS () ;
  #ifndef OPTIMIZED_SPI
    readCommandSPI (inRegisterAddress) ; // Command
    const uint32_t result = readWordSPI () ; // Data
  #else
      const uint16_t readCommand = (inRegisterAddress & 0x0FFF) | (0b0011 << 12) ;
      unsigned char buff[6]={0};
      buff[0] = readCommand >> 8;
      buff[1] = readCommand & 0xFF;
      uint32_t result  = 0;
      mSPI.transfer(buff,6);
      result |= ((uint32_t)buff[2+0]) << 0;
      result |= ((uint32_t)buff[2+1]) << 8;
      result |= ((uint32_t)buff[2+2]) << 16;
      result |= ((uint32_t)buff[2+3]) << 24;
  #endif
  deassertCS () ;
  return result ;
}

Another improvement to speed up the polling time could be to use the CiVEC register witch is only one byte long...

Maybe some of this is more related to efficiency than polling mode and should motivate to open an other issue?

Best, Thomas.

pierremolinaro commented 5 years ago

Hi Thomas,

Sorry for the delay. I am happy that the lib runs on a STM32 Arduino core.

Thank you cvery much for your benchmarks and suggestions, I will read them carefully and I will make a release, after having checked it runs for all cores I currenly support.

Best regards,

Pierre

Le 7 févr. 2019 à 18:40, thomasfla notifications@github.com a écrit :

Hi pierre,

The lib works out of the box for SMT32 arduino core! (With my setup, I can only tested the polling version..)

I realized that MODIF bit of CiINT register was always active, and I do not understand why... This makes the polling time slower because this register is cleared at each poll call.

Looking with an oscilloscope on CLK line I can see that signe byte SPI transfers are quite far appart from each other. Maybe this is just a STM32 core problem?

Using one buffered SPI transfer for both command and data exchange, i got quite good improvment:

Here are my results with 9Mhz SPI: Polling 8 MCP2517FD in a loop with

standard lib: 1.05kHz standard lib without clearing MODIF: 1.33kHz optimized spi transfer : 1.44kHz optimized spi transfer without clearinf MODIF 1.85kHz Polling time is critical in my application, but this should also improve CAN frame transfer..

The drawback is that it breaks your 'LEVEL FUNCTION'

Here is the modified functions:

uint32_t ACAN2517::readWordSPI (void) {

ifndef OPTIMIZED_SPI

uint32_t result = mSPI.transfer (0) ;
result |= ((uint32_t) mSPI.transfer (0)) <<  8 ;
result |= ((uint32_t) mSPI.transfer (0)) << 16 ;
result |= ((uint32_t) mSPI.transfer (0)) << 24 ;

else

uint32_t result  = 0;
unsigned char buff[4]={0};
mSPI.transfer(buff,4);
result |= ((uint32_t)buff[0]) << 0;
result |= ((uint32_t)buff[1]) << 8;
result |= ((uint32_t)buff[2]) << 16;
result |= ((uint32_t)buff[3]) << 24;

endif

return result ; } void ACAN2517::writeByteRegisterSPI (const uint16_t inRegisterAddress, const uint8_t inValue) { assertCS () ;

ifndef OPTIMIZED_SPI

writeCommandSPI (inRegisterAddress) ; // Command
mSPI.transfer (inValue) ; // Data  

else

unsigned char buff[3]={0};  
const uint16_t writeCommand = (inRegisterAddress & 0x0FFF) | (0b0010 << 12) ;
buff[0] = writeCommand >> 8;
buff[1] = writeCommand & 0xFF;
buff[2] = inValue;
mSPI.transfer(buff,3);  

endif

deassertCS () ; } uint32_t ACAN2517::readRegisterSPI (const uint16_t inRegisterAddress) { assertCS () ;

ifndef OPTIMIZED_SPI

readCommandSPI (inRegisterAddress) ; // Command
const uint32_t result = readWordSPI () ; // Data

else

  const uint16_t readCommand = (inRegisterAddress & 0x0FFF) | (0b0011 << 12) ;
  unsigned char buff[6]={0};
  buff[0] = readCommand >> 8;
  buff[1] = readCommand & 0xFF;
  uint32_t result  = 0;
  mSPI.transfer(buff,6);
  result |= ((uint32_t)buff[2+0]) << 0;
  result |= ((uint32_t)buff[2+1]) << 8;
  result |= ((uint32_t)buff[2+2]) << 16;
  result |= ((uint32_t)buff[2+3]) << 24;

endif

deassertCS () ; return result ; } Another improvement to speed up the polling time could be to use the CiVEC register witch is only one byte long...

Maybe some of this is more related to efficiency than polling mode and should motivate to open an other issue?

Best, Thomas.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/pierremolinaro/acan2517/issues/2#issuecomment-461525728, or mute the thread https://github.com/notifications/unsubscribe-auth/ASys1AI9MYvfMb3Nq7knkpLyOa2H7peOks5vLGTwgaJpZM4acgn_.

thomasfla commented 5 years ago

Hi Pierre,

Thanks! BTW, it might be easier to read the code on this commit from my fork : https://github.com/thomasfla/acan2517/commit/8f0a3646a40d7321163a2a4ad438c9849475d2b9

In this commit I also optimized the sending of a CAN frame. This shorten the sending time from 250us to 109us with my 9Mhz SPI on STM32F103.

Some function are not optimized yet like reading a can frame.

About my particular 8CAN setup, I'm considering switching to a teensy 3.6 witch should be faster, connecting the INTs pin to save the polling time, and changing my quartz to a 40Mhz to get 20Mhz SPI. My project can be checked here https://github.com/thomasfla/8XCAN_FD

Finally, I'm also thinking of using SPI DMA to shorten the blank between SPI bytes transition. That will depend on the Teensy performances.