makerplane / CAN-FIX-ArduinoLib

An Arduino library that implements the CAN-FIX avionics protocol.
GNU General Public License v2.0
3 stars 6 forks source link

getting started #1

Closed qubolino closed 1 year ago

qubolino commented 2 years ago

i’m trying to setup an arduino with mcp2515 and use this library. i can’t seem to find where the pins are defined

birkelbach commented 2 years ago

The only pin that is needed here is the slave select pin that you are using and it is given when you instantiate the CANFIX object. You will also need to use the CAN library. That is the library that actually talks to the MCP2515. It uses the built in SPI library which handles all the low level communication to the MCP2515.

qubolino commented 2 years ago

thanks. indeed the others are defined by arduino architecture.

i managed to build and upload a minimal sketch.

#define CAN_MHZ 20
#include "canfix.h"

CanFix *cf;

void setup() {
  Serial.begin(115200);

  /* The constructor takes the pin that slave select for the MCP2515
     is connected to and our CAN-FIX device type.  The Device type
     will be used as the node id if there is nothing in the EEPROM */
  cf = new CanFix(10, 0xB0);
  /* This sets the model number and firmware version of our device.
     This is what will be returned when the Node ID is requested */
  cf->setModel(0x123456);
  cf->setFwVersion(0x01);
  /*  We send a Node status message of zero to indicate that we are
      up and running and all is okay. */
  cf->sendStatus(0x00, NULL, 0);
  /*  Assign all the callback function for the cf object. */
}

void loop() {
  CFParameter p;
  p.type = 0x180;
  p.index = 0;
  p.fcb = 0x00;
  p.data[0] = 45;
  p.data[1] = 45>>8;
  p.length = 2;

  cf->sendParam(p);
  Serial.println("Sent pitch angle");

  delay(250);
}

do you have any idea how i can test if it's sending anything? on the other end of my can bus i have a raspberry with can hat, and running fixgw, but probably need config

birkelbach commented 2 years ago

The best way is with a third USB/CAN interface. You have a lot of variables and CAN is pretty particular about having at least two functioning nodes on the network. If the RPi is working properly then you should be able to use the can-utils utility programs. These are command line utilities that let you access the socketcan stack from user space. The one that you'll want to start with is 'candump,' which will just print any CAN frames that are received to the screen. It has some filtering capabilities as well. You can also send CAN frames with 'cansend.' See the man pages for these two and see how far you get. Once you know that you can read the CAN frames then we can start troubleshooting higher level functions.

qubolino commented 2 years ago

thanks for your answer. i gather that CAN is a bit finicky and setting up a bus with raspberry and arduino / esp32 is beyond the scope of this (github) project.

i avoided CAN so far using quick and dirty I2C modules and plugins that i implemented myself. might give another thought at implementing a proper and generic i2cfix plugin in fixgw...

qubolino commented 2 years ago

more specifically to answer your question, when using on arduino a basic example from https://github.com/sandeepmistry/arduino-CAN

void loop() {
  // send packet: id is 11 bits, packet can contain up to 8 bytes of data
  Serial.print("Sending packet ... ");

  CAN.beginPacket(0x12);
  CAN.write('h');
  CAN.write('e');
  CAN.write('l');
  CAN.write('l');
  CAN.write('o');
  CAN.endPacket();

  Serial.println("done");

  delay(1000);

  // send extended packet: id is 29 bits, packet can contain up to 8 bytes of data
  Serial.print("Sending extended packet ... ");

  CAN.beginExtendedPacket(0xabcdef);
  CAN.write('w');
  CAN.write('o');
  CAN.write('r');
  CAN.write('l');
  CAN.write('d');
  CAN.endPacket();

  Serial.println("done");

  delay(1000);
}

and on raspi

>>> import can
>>> can0 = can.interface.Bus(channel='can0', bustype = 'socketcan_ctypes')
>>> msg = can0.recv(10.0);print(msg)

it seems to intermittently work only

>>> msg = can0.recv(10.0);print(msg)
Timestamp: 1641730467.840655        ID: 0004    S E              DLC:  8    00 04 00 00 00 00 00 00     Channel: can0
>>> msg = can0.recv(10.0);print(msg)
Timestamp: 1641730483.830952        ID: 0004    S E              DLC:  8    00 10 00 00 00 00 00 00     Channel: can0
>>> msg = can0.recv(10.0);print(msg)  # timeout
None
>>> msg = can0.recv(10.0);print(msg)  # timeout
None

i can reproduce if i play with can0 interface on the raspi

pi@ems:~ $ sudo ifconfig can0 down
pi@ems:~ $ sudo ip link set can0 type can bitrate 500000
pi@ems:~ $ sudo ifconfig can0 up

looks like i'm close but not there yet...

birkelbach commented 2 years ago

You are receiving error frames on your RasPi with the Python script. That's what the 'E' means in the "S E" that follows the ID. (The S means a standard frame as opposed to an 'X' extended frame) If you are having to bring the interface down and back up to get it to go again then that is further proof of that. Your RasPi's MCP2515 is going off network and needs a reset to reconnect. You probably have a bitrate mismatch or some bad signaling in the wiring. Lowering the bitrate might help.

qubolino commented 2 years ago

i eventually got CAN to work. the resources that helped me:

https://experimentalavionics.com/raspberry-pi-can-bus-interface https://www.waveshare.com/wiki/RS485_CAN_HAT to config the raspberry CAN

https://github.com/ExperimentalAvionics/EFIS_AHRS https://github.com/autowp/arduino-mcp2515 to config arduino nano + mcp2515

https://github.com/sandeepmistry/arduino-CAN to config esp32 + HVD230 transceiver

i use candump any to monitor all traffic