-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
very unreliable CAN bus reading #9
Comments
I am using this library for more than a year without a problem. I think it is hardware problem. |
Thanks szotyi007, 120 Ohms on end of bus (only 2x 120 Ohms): there is a sold on 120 Ohms on "Dual CAN-Bus adapter for Teensy 3.5, 3.6" and I put a 120 Ohms on the TX2 side; measured is 60 Ohms. Also I put the "Dual CAN-Bus adapter for Teensy 3.5, 3.6" on top of Teensy 3.6 board instead of previously I put the transceiver on a breadboard and wired it to Teensy 3.6. I doubt it is more sensitive of the TX and RX signals of CAN controller, so I make this revision. I am also thinking about to twist the wire (about 32cm or 13 inches) from the transceiver to TX2. But from the oscilloscope, the signals are good. Best Regards, |
I have never used the 230 transceiver. I use the 234 where Rs is the slope control and the special pin is an enable pin that can be used to turn the transceiver on and off. For fast CAN you want to essentially ground the Rs pin to go into fast mode. You can't really do slope control at 1M or likely even at 500k. You need the transceiver to slam the digital signal to the proper level as fast as it can. It seems for your 230 transceiver the extra pin is Vref instead of enable. You will need to leave that pin alone. If it is connected to a pin on your processor then set that processor pin to input or you're going to have a bad time. |
Thanks Collins. I tried to remove the line "digitalWrite(35, LOW);", and it is the same behavior and the measurement of pin 35 is always 0. I then remove the line "pinMode(35, OUTPUT);", no difference. At last I define pin 35 as input, the CAN totally doesn't work. I checked the spec of 230. It says "Rs: SN65HVD230 and SN65HVD231: Mode select pin: strong pull down to GND = high speed mode, strong pull up to VCC = low power mode, 10kΩ to 100kΩ pull down to GND = slope control mode". It seem the same feature as of 234. And 230 have another pin Vref. |
What if you take out the NVidia TX2? And try to connect the two can bus of the teensy? You send a message from Can0 to Can1.. and you print out the received data on Can1? |
Thanks szotyi007, I had tested that example, it works fine. |
Hello Coliin, I just notice in your CAN_message_t, there is no "timeout", is it just removed or it is implemented in other way? And for the new "flags.extended" and "flags.remote", should I explicitly set them to 0 for standard CAN frame and normal frames? For the new "flags.overun", how can I use it? For the tx mailbox, as I understand if exact order is required, it should be set to 1. However, when I set it, the CAN bus never works. Also I saw somewhere, it should be set before the begin() function, however it is even after the begin() function, it still works. |
I set "flags.extended", "flags.remote" and "flags.overrun" to zero, it works much better. But still CAN bus seems freeze after some time. From oscilloscope TX2 still send out CAN frames, but it seems Teensy not answer anything. In the Serial Monitor, all the Serial.print() in the loop is not executed. |
It seems I solve my problem. "flags.overrun" should not be set to zero each time write something to CAN bus. I got it works in the morning. But in the afternoon, the system will freeze after some running. In this situation, Teensy requires reset to work again. With some print out, it seems "loop" and "interrupt handlers" are not working. Should I suspect the hardware? As I use breadboard for the test now, so a lot of flying wires. |
It is possible that hardware issues could cause it. Intermittent freezes after a long time are pretty much the hardest thing to track down. There are many reasons that something like that could occur. With interrupts one very suspect reason would be race conditions. They could be exceedingly rare and hard to trigger but when you're running for hours straight and through millions of loops they can pop up seemingly at random. So, it's difficult to say for sure what the cause is for you. Usually a purpose built PCB will be more reliable though. |
As I tried both interrupt mode and poll mode, so it should not be race conditions. When it happens, it will stop running both interrupt loops and the main loop. It should be mostly the hardware problem. I will try to use less the breadboard. |
Thanks szotyi007, collin80, |
Hello Collin,
Thanks for open a window for asking your expert help. I am trying to build communication on CAN bus using your library.
My system: on one side, NVidia TX2 (with CAN controller CAN MCP2515T-I/ML and transceiver TJA1051TK/3); the other side Teensy 3.6 with "Dual CAN-Bus adapter for Teensy 3.5, 3.6" (https://www.tindie.com/products/Fusion/dual-can-bus-adapter-for-teensy-35-36/) which uses transceiver SN65HVD230D.
My first question is in the example "CANtest", as I understand it is same setup as me, why the enable pin is set to HIGH (which as Pawelsky point out the transceiver SN65HVD230D is in sleep mode)? Is slope mode you are using? Should I put pull down resistor for the enable pin?
I put an oscilloscope on the CANH and CANL, here is a picture of what I got:
If the hardware is of no problem. My problem is the communication on CAN bus always fails after some seconds. I had tried both teachtop's library and your library; I also tried your library and examples. Now I only succeed in the CANtest example with loopback.
On the TX2 side, CAN socket is used. I use a timer (40hz) to send command to read I2C altimeter (LW20/C): send command to CAN bus; delay 1ms; read CAN bus.
On the Teensy 3.6 side, I tried both scan mode and interrupt mode; interrupt mode will be a little bit better, but also failed after some reading the CAN bus (TX2 side). I will attach the code for the interrupt mode in the end. From the debug, it seems the mailboxes (TX) at the Teensy side are not released or the the data wrote to CAN bus from Teensy 3.6 is not read out from the TX2 side. I see there is a "txHandler", how to use it and what is this for? What is the event for this handler?
There are two extra headers for the LED and altimeter I work with. I put the function to read distance here. After this function is the main() of the Teensy 3.6.
static uint8_t getDefaultMedianDistance(byte addr, uint8_t **strCAN)
{
int i = 0;
uint8_t count = 0;
uint8_t str[8];
Wire.beginTransmission(addr);
Wire.write("?LD\r\n");
Wire.endTransmission();
delay(2); //must have a delay even only 1ms, or a lot of mess up
Wire.requestFrom(addr, (byte)12); // general call
while( Wire.available() ) {
char c = Wire.read();
//Serial.print(c);
if(i >= 5 && c != '\r' && c != '\n' && c != ' ' && c != '\0')
{
str[i - 5] = c;
count++;
}
i++;
}
//Serial.print('\n');
*strCAN = str;
return count;
}
The following is the main() of Teensy 3.6:
// -------------------------------------------------------------
// CANtest for Teensy 3.6 dual CAN bus
// by Collin Kidder, Based on CANTest by Pawelsky (based on CANtest by teachop)
//
// Both buses are left at default 250k speed and the second bus sends frames to the first
// to do this properly you should have the two buses linked together. This sketch
// also assumes that you need to set enable pins active. Comment out if not using
// enable pins or set them to your correct pins.
//
// This sketch tests both buses as well as interrupt driven Rx and Tx. There are only
// two Tx buffers by default so sending 5 at a time forces the interrupt driven system
// to buffer the final three and send them via interrupts. All the while all Rx frames
// are internally saved to a software buffer by the interrupt handler.
//
#include <Time.h>
#include "FlexCAN.h"
//#include <Wire.h>
#include <i2c_t3.h> // for multiple i2c ports
#include "BlinkM_funcs.h"
byte addr_BlinkM = 0x09; // address of BlinkM
#include "lw20_funcs.h"
byte addr_lw20 = 0x66;
#ifndef MK66FX1M0
#error "Teensy 3.6 with dual CAN bus is required to run this example"
#endif
class ExampleClass : public CANListener
{
public:
void printFrame(CAN_message_t &frame, int mailbox);
bool frameHandler(CAN_message_t &frame, int mailbox, uint8_t controller); //overrides the parent version so we can actually do something
void txHandler (int mailbox, uint8_t controller);
bool tx_completed_ = false;
};
void ExampleClass::printFrame(CAN_message_t &frame, int mailbox)
{
Serial.print("ID: ");
Serial.print(frame.id, HEX);
Serial.print(" Data: ");
for (int c = 0; c < frame.len; c++)
{
Serial.print(frame.buf[c], HEX);
Serial.write(' ');
}
Serial.write('\r');
Serial.write('\n');
Serial.print("mailbox: ");
Serial.print(mailbox);
Serial.write('\r');
Serial.write('\n');
}
void ExampleClass::txHandler (int mailbox, uint8_t controller)
{
tx_completed_ = true;
Serial.print("One write for mailbox and controller: ");
Serial.println(mailbox);
//Serial.print(", ");
//Serial.println(controller);
}
bool ExampleClass::frameHandler(CAN_message_t &frame, int mailbox, uint8_t controller)
{
CAN_message_t outMsg;
//printFrame(frame, mailbox);
switch (frame.id)
{
case 0x00: //BlinkM LED
{
switch (frame.buf[1])
{
case 'n':
{
BlinkM_setRGB(frame.buf[0], frame.buf[2], frame.buf[3], frame.buf[4]);
// Serial.print("outMsg.buf: ");
// for(int i = 1; i < strCANLen; i++)
// {
// Serial.print((char)outMsg.buf[i]);
// }
// Serial.print('\t');
// Serial.print("Length:");
// Serial.print(strCANLen);
// Serial.print('\n');
}
return true;
}
ExampleClass exampleClass;
// -------------------------------------------------------------
void setup(void)
{
//Can0.setNumTxBoxes(8);
Can1.setNumTxBoxes(8);
//Can0.begin(1000000);
Can1.begin(1000000);
//if using enable pins on a transceiver they need to be set on
pinMode(2, OUTPUT);
pinMode(35, OUTPUT);
//digitalWrite(35, HIGH);
digitalWrite(2, LOW);
digitalWrite(35, LOW);
//Can0.attachObj(&exampleClass);
Can1.attachObj(&exampleClass);
exampleClass.attachGeneralHandler();
//exampleClass.attachMBHandler(2);
//exampleClass.attachMBHandler(14);
Wire.begin();
Serial.begin(115200);
delay(2000);
Serial.println(F("Teensy 3.6 dual CAN, BlinkM and LW20 altimeter."));
// init BlinkM funcs
BlinkM_begin();
BlinkM_off(addr_BlinkM);
// print address of BlinkMs
Serial.print("Address of BlinkM: 0x");
Serial.print(BlinkM_getAddress(addr_BlinkM), HEX);
Serial.println();
}
uint8_t j = 0;
uint32_t clk_count = 0;
unsigned long old_millis = 0;
unsigned long current_millis;
// -------------------------------------------------------------
void loop(void)
{
clk_count++;
if (clk_count > 1000000)
{
//Serial.println(now());//Returns the number of seconds since Jan 1 1970
current_millis = millis(); //Number of milliseconds since the program started (unsigned long)
Serial.println(millis() - old_millis);
old_millis = current_millis;
clk_count = 0;
}
//CAN_message_t inMsg, outMsg;
/*outMsg.buf[0] = 0x00;
outMsg.buf[1] = BlinkM_getAddress(0x09);
outMsg.ext = 0;
outMsg.id = 0x00;
//outMsg.timeout = 100;
outMsg.len = 2;
Can1.write(outMsg);
for(uint8_t i = 0; i < 8; i++, j++)
outMsg.buf[i] = j;
outMsg.ext = 0;
outMsg.id = 0x01;
//outMsg.timeout = 100;
outMsg.len = 8;
Can1.write(outMsg);*/
/*while (Can1.available())
//if (Can1.available())
{
}*/
}
The text was updated successfully, but these errors were encountered: