-
Notifications
You must be signed in to change notification settings - Fork 6
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
Change the libary to use a different CAN driver #2
Comments
I took a quick glance at the state of the CAN libraries in the Arduino and it seems pretty haphazard. There doesn't seem to be any common interface to these libraries. Maybe I'm missing it. If we are going to do this it'd be nice if it would work with other CAN hardware than the MCP2515 only. If this worked with the internal ESP32 CAN controller then Vern's Huvver devices would immediately be CANFiX compatible. If it worked with the internal STM32 CAN controller then this pile of Nucleo boards that I have would be compatible. I'm sure there are other boards as well. Now the question is... what is the best library to use (there are dozens of them) and/or do we commit to that library or write a wrapper in our code? It's been a while since I messed with Arduino libraries. My instinct is that we create some wrapper functions that present a standard CAN interface and then it would use different backend libraries based on #defines that the user would put in their code. This has the added advantage that the existing CANFiX code doesn't have to change much. This doesn't seem very Arduino'ish to me. Suggestions are welcome! |
Thanks Phil. I like the idea of abstracting the underlying library away to give the developer a simple way to interface one of several libraries. Like you said, maintaining all of that code could be tough and there's no reason to re-write it all if someone already has (provided we test our "approved" libraries thoroughly). I'm not a hardware guy, so Arduino is my only experience with microcontrollers of any kind. I'm happy to learn more, but I don't really even know where to start. Also finding the MakerPlane projects two weeks ago started my foray into the mysterious world of CAN. So from a hardware standpoint, I'm not much help, but I'm happy to work on documentation or write object classes for CANFix parameters (if that's helpful), or whatever I can do. Dan |
What do you think about these two for starters... This one is being maintained by Adafruit and supports the ESP32 as well as SAME5x series uCs and the MCP2515. I don't really care for the interface but my guess is that it'll work well. This is the one that was mentioned on the MakerPlane forum. I like it as well. If you only want the MCP2515 then you might be able to save some space with this. Might keep ours too since it's pretty small because it only uses the features that we need for CANFiX. No extended messages or RTRs etc. |
I can confirm that the CAN Adafruit Fork library works with my 8Mhz MCP2515. Using the CANSender.ino example this is a working example of what I to set my setup() block to look like:
I was also able to set my SPI Frequency up to 20Mhz, since I'm using an Arduino Nano with an ATmega328P chip on it. It worked both ways, I was just testing out various settings. I was also able to crank my CAN frequency all the way up to 1Mhz. And, as you know, I already tested the mcp_can library with good results too. Seems like the Adafruit library supports more hardware (proven now on the MCP2515), so I suggest just using that one. If someone needs a slimmer library, maybe look at adding mcp_can as an option later?? Dan |
Okay that’s good info. I’ll try to carve out some time this weekend to write a quick wrapper, and test it on a few boards. I don’t think it’ll be terribly difficult to do. |
I thought about this more last night. I have a similar library that I wrote in C that I use for non-Arduino projects. I had a baked in CAN driver in that one for a while and I finally removed the CAN portion altogether and used user defined callback functions for the CAN stuff. So basically the calling program would be responsible for reading and writing the CAN frames. It would simply pass the received frames to the exec() function in the CANFiX object. If the exec() function needs to send a frame it would use a callback function that the calling program would have to provide for sending the CAN frames. I couldn't think of a way of using multiple libraries without some kind of conditional compilation mechanism. That seems like bad form for a library to me, maybe I'm missing something. We'd also still have to maintain the wrapper code. This way we get out of the CAN sending/receiving business and can concentrate on protocol issues. It would also make unit testing brainlessly easy. We would include examples for the different CAN libraries instead of maintaining wrapper code that would have to be conditionally compiled. It's the same thing we're just moving a little bit more responsibility (and freedom) to the end user. |
Yeah, that sounds like a good path forward to me. I agree: If we're relying on the user to do more, we definitely need to have several simple example snippets for "supported" CAN libraries. I would certainly appreciate that as a new user. Thanks again for taking the time on this! |
I've been fiddling with the CAN Adafruit Fork library and have had good success in reproducing your joystick example with it. The data is just manually hand-jammed into a message (e.g. no callbacks) for now. If you haven't already started on it, maybe I'll take a stab at updating the callbacks this week. I'm getting more and more comfortable with the spec the more I look at it. |
I refactored the library files and wrote an example. The example uses the mcp_can library. I did a little bit of testing so the exec() call works and the can_write_callback() function works but I didn't test much after that. I have not pulled the code into this repo yet. It's currently available in my fork that you can find here... https://github.com/birkelbach/CAN-FIX-ArduinoLib While I was fiddling with it I realized that I was using the EEPROM library internally as well. I'd like to replace this with callback functions as well so the user has control of how this information actually gets stored instead of assuming EEPROM. Not all uCs have EEPROM. I think I'm happy with this idea. The user required interface code is pretty minimal and should be pretty easy for users to figure out, even if we don't offer examples for all of them. As always, comments are welcome. I may fiddle with it some more later. |
Dan, I sent you a PM on the MakerPlane forum. Send me an email and we can coordinate on working on this library. I'd love the help. |
Good day @birkelbach 🙂 |
There is an example in the library that reads a joystick and sends pitch and roll. |
The |
Thank you @birkelbach 🙂
Probably these CAN-FIX-ArduinoLib/examples/joystick.ino Line 43 in afcc983
and CAN-FIX-ArduinoLib/examples/joystick.ino Line 60 in afcc983
I have a pressure sensor, the data from which I receive using the MCU esp32 and output data to the serial port.I want to output data from the esp32 using the example code:
If I transfer the altitude data, which is calculated based on the pressure from the sensor, from the serial port of the microcontroller to the serial port of will this altitude be displayed in the program or do I need to take other steps? |
CAN-FIX is not serial port based. It is CAN Bus. The CAN-FIX specification is at https://github.com/makerplane/canfix-spec. The CAN Bus Specification is referenced in that document. You will need an adapter of some kind to convert CAN Bus into something your PC/Raspberry Pi can read. You can download a pre-built PDF of the specification from my Dropbox. https://www.dropbox.com/scl/fi/7w9okdmhin1vlvqqfij5p/CANFiX-Draft.pdf?rlkey=18md51ulzohrmfk2dm8pkrogu&st=614cpt0m&dl=0 Also, to answer your question. PyEFIS only talks to FiXGateway. FiXGateway is a data aggregator/translator. It has plug-ins that talk to the different types of external devices (serial, CAN, BT, Ethernet, etc), simulators or other software, the keyboard etc. The idea here is that someone may want to develop their own EFIS software. With FiXGateway they don't have to worry about all these other devices / software, and they can just use the interface to FiXGateway. If you can talk to FiXGateway, then you can talk to all the devices that FiXGateway can talk to. If you want to do serial port based communication to FiXGateway then you'd have to figure out how to talk to one of the plugins in FiXGateway or develop your own plugin that talks to your device. This library will not help you do that. |
Yes, I understand that, but in fact, it is not the
I understand this concept too, so I came up with this diagram of the device: The scheme is as follows:
and outputs data (roll, pitch, yaw) to the
I wrote a code example based on these examples:
The physical
Directly example code, but I'm not sure if it works correctly.
Using a
@birkelbach, could you please suggest a correct code example so that I can implement the transmission of orientation angles in FIX-Gateway?🙂 |
I've had better luck using signed longs for my pitch values, but you can probably use signed INT values too. I think your issue is that you're saying your ENTIRE message is only 2 bytes long thinking that you're only specifying the length of the data bytes. Here's a code snippet from a working test message I wrote a while ago for pitch:
Serial.print("pitch: "); Serial.println(pitch); // write the pitch to the console so you can see it in your Arduino IDE Notice I'm setting the length of the CFParameter to 7 (not 2). You need to account for all of the 7 bytes in your CAN message (including the type, the index, the fcb, and the data). I use a signed long (4 bytes) for my pitch values. You should be able to use a signed INT (2 bytes) as well, but in that case, your parameter length value will be 5 instead of 7. Here's my full demo code repository: https://github.com/danderflieger/mcd_can_simple_demo/ I'm using this board (which has an arduino and an MCP2515 on a single board): Here's a YouTube video I made where that board is in use running part of the demo code I mentioned above. In that case, I turned off the sendPitch boolean and captured the pitch data from an AHRS chip: Hopefully that's helpful. Dan |
Thanks @danderflieger for your help🙂
is this an arbitrary numbering of a specific device on the can-fix bus? Also, please tell me, array
Created to create a simulation of And the last question - I have seen it in examples before and in your code I saw the purpose of the pin Perhaps this is in case of using the functionality of this board? But nowhere in the code is an interrupt ever used, do you not see any advantages in bus performance when using interrupts? |
I've changed your code a bit so that building for the platform won't cause compiler warnings - these are minor changes to the sizes and types of variables. The same message is output to the The message ends with I uncommented this code and received the height value in the serial port, i.e. the parameters change, but for some reason they do not enter the
Changed the flag to
Uploaded the firmware and got a completely different
After pressing I feel like I'm missing some important information. Added code here:
|
Good morning @danderflieger Reduced the amount of code to send only one parameter - Now in the But the data does not change on the
|
Ok, it looks like you're getting close. I'm not sure what microcontroller you are using. The data types might differ from what I was using. The standard Arduino Nano requires 4 bytes for a signed long type. Maybe int32_t is interpreted differently?? Or maybe your chip is using different significant bits on your microcontroller??? Perhaps you need to shift the data bits the other direction??? I really don't know - just mentioning things that I might look into next. |
I use Tried specifying different variable types, the result is the same.
|
Here's a working version. Make sure you grab Phil's latest version of the CAN-FIX-ArduinoLib library: This code is making my pyEFIS's airspeed tape increase and decrease between 5kt and 150kt. The messages are sent every 100ms: Since you can already see CAN messages, you probably have that part correct. But you may want to verify that your CAN module is using the correct clock speed. I've used the modules you included in your diagram and they can have either a 8Mhz or a 16Mhz crystal, so make sure you start the module with the correct one or you will get very incorrect data. E.g. in the setup() function, change MCP_16MHZ to MCP_8MHZ if you have the 8Mhz crystal on your CAN module.
|
Thanks @danderflieger again for helping me clarify some of the complexities with the code.
I downloaded the library files from your repo, they are the same, I checked both files.
As you correctly asked above, I am compiling the code for the But in theory there shouldn't be any difference at all, but nevertheless, when I compile the firmware with the example code for the
Having worked in the I can only compile code for The three warnings at the very bottom are simply that byte bitrate and byte result are not used in the code. Of other interest are warnings regarding bit shifts and the function
If I don't add
Outputs the value
And accordingly, the data on the As soon as I write it in the function like this:
Output to serial port works immediately. I repeat that I am describing this oddity just like that, I do not plan to use I have another question for @danderflieger. Does this example accept data sent to the
Organize like here, through a loop, with a link to the data length. |
OK, so you should be good there. ================================
I have never used the STM boards, but this leads me to believe that there are architecture differences between data type definitions of an integer on the STM chip vs. the ATM chip that I'm using. Based on your warnings above, it sounds like bit shifting the integer reading beyond 16 bits is overrunning the variable, so STM probably only defines an integer value with 16 bits (00000000 00000010) rather than the long value I'm using in my code, which the ATM chips use 32 bits to describe (00000000 00000000 00000000 00000010). I don't have any STM chips to play with, so I can't say for certain either way. Just a thought. Perhaps try this instead, if you haven't already:
================================
Yes, it does receive CAN messages, but not only for CAN-FiX - it would work with ANY standard (11-bit) CAN message. All it does is receive the message and print it to the Serial monitor. You would need to interpret the message to do anything with it. For example, you could use this code on a second CAN-enabled microcontroller with a TFT screen to receive all messages from the CAN bus. Then you would ignore all messages except, for example, the Airspeed messages. If an Airspeed message arrived, you might use the data in the message to display an airspeed indicator with a moving needle on your TFT screen. But you would need to write the code to either ignore or do something with each CAN message that arrived on the bus. By the way, I've done a little testing with this board from Adafruit that has an onboard CAN transceiver and a Cortex M4 microcontroller: Adafruit doesn't have any in stock, but DigiKey has 249 of them today: There are good code samples on the Adafruit website, which includes an example of writing CAN messages from one to another that receives the messages: That board uses a fairly different CAN library, though, so you'd need to change pretty much all of the CAN processing code. |
Yes, I tried that too, but the result is the same - messages on the
for physical transmission of
It seems to me that the problem of unstable operation of
If you do not specify |
Thank you @danderflieger for your efforts, but since you don't have an
New
But both codes work +/- the same.
The serial port data goes as expected.
There's complete nonsense with the can, the first frame sends 15 and that's it, then it freezes in all frames. I read somewhere that the |
Right now we are using our own MCP2515 CAN driver. There are other Arduino CAN libraries out there that would also give us the ability to use internal CAN hardware for Arduinos that have those (i.e. ESP32 or STM32) or other external controller chips if someone has done that. Also this would keep us from having to maintain that code base.
The text was updated successfully, but these errors were encountered: