CAN Issue with Arduino (NAK)

Hi all,

I've been bashing my head against an issue with CAN for a while and was hoping someone here might have some advice.

I originally started this project with a Teensy 4.0 chip, but have replicated the issue on an ESP32-WROOM as well, specifically the following devkit:

I am trying to set up a CAN communication system using multiple Arduinos, the idea being that each "node" can shout on the same bus and different nodes can listen in using an ID based filtering. However I end up running into some really early issues that have been stumping me.

I am using the SN65HVD230 chip on a breakout board, similar to the following posting:

I believe these chips include the 120 ohm resistor, since a multimeter shows the expected resistance between CANH and CANL and I can identify an SMD resistor code 121 on the board between the high and low buses. I have also verified that my pinout is correct (Some of these boards are known to have bad labels).

I have written multiple scripts to basically have two MCUs shout at each other over the bus, with an example using the ACAN-ESP32 library from Pierre Molinaro on GitHub.

#include "ESP32_CAN_Test.h"

#include <ACAN_ESP32.h>
#include <Streaming.h>

void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);

  #if SERIAL_OUT
    Serial_Out.begin(115200);
    while (!Serial_Out);
  #endif

  Serial_Out << "Initializing CAN Device." << endl;

  ACAN_ESP32_Settings settings(1000000);
  settings.mRxPin = RX_PIN;
  settings.mTxPin = TX_PIN;
  uint32_t errorCode = ACAN_ESP32::can.begin(settings);
  if (errorCode == 0) {
    Serial_Out << "Can Device successfully initialized." << endl;
  }
  else {
    Serial_Out << "Can Device failed to initialize with error code " << _HEX(errorCode) << "." << endl;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  static uint32_t timer = millis();
  if (millis() - timer > 500) {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

    #if CAN_TRANSMIT
      CANMessage msg;
      msg.id = 0x123;
      msg.rtr = false;
      msg.len = 8;
      for (uint8_t i = 0; i < 8; i++) { msg.data[i] = i+1; }
      
      Serial_Out << "Sending CAN Message with ID " << _HEX(msg.id) << "." << endl;
  
      if (ACAN_ESP32::can.tryToSend(msg)) {
        Serial_Out << "CAN Message sent successfully." << endl;
      }
      else {
        Serial_Out << "CAN Message failed to send." << endl;
      }
    #endif

    timer = millis();
  }

  // Catch received messages 
  // TODO: Use ISR  
  CANMessage frame;
  if (ACAN_ESP32::can.receive (frame)) {
    Serial_Out.print ("**** Received ") ;
    Serial_Out.print (frame.ext ? "extended " : "standard ") ;
    Serial_Out.print (frame.rtr ? "remote " : "data ") ;
    Serial_Out.print ("frame, id 0x") ;
    Serial_Out.println (frame.id, HEX) ;
  }
}

Along with the following header:

#ifndef _ESP32_CAN_Test_H
#define _ESP32_CAN_Test_H

// Pins for usage with CAN
#define TX_PIN GPIO_NUM_22
#define RX_PIN GPIO_NUM_23

#define CAN_TRANSMIT true
#define SERIAL_OUT true

class NullOut {
  public:
    void print(const char*) { return; }  
    void println(const char*) { return; }   
    void println(uint32_t, int) { return; }  
};

template<class T>
NullOut &operator <<(NullOut &stream, T arg) {
  return stream;
}

NullOut null_out;
#if SERIAL_OUT
  #define Serial_Out Serial
#else
  #define Serial_Out null_out
#endif

// Pin name for the built in LED on the ESP32 board
#define LED_BUILTIN 2

// Struct for message contents, will be merged into boilerplate code
typedef struct {
  uint8_t buf[8];
  uint32_t id;
} CAN_message;

#endif

I'm doing some weird stuff for debugging output, but I've also see the issue without those being present.

When I run this script on two different MCUs (I see the same behavior with a different script on Teensy 4.0s with the FlexCAN_T4 library), wired into the SN65HVD230 chip, I can see the message being sent on both the TX and RX pins of the chip that is transmitting, however it shows a NAK at the end of the sequence and it doesn't appear that the message manages to cross the bus. I'm using the Digilent Analog Discovery 2 with Waveforms to observe scope readings and I've attached a photo of what my message frame looks like on the TX and RX pins below:

