About the CAN controller.

jcsbanks
Posts: 305
Joined: Tue Mar 28, 2017 8:03 pm

Re: About the CAN controller.

Postby jcsbanks » Wed Apr 05, 2017 12:36 pm

It is working with MCP2551.

Kvaser log, I sent 8 zeros in the first three packets, then 0, 52 then six zeroes in the subsequent packets and the ESP32 echoes them.

The 2018 is the CAN ID, 8 is the DLC, then the payload, then the timestamp and Transmit or Receive.

Code: Select all

 0        2018         8   0   0   0   0   0   0   0   0      66.129150 T
 0        2018         8   0   0   0   0   0   0   0   0      66.133580 R
 0        2018         8   0   0   0   0   0   0   0   0      76.258980 T
 0        2018         8   0   0   0   0   0   0   0   0      76.263080 R
 0        2018         8   0   0   0   0   0   0   0   0      80.845390 T
 0        2018         8   0   0   0   0   0   0   0   0      80.853070 R
 0        2018         8   0  52   0   0   0   0   0   0      87.391740 T
 0        2018         8   0  52   0   0   0   0   0   0      87.393020 R
 0        2018         8   0  52   0   0   0   0   0   0      89.739940 T
 0        2018         8   0  52   0   0   0   0   0   0      89.743010 R
 0        2018         8   0  52   0   0   0   0   0   0      90.887330 T
 0        2018         8   0  52   0   0   0   0   0   0      90.893050 R
 0        2018         8   0  52   0   0   0   0   0   0      92.257020 T
 0        2018         8   0  52   0   0   0   0   0   0      92.262990 R
 0        2018         8   0  52   0   0   0   0   0   0      93.409870 T
 0        2018         8   0  52   0   0   0   0   0   0      93.413030 R
 0        2018         8   0  52   0   0   0   0   0   0      94.374990 T
 0        2018         8   0  52   0   0   0   0   0   0      94.383010 R
What is interesting is the round trip time varies from 1ms to 8ms. 500kbps bus, nothing else on the bus. Any ideas on getting the latency lower? It isn't bad, but my 180MHz ECU usually replies in 1ms to Kvaser.

Getting rid of printf and changing

Code: Select all

if(xQueueReceive(CAN_cfg.rx_queue,&__RX_frame, 3*portTICK_PERIOD_MS)==pdTRUE){
to

Code: Select all

if(xQueueReceive(CAN_cfg.rx_queue,&__RX_frame, 1*portTICK_PERIOD_MS)==pdTRUE){
doesn't change it.

ThomasB
Posts: 38
Joined: Sun Dec 25, 2016 12:11 am

Re: About the CAN controller.

Postby ThomasB » Wed Apr 05, 2017 4:41 pm

While the rx frame is handled in an ISR, the tx frame is send in a task context. As we have plenty of tasks for wifi etc. you can not know if there are currently higher priority tasks pending and as the tx task has no synchronisation point, the delay jitters.

You can place the tx directly in the rx is context or try to increase the tx task priorit to remove or reduce jitter.

jcsbanks
Posts: 305
Joined: Tue Mar 28, 2017 8:03 pm

Re: About the CAN controller.

Postby jcsbanks » Sat Apr 15, 2017 7:30 pm

First eight packets are with a FreeRTOS task replying with an echo of packets received, so four are sent, four received. Second eight packets are with the reply in an ISR. Moving from FreeRTOS to an ISR drops the latency 20 times from average of 5.3ms to 260us.
latency.png
latency.png (18.63 KiB) Viewed 24805 times

Fusion
Posts: 20
Joined: Wed Apr 26, 2017 3:34 pm

Re: About the CAN controller.

Postby Fusion » Wed Apr 26, 2017 3:38 pm

Hi guys.
Just to confirm:

Wroom32 GPIO5 <---------> CAN TXD (D)
Wroom32 GPIO4 <---------> CAN RXD (R)

Is this correct?

User avatar
rudi ;-)
Posts: 1729
Joined: Fri Nov 13, 2015 3:25 pm

Re: About the CAN controller.

Postby rudi ;-) » Wed Apr 26, 2017 4:27 pm

Fusion wrote:Hi guys.
Just to confirm:

Wroom32 GPIO5 <---------> CAN TXD (D)
Wroom32 GPIO4 <---------> CAN RXD (R)

Is this correct?
In relation to the nature of the question, first,
how you want drive CAN on ESP32?
MCP2551, TJA1051, SN65HVD233

5V / 3.7V / 3.3V
cause ESP32 is 3.3V - be sure your Receive Lines are LevelShifted to 3.3V
example MCP2551 is 5V and on Rx Line, this comes from MCP2551 and goes to ESP32 GPIO PIN; without a resistor / levelshift this can destroy your gpio cause 5V line....
.. there are several examples how you can do 5V Transceiver to a 3.3V Controller
example look how olimex this do..
or you can use 3.3V CAN Transceiver example sn65hvd233.


to your question itself:
how you set it you can use it
example in code..

Code: Select all

CAN_device_t CAN_cfg = {
	.speed=CAN_SPEED_125KBPS,		// CAN Node baudrade
	.tx_pin_id = GPIO_NUM_5,		// CAN TX pin
	.rx_pin_id = GPIO_NUM_4,		// CAN RX pin
	.rx_queue=NULL,					// FreeRTOS queue for RX frames
};
third party CAN driver
example in menuconfig
CAN_SET_MENU.jpg
CAN_SET_MENU.jpg (129.69 KiB) Viewed 24705 times
best wishes
rudi ;-)

edit:
my favority own circuit MCP2551 and ESP32 is this
IMG_6323_personaly_shem.jpg
IMG_6323_personaly_shem.jpg (21.41 KiB) Viewed 24625 times
Last edited by rudi ;-) on Fri Apr 28, 2017 7:11 am, edited 1 time in total.
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

Fusion
Posts: 20
Joined: Wed Apr 26, 2017 3:34 pm

Re: About the CAN controller.

Postby Fusion » Wed Apr 26, 2017 6:17 pm

Thanks for the info. I will be using the SN65HVD230.

Any idea when Can support will be available in ESP32 Arduino?

santanapablo1975
Posts: 34
Joined: Wed Feb 15, 2017 8:31 pm

Re: About the CAN controller.

Postby santanapablo1975 » Fri May 05, 2017 1:11 pm

Hi Thomas and Rudi!

Thanks for the sources around CAN, I made a test with success, 2 ESP32 tx and rx the test frame!

Regards

Bis dann denn!

MfG

Juan

Beck-Sisyphus
Posts: 14
Joined: Sun Jan 03, 2016 12:15 am

Re: About the CAN controller.

Postby Beck-Sisyphus » Thu May 11, 2017 10:57 am

Hi Rudi and Thomas,

It's great that you complete the CAN bus driver for ESP32!

When I configure the driver with different pinout, in my case is GPIO5->CAN TX and GPIO16->CAN RX, the menuconfig shows they are invalid pins. Running the code on both device successfully, but no communication yet. Is there a way to change the GPIO pinout for CAN bus?

Platform: ESP-IDF
Board: ESP-WROOM-32
CAN Transceiver: SN65HVD232 (3.3V)
Termination: 120 Ohm

Another question is about CAN bus protocol itself. Currently I planned to have one masters on the bus and two slaves, with masters and slaves both sending and receiving. How to define the address of the three device?


Thanks,

Beck
Attachments
Screen Shot 2017-05-11 at 6.50.31 PM.png
Screen Shot 2017-05-11 at 6.50.31 PM.png (44.39 KiB) Viewed 24613 times

User avatar
rudi ;-)
Posts: 1729
Joined: Fri Nov 13, 2015 3:25 pm

Re: About the CAN controller.

Postby rudi ;-) » Thu May 11, 2017 11:45 am

Beck-Sisyphus wrote:
When I configure the driver with different pinout, in my case is GPIO5->CAN TX and GPIO16->CAN RX, the menuconfig shows they are invalid pins.
it is cause the pins are selected as "Valid pins" in the menuconfig file for CAN-
feel free to set your own "Valid" config on this
change here the "valid pins" and here

4 and 5 are the successfully tested pins,
you can use other too
Beck-Sisyphus wrote:
Running the code on both device successfully, but no communication yet.
Is there a way to change the GPIO pinout for CAN bus?

Platform: ESP-IDF
Board: ESP-WROOM-32
CAN Transceiver: SN65HVD232 (3.3V)
Termination: 120 Ohm
yes. see the preview text.
Beck-Sisyphus wrote:
Another question is about CAN bus protocol itself.
Currently I planned to have one masters on the bus and two slaves,
with masters and slaves both sending and receiving. How to define the address of the three device?
you can set example "itself" node
and send the message by using this itself node address.
example a "slave" - i will named it as CAN-Unit
send the ADC Value of one ADC Pin
and use the itself node address for the frame for this.
( the frame content not a delivery ( "Receiver" ) address, the frame content the "Transceiver" )
this is the base of CAN.

example with an counter :

Code: Select all


