#include <FlexCAN.h>
#include <kinetis_flexcan.h>
#include <SD.h>
#include <SD_t3.h>
#include <Metro.h>
#include <SPI.h>
/*
Epic Solutions 32 Relay board
Mike Benson
Rev 6 3/17/16
*/
void updateRelays (byte relayOutA, byte relayOutB, byte relayOutC, byte relayOutD);
FlexCAN CANbus(1000000);
static struct CAN_message_t rxmsg;
static struct CAN_filter_t filter, mask;
Metro lostComms = Metro(500);
byte i;
byte newCANinfo [8];
bool newCANinfoflag = false;
byte relayInA[4] = {0};
byte relayInB[4] = {0};
byte relayInC[4] = {0};
byte relayInD[4] = {0};
byte finaloutA = 0;
byte finaloutB = 0;
byte finaloutC = 0;
byte finaloutD = 0;
byte CANidBits[4] = {0};
byte CANid = 0;
byte PLCid = 0;
const int LED_U5 = 20; // I/O pin numbers
const int LED_U9 = 21;
const int SpeedPulse = 0;
const int StrokeA = 5;
const int StrokeB = 6;
const int StrokeC = 7;
const int MicroSD_CS = 8;
const int SPIexpand2_CS = 9;
const int SPIexpand1_CS = 10;
const int CANid1 = 14;
const int CANid2 = 15;
const int CANid4 = 16;
const int CANid8 = 17;
byte lostCommCounter = 0;
/* The following setup routine initialises I/O pins, starts the CANbus and SPI bus, sets the pulse counters to a high number, then attatches an
interrupt for the speed pulse. Finally the SPI settings are initialized and the SPI expanders are initialized and configured.*/
void setup()
{
pinMode (CANid1, INPUT);
pinMode (CANid2, INPUT);
pinMode (CANid4, INPUT);
pinMode (CANid8, INPUT);
mask.id = (byte) 0xFF;
CANidBits[0] = digitalRead(CANid1);
CANidBits[1] = digitalRead(CANid2);
CANidBits[2] = digitalRead(CANid4);
CANidBits[3] = digitalRead(CANid8);
CANid = (byte) (1 * CANidBits[0] + 2 * CANidBits[1]+ 4 * CANidBits[2] + 8 * CANidBits[3]);
CANid = (byte) CANid<<3;
CANid = CANid + 4;
filter.id = (byte) CANid;
CANbus.setFilter(filter,0);
CANbus.begin(1000000, mask);
SPI.begin();
SD.begin(8); // CS pin 8
pinMode (SpeedPulse, INPUT); // I/O pin direction and initialization
pinMode (StrokeA, INPUT);
pinMode (StrokeB, INPUT);
pinMode (StrokeC, INPUT);
pinMode (MicroSD_CS, OUTPUT);
digitalWrite (MicroSD_CS, 1);
pinMode (SPIexpand2_CS, OUTPUT);
digitalWrite (SPIexpand2_CS, 1);
pinMode (SPIexpand1_CS, OUTPUT);
digitalWrite (SPIexpand1_CS, 1);
pinMode (LED_U5, OUTPUT);
digitalWrite (LED_U5, 0);
pinMode (LED_U9, OUTPUT);
digitalWrite (LED_U9, 0);
// CANid = (byte) (1 * CANidBits[0] + 2 * CANidBits[1]+ 4 * CANidBits[2] + 8 * CANidBits[3]);
// CANid = (byte) CANid<<3 + 4;
// Serial.println(CANid);
//
// filter.id = (byte) CANid;
// CANbus.setFilter(filter,0);
digitalWrite(LED_U5, 1);
delay(100);
SPISettings(10000000, MSBFIRST, SPI_MODE0);
digitalWrite(SPIexpand1_CS, 0); // Select I/O Expander A for initialization
SPI.transfer16(0x400A); // OPcode to write to Expander A and The address of the configuration register
SPI.transfer(0x1A); // sets register addresses, enables sequential write operation, and enables hardware address bits
digitalWrite(SPIexpand1_CS, 1);
digitalWrite(SPIexpand1_CS, 0);
SPI.transfer16(0x4000); // OPcode and address for IO configuration register
SPI.transfer16(0x0000); // Sets all expanded connections as outputs
digitalWrite(SPIexpand1_CS, 1);
digitalWrite(SPIexpand1_CS, 0); // This set of commands ensures that the relays start in the off state
SPI.transfer16(0x4014);
SPI.transfer16(0x0000);
digitalWrite(SPIexpand1_CS, 1);
digitalWrite(SPIexpand2_CS, 0); // Select I/O Expander B for initialization
SPI.transfer16(0x420A); // OPcode to write to Expander B and The address of the configuration register
SPI.transfer(0x1A); // sets register addresses and enables sequential write operation
digitalWrite(SPIexpand2_CS, 1);
digitalWrite(SPIexpand2_CS, 0);
SPI.transfer16(0x4200); // OPcode and address for IO configuration register
SPI.transfer16(0x0000); // Sets all 16 expanded connections as outputs
digitalWrite(SPIexpand2_CS, 1);
digitalWrite(SPIexpand2_CS, 0); // This set of commands ensures that the relays start in the off state
SPI.transfer16(0x4214);
SPI.transfer16(0x0000);
digitalWrite(SPIexpand2_CS, 1);
updateRelays(0,0,0,0);
delay(5000);
digitalWrite(LED_U5, 0);
}
void loop()
{
// put your main code here, to run repeatedly:
Serial.println(CANid);
if (CANid == 4)
{
delay(100);
if (finaloutD < 255)
{
if (finaloutC < 255)
{
if (finaloutB< 255)
{
if (finaloutA < 255)
{
finaloutA++;
}
if(finaloutA == 255)
finaloutB++;
}
if(finaloutB ==255)
finaloutC++;
}
if (finaloutC == 255)
finaloutD++;
}
updateRelays(finaloutA, finaloutB, finaloutC, finaloutD);
} else if (CANid != 4)
{
if (CANbus.available())
{ // checks if there is a waiting message, if so then it reads it in
digitalWrite(LED_U9, 0);
while (CANbus.read(rxmsg))
{
lostCommCounter = 0;
// Serial.println(CANid);
// Serial.println("ID");
// Serial.println(rxmsg.id);
// Serial.println("\n");
// Serial.println("EXT");
// Serial.println(rxmsg.ext);
// Serial.println("LENGTH");
// Serial.println(rxmsg.len);
// Serial.println("timeout");
// Serial.println(rxmsg.timeout);
// if (CANid == (byte) rxmsg.id)
// {
for (i = 0; i < 8; i++)
{
newCANinfo[i] = (byte) rxmsg.buf[i];
// Serial.println(newCANinfo[i]);
newCANinfoflag = true;
// Serial.println(rxmsg.buf[i]);
}
// }
}
lostComms.reset();
// Serial.println("\n\n");
} else if (lostComms.check())
{
if (lostCommCounter < 2)
{
lostCommCounter++;
}
if (lostCommCounter == 2)
updateRelays(0,0,0,0);
digitalWrite(LED_U9, 1);
}
if (newCANinfoflag)
{
PLCid = (byte) newCANinfo[4]-15;
// Serial.println(PLCid);
if ((0 <= PLCid) && (PLCid <= 3))
{
relayInA [PLCid] = (byte) newCANinfo[0];
relayInB [PLCid] = (byte) newCANinfo[1];
relayInC [PLCid] = (byte) newCANinfo[2];
relayInD [PLCid] = (byte) newCANinfo[3];
finaloutA = relayInA[0] | relayInA[1] | relayInA[2] | relayInA[3];
finaloutB = relayInB[0] | relayInB[1] | relayInB[2] | relayInB[3];
finaloutC = relayInC[0] | relayInC[1] | relayInC[2] | relayInC[3];
finaloutD = relayInD[0] | relayInD[1] | relayInD[2] | relayInD[3];
updateRelays(finaloutA, finaloutB, finaloutC, finaloutD);
newCANinfoflag = false;
} else
{
newCANinfoflag = false;
}
}
}
}
//This funcion turns on the correct output pins based on the state of the relay output variabls.
void updateRelays (byte relayOutA, byte relayOutB, byte relayOutC, byte relayOutD)
{
// Serial.println("Update Relays");
// Serial.println(relayOutA, HEX);
// Serial.println(relayOutB, HEX);
// Serial.println(relayOutC, HEX);
// Serial.println(relayOutD, HEX);
// Serial.print("\n \n");
unsigned long relayMap = 0;
relayMap = relayOutA + 0x100 * relayOutB + 0x10000 * relayOutC + 0x1000000 * relayOutD; // Joins the relay variables to allow mapping of the output connections
// Serial.println(relayMap, HEX);
relayMap = (unsigned long) (relayMap & 0x000001ff) // Mapping operations to arrange output connections
| ((relayMap & 0x00000e00) << 20)
| ((relayMap & 0xfffff000) >> 3);
relayOutA = (byte) relayMap; // Split mapped variable into seperate bytes to send to SPI expander
relayMap = relayMap >> 8;
relayOutB = (byte) relayMap;
relayMap = relayMap >> 8;
relayOutC = (byte) relayMap;
relayMap = relayMap >> 8;
relayOutD = (byte) relayMap;
// Serial.println("Update Relays");
// //
// Serial.println(relayOutA, HEX);
// Serial.println(relayOutB, BIN);
// Serial.println(relayOutC, HEX);
// Serial.println(relayOutD, HEX);
// Serial.print("\n \n");
digitalWrite(SPIexpand1_CS, 0); // Update relays on Expander A first
SPI.transfer16(0x4014); // Expander A address and address for port A
SPI.transfer(relayOutC); // sets the state for the A bank of outputs to relayOutC
SPI.transfer(relayOutD); // sets the state for the B bank of outputs to relayOutD
digitalWrite(SPIexpand1_CS, 1);
digitalWrite(SPIexpand2_CS, 0); // Update relays on Expander B
SPI.transfer16(0x4214); // Expander B address and address for Port A
SPI.transfer(relayOutA); // sets the state for the A bank of outputs to relayOutA
SPI.transfer(relayOutB); // sets the state for the B bank of outputs to relayOutB
digitalWrite(SPIexpand2_CS, 1);
// relayOutA++;
// digitalWrite(LED_U5, 0);
}