├── library.properties ├── NMEA2000_SocketCAN.h ├── README.md ├── NMEA2000_SocketCAN.cpp └── Raspberry-Pi-CAN.md /library.properties: -------------------------------------------------------------------------------- 1 | name=NMEA2000_socketCAN 2 | version=1.0.0 3 | author=Al Thomason 4 | maintainer=Al Thomason 5 | sentence=NMEA2000 library driver for socketCAN (e.g., Linux, RPi) 6 | paragraph=Tested primarly on RPi-3 7 | category=Communication 8 | url=https://github.com/thomasonw/NMEA2000_socketCAN 9 | architectures=linux 10 | -------------------------------------------------------------------------------- /NMEA2000_SocketCAN.h: -------------------------------------------------------------------------------- 1 | /* 2 | NMEA2000_socketCAN.h 3 | 4 | 2017 Copyright (c) Al Thomason All rights reserved 5 | 6 | Support the socketCAN access (ala, Linux, RPi) 7 | See: https://github.com/thomasonw/NMEA2000_socketCAN 8 | https://github.com/ttlappalainen/NMEA2000 9 | 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of 12 | this software and associated documentation files (the "Software"), to deal in 13 | the Software without restriction, including without limitation the rights to use, 14 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 15 | Software, and to permit persons to whom the Software is furnished to do so, 16 | subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 23 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 24 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 26 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 27 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | 30 | Inherited NMEA2000 object for socketCAN setup. See also NMEA2000 library. 31 | */ 32 | 33 | 34 | 35 | #ifndef NMEA2000_SOCKETCAN_H_ 36 | #define NMEA2000_SOCKETCAN_H_ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | using namespace std; 43 | 44 | 45 | 46 | 47 | //----------------------------------------------------------------------------- 48 | class tNMEA2000_SocketCAN : public tNMEA2000 49 | { 50 | protected: 51 | bool CANSendFrame(unsigned long id, unsigned char len, const unsigned char *buf, bool wait_sent); 52 | bool CANOpen(); 53 | bool CANGetFrame(unsigned long &id, unsigned char &len, unsigned char *buf); 54 | 55 | int skt; 56 | char* _CANport; 57 | 58 | 59 | public: 60 | tNMEA2000_SocketCAN(char* CANport=NULL); 61 | void SetCANport(char *CANport=NULL); // If used, must be called before CANOpen() 62 | 63 | }; 64 | 65 | 66 | 67 | //----------------------------------------------------------------------------- 68 | class tSocketStream : public N2kStream { 69 | protected: 70 | int port; 71 | public: 72 | tSocketStream(const char *_port=0); 73 | virtual ~tSocketStream(); 74 | int read(); 75 | size_t write(const uint8_t* data, size_t size); 76 | }; 77 | 78 | 79 | void delay(uint32_t ms); 80 | uint32_t millis(void); 81 | 82 | #endif /* NMEA2000_SOCKETCAN_H */ 83 | 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NMEA2000_socketCAN 2 | 3 | This library provides support for linux socketCAN environments - including the RPi. It allows access to the [NMEA2000](https://github.com/ttlappalainen/NMEA2000) library using socketCAN Linux CAN devices. 4 | 5 | See https://github.com/thomasonw/NMEA2000_socketCAN 6 | 7 | Though any socketCAN implementation should work, testing is primarily on: 8 | - Raspberry Pi 3 9 | - PiCAN2 - Duo 10 | 11 |

