Sample code for Arduino CAN

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
jedh
Date:
Mon Feb 29 19:33:12 2016 +0000
Commit message:
Arduino CAN

Changed in this revision

arduinoCAN.cpp Show annotated file Show diff for this revision Revisions of this file
arduinoCAN.h Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arduinoCAN.cpp	Mon Feb 29 19:33:12 2016 +0000
@@ -0,0 +1,897 @@
+/*
+ *  Copyright (C) 2009 Libelium Comunicaciones Distribuidas S.L.
+ *  http://www.libelium.com
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 2.1 of the License, or
+ *  (at your option) any later version.
+   
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Lesser General Public License for more details.
+  
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Version:	0.3
+ *  Design:		David Gascon
+ *  Implementation:		Luis Antonio Martin & Ahmad Saad
+ */
+ 
+#include "Arduino.h"
+#include "arduinoCAN.h"
+#include "../SPI/SPI.h"
+#include "../arduino-api/arduinoMultiprotocol.h"
+#include "../arduino-api/arduinoUtils.h"
+
+
+
+#define DEBUGMODE 0
+/***********************************************************************
+ * Constructors
+ ***********************************************************************/
+
+CAN::CAN(void){}
+
+
+/***********************************************************************
+ * PUBLIC METHODS
+ ***********************************************************************/
+
+//!*************************************************************
+//!	Name:	ON()													
+//!	Description: 	Initialization MCP2515
+//!	Param : void														
+//!	Returns: "1" if no error, "0" if error							
+//!*************************************************************
+bool CAN::begin(uint16_t speed)
+{
+
+	#if (DEBUGMODE ==1 )
+		Serial.println("-- Constructor Can(uint16_t speed) --");
+	#endif
+	
+	// Initialize in Socket1
+    Utils.setONSocket0();
+    Utils.setMUXSocket0();
+    Utils.unsetCSSocket0();
+	
+	//Initialization SPI
+	SPI.begin();
+	SPI.detachInterrupt();	
+	SPI.setBitOrder(MSBFIRST);
+	// both mode 0 & 3 should work
+	SPI.setDataMode(SPI_MODE0); 
+	
+	//Set the SPI frequency
+	SPI.setClockDivider(SPI_CLOCK_DIV128);
+	
+	#if (DEBUGMODE==1)
+		Serial.println("SPI configured");
+	#endif
+	
+	
+	//Software resets MCP2515
+	reset();
+	delay(10);
+	
+	//After the reset enters configuration mode	
+	
+	//Choose the rate of CAN-bus
+	switch(speed){
+	  
+    	case 1000:
+		#if (DEBUGMODE==1)
+			Serial.println("Speed=1Mbps");
+		#endif
+            Utils.setCSSocket0();
+			SPI.transfer(SPI_WRITE);
+			SPI.transfer(CNF3);
+			SPI.transfer((1<<PHSEG21));	
+			SPI.transfer((1<<BTLMODE)|(1<<PHSEG11));	
+            Utils.unsetCSSocket0();
+      	break;
+
+    	case 500:
+		#if (DEBUGMODE==1)
+			Serial.println("Speed=500kps");
+		#endif
+            Utils.setCSSocket0();
+      		SPI.transfer(SPI_WRITE);
+			SPI.transfer(CNF3);
+			SPI.transfer((1<<PHSEG21));	
+			SPI.transfer((1<<BTLMODE)|(1<<PHSEG11));
+			SPI.transfer((1<<BRP0));		
+            Utils.unsetCSSocket0();
+		break;
+
+    	case 250:
+		#if (DEBUGMODE==1)
+			Serial.println("Speed=250kps");
+		#endif
+            Utils.setCSSocket0();
+			SPI.transfer(SPI_WRITE);
+			SPI.transfer(CNF3);
+			SPI.transfer((1<<PHSEG20)|(1<<PHSEG22));	
+			SPI.transfer((1<<BTLMODE)|(1<<PHSEG12)|(1<<PHSEG11)|(1<<PHSEG10));
+			SPI.transfer((1<<BRP0));		
+            Utils.unsetCSSocket0();
+		break;
+
+		default:
+		#if (DEBUGMODE==1)
+			Serial.println("The rate requested is unavailable, is set to 125 Kbit/s by default");
+		#endif
+            Utils.setCSSocket0();
+			SPI.transfer(SPI_WRITE);
+			SPI.transfer(CNF3);
+			SPI.transfer((1<<PHSEG21));	
+			SPI.transfer((1<<BTLMODE)|(1<<PHSEG11));
+			SPI.transfer((1<<BRP2)|(1<<BRP1)|(1<<BRP0));		
+            Utils.unsetCSSocket0();
+		break;
+
+  	}
+	
+	//Enable interrupts the Rx Buffer 
+	writeRegister(CANINTE,(1<<RX1IE)|(1<<RX0IE));
+		
+	//Filters and masks
+  	//Bufer 0: All the messages and Rollover
+  	writeRegister(RXB0CTRL,(1<<RXM1)|(1<<RXM0)|(1<<BUKT)); 
+	
+  	//Bufer 1: All the messages
+	writeRegister(RXB1CTRL,(1<<RXM1)|(1<<RXM0)); 
+	
+	//All bits of the mask reception delete
+ 	writeRegister( RXM0SIDH, 0 );
+ 	writeRegister( RXM0SIDL, 0 );
+ 	writeRegister( RXM0EID8, 0 );
+  	writeRegister( RXM0EID0, 0 );
+ 	writeRegister( RXM1SIDH, 0 );
+    writeRegister( RXM1SIDL, 0 );
+  	writeRegister( RXM1EID8, 0 );
+  	writeRegister( RXM1EID0, 0 );
+	
+	//Disable pins RXnBF pins (high impedance state) 
+	writeRegister( BFPCTRL, 0 );
+	
+	//Set normal mode
+	setMode(NORMAL_MODE);
+	
+	//Test its correct mode
+	/*
+	if (read_register(CANSTAT) != 0) {
+		Serial.println("Failed to initialize the MCP2515, normal mode not activated");
+		return false;
+	}*/
+	
+	#if (DEBUGMODE==1)
+		Serial.println("-- End Constructor Can(uint16_t speed) --");
+		Serial.println("");
+	#endif
+
+	return 1;
+}
+
+//!*************************************************************
+//!	Name:	getMessage()												
+//!	Description: 	Take the CAN message								
+//!	Param : messageCAN *rec_msje: pointer to reception buffer	
+//!	Returns: "1" if no error, "0" if error							
+//!*************************************************************
+char CAN::getMessage(messageCAN *rec_msje)
+{
+	//Bought that buffer is the message
+	char status = readStatus(SPI_RX_STATUS);
+	char addr;
+	static uint8_t previoSerialuffer;
+
+	/*	
+		if (bit_is_set(status,6)) {	    
+			//If the message is in the Buffer 1
+			addr = SPI_READ_RX;
+		} 
+		else if (bit_is_set(status,7)) 
+		{	    
+			//If the message is in the Buffer 2
+			addr = SPI_READ_RX | 0x04;
+		} 
+		else {	    
+			// Error, the message is not available
+			return 0;
+	  }*/
+
+	if ( (((status & 0b11000000)>>6)&0b00000011) >2 )
+	{
+		addr=SPI_READ_RX | (previoSerialuffer++ & 0x01)<<2;
+		#if (DEBUGMODE==1)
+			Serial.println("Data in buffer available");
+		#endif
+	}
+	else if (bit_is_set(status,6)) 
+	{		
+		addr = SPI_READ_RX;
+		#if (DEBUGMODE==1)
+			Serial.println("Data in buffer 0");
+		#endif
+	}
+	else if (bit_is_set(status,7)) 
+	{
+		addr = SPI_READ_RX | 0x04;
+		#if (DEBUGMODE==1)
+			Serial.println("Data in buffer 1");
+		#endif
+	}
+	else {
+		// Error: no message available
+		#if (DEBUGMODE==1)
+			Serial.println("No messages");
+		#endif
+
+		return 0;
+	}
+	
+    Utils.setCSSocket0();
+	SPI.transfer(addr);
+	
+	//Read id 
+	rec_msje->id  = (unsigned int) SPI.transfer(0xff) << 3;   //Read the top
+	rec_msje->id |=                  SPI.transfer(0xff) >> 5;   //Read the lower
+	
+	//Return the Extended ID
+	SPI.transfer(0xff);
+	SPI.transfer(0xff);
+	
+	//Read DLC
+	char length = SPI.transfer(0xff) & 0x0f;   
+	
+	rec_msje->header.length = length;
+	rec_msje->header.rtr = (bit_is_set(status, 3)) ? 1 : 0;
+	
+	//Read data
+	    for (char i=0;i<length;i++) {
+			rec_msje->data[i] = SPI.transfer(0xFF);
+	    }
+	    
+    Utils.unsetCSSocket0();
+	
+	//Delete the interruptions flags
+	    if (bit_is_set(status, 6)) {
+			bitModify(CANINTF, (1<<RX0IF), 0);
+		}
+		else {
+			bitModify(CANINTF, (1<<RX1IF), 0);
+		}
+	
+	return status;
+}
+
+
+
+//!*************************************************************
+//!	Name:	sendMessage()												
+//!	Description: 	Send the CAN message
+//!	Param: messageCAN *send_msje: pointer to transmission buffer
+//!	Returns: "1" if no error, "0" if error							
+//!*************************************************************
+char CAN::sendMessage(messageCAN *send_msje)
+{
+	char status = readStatus(SPI_READ_STATUS);
+	
+	/* Status char:
+	 * 
+	 * Bit	Funcion
+	 *  2	TXB0CNTRL.TXREQ
+	 *  4	TXB1CNTRL.TXREQ
+	 *  6	TXB2CNTRL.TXREQ
+	 */
+	
+	char address;
+	
+	if (bit_is_clear(status, 2)) {
+		address = 0x00;
+	} else if (bit_is_clear(status, 4)) {
+		address = 0x02;
+	} else if (bit_is_clear(status, 6)) {
+		address = 0x04;
+	} else {
+		//All buffers are used can not send messages (returns 0)
+		return 0;
+	}
+	
+    Utils.setCSSocket0();
+	SPI.transfer(SPI_WRITE_TX | address);
+	//First, send the top ID10....ID3
+	SPI.transfer(send_msje->id >> 3);
+	//After sending the lower ID2....ID0
+	SPI.transfer(send_msje->id << 5);
+
+	//As we will not use the Extended ID you set it to 0
+	SPI.transfer(0);
+	SPI.transfer(0);
+	
+	char length = send_msje->header.length & 0x0F;
+	
+		if (send_msje->header.rtr) {
+			SPI.transfer((1<<RTR) | length);
+		} else {
+		//Send the message length
+			SPI.transfer(length);		
+		//Send data
+			for (char i=0;i<length;i++) {
+				SPI.transfer(send_msje->data[i]);
+			}
+		}
+	
+    Utils.unsetCSSocket0();
+	
+	//Send message
+    Utils.setCSSocket0();
+	address = (address == 0) ? 1 : address;
+	SPI.transfer(SPI_RTS | address);
+    Utils.unsetCSSocket0();
+	
+	return address;
+}
+
+
+//!*************************************************************
+//!	Name:	printMessage()											
+//!	Description: 	CAN message print out the serial port			
+//!	Param : messageCAN *msje: pointer to the message				
+//!	Returns: "1" if no error, "0" if error							
+//!*************************************************************
+void CAN::printMessage(messageCAN *msje)
+{
+	Serial.print("  id: ");
+	Serial.print(messageRx.id,HEX); 
+	Serial.print("  rtr: ");
+	Serial.print(messageRx.header.rtr,HEX); 
+	Serial.print(" => ");
+    
+	if (!msje->header.rtr) {
+		//Data
+		Serial.print(" data:  ");
+		Serial.print(messageRx.data[0],HEX); Serial.print(",");
+		Serial.print(messageRx.data[1],HEX); Serial.print(","); 
+		Serial.print(messageRx.data[2],HEX); Serial.print(",");
+		Serial.print(messageRx.data[3],HEX); Serial.print(",");
+		Serial.print(messageRx.data[4],HEX); Serial.print(",");
+		Serial.print(messageRx.data[5],HEX); Serial.print(",");
+		Serial.print(messageRx.data[6],HEX); Serial.print(",");
+		Serial.println(messageRx.data[7],HEX);
+	}
+}
+
+
+//!*************************************************************
+//!	Name:	setMode()													
+//!	Description: 	Configure the MCP2515							
+//!	Param : uint8_t mode: The work mode							
+//!	Returns: void														
+//!*************************************************************
+void CAN::setMode(uint8_t mode)
+{
+	uint8_t mode_register = 0;
+	
+	if (mode == LISTEN_ONLY_MODE) {
+		mode_register = (0<<REQOP2)|(1<<REQOP1)|(1<<REQOP0);
+	}
+	else if (mode == LOOPBACK_MODE) {
+		mode_register = (0<<REQOP2)|(1<<REQOP1)|(0<<REQOP0);
+	}
+	else if (mode == SLEEP_MODE) {
+		mode_register = (0<<REQOP2)|(0<<REQOP1)|(1<<REQOP0);
+	}
+	else if (mode == NORMAL_MODE) {
+		mode_register = (0<<REQOP2)|(0<<REQOP1)|(0<<REQOP0);
+	}
+		
+	//Set the new mode
+	bitModify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), mode_register);
+	
+	//Wait until the mode has been changed
+	while ((readRegister(CANSTAT) & 0xe0) != mode_register) {	}
+}
+
+
+//!*************************************************************
+//!	Name:	messageAvailable()										
+//!	Description: 	Check if there is any message					
+//!	Param : void							
+//!	Returns: 1 if available, 0 if not. 														
+//!*************************************************************
+uint8_t CAN::messageAvailable(void)
+{
+	char status = readStatus(SPI_RX_STATUS);
+
+	if ( (((status & 0b11000000)>>6)&0b00000011) >2 )
+	{		
+		return 1;	
+	} else if (bit_is_set(status,6))  {
+		return 1;
+	} else if (bit_is_set(status,7)) {
+		return 1;
+	} else  {
+		return 0;
+	
+		#if (DEBUGMODE==1)
+			Serial.println("No data available");
+		#endif		
+	}
+}
+
+//**********************************************************************
+// Standars PIDs
+//**********************************************************************
+
+
+//!*************************************************************
+//!	Name:	getEngineLoad()										
+//!	Description: 	Calculated engine load value				
+//!	Param : void							
+//!	Returns: unsigned int: engine load value (0-100)				
+//!*************************************************************
+unsigned int CAN::getEngineLoad()
+{
+	unsigned int data;
+
+	CiARequest(CALC_ENGINE_LOAD);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3] * 100)  / 255; 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+}
+
+
+//!*************************************************************
+//!	Name:	getEngineCoolantTemp()								
+//!	Description: 	Engine coolant temperature					
+//!	Param : void							
+//!	Returns: Engine coolant temperature(-40 - 215)
+//!*************************************************************
+unsigned int CAN::getEngineCoolantTemp()
+{
+	unsigned int data;
+
+	CiARequest(ENGINE_COOLANT_TEMP);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3] - 40); 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+}
+
+
+//!*************************************************************
+//!	Name:	getFuelPressure()										
+//!	Description: 	Fuel pressure					
+//!	Param : void							
+//!	Returns: unsigned int: Fuel pressure (0 - 765 Kpa)				
+//!*************************************************************
+unsigned int CAN::getFuelPressure()
+{
+	unsigned int data;
+
+	CiARequest(FUEL_PRESSURE);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3] * 3) ; 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+}
+
+
+//!*************************************************************
+//!	Name:	getIntakeMAPressure()									
+//!	Description: 	Intake manifold absolute pressure 				
+//!	Param : void							
+//!	Returns: unsigned int: absolute pressure 	(0 - 255 Kpa)		
+//!*************************************************************
+unsigned int CAN::getIntakeMAPressure()
+{
+	unsigned int data;
+
+	CiARequest(INTAKE_M_A_PRESSURE);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  messageRx.data[3]; 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+	
+	
+}
+
+
+//!*************************************************************
+//!	Name:	getEngineRPM()										
+//!	Description: 	Engine RPM					
+//!	Param : void							
+//!	Returns: unsigned int: Engine RPM (0 - 16,383 RPM) 						
+//!*************************************************************
+unsigned int CAN::getEngineRPM()
+{	
+	
+	unsigned int data;
+
+	CiARequest(ENGINE_RPM);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  (uint16_t(messageRx.data[3]*256) + messageRx.data[4])/4; 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+}
+
+
+//!*************************************************************
+//!	Name:	getVehicleSpeed()										
+//!	Description: 	Vehicle speed					
+//!	Param : void							
+//!	Returns: unsigned int: Vehicle speed (0 - 255)				
+//!*************************************************************
+unsigned int CAN::getVehicleSpeed()
+{
+	unsigned int data;
+
+	CiARequest(VEHICLE_SPEED);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3]); 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+	
+}
+
+
+//!*************************************************************
+//!	Name:	getTimingAdvance()										
+//!	Description: 	Timing advance					
+//!	Param : void							
+//!	Returns: unsigned int: Time (-64 - 63.5)		 							
+//!*************************************************************
+unsigned int CAN::getTimingAdvance()
+{
+	unsigned int data;
+
+	CiARequest(TIMING_ADVANCE);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3] / 2- 64); 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+}
+	
+//!*************************************************************
+//!	Name:	getIntankeAirTemp()										
+//!	Description: 	Intake air temperature					
+//!	Param : void							
+//!	Returns: unsigned int: Intake air temperature(-40 - 215) 
+//!*************************************************************
+unsigned int CAN::getIntankeAirTemp()
+{
+	unsigned int data;
+
+	CiARequest(INTAKE_AIR_TEMP);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3] - 40); 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+}
+
+
+//!*************************************************************
+//!	Name:	getMAFairFlowRate()										
+//!	Description: 	MAF air flow rate					
+//!	Param : void							
+//!	Returns: unsigned int: air flow rate	(0 - 655.35 g/s) 						
+//!*************************************************************
+unsigned int CAN::getMAFairFlowRate()
+{
+	unsigned int data;
+
+	CiARequest(MAF_AIR_FLOW_RATE);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  ( uint16_t(messageRx.data[3] * 256) + messageRx.data[4]) / 100; 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+	
+}
+
+
+//!*************************************************************
+//!	Name:	getThrottlePosition()									
+//!	Description: 	Throttle position					
+//!	Param : void							
+//!	Returns: unsigned int: Throttle position	(0 - 100%) 		
+//!*************************************************************
+unsigned int CAN::getThrottlePosition()
+{
+	unsigned int data;
+
+	CiARequest(THROTTLE_POSITION);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3] * 100) / 255; 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+	
+	
+}
+
+
+//!*************************************************************
+//!	Name:	getFuelLevel()										
+//!	Description: 	Fuel Level Input				
+//!	Param : void							
+//!	Returns: unsigned int: Fuel Level Input (0 - 100%) 							
+//!*************************************************************
+unsigned int CAN::getFuelLevel()
+{
+	unsigned int data;
+
+	CiARequest(FUEL_LEVEL);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3] * 100)  / 255; 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+	
+}
+
+
+//!*************************************************************
+//!	Name:	getBarometricPressure()									
+//!	Description: 	Barometric pressure					
+//!	Param : void							
+//!	Returns: unsigned int: Barometric pressure (0 - 255 Kpa)		
+//!*************************************************************
+unsigned int CAN::getBarometricPressure()
+{
+	unsigned int data;
+
+	CiARequest(BAROMETRIC_PRESSURE);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data =  uint16_t(messageRx.data[3]); 
+
+		#if (DEBUGMODE == 1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+}
+
+
+//!*************************************************************
+//!	Name:	getEngineFuelRate()										
+//!	Description: 	Engine fuel rate					
+//!	Param : void							
+//!	Returns: unsigned int: Engine fuel rate	 (0 - 3212 L/h)	
+//!*************************************************************
+unsigned int CAN::getEngineFuelRate()
+{
+	unsigned int data;
+
+	CiARequest(ENGINE_FUEL_RATE);
+	
+	if (messageRx.id==ID_RESPONSE) {
+		data = uint16_t((messageRx.data[3] * 256) + messageRx.data[4]) * 0.05; 
+
+		#if (DEBUGMODE==1)
+			printMessage(&messageRx);
+		#endif
+	}
+	
+	return data;
+	
+}
+
+
+/***********************************************************************
+                          CAN in Automation (CiA)
+ ***********************************************************************/
+
+//Request information through OBD
+void CAN::CiARequest(uint8_t PID)
+{   
+	messageTx.id = ID_QUERY;
+	messageTx.header.rtr = 0;
+	messageTx.header.length = 8;
+	messageTx.data[0]= 0x02;
+	messageTx.data[1]= 0x01;
+	messageTx.data[2]= PID;  
+   
+	
+	sendMessage(&messageTx);
+	delay(5);
+
+	if (messageAvailable()) {
+		//Read the message buffers
+		getMessage(&messageRx);
+	}
+
+}
+
+
+/***********************************************************************
+ * PRIVATE METHODS
+ ***********************************************************************/
+
+//Write a MCP2515 register
+void CAN::writeRegister( char direction, char data )
+{
+	//CS low to select the MCP2515 
+    Utils.setCSSocket0();
+
+	SPI.transfer(SPI_WRITE);
+	SPI.transfer(direction);
+	SPI.transfer(data);
+	
+	//CS line again to release 
+    Utils.unsetCSSocket0();
+}
+
+
+//**********************************************************************
+
+//Read a MCP2515 register
+char CAN::readRegister(char direction)
+{
+	char data;
+	
+	//CS low to select the MCP2515 
+    Utils.setCSSocket0();
+	
+	SPI.transfer(SPI_READ);
+	SPI.transfer(direction);	
+	//Read data SPI
+	data = SPI.transfer(0xff);	
+	
+	//CS line again to release 
+    Utils.unsetCSSocket0();
+	
+	return data;
+}
+
+
+//***********************************************************************
+
+//Modify a bit of the MCP2515 registers
+void CAN::bitModify(char direction, char mask, char data)
+{
+	//CS low to select the MCP2515 
+    Utils.setCSSocket0();
+	
+	SPI.transfer(SPI_BIT_MODIFY);
+	SPI.transfer(direction);
+	SPI.transfer(mask);
+	SPI.transfer(data);
+	
+	//CS line again to release 
+    Utils.unsetCSSocket0();
+}
+
+
+//***********************************************************************
+
+//Check the status of the MCP2515 registers (SPI_RX_STATUS / SPI_READ_STATUS)
+char CAN::readStatus(char type)
+{
+	char data;
+	
+	//CS low to select the MCP2515 
+    Utils.setCSSocket0();
+		
+	SPI.transfer(type);	
+	//Read data SPI 
+	data = SPI.transfer(0xFF); 
+	 	
+	//CS line again to release 
+    Utils.unsetCSSocket0();
+	
+	return data;
+}
+
+
+//***********************************************************************
+
+//Check if the buffers are empty
+bool CAN::checkFreeBuffer(void)
+{
+	char status = readStatus(SPI_READ_STATUS);
+	
+	
+	if ((status & 0x54) == 0x54) 
+	{	  
+		//All buffers used
+		return false;
+	}
+	
+	return true;
+}
+
+
+//***********************************************************************
+
+//Reset MCP2515
+void CAN::reset(void)
+{
+	//CS low to select the MCP2515 
+    Utils.setCSSocket0();
+
+	SPI.transfer(SPI_RESET);	
+	//CS line again to release 
+    Utils.unsetCSSocket0();
+
+
+	//Wait a bit to be stabilized after the reset MCP2515
+	delay(10);
+	
+	#if (DEBUGMODE==1)
+		Serial.println("The MCP2515 has been successfully reset, configuration mode activated");
+	#endif
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arduinoCAN.h	Mon Feb 29 19:33:12 2016 +0000
@@ -0,0 +1,501 @@
+/*! \file CAN.h
+    \brief  Library for managing CAN-bus modules
+    
+    Copyright (C) 2011 Libelium Comunicaciones Distribuidas S.L.
+    http://www.libelium.com
+ 
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 2.1 of the License, or
+    (at your option) any later version.
+   
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+  
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  
+    Version:		0.3
+    Design:		David Gascón
+    Implementation:	Luis Antonio Martín Nuez
+
+ */
+
+/*! \def WaspCAN_h
+    \brief The library flag
+ */
+
+#ifndef ARDUINOCAN_h
+#define ARDUINOCAN_h
+
+
+/******************************************************************************
+ * Includes
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Definitions & Declarations
+ ******************************************************************************/
+
+//CAN-bus connection pins
+
+#define CAN_CS        6
+#define CAN_INT       4
+
+//MCP2515 Opcodes 
+
+#define SPI_RESET               0xC0
+#define SPI_READ                0x03
+#define SPI_READ_RX             0x90
+#define SPI_WRITE               0x02
+#define SPI_WRITE_TX            0x40
+#define SPI_RTS                 0x80
+#define SPI_READ_STATUS         0xA0
+#define SPI_RX_STATUS           0xB0
+#define SPI_BIT_MODIFY          0x05
+
+#define LISTEN_ONLY_MODE	0x01
+#define LOOPBACK_MODE		0x02
+#define SLEEP_MODE		0x03
+#define NORMAL_MODE		0x04
+
+/****************************************************************************
+                                MCP2515 REGISTERS
+ ****************************************************************************/
+
+//Message acceptance filters registers - Buffer 0
+
+#define RXF0SIDH                0x00
+#define RXF0SIDL                0x01
+#define RXF0EID8                0x02
+#define RXF0EID0                0x03
+#define RXF1SIDH                0x04
+#define RXF1SIDL                0x05
+#define RXF1EID8                0x06
+#define RXF1EID0                0x07
+#define RXF2SIDH                0x08
+#define RXF2SIDL                0x09
+#define RXF2EID8                0x0A
+#define RXF2EID0                0x0B
+
+//Digital outputs/inputs registers
+
+#define BFPCTRL                 0x0C
+#define TXRTSCTRL               0x0D
+
+//CAN-bus control and status registers
+
+#define CANSTAT                 0x0E
+#define CANCTRL                 0x0F
+
+//Message acceptance filters registerts - Buffer 1
+
+#define RXF3SIDH                0x10
+#define RXF3SIDL                0x11
+#define RXF3EID8                0x12
+#define RXF3EID0                0x13
+#define RXF4SIDH                0x14
+#define RXF4SIDL                0x15
+#define RXF4EID8                0x16
+#define RXF4EID0                0x17
+#define RXF5SIDH                0x18
+#define RXF5SIDL                0x19
+#define RXF5EID8                0x1A
+#define RXF5EID0                0x1B
+
+//Error counters registers
+
+#define TEC                     0x1C
+#define REC                     0x1D
+
+//Message acceptance masks registers
+
+#define RXM0SIDH                0x20
+#define RXM0SIDL                0x21
+#define RXM0EID8                0x22
+#define RXM0EID0                0x23
+#define RXM1SIDH                0x24
+#define RXM1SIDL                0x25
+#define RXM1EID8                0x26
+#define RXM1EID0                0x27
+
+//Bit timing registers
+
+#define CNF3                    0x28
+#define CNF2                    0x29
+#define CNF1                    0x2A
+
+//Interrups registers
+
+#define CANINTE                 0x2B
+#define CANINTF                 0x2C
+
+//Error flags registers
+
+#define EFLG                    0x2D
+
+//Message transmission registers - 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
+
+//Message transmission registers - 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
+
+//Message transmission registers - 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
+
+//Message reception registers - 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
+
+//Message reception registers - 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
+
+//Control registers 
+
+/** BFPCTRL **/
+#define B1BFS                   5
+#define B0BFS                   4
+#define B1BFE                   3
+#define B0BFE                   2
+#define B1BFM                   1
+#define B0BFM                   0
+
+/** TXRTSCTRL **/
+#define B2RTS                   5
+#define B1RTS                   4
+#define B0RTS                   3
+#define B2RTSM                  2
+#define B1RTSM                  1
+#define B0RTSM                  0
+
+/** CANSTAT **/
+#define OPMOD2                  7
+#define OPMOD1                  6
+#define OPMOD0                  5
+#define ICOD2                   3
+#define ICOD1                   2
+#define ICOD0                   1
+
+/** CANCTRL **/
+#define REQOP2                  7
+#define REQOP1                  6
+#define REQOP0                  5
+#define ABAT                    4
+#define CLKEN                   2
+#define CLKPRE1                 1
+#define CLKPRE0                 0
+
+/** CNF3 **/
+#define SOF                     7
+#define WAKFIL                  6
+#define PHSEG22                 2
+#define PHSEG21                 1
+#define PHSEG20                 0
+
+/** CNF2 **/
+#define BTLMODE                 7
+#define SAM                     6
+#define PHSEG12                 5
+#define PHSEG11                 4
+#define PHSEG10                 3
+#define PHSEG2                  2
+#define PHSEG1                  1
+#define PHSEG0                  0
+
+/** CNF1 **/
+#define SJW1                    7
+#define SJW0                    6
+#define BRP5                    5
+#define BRP4                    4
+#define BRP3                    3
+#define BRP2                    2
+#define BRP1                    1
+#define BRP0                    0
+
+/** CANINTE **/
+#define MERRE                   7
+#define WAKIE                   6
+#define ERRIE                   5
+#define TX2IE                   4
+#define TX1IE                   3
+#define TX0IE                   2
+#define RX1IE                   1
+#define RX0IE                   0
+
+/** CANINTF */
+#define MERRF                   7
+#define WAKIF                   6
+#define ERRIF                   5
+#define TX2IF                   4
+#define TX1IF                   3
+#define TX0IF                   2
+#define RX1IF                   1
+#define RX0IF                   0
+
+/** EFLG **/
+#define RX1OVR                  7
+#define RX0OVR                  6
+#define TXB0                    5
+#define TXEP                    4
+#define RXEP                    3
+#define TXWAR                   2
+#define RXWAR                   1
+#define EWARN                   0
+
+/** TXBnCTRL (n = 0, 1, 2) **/
+#define ABTF                    6
+#define MLOA                    5
+#define TXERR                   4
+#define TXREQ                   3
+#define TXP1                    1
+#define TXP0                    0
+
+/** RXB0CTRL **/
+#define RXM1                    6
+#define RXM0                    5
+#define RXRTR                   3
+#define BUKT                    2
+#define BUKT1                   1
+#define FILHIT0                 0
+
+/** RXB1CTRL **/
+#define RSM1                    6
+#define FILHIT2                 2
+#define FILHIT1                 1
+
+/** TXBnSIDL (n = 0, 1) **/
+#define EXIDE                   3
+
+/** RXBnSIDL (n = 0, 1) **/
+#define SRR                     4
+#define IDE                     3
+
+/** RXBnDLC (n = 0, 1) / TXBnDLC **/
+#define RTR                     6
+#define DLC3                    3
+#define DLC2                    2
+#define DLC1                    1
+#define DLC0                    0
+
+
+/******************************************************************************
+                          CAN in Automation (CiA)
+ ******************************************************************************/
+
+//Standard OBD requests and responses
+
+#define ID_QUERY                    0x7DF
+#define ID_RESPONSE	            0x7E8
+
+
+//Standars PIDs
+
+                                        //Mode  PID  Data ret......Description...............min_val...max_val..units...formula
+					
+#define CALC_ENGINE_LOAD            0X04  //01 	04 	1 	Calculated engine load value 	  0 	100 	 % 	A*100/255
+#define ENGINE_COOLANT_TEMP         0x05  //01 	05 	1 	Engine coolant temperature 	-40 	215 	°C 	A-40
+#define SHORT_TERM_FUEL_1           0x06  //01 	06 	1 	Short term fuel % trim—Bank 1 	-100 (Rich) 	99.22 (Lean) 	 % 	(A-128) * 100/128
+#define LONG_TERM_FUEL_1            0x07  //01 	07 	1 	Long term fuel % trim—Bank 1 	-100 (Rich) 	99.22 (Lean) 	 % 	(A-128) * 100/128
+#define SHORT_TERM_FUEL_2           0x08  //01 	08 	1 	Short term fuel % trim—Bank 2 	-100 (Rich) 	99.22 (Lean) 	 % 	(A-128) * 100/128
+#define LONG_TERM_FUEL_2            0x09  //01 	09 	1 	Long term fuel % trim—Bank 2 	-100 (Rich) 	99.22 (Lean) 	 % 	(A-128) * 100/128
+#define O2_B1_S1_VOLTAGE            0x14  //01 	14 	2 	Bank 1, Sensor 1:Oxygen sensor voltage,Short term fuel trim 	0-100(lean)	1.275 99.2(rich) 	Volts % 	A/200(B-128) * 100/128 (if B==0xFF, sensor is not used in trim calc)
+#define FUEL_PRESSURE               0x0A  //01 	0A 	1 	Fuel pressure 	0 	765 	kPa (gauge) 	A*3
+#define INTAKE_M_A_PRESSURE         0x0B  //01 	0B 	1 	Intake manifold absolute pressure 	0 	255 	kPa (absolute) 	A
+#define ENGINE_RPM                  0x0C  //01 	0C 	2 	Engine RPM 	0 	16,383.75 	rpm 	((A*256)+B)/4
+#define VEHICLE_SPEED               0x0D  //01 	0D 	1 	Vehicle speed 	0 	255 	km/h 	A
+#define TIMING_ADVANCE              0x0E  //01 	0E 	1 	Timing advance 	-64 	63.5 	° relative to #1 cylinder 	A/2 - 64
+#define INTAKE_AIR_TEMP             0x0F  //01 	0F 	1 	Intake air temperature 	-40 	215 	°C 	A-40
+#define MAF_AIR_FLOW_RATE           0x10  //01 	10 	2 	MAF air flow rate 	0 	655.35 	g/s 	((A*256)+B) / 100
+#define THROTTLE_POSITION           0x11  //01 	11 	1 	Throttle position 	0 	100 	 % 	A*100/255
+#define RUNTIME_SINCE_START         0x1F  //01 	1F 	2 	Run time since engine start 	0 	65,535 	seconds 	(A*256)+B
+#define DISTANCE_WITH_MALF          0x21  //01 	21 	2 	Distance traveled with malfunction indicator lamp (MIL) on 	0 	65,535 	km 	(A*256)+B
+#define FUEL_RAIL_PRESSURE_RELATIVE 0x22  //01 	22 	2 	Fuel Rail Pressure (relative to manifold vacuum) 	0 	5177.265 	kPa 	(((A*256)+B) * 10) / 128
+#define FUEL_RAIL_PRESSURE_DIESEL   0x23  //01 	23 	2 	Fuel Rail Pressure (diesel) 	0 	655350 	kPa (gauge) 	((A*256)+B) * 10
+#define FUEL_LEVEL                  0x2F   //01 	2F 	1 	Fuel Level Input 	0 	100 	 % 	100*A/255
+#define NUM_WARMUPS_SINCE_CODES     0x30   //01 	30 	1 	# of warm-ups since codes cleared 	0 	255 	N/A 	A
+#define DISTANCE_SINCE_CODES        0x31   //01 	31 	2 	Distance traveled since codes cleared 	0 	65,535 	km 	(A*256)+B
+#define EVAP_SYSTEM_VAPOR_PRESSURE  0x32   //01 	32 	2 	Evap. System Vapor Pressure 	-8,192 	8,192 	Pa 	((A*256)+B)/4 (A is signed)
+#define BAROMETRIC_PRESSURE         0x33   //01 	33 	1 	Barometric pressure 	0 	255 	kPa (Absolute) 	A
+#define CONTROL_MODULE_VOLTAGE      0x42   //01 	42 	2 	Control module voltage 	0 	65.535 	V 	((A*256)+B)/1000
+#define ABSOLUTE_LOAD_VALUE         0x43   //01 	43 	2 	Absolute load value 	0 	25,700 	 % 	((A*256)+B)*100/255
+#define COMMAND_EQUIV_RATIO         0x44   //01 	44 	2 	Command equivalence ratio 	0 	2 	N/A 	((A*256)+B)/32768
+#define REL_THROTTLE_POSITION       0x45   //01 	45 	1 	Relative throttle position 	0 	100 	 % 	A*100/255
+#define AMBIENT_AIR_TEMPERATURE     0x46   //01 	46 	1 	Ambient air temperature 	-40 	215 	°C 	A-40
+#define ABS_THROTTLE_POSITION_B     0x47   //01 	47 	1 	Absolute throttle position B 	0 	100 	 % 	A*100/255
+#define ABS_THROTTLE_POSITION_C     0x48   //01 	48 	1 	Absolute throttle position C 	0 	100 	 % 	A*100/255
+#define ABS_THROTTLE_POSITION_D     0x49   //01 	49 	1 	Accelerator pedal position D 	0 	100 	 % 	A*100/255
+#define ABS_THROTTLE_POSITION_E     0x4A   //01 	4A 	1 	Accelerator pedal position E 	0 	100 	 % 	A*100/255
+#define ABS_THROTTLE_POSITION_F     0x4B   //01 	4B 	1 	Accelerator pedal position F 	0 	100 	 % 	A*100/255
+#define COMMANDED_THROTTLE_ACTUATOR 0x4C   //01 	4C 	1 	Commanded throttle actuator 	0 	100 	 % 	A*100/255
+#define TIME_RUN_WITH_MIL_ON        0x4D   //01 	4D 	2 	Time run with MIL on 	0 	65,535 	minutes 	(A*256)+B
+#define TIME_SINCE_T_CODES_CLEAR    0x4E   //01 	4E 	2 	Time since trouble codes cleared 	0 	65,535 	minutes 	(A*256)+B
+#define FUEL_TYPE                   0x51   //01 	51 	1 	Fuel Type 				From fuel type table see below
+#define ETHANOL_FUEL                0x52   //01 	52 	1 	Ethanol fuel % 	0 	100 	 % 	A*100/255
+#define ABS_EVAP_SYST_VAPOUR_PRESS  0x53   //01 	53 	2 	Absoulute Evap system Vapour Pressure 	0 	327675 	kpa 	1/200 per bit
+#define ENGINE_FUEL_RATE			0x5E  //01 	5E 		2 		Engine fuel rate 0 - 3212.75 		L/h		 ((A*256)+B)*0.05
+
+
+#include <inttypes.h>
+
+
+/******************************************************************************
+ * Class
+ ******************************************************************************/
+
+  //! CAN Class
+/*!
+	CAN Class defines all the variables and functions used to manage CAN-bus modules
+ */
+
+class CAN
+{
+
+	private:
+		// Write a register of the MCP2515 using SPI
+		void writeRegister( char direction, char data );
+		// Read a register of the MCP2515 using SPI
+		char readRegister(char direction);		
+		// Modify a bit of the MCP2515 using SPI
+		void bitModify(char direction, char mask, char data);
+		// Check the status of the MCP2515 registers 
+		char readStatus(char type);
+		// Check if the buffers are empty
+		bool checkFreeBuffer(void);	
+		// Reset MCP2515
+		void reset(void);
+		
+
+	public:
+	
+		// Data structure 
+		typedef struct{
+				unsigned int id;
+				struct
+				{ 
+				  char rtr : 1;
+				  char length : 4;
+				}header;
+			
+				uint8_t data[8];
+		}messageCAN;
+	
+		// Receive buffer
+		messageCAN messageRx;
+		// Trasmit buffer
+		messageCAN messageTx;
+		// Empty constructor
+		CAN(void);
+		// Powers the CANBus module and opens the SPI
+		bool begin(uint16_t speed);
+		// Check if there is any message
+		uint8_t messageAvailable(void);
+		// Take the CAN message
+		char getMessage(messageCAN *msje);
+		// Send the CAN message
+		char sendMessage(messageCAN *msje);
+		// CAN message print out the serial port
+		void printMessage(messageCAN *msje);
+		// Configure the MCP2515
+		void setMode(uint8_t mode);
+
+/***********************************************************************
+					CAN in Automation (CiA)
+***********************************************************************/
+		
+		unsigned int getEngineLoad();
+		unsigned int getEngineCoolantTemp();
+		unsigned int getFuelPressure();
+		unsigned int getIntakeMAPressure();
+		unsigned int getEngineRPM();
+		unsigned int getVehicleSpeed();
+		unsigned int getTimingAdvance();
+		unsigned int getIntankeAirTemp();
+		unsigned int getMAFairFlowRate();
+		unsigned int getThrottlePosition();
+		unsigned int getFuelLevel();
+		unsigned int getBarometricPressure();
+		unsigned int getEngineFuelRate();
+		
+		// General Function
+		void CiARequest(uint8_t PID);
+
+
+};
+
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Feb 29 19:33:12 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/252557024ec3
\ No newline at end of file