void task_CAN_TX(void* pvParameters) {

   CAN_frame_t __TX_frame;
   uint32_t counter = 0;

      __TX_frame.MsgID = CONFIG_ESP_CAN_NODE_ITSELF; // address from menuconfig set
      __TX_frame.DLC   =  8;
      __TX_frame.data.u8[0] = 'E';
      __TX_frame.data.u8[1] = 'S';
      __TX_frame.data.u8[2] = 'P';
      __TX_frame.data.u8[3] = '-';
      __TX_frame.data.u8[4] = 'C';
      __TX_frame.data.u8[5] = 'A';
      __TX_frame.data.u8[6] = 'N';
      __TX_frame.data.u8[7] = counter;

while(1) {
      __TX_frame.data.u8[7] = counter;
      CAN_write_frame(&__TX_frame);
/*      printf("Frame from : 0x%08x, DLC %d \n", __TX_frame.MsgID, __TX_frame.DLC);
      printf("D0: 0x%02x, ", __TX_frame.data.u8[0]);
      printf("D1: 0x%02x, ", __TX_frame.data.u8[1]);
      printf("D2: 0x%02x, ", __TX_frame.data.u8[2]);
      printf("D3: 0x%02x, ", __TX_frame.data.u8[3]);
      printf("D4: 0x%02x, ", __TX_frame.data.u8[4]);
      printf("D5: 0x%02x, ", __TX_frame.data.u8[5]);
      printf("D6: 0x%02x, ", __TX_frame.data.u8[6]);
      printf("D7: 0x%02x\n", __TX_frame.data.u8[7]);
      printf("==============================================================================\n");
      printf("..Frame written\n");

 */    
      vTaskDelay( 1000  / portTICK_PERIOD_MS);  // to see ( printf on receiver side ) what happend..
      counter++;
      if (counter >= 256) counter = 0;
  }
}



each "Master" - i name it CAN-Controll
then decides to use the Information for a "address"
example:
this prints each Info..
if you want to use a Info of a certain address, check out the line
..

Code: Select all

if ( __RX_frame.MsgID == YOUR_CHOICE) {..

example:

Code: Select all


void task_CAN( void *pvParameters ){
    (void)pvParameters;

    //frame buffer
    CAN_frame_t __RX_frame;

    //create CAN RX Queue
    CAN_cfg.rx_queue = xQueueCreate(10,sizeof(CAN_frame_t));

    //start CAN Module
    CAN_init();

    while (1){
        //receive next CAN frame from queue
        if(xQueueReceive(CAN_cfg.rx_queue,&__RX_frame, 3*portTICK_PERIOD_MS)==pdTRUE){

        	//do stuff!

			/* brief: rudi
			* new we switch to NODE Identifier here
			* only if we are interest to this comming node
			* we print / use the node date where commes in from
			*
			*/
			/* @Beck: here is your magic if you want only from a certain node */
			// if ( __RX_frame.MsgID == YOUR_CHOICE) {

			// printf("New Frame form 0x%08x, DLC %d, dataL: 0x%08x, dataH: 0x%08x \r\n",__RX_frame.MsgID,  __RX_frame.DLC, __RX_frame.data.u32[0],__RX_frame.data.u32[1]);
			printf("Frame from : 0x%08x, DLC %d \n", __RX_frame.MsgID, __RX_frame.DLC);
			printf("D0: 0x%02x, ", __RX_frame.data.u8[0]);
			printf("D1: 0x%02x, ", __RX_frame.data.u8[1]);
			printf("D2: 0x%02x, ", __RX_frame.data.u8[2]);
			printf("D3: 0x%02x, ", __RX_frame.data.u8[3]);
			printf("D4: 0x%02x, ", __RX_frame.data.u8[4]);
			printf("D5: 0x%02x, ", __RX_frame.data.u8[5]);
			printf("D6: 0x%02x, ", __RX_frame.data.u8[6]);
			printf("D7: 0x%02x\n", __RX_frame.data.u8[7]);
			printf("==============================================================================\n");

        	//loop back frame
        	// CAN_write_frame(&__RX_frame);
			// } /* comment out if you use YOUR_CHOICE */

...
...
hope this helps

best wishes
rudi ;-)
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

iosixllc
Posts: 71
Joined: Fri Mar 17, 2017 12:13 am

Re: About the CAN controller.

Postby iosixllc » Fri May 12, 2017 7:16 am

A note - unless you are only going to configure on a hard power-up (instead of after firmware OTA or other reset), you should add the following after the Pelican mode change [MODULE_CAN->CDR.B.CAN_M = 0x1;]:

MODULE_CAN->MOD.B.RM = 1;

Otherwise, the code cannot change the module configuration.

Who is online

Users browsing this forum: jesper and 110 guests