I feel like I'm missing something simple, but having shown this to multiple friends and people at my university over weeks/months of on and off work with this has repeatedly stumped myself and everyone else. I haven't covered everything I've done to debug this here, but I'm happy to add information (I've tried so much stuff I could probably write a 50 page report at this point -_-). Any help would be greatly appreciated!

Replying instead of editing, new account so it won't let me attach two photos.

Adding some additional details, I put together a quick schematic to show my wiring, just in case there is an issue there. I'm about 90% sure that its correct, but I would appreciate a sanity check.

I also just confirmed that in loopback mode with the ACAN library I do receive messages. This is what I would expect as I can see the transmitted message on the RX pin, shown in my scope screenshot above. Despite this, it doesn't show up on the other side of the bus. My suspicion is this is some kind of arbitration issue between the two transceivers, but I've tried brand new breakouts for the SN65HVD230 boards and that hasn't resolved the issue, so unless my above schematic has an issue, I'm at a loss. My next guess is to try a TJA1050 with level converter to try and determine if its a voltage issue. I'll update once I've done that.

Do you see signals on the CAN low and CAN high lines that match up with the Tx signal going into the transceiver?

If not, test the transceiver in isolation by putting a 20 kHz square wave into the Tx and check for activity on the CAN low and CAN high lines. If that is successful then repeat at 1 MHz.

I've attached an older screenshot I had showing the activity on the CANH/CANL lines as well.

I'll confess my understanding of how CAN handles signals at the hardware level isn't great, what should I expect to see on the buses when I apply the square wave? I'll do it now.

Hi,
Just an observation, and good that you checked that the module had 120R resistors.


But in the description on Amazon;

They say High input Impedance which is obviously incorrect.

If you are going to connect more than 2 to your network you will need to remove some of the 120Rs, a network impedance of lower than 60R is not recommended.

Tom... :smiley: :+1: :coffee: :australia:
PS. Thanks for the clear schematic, your circuit looks fine.

I ran it at 20 kHz, 500 kHz, and 1 MHz. Started seeing some definitive noise off my pattern generator at 500 kHz. Just to make sure I set this up right, I disconnected the bus on the transceiver, put channel 1 of my scope on CANL (Though it shows the same thing on CANH as CANL), put my pattern generator on TX after disconnecting pins 22 and 23 from the ESP. Then triggered on my digital logic analyzers rising edge. Hopefully that makes sense!

20 kHz:

Hi Tom,

Thanks for the input, I had taken note of that, but since all my testing is taking place in a 2 node configuration I figured that shouldn't be the issue. Or at least it shouldn't be my current issue.

Thanks for the confirmation on my schematic!

Following up with more of the square wave screenshots since it will only let me put 1 photo in each post, just going to add the 1 MHz, the 500 kHz one isn't really significant, just a mid-point between the 20 kHz and 1 MHz examples.

Hi,
Your trace in post #8 appears to be showing "ringing" on the waveform.
What probes are you using.
What is the yellow trace connected too?

Can you please post an image(s) of your project?

What is the distance between the modules on you test project?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:
PS. What have you got the CanBus speed set at?

Yellow probe is connected to CANL, I've also put it on CANH and it shows as basically the same, will edit this post shortly with a photo of my setup. But, I'm using an Analog Discovery 2, which is a little desktop oscilloscope / pattern generator. I don't have access to a full size one so this is my best option right now. The probes are a breakout set of stranded wires with dupont terminals. So the ringing might just be a limitation off the tool.

Also, baud rate is 1000000 (1 MHz). I have run it at a lower baud rate previously and saw the same issue, didn't try a slower one today and it was the first time I'd revisited this in a couple weeks.

When I looked around online, I saw that 1 MHz is fine up to around ~30-40 feet? Not sure if that only applies for wires and having a breadboard in the system impacts that.

Those CANL waveforms look very strange.
This document from TI has example oscilloscope pictures you would expect to see https://www.ti.com/lit/an/slyt529/slyt529.pdf

In your case at 20 kHz you would expect the shape of CANL to track the Tx signal almost exactly, (with min and max voltages of about 0.7 and 3v respectively).

I have no idea what it's doing at 1 MHz.

Assuming your power supply is OK then you are another victim of the fake or defective CAN transceiver plague afflicting the entire supply chain. Pretty much everything from Ebay, Aliexpress, Amazon etc. manufactured within the last 2 years is suspect.

I swear if that is the issue I'm going to have a conniption. I'm going to put together the TJA1050 + level converter circuit right now and test that. I'm pretty sure that was the original configuration that I had working. Will also give that doc you linked a full read, that seems worth knowing regardless.

You were right, the TJA1050 with logic level converters worked.... I'm absolutely pissed about that. Do you have any recommendations for 3.3 V CAN transceivers? If I custom design a PCB and purchase the chips from Digikey (Assuming they are in stock) do you believe that would be a safe option? Thank you so much, this has been driving me insane for literally months, its ridiculous that there are that many defective/bad chips floating around.

In August 2022 I bought some of these

which appear to use genuine chips.

That was several months ago, so before buying I would recommend that you ask them to confirm that the boards they are currently shipping are using genuine chips.

There are a wide range of fakes that range from 'completely broken' to 'works but not to spec'. See this post for pictures of good/bad waveforms Spot the fake CAN transceiver - Page 1

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.