12 | 13 | 14 | 15 | ## Usage 16 | 17 | This library is in support of ttlappalainen's NMEA2000 library. See the [NMEA2000](https://github.com/ttlappalainen/NMEA2000) for more examples. Include this library in your build files. 18 | Here is a very simple example on RPi: 19 | 20 | 21 | ``` 22 | /* 23 | * File: main.cpp 24 | * Author: al 25 | * 26 | * Testing for CAN and RPI 27 | * 28 | * See: https://github.com/thomasonw/NMEA2000_socketCAN 29 | * 30 | * Created on February 12, 2017, 2:37 PM 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include "NMEA2000_CAN.h" 37 | 38 | using namespace std; 39 | 40 | int main(void) 41 | { 42 | cout << "Starting CAN watching" << endl; 43 | 44 | setvbuf (stdout, NULL, _IONBF, 0); // No buffering on stdout, just send chars as they come. 45 | 46 | NMEA2000.SetForwardStream(&serStream); // Connect bridge function for streaming output. 47 | NMEA2000.SetForwardType(tNMEA2000::fwdt_Text); // Show in clear text (for now) 48 | 49 | if (!NMEA2000.Open()) { 50 | cout << "Failed to open CAN port" << endl; 51 | return 1; 52 | } 53 | 54 | cout << endl << "CAN started, going to watch it now" << endl; 55 | 56 | while(1) { 57 | NMEA2000.ParseMessages(); // Will send out CAN messages in open text 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | ``` 64 | 65 | 66 |

67 | ## Selecting CAN stream source 68 | 69 | Linux streams allows a wide variety of sources to be selected for the CAN. Typically `can0` or `can1` for hardware CAN ports, but also virtual ports and even captured log files. NMEA2000_soceketCAN defaults to connecting to `can0`. Other ports may be selected through the passing of initialization parameters. The following two code snippets shows how the stream source may be selected either statically at compile time, or dynamically during runtime. 70 | 71 | 72 | #### Static (Compile time) socket name example: 73 | 74 | ``` 75 | /* 76 | * Example of static CAN port selection 77 | */ 78 | 79 | #include 80 | #include 81 | #include 82 | 83 | #define SOCKET_CAN_PORT "can1" //Compile-time selection of CAN1 socket name. Place this BEFORE #include NMEA2000_CAN.h 84 | #include "NMEA2000_CAN.h" 85 | 86 | using namespace std; 87 | 88 | int main(void) 89 | { 90 | 91 | . . . . . . . . . . . 92 | 93 | 94 | ``` 95 | 96 |

97 | 98 | #### Dynamic (run-time) socket name example: 99 | 100 | ``` 101 | /* 102 | * Example of Dynamic CAN port selection 103 | */ 104 | 105 | #include 106 | #include 107 | #include 108 | 109 | char socketName[50]; 110 | #define SOCKET_CAN_PORT socketName 111 | #include "NMEA2000_CAN.h" 112 | 113 | using namespace std; 114 | 115 | int main(void) 116 | { 117 | 118 | 119 | . . . . . . . . . . 120 | 121 | 122 | 123 | strcpy(socketName,"can1"); // Populate string 'socketName' BEFORE calling NMEA2000.Open(); 124 | if (!NMEA2000.Open()) { 125 | cout << "Failed to open CAN port: " << socketName << endl; 126 | return 1; 127 | } 128 | 129 | 130 | 131 | 132 | . . . . . . . . . . . 133 | 134 | 135 | ``` 136 | 137 | 138 | 139 |

140 | ## Dependencies 141 | socketCAN must be installed and working on your system - refer to the adapters users guide. And make sure to 'start up' the CAN port, example: 142 | ``` 143 | $ sudo /sbin/ip link set can0 up type can bitrate 250000 144 | ``` 145 | 146 | You can test out your socketCAN install by doing the following (Skip the install if the tools are already present) 147 | 148 | ``` 149 | # Skip this step if can-utils are already installed 150 | $ sudo apt-get install can-utils 151 | 152 | 153 | $ candump can0 154 | can0 19FFFD80 [8] 01 78 0D 01 AB 91 35 77 155 | can0 19FFFC80 [7] 01 78 FF 7F FF FF FF 156 | can0 19FEC880 [8] 01 78 B0 34 00 00 FF FF 157 | can0 19FFFD80 [8] 01 78 0D 01 B2 8E 35 77 158 | can0 19FFFC80 [7] 01 78 FF 7F FF FF FF 159 | can0 19FEC880 [8] 01 78 B6 34 00 00 FF FF 160 | can0 19F21280 [8] 00 09 49 01 00 FF FF FF 161 | can0 19F21280 [8] 01 FF FF FF 00 00 00 00 162 | can0 19F21480 [8] 01 46 05 F9 FF 00 00 49 163 | can0 19F21980 [8] 01 D0 01 DC 05 00 FF 00 164 | can0 19FFFD80 [8] 01 78 0E 01 5D 93 35 77 165 | can0 19FFFC80 [7] 01 78 FF 7F FF FF FF 166 | can0 19FEC880 [8] 01 78 BE 34 00 00 FF FF 167 | can0 19FFFD80 [8] 01 78 0E 01 73 8A 35 77 168 | can0 19FFFC80 [7] 01 78 FF 7F FF FF FF 169 | can0 19FEC880 [8] 01 78 BE 34 00 00 FF FF 170 | 171 | ``` 172 |

