0
Offline
Jr. Member
Karma: 0
Posts: 91
Arduino rocks
|
 |
« on: November 08, 2010, 12:54:35 am » |
Well, here's my first *complete* project for the Arduino. (Never really complete, are they.)  Now I understand that there are a few CAN implementations out there, but the more the merrier, right?  This one uses the MCP2515/MCP2551 chips like most of them do. It has a switchable CS pin so that you can use other SPI shields with it that might have hardwired D10 as CS. It has a switch to draw power from the CAN Bus if desired, if you wanted to add a WiFi or Bluetooth shield for example. And for newbies like me it's an entirely through hole design making it an easy DIY project.  I've also written a library that's a complete implementation of the MCP2515 SPI command set. It doesn't yet have any wrappers for filters or masks, but these are all accessible through the read and write commands. I have a simple Init function that takes a bus speed and clock frequency and calculates out all the necessary bit timing parameters, which makes it pretty straightforward to setup and use. Now all I need is something to connect it to ......  (I actually have a need for this in another project that has been temporarily sidelined.)
|
|
|
|
|
Logged
|
|
|
|
|
Melbourne, Australia
Offline
Full Member
Karma: 0
Posts: 226
Cyborg-in-progress
|
 |
« Reply #1 on: November 08, 2010, 11:50:49 pm » |
Now all I need is something to connect it to You didn't mention if you're wanting to use this for an automotive project, but if you are then something that might be useful for development is a mOByDic 1610: http://www.ozenelektronik.com/?s=products2&group=eobd-obdii-ecu-simulatorsDeveloping against an ECU is no fun if you have to sit in the garage with your laptop while you're coding! I've spent way too long out in the driveway with a lappie and a long extension cable. Much nicer to be able to sit at your bench and twiddle the knobs to simulate different behavior. -- Jon Vehicle Telemetry Platform: www.practicalarduino.com/projects/vehicle-telemetry-platform
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 91
Arduino rocks
|
 |
« Reply #2 on: November 08, 2010, 11:59:09 pm » |
It's actually going to be used to interface to an Electric Vehicle controller, so no OBD-II needed. Of course, it's a proprietry system that I've got to hack, so we'll see how that goes. :  Should be fun though. 
|
|
|
|
« Last Edit: November 08, 2010, 11:59:43 pm by DaveAK »
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 91
Arduino rocks
|
 |
