The TAS has two Ethernet/CAN bus gateways for reason of redundancy. If one fails to respond the second one is activated to take over the message relais function. The gateway simply forwards the CAN bus message sent over Ethernet to the CAN bus client and realais the response back to the sender over Ethernet. I stated at another occasion that I decided to use the CAN bus because of the number of client processors and the fact that Ethernet would require far too many switches (ports) and cables to connect each client. The CAN bus is a real bus network unlike the Ethernet and far more efficient connecting nodes in a smaller network. The CAN bus is not as fast as the Ethernetbut fast enough for the application at hand. I run it at a baudrate of 500k. Below is the current version of the program.
// below if is required to process if defined statements properly #if 1 __asm volatile ("nop"); #endif // The CAN bus gateway relais CAN bus packets over Ethernet to the central application. // No local functionality or sensors are connected. Only packet routing is performed. // The gateway does only listen to CAN packets when a request has been received over // Ethernet. #include <mcp_can.h> #include <mcp_can_dfs.h> #include <Timer.h> #include <SPI.h> #include <Ethernet.h> #include <EthernetUdp.h> // UDP library from: bjoern@cs.stanford.edu 12/30/2008 #define DEBUG /* ------------------------------------------------------------------------------------------------------------------------------------ * Ethernet definitions * ------------------------------------------------------------------------------------------------------------------------------------ */ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xF1}; IPAddress ip(192,168,0,170); unsigned int localPort = 8000; // local port to listen on // buffers for receiving and sending data char packetBuffer[24]; // buffer to hold incoming packet, char replyBuffer[24] ; // a string to send back EthernetUDP Udp; // An EthernetUDP instance to let us send and receive packets over UDP /* ------------------------------------------------------------------------------------------------------------------------------------ * CAN bus definitions * ------------------------------------------------------------------------------------------------------------------------------------ */ MCP_CAN CAN(9); // Set CS to pin 9 byte ourId=0xB0; // fixed CAN bus id for the Gateway unsigned char len = 8; unsigned char buf[8]; //char str[20]; int heartBeat=0; int Flag_Restart=0; // output buffer for CAN write unsigned char stmpOut[8] = {100, 0x01, 0, 0, 0, 0, 0, 0}; unsigned char stmpIn[8] = {100, 0x01, 0, 0, 0, 0, 0, 0}; /* ------------------------------------------------------------------------------------------------------------------------------------ * Timer definitions * ------------------------------------------------------------------------------------------------------------------------------------ */ Timer watchDogTimer; boolean responseExpected=false; boolean canTimeout = false; /* ------------------------------------------------------------------------------------------------------------------------------------ * Initialise * ------------------------------------------------------------------------------------------------------------------------------------ */ void setup() { Serial.begin(9600); while (CAN_OK != CAN.begin(CAN_500KBPS)){ // init can bus : baudrate = 500k Serial.println("CAN BUS Shield init fail"); delay(1000); } Serial.println("CAN BUS Shield init ok!"); // start the Ethernet and UDP: Ethernet.begin(mac, ip); Udp.begin(localPort); watchDogTimer.every(2000, checkTransmissionTimeout); } /* ------------------------------------------------------------------------------------------------------------------------------------ * Software Reset * ------------------------------------------------------------------------------------------------------------------------------------ */ void(* resetFunc) (void) = 0; //declare reset function @ address 0 /* ------------------------------------------------------------------------------------------------------------------------------------ * Ethernet Functions * ------------------------------------------------------------------------------------------------------------------------------------ */ // send a reply, to the IP address and port that sent us the packet we received void sendReplyPacketOverEthernet( char* outBuffer) { Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(outBuffer); Udp.endPacket(); } // just acknowledge receipt of the test packet void replyToHeartBeat() { replyBuffer[0] = 'A'; replyBuffer[1] = 'c'; replyBuffer[2] = 'k'; sendReplyPacketOverEthernet(replyBuffer); } void forwardCANbusMessage(unsigned char* CANbuffer) { for (int i=0; i<24;i++) { replyBuffer[i]=0; } replyBuffer[0] = 'A'; // Answer replyBuffer[1] = 'C'; // to CAN request for (int i=0; i<len;i++) { replyBuffer[i+8]= CANbuffer[i]; // CAN bus message to byte 9 for reply } sendReplyPacketOverEthernet(replyBuffer); } void CANbusTimeOutMessage() { replyBuffer[0] = 'A'; // Answer replyBuffer[1] = 'C'; // CAN request replyBuffer[2] = 'O'; // Client Off-Line sendReplyPacketOverEthernet(replyBuffer); } /* ------------------------------------------------------------------------------------------------------------------------------------ * CAN bus functions * ------------------------------------------------------------------------------------------------------------------------------------ */ void sendCanMessage(int clientId,int format, int length, unsigned char* buf) { #if defined(DEBUG) Serial.println("Send CAN package "); #endif int canStatus = CAN.sendMsgBuf(clientId, format, length, buf); if (canStatus != 0) { Serial.print("CAN bus status "); Serial.print(canStatus); Serial.println(); }else { heartBeat++; } } // CAN message is 8 bytes, just copy from sender message to output void prepareCANmessage( char* inBuffer, unsigned char* outBuffer) { for (int i=0; i<len;i++) { outBuffer[i]= inBuffer[i+8]; // CAN bus message starts at byte 9 } } void readCANbusReply(unsigned char* canInBuffer){ while (CAN_MSGAVAIL == CAN.checkReceive()) { // read data, len: data length, buf: data buf int canStatus = CAN.readMsgBuf(&len, canInBuffer); if (canStatus != 0 && canStatus != 8) { Serial.print("CAN bus status "); Serial.print(canStatus); Serial.println(); }else { #if defined(DEBUG) Serial.println(" CAN response package received"); #endif responseExpected=false; // CAN bus message was read successfully - now send it back over the Ethernet forwardCANbusMessage(canInBuffer); heartBeat++; } watchDogTimer.update(); } } void checkTransmissionTimeout() { if (responseExpected) { canTimeout=true; } } /* ------------------------------------------------------------------------------------------------------------------------------------ * Main loop * Receive datagrams from a sender, pass on CAN bus commands and wait for answer. * If CAN bus clienet does not answer and timout reply is sent to the sender. * Datagram format: * Byte 0: "R" for Request * Byte 1: Command "T" = Test (Heartbeat) "C" = CAN bus message to client * ------------------------------------------------------------------------------------------------------------------------------------ */ void loop() { int packetSize = Udp.parsePacket(); // check presence of UDB packet if (packetSize>0){ Udp.read(packetBuffer, 24); // read the packet into packetBufffer switch ( packetBuffer[1] ) { case 'T': #if defined(DEBUG) Serial.println("Test Packet Received"); #endif replyToHeartBeat(); break; case 'C': #if defined(DEBUG) Serial.println("CAN Bus Packet Received"); #endif prepareCANmessage(packetBuffer,stmpOut); sendCanMessage(ourId,0,8,stmpOut); responseExpected=true; delay(50); readCANbusReply(stmpIn); break; } } if (canTimeout) { responseExpected= false; canTimeout = false; #if defined(DEBUG) Serial.println("CAN bus timeout"); CANbusTimeOutMessage(); #endif } watchDogTimer.update(); }
Add Comment
You must be logged in to post a comment.