173 | 174 | 175 | ## Hardware 176 | 177 | Any hardware which enabled socketCAN's should work. Refer to hardware user’s guide for installation 178 | -------------------------------------------------------------------------------- /NMEA2000_SocketCAN.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | NMEA2000_SocketCAN.cpp 4 | 5 | 2017 Copyright (c) Al Thomason All rights reserved 6 | 7 | Support the socketCAN access (ala, Linux, RPi) 8 | See: https://github.com/thomasonw/NMEA2000_socketCAN 9 | https://github.com/ttlappalainen/NMEA2000 10 | 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of 13 | this software and associated documentation files (the "Software"), to deal in 14 | the Software without restriction, including without limitation the rights to use, 15 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 16 | Software, and to permit persons to whom the Software is furnished to do so, 17 | subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 24 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 25 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 26 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 27 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 28 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | Inherited NMEA2000 object for socketCAN 31 | See also NMEA2000 library. 32 | */ 33 | 34 | 35 | #include "NMEA2000_SocketCAN.h" 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | //***************************************************************************** 50 | // Pass in pointer to character array which contains (or will contain) the 51 | // string of the CANsocket to use in :open(). If no paramater is passed in, 52 | // or NULL is passed in, the defalt socket 'can0' will be used 53 | tNMEA2000_SocketCAN::tNMEA2000_SocketCAN(char* CANport) : tNMEA2000() 54 | { 55 | static char defaultCANport[] = "can0"; 56 | 57 | if (CANport != NULL) 58 | _CANport = CANport; 59 | else 60 | _CANport = defaultCANport; // NULL passed in, set to port to default: CAN0 61 | 62 | } 63 | 64 | 65 | 66 | //***************************************************************************** 67 | void tNMEA2000_SocketCAN::SetCANport(char *CANport) { 68 | if (CANport != NULL) 69 | _CANport = CANport; 70 | } 71 | 72 | 73 | 74 | //***************************************************************************** 75 | bool tNMEA2000_SocketCAN::CANOpen() { 76 | struct ifreq ifr; 77 | struct sockaddr_can addr; 78 | int flags; 79 | 80 | //---- Open a socket to the CAN port 81 | skt = socket(PF_CAN, SOCK_RAW, CAN_RAW); 82 | if(skt < 0) { 83 | cerr << "Failed open CAN socket: " << _CANport << endl; 84 | return (false); 85 | } 86 | 87 | strncpy(ifr.ifr_name, _CANport, (sizeof(ifr.ifr_name)-1)); 88 | ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0'; // (And make sure to null terminate) 89 | 90 | if (ioctl(skt, SIOCGIFINDEX, &ifr) < 0) { 91 | cerr << "Failed CAN ioctl: " << ifr.ifr_name << endl; 92 | return (false); 93 | } 94 | 95 | addr.can_family = AF_CAN; 96 | addr.can_ifindex = ifr.ifr_ifindex; 97 | if (bind(skt, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 98 | cerr << "Failed CAN bind" << endl; 99 | return (false); 100 | } 101 | 102 | 103 | //----- Set socket for non-blocking 104 | flags = fcntl(skt, F_GETFL, 0); 105 | if (flags < 0) { 106 | cerr << "Failed CAN flag fetch" << endl; 107 | return (false); 108 | } 109 | 110 | if (fcntl(skt, F_SETFL, flags | O_NONBLOCK) < 0) { 111 | cerr << "Failed CAN flag set" << endl; 112 | return (false); 113 | } 114 | 115 | return true; 116 | } 117 | 118 | 119 | //***************************************************************************** 120 | bool tNMEA2000_SocketCAN::CANSendFrame(unsigned long id, unsigned char len, const unsigned char *buf, bool wait_sent) { 121 | struct can_frame frame_wr; 122 | 123 | frame_wr.can_id = id | CAN_EFF_FLAG; 124 | frame_wr.can_dlc = len; 125 | memcpy(frame_wr.data, buf, 8); 126 | 127 | return (write(skt, &frame_wr, sizeof(frame_wr)) == sizeof(frame_wr)); // Send this frame out to the socketCAN handler 128 | 129 | // socketCAN works to keeping all packets in-order, so 130 | // no need to do anything special for wait-sent 131 | } 132 | 133 | 134 | //***************************************************************************** 135 | bool tNMEA2000_SocketCAN::CANGetFrame(unsigned long &id, unsigned char &len, unsigned char *buf) { 136 | struct can_frame frame_rd; 137 | struct timeval tv = {0, 0}; // Non-blocking timout when checking 138 | fd_set fds; 139 | 140 | FD_ZERO(&fds); 141 | FD_SET(skt, &fds); 142 | 143 | if (select((skt + 1), &fds, NULL, NULL, &tv) < 0) // Is there a FD with something to read out there? 144 | return false; 145 | 146 | if (FD_ISSET(skt, &fds)) { // Was it our CAN file-descriptor that is ready? 147 | if (read(skt, &frame_rd, sizeof(frame_rd)) > 0) { 148 | memcpy(buf, frame_rd.data, 8); 149 | len = frame_rd.can_dlc; 150 | id = frame_rd.can_id; 151 | return true; 152 | } 153 | } 154 | return false; 155 | 156 | } 157 | 158 | 159 | //***************************************************************************** 160 | tSocketStream::tSocketStream(const char *_port) : port(-1) { 161 | if ( _port!=0 ) { 162 | port=open(_port, O_RDWR | O_NOCTTY | O_NDELAY); 163 | } 164 | 165 | if ( port!=-1 ) { 166 | cout << _port << " opened" << endl; 167 | } else { 168 | if ( _port!=0 ) cerr << "Failed to open port " << _port << ". Using stdout"<< endl; 169 | } 170 | } 171 | 172 | //***************************************************************************** 173 | tSocketStream::~tSocketStream() { 174 | if ( port!=-1 ) { 175 | close(port); 176 | } 177 | } 178 | 179 | 180 | /******************************************************************** 181 | * Other 'Bridge' functions and classes 182 | * 183 | * 184 | * 185 | **********************************************************************/ 186 | int tSocketStream::read() { 187 | if ( port!=-1 ) { 188 | return -1; 189 | } else { 190 | // Serial stream bridge -- Returns first byte if incoming data, or -1 on no available data. 191 | struct timeval tv = { 0L, 0L }; 192 | fd_set fds; 193 | 194 | FD_ZERO(&fds); 195 | FD_SET(0, &fds); 196 | if (select(1, &fds, NULL, NULL, &tv) < 0) // Check fd=0 (stdin) to see if anything is there (timeout=0) 197 | return -1; // Nothing is waiting for us. 198 | 199 | return (getc(stdin)); // Something is there, go get one char of it. 200 | } 201 | } 202 | 203 | 204 | 205 | //***************************************************************************** 206 | size_t tSocketStream::write(const uint8_t* data, size_t size) { // Serial Stream bridge -- Write data to stream. 207 | if ( port!=-1 ) { 208 | return ::write(port,data,size); 209 | } else { 210 | size_t i; 211 | 212 | for (i=0; (i
14 | 15 | *** 16 | ###1. CAN Hardware Interface 17 | The quickest and easiest CAN hardware for the RPi is the PiCAN-2 series of devices by Spang electronics: 18 | http://skpang.co.uk/catalog/pican2-canbus-board-for-raspberry-pi-23-p-1475.html 19 | http://copperhilltech.com/pican-2-can-interface-for-raspberry-pi/ 20 | 21 | 22 | Based on the MCP2515 CAN controller chip there are several options including dual CAN controllers, and even isolated ones. Follow the installation guide for these boards to install the hardware as well as bring up the socketCAN interface on the Raspberry Pi: 23 | www.skpang.co.uk/catalog/images/raspberrypi/pi_2/PICAN2_jessie_2016-05-10.pdf 24 | www.copperhilltech.com/content/PICAN2_jessie_2016-05-10.pdf 25 | 26 |