« Reply #3 on: December 09, 2010, 11:43:51 pm » |
Here's the library code: MCP2515.h /* MCP2515.h - Library for Microchip MCP2515 CAN Controller Author: David Harding Created: 11/08/2010 For further information see: http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf http://en.wikipedia.org/wiki/CAN_bus */
#ifndef MCP2515_h #define MCP2515_h
#include "WProgram.h" #include "MCP2515_defs.h"
class MCP2515 { public: // Constructor defining which pins to use for CS and INT MCP2515(byte CS_Pin, byte INT_Pin); // Overloaded initialization function int Init(int baud, byte freq); int Init(int baud, byte freq, byte sjw); // Basic MCP2515 SPI Command Set void Reset(); byte Read(byte address); void Read(byte address, byte data[], byte bytes); Frame ReadBuffer(byte buffer); void Write(byte address, byte data); void Write(byte address, byte data[], byte bytes); void LoadBuffer(byte buffer, Frame message); void SendBuffer(byte buffers); byte Status(); byte RXStatus(); void BitModify(byte address, byte mask, byte data);
// Extra functions bool Interrupt(); // Expose state of INT pin bool Mode(byte mode); // Returns TRUE if mode change successful private: bool _init(int baud, byte freq, byte sjw, bool autoBaud); // Pin variables byte _CS; byte _INT; };
#endif MCP2515_defs.h /* MCP2515_defs.h - Library for Microchip MCP2515 CAN Controller Author: David Harding Created: 11/08/2010 For further information see: http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf http://en.wikipedia.org/wiki/CAN_bus */
#ifndef MCP2515_defs_h #define MCP2515_defs_h
#include "WProgram.h"
typedef struct { unsigned long id; // EID if ide set, SID otherwise byte srr; // Standard Frame Remote Transmit Request byte rtr; // Remote Transmission Request byte ide; // Extended ID flag byte dlc; // Number of data bytes byte data[8]; // Data bytes } Frame;
// MCP2515 SPI Commands #define CAN_RESET 0xC0 #define CAN_READ 0x03 #define CAN_WRITE 0x02 #define CAN_RTS 0x80 #define CAN_STATUS 0xA0 #define CAN_BIT_MODIFY 0x05 #define CAN_RX_STATUS 0xB0 #define CAN_READ_BUFFER 0x90 #define CAN_LOAD_BUFFER 0X40
// Register Bit Masks // CANSTAT #define MODE_CONFIG 0x80 #define MODE_LISTEN 0x60 #define MODE_LOOPBACK 0x40 #define MODE_SLEEP 0x20 #define MODE_NORMAL 0x00 // CANINTF #define RX0IF 0x01 #define RX1IF 0x02 #define TX0IF 0x04 #define TX1IF 0x08 #define TX2IF 0x10 #define ERRIF 0x20 #define WAKIF 0x40 #define MERRF 0x80
// Configuration Registers #define CANSTAT 0x0E #define CANCTRL 0x0F #define BFPCTRL 0x0C #define TEC 0x1C #define REC 0x1D #define CNF3 0x28 #define CNF2 0x29 #define CNF1 0x2A #define CANINTE 0x2B #define CANINTF 0x2C #define EFLG 0x2D #define TXRTSCTRL 0x0D
// TX Buffer 0 #define TXB0CTRL 0x30 #define TXB0SIDH 0x31 #define TXB0SIDL 0x32 #define TXB0EID8 0x33 #define TXB0EID0 0x34 #define TXB0DLC 0x35 #define TXB0D0 0x36 #define TXB0D1 0x37 #define TXB0D2 0x38 #define TXB0D3 0x39 #define TXB0D4 0x3A #define TXB0D5 0x3B #define TXB0D6 0x3C #define TXB0D7 0x3D // TX Buffer 1 #define TXB1CTRL 0x40 #define TXB1SIDH 0x41 #define TXB1SIDL 0x42 #define TXB1EID8 0x43 #define TXB1EID0 0x44 #define TXB1DLC 0x45 #define TXB1D0 0x46 #define TXB1D1 0x47 #define TXB1D2 0x48 #define TXB1D3 0x49 #define TXB1D4 0x4A #define TXB1D5 0x4B #define TXB1D6 0x4C #define TXB1D7 0x4D
// TX Buffer 2 #define TXB2CTRL 0x50 #define TXB2SIDH 0x51 #define TXB2SIDL 0x52 #define TXB2EID8 0x53 #define TXB2EID0 0x54 #define TXB2DLC 0x55 #define TXB2D0 0x56 #define TXB2D1 0x57 #define TXB2D2 0x58 #define TXB2D3 0x59 #define TXB2D4 0x5A #define TXB2D5 0x5B #define TXB2D6 0x5C #define TXB2D7 0x5D // RX Buffer 0 #define RXB0CTRL 0x60 #define RXB0SIDH 0x61 #define RXB0SIDL 0x62 #define RXB0EID8 0x63 #define RXB0EID0 0x64 #define RXB0DLC 0x65 #define RXB0D0 0x66 #define RXB0D1 0x67 #define RXB0D2 0x68 #define RXB0D3 0x69 #define RXB0D4 0x6A #define RXB0D5 0x6B #define RXB0D6 0x6C #define RXB0D7 0x6D // RX Buffer 1 #define RXB1CTRL 0x70 #define RXB1SIDH 0x71 #define RXB1SIDL 0x72 #define RXB1EID8 0x73 #define RXB1EID0 0x74 #define RXB1DLC 0x75 #define RXB1D0 0x76 #define RXB1D1 0x77 #define RXB1D2 0x78 #define RXB1D3 0x79 #define RXB1D4 0x7A #define RXB1D5 0x7B #define RXB1D6 0x7C #define RXB1D7 0x7D
// Buffer Bit Masks #define RXB0 0x00 #define RXB1 0x02 #define TXB0 0x01 #define TXB1 0x02 #define TXB2 0x04 #define TXB_ALL TXB0 | TXB1 | TXB2
#endif Continued next post ...
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 91
Arduino rocks
|
 |
« Reply #4 on: December 09, 2010, 11:44:33 pm » |
MCP2515.cpp /* MCP2515.cpp - Library for Microchip MCP2515 CAN Controller Author: David Harding Created: 11/08/2010 For further information see: http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf http://en.wikipedia.org/wiki/CAN_bus */
#include "WProgram.h" #include "SPI.h" #include "MCP2515.h" #include "MCP2515_defs.h"
MCP2515::MCP2515(byte CS_Pin, byte INT_Pin) { pinMode(CS_Pin, OUTPUT); digitalWrite(CS_Pin,HIGH);
pinMode(INT_Pin,INPUT); digitalWrite(INT_Pin,HIGH); _CS = CS_Pin; _INT = INT_Pin; }
/* Initialize MCP2515 int CAN_Bus_Speed = transfer speed in kbps int Freq = MCP2515 oscillator frequency in MHz int SJW = Synchronization Jump Width Length bits - 1 to 4 (see data sheet) returns baud rate set Sending a bus speed of 0 kbps initiates AutoBaud and returns zero if no baud rate could be determined. There must be two other active nodes on the bus! */ int MCP2515::Init(int CAN_Bus_Speed, byte Freq) { if(CAN_Bus_Speed>0) { if(_init(CAN_Bus_Speed, Freq, 1, false)) return CAN_Bus_Speed; } else { int i=0; byte interruptFlags = 0; for(i=5; i<1000; i=i+5) { if(_init(i, Freq, 1, true)) { // check for bus activity Write(CANINTF,0); delay(500); // need the bus to be communicating within this time frame if(Interrupt()) { // determine which interrupt flags have been set interruptFlags = Read(CANINTF); if(!(interruptFlags & MERRF)) { // to get here we must have received something without errors Mode(MODE_NORMAL); return i; } } } } } return 0; }
int MCP2515::Init(int CAN_Bus_Speed, byte Freq, byte SJW) { if(SJW < 1) SJW = 1; if(SJW > 4) SJW = 4; if(CAN_Bus_Speed>0) { if(_init(CAN_Bus_Speed, Freq, SJW, false)) return CAN_Bus_Speed; } else { int i=0; byte interruptFlags = 0; for(i=5; i<1000; i=i+5) { if(_init(i, Freq, SJW, true)) { // check for bus activity Write(CANINTF,0); delay(500); // need the bus to be communicating within this time frame if(Interrupt()) { // determine which interrupt flags have been set interruptFlags = Read(CANINTF); if(!(interruptFlags & MERRF)) { // to get here we must have received something without errors Mode(MODE_NORMAL); return i; } } } } } return 0; }
bool MCP2515::_init(int CAN_Bus_Speed, byte Freq, byte SJW, bool autoBaud) { // Reset MCP2515 which puts it in configuration mode Reset(); // Calculate bit timing registers byte BRP; float TQ; byte BT; float tempBT;
float NBT = 1.0 / (float)CAN_Bus_Speed * 1000.0; // Nominal Bit Time for(BRP=0;BRP<8;BRP++) { TQ = 2.0 * (float)(BRP + 1) / (float)Freq; tempBT = NBT / TQ; if(tempBT<=25) { BT = (int)tempBT; if(tempBT-BT==0) break; } } byte SPT = (0.7 * BT); // Sample point byte PRSEG = (SPT - 1) / 2; byte PHSEG1 = SPT - PRSEG - 1; byte PHSEG2 = BT - PHSEG1 - PRSEG - 1;
// Programming requirements if(PRSEG + PHSEG1 < PHSEG2) return false; if(PHSEG2 <= SJW) return false; byte BTLMODE = 1; byte SAM = 0; // Set registers byte data = (((SJW-1) << 6) | BRP); Write(CNF1, data); Write(CNF2, ((BTLMODE << 7) | (SAM << 6) | ((PHSEG1-1) << 3) | (PRSEG-1))); Write(CNF3, (B10000000 | (PHSEG2-1))); Write(TXRTSCTRL,0); if(!autoBaud) { // Return to Normal mode if(!Mode(MODE_NORMAL)) return false; } else { // Set to Listen Only mode if(!Mode(MODE_LISTEN)) return false; } // Enable all interupts Write(CANINTE,255); // Test that we can read back from the MCP2515 what we wrote to it byte rtn = Read(CNF1); return (rtn==data); }
void MCP2515::Reset() { digitalWrite(_CS,LOW); SPI.transfer(CAN_RESET); digitalWrite(_CS,HIGH); }
byte MCP2515::Read(byte address) { digitalWrite(_CS,LOW); SPI.transfer(CAN_READ); SPI.transfer(address); byte data = SPI.transfer(0x00); digitalWrite(_CS,HIGH); return data; }
void MCP2515::Read(byte address, byte data[], byte bytes) { // allows for sequential reading of registers starting at address - see data sheet byte i; digitalWrite(_CS,LOW); SPI.transfer(CAN_READ); SPI.transfer(address); for(i=0;i<bytes;i++) { data[i] = SPI.transfer(0x00); } digitalWrite(_CS,HIGH); }
Frame MCP2515::ReadBuffer(byte buffer) { // Reads an entire RX buffer. // buffer should be either RXB0 or RXB1 Frame message; digitalWrite(_CS,LOW); SPI.transfer(CAN_READ_BUFFER | (buffer<<1)); byte byte1 = SPI.transfer(0x00); // RXBnSIDH byte byte2 = SPI.transfer(0x00); // RXBnSIDL byte byte3 = SPI.transfer(0x00); // RXBnEID8 byte byte4 = SPI.transfer(0x00); // RXBnEID0 byte byte5 = SPI.transfer(0x00); // RXBnDLC
message.srr=(byte2 & B00010000); message.ide=(byte2 & B00001000);
if(message.ide) { message.id = (byte1>>3); message.id = (message.id<<8) | ((byte1<<5) | ((byte2>>5)<<2) | (byte2 & B00000011)); message.id = (message.id<<8) | byte3; message.id = (message.id<<8) | byte4; } else { message.id = ((byte1>>5)<<8) | ((byte1<<3) | (byte2>>5)); }
message.rtr=(byte5 & B01000000); message.dlc = (byte5 & B00001111); // Number of data bytes for(int i=0;i<message.dlc;i++) { message.data[i] = SPI.transfer(0x00); } digitalWrite(_CS,HIGH);
return message; }
void MCP2515::Write(byte address, byte data) { digitalWrite(_CS,LOW); SPI.transfer(CAN_WRITE); SPI.transfer(address); SPI.transfer(data); digitalWrite(_CS,HIGH); }
void MCP2515::Write(byte address, byte data[], byte bytes) { // allows for sequential writing of registers starting at address - see data sheet byte i; digitalWrite(_CS,LOW); SPI.transfer(CAN_WRITE); SPI.transfer(address); for(i=0;i<bytes;i++) { SPI.transfer(data[i]); } digitalWrite(_CS,HIGH); }
void MCP2515::SendBuffer(byte buffers) { // buffers should be any combination of TXB0, TXB1, TXB2 ORed together, or TXB_ALL digitalWrite(_CS,LOW); SPI.transfer(CAN_RTS | buffers); digitalWrite(_CS,HIGH); }
void MCP2515::LoadBuffer(byte buffer, Frame message) { // buffer should be one of TXB0, TXB1 or TXB2 if(buffer==TXB0) buffer = 0;
byte byte1=0; // TXBnSIDH byte byte2=0; // TXBnSIDL byte byte3=0; // TXBnEID8 byte byte4=0; // TXBnEID0 byte byte5=0; // TXBnDLC
if(message.ide) { byte1 = byte((message.id<<3)>>24); // 8 MSBits of SID byte2 = byte((message.id<<11)>>24) & B11100000; // 3 LSBits of SID byte2 = byte2 | byte((message.id<<14)>>30); // 2 MSBits of EID byte2 = byte2 | B00001000; // EXIDE byte3 = byte((message.id<<16)>>24); // EID Bits 15-8 byte4 = byte((message.id<<24)>>24); // EID Bits 7-0 } else { byte1 = byte((message.id<<21)>>24); // 8 MSBits of SID byte2 = byte((message.id<<29)>>24) & B11100000; // 3 LSBits of SID byte3 = 0; // TXBnEID8 byte4 = 0; // TXBnEID0 } byte5 = message.dlc; if(message.rtr) { byte5 = byte5 | B01000000; } digitalWrite(_CS,LOW); SPI.transfer(CAN_LOAD_BUFFER | buffer); SPI.transfer(byte1); SPI.transfer(byte2); SPI.transfer(byte3); SPI.transfer(byte4); SPI.transfer(byte5); for(int i=0;i<message.dlc;i++) { SPI.transfer(message.data[i]); } digitalWrite(_CS,HIGH); }
byte MCP2515::Status() { digitalWrite(_CS,LOW); SPI.transfer(CAN_STATUS); byte data = SPI.transfer(0x00); digitalWrite(_CS,HIGH); return data; /* bit 7 - CANINTF.TX2IF bit 6 - TXB2CNTRL.TXREQ bit 5 - CANINTF.TX1IF bit 4 - TXB1CNTRL.TXREQ bit 3 - CANINTF.TX0IF bit 2 - TXB0CNTRL.TXREQ bit 1 - CANINTFL.RX1IF bit 0 - CANINTF.RX0IF */ }
byte MCP2515::RXStatus() { digitalWrite(_CS,LOW); SPI.transfer(CAN_RX_STATUS); byte data = SPI.transfer(0x00); digitalWrite(_CS,HIGH); return data; /* bit 7 - CANINTF.RX1IF bit 6 - CANINTF.RX0IF bit 5 - bit 4 - RXBnSIDL.EIDE bit 3 - RXBnDLC.RTR bit 2 | 1 | 0 | Filter Match ------|---|---|------------- 0 | 0 | 0 | RXF0 0 | 0 | 1 | RXF1 0 | 1 | 0 | RXF2 0 | 1 | 1 | RXF3 1 | 0 | 0 | RXF4 1 | 0 | 1 | RXF5 1 | 1 | 0 | RXF0 (rollover to RXB1) 1 | 1 | 1 | RXF1 (rollover to RXB1) */ }
void MCP2515::BitModify(byte address, byte mask, byte data) { // see data sheet for explanation digitalWrite(_CS,LOW); SPI.transfer(CAN_BIT_MODIFY); SPI.transfer(address); SPI.transfer(mask); SPI.transfer(data); digitalWrite(_CS,HIGH); }
bool MCP2515::Interrupt() { return (digitalRead(_INT)==LOW); }
bool MCP2515::Mode(byte mode) { /* mode can be one of the following: MODE_CONFIG MODE_LISTEN MODE_LOOPBACK MODE_SLEEP MODE_NORMAL */ BitModify(CANCTRL, B11100000, mode); delay(10); // allow for any transmissions to complete byte data = Read(CANSTAT); // check mode has been set return ((data & mode)==mode); }
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 91
Arduino rocks
|
 |
« Reply #5 on: December 09, 2010, 11:47:26 pm » |
keywords.txt ####################################### # Syntax Coloring Map MCP2515 #######################################
####################################### # Datatypes (KEYWORD1) #######################################
MCP2515 KEYWORD1
####################################### # Methods and Functions (KEYWORD2) ####################################### Init KEYWORD2 Reset KEYWORD2 Read KEYWORD2 ReadBuffer KEYWORD2 Write KEYWORD2 LoadBuffer KEYWORD2 SendBuffer KEYWORD2 Status KEYWORD2 RXStatus KEYWORD2 BitModify KEYWORD2 Interrupt KEYWORD2
####################################### # Constants (LITERAL1) ####################################### CAN_RESET LITERAL1 CAN_READ LITERAL1 CAN_WRITE LITERAL1 CAN_RTS LITERAL1 CAN_STATUS LITERAL1 CAN_BIT_MODIFY LITERAL1 CAN_RX_STATUS LITERAL1 CAN_READ_BUFFER LITERAL1 CAN_LOAD_BUFFER LITERAL1
RXB0 LITERAL1 RXB1 LITERAL1 TXB0 LITERAL1 TXB1 LITERAL1 TXB2 LITERAL1 TXB_ALL LITERAL1
MODE_CONFIG LITERAL1 MODE_LISTEN LITERAL1 MODE_LOOPBACK LITERAL1 MODE_SLEEP LITERAL1 MODE_NORMAL LITERAL1
RX0IF LITERAL1 RX1IF LITERAL1 TX0IF LITERAL1 TX1IF LITERAL1 TX2IF LITERAL1 ERRIF LITERAL1 WAKIF LITERAL1 MERRF LITERAL1 CANTest.pde /* MCP2515 CAN Interface Using SPI Author: David Harding Created: 11/08/2010 For further information see: http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf http://en.wikipedia.org/wiki/CAN_bus The MCP2515 Library files also contain important information This sketch shows the most basic of steps to send and receive CAN messages. It has been tested with a Microchip MCP2515DM-BM Demo Board, which consists of two identical boards that pass messages between each other. There is a connector available so that another CAN device can be connected to the bus. Using this I was able to read the messages passed between the two boards, and also introduce my own messages to the bus, which are then displayed by the software supplied with the demo kit. NOTE!!! If you use this sketch to test on a live system I suggest that you comment out the send messages lines unless you are certain that they will have no detrimental effect! */
#include <SPI.h> // Arduino SPI Library #include <MCP2515.h>
// Pin definitions specific to how the MCP2515 is wired up. #define CS_PIN 10 #define INT_PIN 6
// Create CAN object with pins as defined MCP2515 CAN(CS_PIN, INT_PIN);
void setup() { Serial.begin(115200); Serial.println("Initializing ...");
// Set up SPI Communication // dataMode can be SPI_MODE0 or SPI_MODE3 only for MCP2515 SPI.setClockDivider(SPI_CLOCK_DIV2); SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(MSBFIRST); SPI.begin(); // Initialise MCP2515 CAN controller at the specified speed and clock frequency // In this case 125kbps with a 16MHz oscillator // (Note: This is the oscillator attached to the MCP2515, not the Arduino oscillaltor) int baudRate=CAN.Init(125,16); if(baudRate>0) { Serial.println("MCP2515 Init OK ..."); Serial.print("Baud Rate (kbps): "); Serial.println(baudRate,DEC); } else { Serial.println("MCP2515 Init Failed ..."); }
Serial.println("Ready ..."); }
byte i=0;
// CAN message frame (actually just the parts that are exposed by the MCP2515 RX/TX buffers) Frame message;
void loop() { message.id = 0; // This implementation utilizes the MCP2515 INT pin to flag received messages or other events if(CAN.Interrupt()) { // determine which interrupt flags have been set byte interruptFlags = CAN.Read(CANINTF); if(interruptFlags & RX0IF) { // read from RX buffer 0 message = CAN.ReadBuffer(RXB0); } if(interruptFlags & RX1IF) { // read from RX buffer 1 message = CAN.ReadBuffer(RXB1); // (this is poor code as clearly if two messages are received then the second will overwrite the first) } if(interruptFlags & TX0IF) { // TX buffer 0 sent } if(interruptFlags & TX1IF) { // TX buffer 1 sent } if(interruptFlags & TX2IF) { // TX buffer 2 sent } if(interruptFlags & ERRIF) { // error handling code } if(interruptFlags & MERRF) { // error handling code // if TXBnCTRL.TXERR set then transmission error // if message is lost TXBnCTRL.MLOA will be set } } if(message.id>0) { // Print message Serial.print("ID: "); Serial.println(message.id,HEX); Serial.print("Extended: "); if(message.ide) { Serial.println("Yes"); } else { Serial.println("No"); } Serial.print("DLC: "); Serial.println(message.dlc,DEC); for(i=0;i<message.dlc;i++) { Serial.print(message.data[i],HEX); Serial.print(" "); } Serial.println();
// Send out a return message for each one received // Simply increment message id and data bytes to show proper transmission // Note: Please see explanation at top of sketch. You might want to comment this out! message.id++; for(i=0;i<message.dlc;i++) { message.data[i]++; } CAN.LoadBuffer(TXB0, message); CAN.SendBuffer(TXB0); } }
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 91
Arduino rocks
|
 |
« Reply #6 on: December 10, 2010, 12:02:48 am » |
The above is the latest revision of my code. I've added in an AutoBaud rate feature that works, but is a little clunky code wise. It requires that there are at least two active nodes on the bus, (not including the one you're using), and they must send messages at least every half second. It starts at a baud rate of 5kbps and goes up in increments of 5kbps until it reaches 1000kbps, (max rate for CAN V2.0B). This means that it could take nearly two minutes to detect the baud rate being used by the bus.
It does have a simple to use initialization routine though that simply requires a baud rate, (zero for AutoBaud), and a clock frequency, (frequency of MCP2515 oscillator, not Arduino). It then calculates out the proper bit timing for you.
Any comments or suggestions on the code would be welcome. Right now I'm waiting for a version 1.1 PCB, but I have the v1.0 shield pictured up and running just fine connected to SepEx motor controller at 125kbps. It happily streams data all day long. If the code doesn't work for you I'd be interested to know so that I can make it more universal.
|
|
|
|
« Last Edit: December 10, 2010, 12:03:33 am by DaveAK »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #7 on: December 15, 2010, 04:32:07 pm » |
Im trying to make my own CAN shield and eventually an complete unit with atmega mcu and can controller and tranceiver. I have a working beta version of the hardware, and got the canbus working with the library from: www.kreatives-chaos.com/artikel/universelle-can-bibliothekBut as soon as i try to add a filter it all goes badly. either no message gets through or all messages gets through. This is my filter code: // create a new filter for receiving messages can_filter_t filter = { .id = 0x1ff, .mask = 0x7ff, .flags = { .rtr = 0, .extended = 0 } };
can_set_filter(0, &filter);
can_init(BITRATE_1_MBPS);
This is done in the init part of the program, Is anything else needed to activate the filters ? the sending-part of my program that sends the message looks like this: can_t msg; msg.id = 0x7FF; msg.flags.rtr = 0; msg.flags.extended = 0; msg.length = 4; msg.data[0] = 0xde; msg.data[1] = 0xad; msg.data[2] = 0xbe; msg.data[3] = 0xef; can_send_message(&msg);
This message is still received, even though the id = 0x1ff should ignore it in the filter as i understand it.
|
|
|
|
« Last Edit: December 15, 2010, 04:36:07 pm by Riiiis »
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 91
Arduino rocks
|
 |
« Reply #8 on: December 15, 2010, 05:32:06 pm » |
From what I can gather from a quick glance at the data sheet and your code the filter works on the first two data bytes of a standard frame, not the message ID. I think you're trying to filter on the message ID, but you're using a standard frame, so this won't work.
If you use an extended frame then the mask applies to the full 29 bit ID field.
The mask you have requires an exact match between the message ID and the filter - i.e. only one specific message ID will be received. I think your test code is correct, (i.e. you're right and the message should be rejected), but again, it comes down to using a standard ID instead of an extended ID.
See figure 4-4 on page 32 of the MCP2515 datasheet.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 4
Arduino rocks
|
 |
« Reply #9 on: December 16, 2010, 11:25:29 pm » |
Would you be willing to share your schematic and/or eagle files? I'm trying to start up a similar project, and could use a decent reference.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #10 on: December 17, 2010, 09:45:59 am » |
My prototype is a small (2,5 x 5 cm) shield for the arduino, which just fits the mcp2515 and a can tranceiver (both can be sampled from TI afair). All is done with smd components and pinheaders through hole, as i think thats easiest. The shield's size makes all the analog and half of the digital i/o pins available when the shield is on.
I can upload the eagle files if you want
|
|
|
|
« Last Edit: December 17, 2010, 09:47:05 am by Riiiis »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 3
Arduino rocks
|
 |
« Reply #11 on: December 18, 2010, 08:23:38 am » |
Hello RiiiisDK! I would be very interessted in seeing your design. I am searching especially for a small desing for an Arduino Mini pro project.
cheers, Michael
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 3
Arduino rocks
|
 |
« Reply #12 on: December 18, 2010, 11:01:37 am » |
Hello! I get a lot of errors when trying to compile Dave AKs Code: C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::Reset()':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:153: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'byte MCP2515::Read(byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:159: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:160: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:161: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::Read(byte, byte*, byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:170: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:171: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:173: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'Frame MCP2515::ReadBuffer(byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:186: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:187: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:188: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:189: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:190: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:191: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:208: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::Write(byte, byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:217: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:218: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:219: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::Write(byte, byte*, byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:227: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:228: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:230: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::SendBuffer(byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:238: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::LoadBuffer(byte, Frame)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:272: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:273: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:274: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:275: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:276: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:277: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:280: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'byte MCP2515::Status()':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:287: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:288: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'byte MCP2515::RXStatus()':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:305: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:306: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::BitModify(byte, byte, byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:331: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:332: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:333: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:334: error: expected unqualified-id before '.' token Any ideas where to look at? Would it be possible to post the code in file form? Regards, Michael
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 3
Arduino rocks
|
 |
« Reply #13 on: December 20, 2010, 11:48:22 am » |
hi. Seems to work on Arduino 0021. Sorry for the confusion, I would be intressted in dem SMT design thought. Thanks a lot to all for all the effort.
regards, Michael
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 106
Arduino rocks
|
 |
« Reply #14 on: December 20, 2010, 11:51:26 am » |
You are so right the projects never end. I'll have to email that to a few people make there days as great as mine also great job.
MakerMann
|
|
|
|
|
Logged
|
|
|
|
|
|