27 | *** 28 | ==***Note on RPi verion used and other non RPi Linux system***== 29 | 30 | SocketCAN is a widely supported capability available on almost all current releases of Linux. The links provided in step #1 above are specific to the 2017 'jessey' release of Raspberry Pi software. If you are using a prior release for your RPi make sure to locate the corresponding instructions from the CAN hardware provider. 31 | 32 | Once the hardware is installed and the socketCAN enabled steps 2 & 3 are universally applied to almost all releases of RPi software. 33 | 34 | In a like way, steps 2 & 3 may also be applied to almost any Linux system - once appropriate CAN hardware has been installed and the socketCAN ability enabled. A likely approach would be through a CAN <--> USB adapter. Searching for 'CAN USB adapter socketCAN' will show several options. See below in section *'Alternative CAN hardware'* for some links. 35 | 36 | 37 |

38 | *** 39 | ###2. Configuring and starting socketCAN 40 | 41 | After following the driver installation instructions above, you can next test your CAN hardware before proceeding. The simplest way is to install Linux ```can-utils```, connect your can hardware to some other known CAN device which is broadcasting information, and then do a can dump. 42 | 43 | 'Start up' the CAN port using: 44 | ``` 45 | $ sudo /sbin/ip link set can0 up type can bitrate 250000 46 | ``` 47 |
48 | Connect up another CAN device which sends out messages and do the following on your RPi. You should see the CAN packets displayed as they come in: 49 | 50 | ``` 51 | # Skip these two steps if can-utils are already installed 52 | $ sudo apt-get update 53 | $ sudo apt-get install can-utils 54 | 55 | 56 | $ candump can0 57 | can0 19FFFD80 [8] 01 78 0D 01 AB 91 35 77 58 | can0 19FFFC80 [7] 01 78 FF 7F FF FF FF 59 | can0 19FEC880 [8] 01 78 B0 34 00 00 FF FF 60 | can0 19FFFD80 [8] 01 78 0D 01 B2 8E 35 77 61 | can0 19FFFC80 [7] 01 78 FF 7F FF FF FF 62 | can0 19FEC880 [8] 01 78 B6 34 00 00 FF FF 63 | can0 19F21280 [8] 00 09 49 01 00 FF FF FF 64 | can0 19F21280 [8] 01 FF FF FF 00 00 00 00 65 | can0 19F21480 [8] 01 46 05 F9 FF 00 00 49 66 | can0 19F21980 [8] 01 D0 01 DC 05 00 FF 00 67 | can0 19FFFD80 [8] 01 78 0E 01 5D 93 35 77 68 | can0 19FFFC80 [7] 01 78 FF 7F FF FF FF 69 | can0 19FEC880 [8] 01 78 BE 34 00 00 FF FF 70 | can0 19FFFD80 [8] 01 78 0E 01 73 8A 35 77 71 | can0 19FFFC80 [7] 01 78 FF 7F FF FF FF 72 | can0 19FEC880 [8] 01 78 BE 34 00 00 FF FF 73 | 74 | ``` 75 | 76 | This will verify the hardware and the socketCAN software is functioning correctly.   77 | Hint: place the 'Start-up' command in your `/etc/network/interfaces.d/can0` file so the CAN port will be started each time the RPi boots: 78 | 79 | ``` 80 | sudo nano /etc/network/interfaces.d/can0 81 | 82 | /*then add the following lines at the bottom: */ 83 | 84 | auto can0 85 |    iface can0 inet manual 86 |    pre-up /sbin/ip link set can0 type can bitrate 250000 triple-sampling on 87 |    up /sbin/ifconfig can0 up 88 |    down /sbin/ifconfig can0 down 89 | 90 | auto can1 91 |    iface can1 inet manual 92 |    pre-up /sbin/ip link set can1 type can bitrate 250000 triple-sampling on 93 |    up /sbin/ifconfig can1 up 94 |    down /sbin/ifconfig can1 down 95 | ``` 96 | 97 | (Only add "auto can1" section if you have a dual-port CAN adapter). 98 | 99 | Note for dual port Pican2 cards: The code refers to the can ports as "can0" and "can1", however, the Pican2 card has ports labeled "CANA" and "CANB". If you are using can0, your cable/wiring should go to Pican2 "CANB" connector. if you are using can1, your cable/wiring should go to Pican2 "CANA" connector. 100 | 101 | Remember to properly terminate the can bus with two 120 ohm resistors (one on each end of the bus). The Pican boards have onboard termination. PCB Universal Screw Terminals (with jumper wire) or headers (with jumpers) can be soldered onto the Pican2 board to use onboard termination. 102 | 103 | 104 |

105 | *** 106 | ###3. Using the NMEA2000 library 107 | 108 | Once you have verified the hardware and socketCAN is functioning import the following two libraries into your development environment**: 109 | 110 | https://github.com/ttlappalainen/NMEA2000 111 | https://github.com/thomasonw/NMEA2000_socketCAN 112 | 113 | Then use the built-in examples to test your new CAN enabled Raspberry Pi - or the following simple program to emulate ```canDump``` above: 114 | 115 | 116 | 117 | ``` 118 | /* 119 | * File: main.cpp 120 | * Author: al 121 | * 122 | * Testing for CAN and RPI 123 | * 124 | * See: https://github.com/thomasonw/NMEA2000_socketCAN 125 | * 126 | * Created on February 12, 2017, 2:37 PM 127 | */ 128 | 129 | #include 130 | #include 131 | #include 132 | #include "NMEA2000_CAN.h" 133 | 134 | using namespace std; 135 | 136 | int main(void) 137 | { 138 | cout << "Starting CAN watching" << endl; 139 | 140 | setvbuf (stdout, NULL, _IONBF, 0); // No buffering on stdout, just send chars as they come. 141 | 142 | NMEA2000.SetForwardStream(&serStream); // Connect bridge function for streaming output. 143 | NMEA2000.SetForwardType(tNMEA2000::fwdt_Text); // Show in clear text (for now) 144 | 145 | if (!NMEA2000.Open()) { // Defaults to port can0, see ref for how to use other ports 146 | cout << "Failed to open CAN0 port" << endl; 147 | return 1; 148 | } 149 | 150 | cout << endl << "CAN started, going to watch it now" << endl; 151 | 152 | while(1) { 153 | NMEA2000.ParseMessages(); // Will send out CAN messages in open text 154 | } 155 | 156 | return 0; 157 | } 158 | 159 | 160 | 161 | ``` 162 | If everything is working well, you should see an output like this: 163 | ``` 164 | Starting CAN watching 165 | CAN device ready 166 | 167 | CAN started, going to watch it now 168 | Pri:6 PGN:131069 Source:128 Dest:255 Len:8 Data:1,78,c,1,ab,91,35,77 169 | Pri:6 PGN:131068 Source:128 Dest:255 Len:7 Data:1,78,ff,7f,ff,ff,ff 170 | Pri:6 PGN:130760 Source:128 Dest:255 Len:8 Data:1,78,60,34,0,0,ff,ff 171 | Pri:6 PGN:127506 Source:128 Dest:255 Len:9 Data:e8,1,0,ff,ff,ff,ff,ff,ff 172 | Pri:6 PGN:127508 Source:128 Dest:255 Len:8 Data:1,3d,5,3,0,0,0,e8 173 | Pri:6 PGN:127513 Source:128 Dest:255 Len:8 Data:1,d0,1,dc,5,0,ff,0 174 | Pri:6 PGN:131069 Source:128 Dest:255 Len:8 Data:1,78,c,1,dd,8f,35,77 175 | Pri:6 PGN:131068 Source:128 Dest:255 Len:7 Data:1,78,ff,7f,ff,ff,ff 176 | Pri:6 PGN:130760 Source:128 Dest:255 Len:8 Data:1,78,60,34,0,0,ff,ff 177 | Pri:6 PGN:131069 Source:128 Dest:255 Len:8 Data:1,78,c,1,59,91,35,77 178 | Pri:6 PGN:131068 Source:128 Dest:255 Len:7 Data:1,78,ff,7f,ff,ff,ff 179 | Pri:6 PGN:130760 Source:128 Dest:255 Len:8 Data:1,78,61,34,0,0,ff,ff 180 | Pri:6 PGN:127506 Source:128 Dest:255 Len:9 Data:e9,1,0,ff,ff,ff,ff,ff,ff 181 | Pri:6 PGN:127508 Source:128 Dest:255 Len:8 Data:1,3d,5,f3,ff,0,0,e9 182 | Pri:6 PGN:127513 Source:128 Dest:255 Len:8 Data:1,d0,1,dc,5,0,ff,0 183 | . . . 184 | ``` 185 | 186 | ** Note: I use the NetBeans IDE -- using the remote SSH attachment to my RPi. Details here: 187 | http://www.raspberry-projects.com/pi/programming-in-c/compilers-and-ides/netbeans-windows/installing-netbeans-for-c-remote-development-on-a-raspberry-pi 188 | (Make sure to install and enable SSH services on your RPi before trying to use it!) 189 | 190 |


191 | *** 192 |

193 | 194 | #Alternative CAN hardware 195 | 196 | In addition to the PiCAN-2 devices, one could use any CAN adapter which includes soketCAN support. An overview of those can be found here: 197 | http://elinux.org/CAN_Bus#SocketCAN_Supported_Controllers 198 | 199 | 200 | 201 | 202 | 203 | USB-CAN adapters are available, some for less than $20us. You will need to verify if they support socketCAN. Some examples which do include: 204 | http://canable.io/ 205 | https://github.com/kahiroka/slcanuino 206 | http://www.fischl.de/usbtin/ 207 | 208 | These would also be a likely choice for non PRi Linux systems. Install the USB <--> CAN adapter, socektCAN and then proceed to steps #2 and 3 above. 209 | 210 |


211 | 212 | 213 | Another option is to use one of the widely available MCP2515 + MCP2562 adapter boards, often for around $2. But those come with one caution: The Raspberry Pi board is a 3.3v device, while the CAN bus specifics 5v levels. This is most easily solved by utilizing the MPC2562's separate IO and DRV supply pins, as shown here: 214 | 215 | ![ref: http://lnxpps.de/rpie/](http://lnxpps.de/rpie/RPi-MCP2515_new.png "3.3v/5v CAN adapter") 216 | (design reference: http://lnxpps.de/rpie/ ) 217 | 218 | Locating an adapter board which allows independent voltages is not simple. If you are careful one could modify a common PCB to isolate pin #3 on the MCP2562. Read more here: 219 | https://www.raspberrypi.org/forums/viewtopic.php?f=44&t=141052 220 | http://lnxpps.de/rpie/ 221 | 222 | 223 | Here is one board at a resonable cost with seperate IO and DRV supply pins: http://modtronix.com/im1can.html 224 | 225 |

226 | *** 227 |
228 | ^(Original of this document may be found here: https://github.com/thomasonw/NMEA2000_socketCAN/blob/master/Raspberry-Pi-CAN.md )^ 229 | --------------------------------------------------------------------------------