Railway Challenge
/
challenge
Uncommenting of part that allow supercaps to charge up from the batteries
remoteControl.cpp@30:a04afea230fb, 2022-06-15 (annotated)
- Committer:
- jamesmcildowietfl
- Date:
- Wed Jun 15 11:33:56 2022 +0000
- Revision:
- 30:a04afea230fb
- Parent:
- 0:4788e1df7b55
Forgot to add light pins to header, done now ;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
rwcjoliver | 0:4788e1df7b55 | 1 | #include <mbed.h> |
rwcjoliver | 0:4788e1df7b55 | 2 | #include "remoteControl.h" |
rwcjoliver | 0:4788e1df7b55 | 3 | #include "definitions.h" |
rwcjoliver | 0:4788e1df7b55 | 4 | |
rwcjoliver | 0:4788e1df7b55 | 5 | Remote::Remote(SPI& remoteControl, DigitalOut& remoteControlCS) : _remoteControl(remoteControl), _remoteControlCS(remoteControlCS) { |
rwcjoliver | 0:4788e1df7b55 | 6 | _remoteControl.format(8,0); // FORMAT SPI AS 8-BIT DATA, SPI CLOCK MODE 0 |
rwcjoliver | 0:4788e1df7b55 | 7 | const long arduinoClock = 16000000; |
rwcjoliver | 0:4788e1df7b55 | 8 | long spiFrequency = arduinoClock / 4; |
rwcjoliver | 0:4788e1df7b55 | 9 | _remoteControl.frequency(spiFrequency); // SET SPI CLOCK FREQUENCY |
rwcjoliver | 0:4788e1df7b55 | 10 | |
rwcjoliver | 0:4788e1df7b55 | 11 | _remoteControlCS = 1; // DISABLE SLAVE |
rwcjoliver | 0:4788e1df7b55 | 12 | spiDelay = 600; //DELAY BETWEEN SPI TRANSACTIONS (SO ARDUINO CAN KEEP UP WITH REQUESTS) |
rwcjoliver | 0:4788e1df7b55 | 13 | |
rwcjoliver | 0:4788e1df7b55 | 14 | commsGood = false; // Successful Comms Between Nucleo and Remote Control |
rwcjoliver | 0:4788e1df7b55 | 15 | commsFailures = 0; // Number of consecutive remote comms failures |
rwcjoliver | 0:4788e1df7b55 | 16 | errorIndex = 0; |
rwcjoliver | 0:4788e1df7b55 | 17 | |
rwcjoliver | 0:4788e1df7b55 | 18 | // remoteSwitchStateTicker.attach(this, &Remote::getSwitchStates, 0.2); |
rwcjoliver | 0:4788e1df7b55 | 19 | commsCheckTicker.attach(this, &Remote::commsCheck, 0.2); // Run the commsCheck function every 0.1s with the commsCheckTicker. - &commsCheck = The address of the function to be attached and 0.1 = the interval |
rwcjoliver | 0:4788e1df7b55 | 20 | } |
rwcjoliver | 0:4788e1df7b55 | 21 | |
rwcjoliver | 0:4788e1df7b55 | 22 | int Remote::sendData(int precursor, int data) { |
rwcjoliver | 0:4788e1df7b55 | 23 | int response = 0; |
rwcjoliver | 0:4788e1df7b55 | 24 | |
rwcjoliver | 0:4788e1df7b55 | 25 | _remoteControlCS = 0; // ENABLE REMOTE SPI |
rwcjoliver | 0:4788e1df7b55 | 26 | // pc.printf("Enabled \r\n"); |
rwcjoliver | 0:4788e1df7b55 | 27 | _remoteControl.write(precursor); // Prepare arduino to receive data |
rwcjoliver | 0:4788e1df7b55 | 28 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 29 | _remoteControl.write(data); // SEND DATA |
rwcjoliver | 0:4788e1df7b55 | 30 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 31 | response = _remoteControl.write(255); |
rwcjoliver | 0:4788e1df7b55 | 32 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 33 | |
rwcjoliver | 0:4788e1df7b55 | 34 | _remoteControlCS = 1; // DISABLE REMOTE SPI |
rwcjoliver | 0:4788e1df7b55 | 35 | // pc.printf("Disabling\r\n"); |
rwcjoliver | 0:4788e1df7b55 | 36 | |
rwcjoliver | 0:4788e1df7b55 | 37 | return response; |
rwcjoliver | 0:4788e1df7b55 | 38 | } |
rwcjoliver | 0:4788e1df7b55 | 39 | |
rwcjoliver | 0:4788e1df7b55 | 40 | void Remote::commsCheck() { |
rwcjoliver | 0:4788e1df7b55 | 41 | // Send a random number to the controller and expect its square in return for valid operation. |
rwcjoliver | 0:4788e1df7b55 | 42 | |
rwcjoliver | 0:4788e1df7b55 | 43 | // Random number between 2 and 15. Reply should be the squared, and within the 1 byte size limit of 255 for SPI comms. |
rwcjoliver | 0:4788e1df7b55 | 44 | // Does not conflict with switch states as they use ASCII A, B C etc which are Decimal 65+ |
rwcjoliver | 0:4788e1df7b55 | 45 | int randomNumber = rand() % (15 - 2 + 1) + 2; // rand()%(max-min + 1) + min inclusive of max and min |
rwcjoliver | 0:4788e1df7b55 | 46 | int expectedResponse = randomNumber * randomNumber; |
rwcjoliver | 0:4788e1df7b55 | 47 | int actualResponse = 0; |
rwcjoliver | 0:4788e1df7b55 | 48 | |
rwcjoliver | 0:4788e1df7b55 | 49 | actualResponse = sendData(1, randomNumber); |
rwcjoliver | 0:4788e1df7b55 | 50 | |
rwcjoliver | 0:4788e1df7b55 | 51 | // pc.printf("Random Number: %d\r\n", randomNumber); |
rwcjoliver | 0:4788e1df7b55 | 52 | // pc.printf("Expected: %d\r\n", expectedResponse); |
rwcjoliver | 0:4788e1df7b55 | 53 | // pc.printf("Actual: %d\r\n", actualResponse); |
rwcjoliver | 0:4788e1df7b55 | 54 | |
rwcjoliver | 0:4788e1df7b55 | 55 | if (actualResponse == expectedResponse) { |
rwcjoliver | 0:4788e1df7b55 | 56 | commsGood = true; |
rwcjoliver | 0:4788e1df7b55 | 57 | commsFailures = 0; // Reset consecutive failure count |
rwcjoliver | 0:4788e1df7b55 | 58 | } |
rwcjoliver | 0:4788e1df7b55 | 59 | else |
rwcjoliver | 0:4788e1df7b55 | 60 | { |
rwcjoliver | 0:4788e1df7b55 | 61 | // pc.printf("Failed at: \r\n"); |
rwcjoliver | 0:4788e1df7b55 | 62 | // pc.printf("Random Number: %d\r\n", randomNumber); |
rwcjoliver | 0:4788e1df7b55 | 63 | // pc.printf("Expected: %d\r\n", expectedResponse); |
rwcjoliver | 0:4788e1df7b55 | 64 | // pc.printf("Actual: %d\r\n", actualResponse); |
rwcjoliver | 0:4788e1df7b55 | 65 | |
rwcjoliver | 0:4788e1df7b55 | 66 | if (commsFailures++ > 3) { // Increment consecutive failure count |
rwcjoliver | 0:4788e1df7b55 | 67 | commsGood = false; // Flag comms failure after 3 failures (> 0.3 seconds) |
rwcjoliver | 0:4788e1df7b55 | 68 | // pc.printf("Remote Comms Failure!\r\n"); |
rwcjoliver | 0:4788e1df7b55 | 69 | } |
rwcjoliver | 0:4788e1df7b55 | 70 | } |
rwcjoliver | 0:4788e1df7b55 | 71 | // pc.printf("commsGood: %d\r\n", commsGood); |
rwcjoliver | 0:4788e1df7b55 | 72 | } |
rwcjoliver | 0:4788e1df7b55 | 73 | |
rwcjoliver | 0:4788e1df7b55 | 74 | // CONVERT BYTE TO BITS |
rwcjoliver | 0:4788e1df7b55 | 75 | /* |
rwcjoliver | 0:4788e1df7b55 | 76 | The received bytes from the remote control uses bitmapping. |
rwcjoliver | 0:4788e1df7b55 | 77 | Each 0/1 bit represents the on/ off state of a switch. |
rwcjoliver | 0:4788e1df7b55 | 78 | This function takes each bit and assigned it to a switch variable. |
rwcjoliver | 0:4788e1df7b55 | 79 | */ |
rwcjoliver | 0:4788e1df7b55 | 80 | void Remote::ByteToBits(unsigned char character, bool *boolArray) |
rwcjoliver | 0:4788e1df7b55 | 81 | { |
rwcjoliver | 0:4788e1df7b55 | 82 | for (int i=0; i < 8; ++i) { |
rwcjoliver | 0:4788e1df7b55 | 83 | boolArray[i] = (character & (1<<i)) != 0; |
rwcjoliver | 0:4788e1df7b55 | 84 | } |
rwcjoliver | 0:4788e1df7b55 | 85 | } |
rwcjoliver | 0:4788e1df7b55 | 86 | |
rwcjoliver | 0:4788e1df7b55 | 87 | void Remote::getSwitchStates() { |
rwcjoliver | 0:4788e1df7b55 | 88 | // GET THE SWITCH STATES FROM THE REMOTE CONTROL |
rwcjoliver | 0:4788e1df7b55 | 89 | |
rwcjoliver | 0:4788e1df7b55 | 90 | |
rwcjoliver | 0:4788e1df7b55 | 91 | bool bitGroupA[8] = {1, 1, 1, 1, 1, 1, 1, 1}; |
rwcjoliver | 0:4788e1df7b55 | 92 | bool bitGroupB[8] = {1, 1, 1, 1, 1, 1, 1, 1}; |
rwcjoliver | 0:4788e1df7b55 | 93 | |
rwcjoliver | 0:4788e1df7b55 | 94 | char slaveReceivedA, slaveReceivedB; // BYTE RECEIVED FROM REMOTE CONTROL |
rwcjoliver | 0:4788e1df7b55 | 95 | |
rwcjoliver | 0:4788e1df7b55 | 96 | slaveReceivedA = sendData(3, 3); |
rwcjoliver | 0:4788e1df7b55 | 97 | slaveReceivedB = sendData(4, 4); |
rwcjoliver | 0:4788e1df7b55 | 98 | throttle = sendData(5, 5); |
rwcjoliver | 0:4788e1df7b55 | 99 | braking = sendData(6, 6); |
rwcjoliver | 0:4788e1df7b55 | 100 | |
rwcjoliver | 0:4788e1df7b55 | 101 | ByteToBits(slaveReceivedA, bitGroupA); // CONVERT GROUP A BYTE TO BITS |
rwcjoliver | 0:4788e1df7b55 | 102 | ByteToBits(slaveReceivedB, bitGroupB); // CONVERT GROUP B BYTE TO BITS |
rwcjoliver | 0:4788e1df7b55 | 103 | |
rwcjoliver | 0:4788e1df7b55 | 104 | // ASSIGN VARIABLES FROM BIT GROUPS |
rwcjoliver | 0:4788e1df7b55 | 105 | |
rwcjoliver | 0:4788e1df7b55 | 106 | start = bitGroupA[0]; |
rwcjoliver | 0:4788e1df7b55 | 107 | forward = bitGroupA[1]; |
rwcjoliver | 0:4788e1df7b55 | 108 | park = bitGroupA[2]; |
rwcjoliver | 0:4788e1df7b55 | 109 | reverse = bitGroupA[3]; |
rwcjoliver | 0:4788e1df7b55 | 110 | compressor = bitGroupA[4]; |
rwcjoliver | 0:4788e1df7b55 | 111 | autoStop = bitGroupA[5]; |
rwcjoliver | 0:4788e1df7b55 | 112 | regenBrake = bitGroupA[6]; |
rwcjoliver | 0:4788e1df7b55 | 113 | regenThrottle = bitGroupA[7]; |
rwcjoliver | 0:4788e1df7b55 | 114 | |
rwcjoliver | 0:4788e1df7b55 | 115 | whistle = bitGroupB[0]; |
rwcjoliver | 0:4788e1df7b55 | 116 | innovation = bitGroupB[1]; |
rwcjoliver | 0:4788e1df7b55 | 117 | |
rwcjoliver | 0:4788e1df7b55 | 118 | // pc.printf("Start: %d\n\r", start); |
rwcjoliver | 0:4788e1df7b55 | 119 | // pc.printf("Forward: %d\n\r", forward); |
rwcjoliver | 0:4788e1df7b55 | 120 | // pc.printf("Park: %d\n\r", park); |
rwcjoliver | 0:4788e1df7b55 | 121 | // pc.printf("Reverse: %d\n\r", reverse); |
rwcjoliver | 0:4788e1df7b55 | 122 | // pc.printf("Compressor: %d\n\r", compressor); |
rwcjoliver | 0:4788e1df7b55 | 123 | // pc.printf("AutoStop: %d\n\r", autoStop); |
rwcjoliver | 0:4788e1df7b55 | 124 | // pc.printf("Regen Brake: %d\n\r", regenBrake); |
rwcjoliver | 0:4788e1df7b55 | 125 | // pc.printf("Regen Throttle: %d\n\r", regenThrottle); |
rwcjoliver | 0:4788e1df7b55 | 126 | // pc.printf("Whistle: %d\n\r", whistle); |
rwcjoliver | 0:4788e1df7b55 | 127 | // pc.printf("Innovation: %d\n\r", innovation); |
rwcjoliver | 0:4788e1df7b55 | 128 | // pc.printf("Throttle: %d\n\r", throttle); |
rwcjoliver | 0:4788e1df7b55 | 129 | // pc.printf("Brake: %d\n\r", braking); |
rwcjoliver | 0:4788e1df7b55 | 130 | |
rwcjoliver | 0:4788e1df7b55 | 131 | } |
rwcjoliver | 0:4788e1df7b55 | 132 | |
rwcjoliver | 0:4788e1df7b55 | 133 | void Remote::setTime(int hr, int min, int sec, int day, int mon, int yr) { |
rwcjoliver | 0:4788e1df7b55 | 134 | _remoteControlCS = 0; |
rwcjoliver | 0:4788e1df7b55 | 135 | |
rwcjoliver | 0:4788e1df7b55 | 136 | _remoteControl.write(7); |
rwcjoliver | 0:4788e1df7b55 | 137 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 138 | _remoteControl.write(hr); |
rwcjoliver | 0:4788e1df7b55 | 139 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 140 | _remoteControl.write(min); |
rwcjoliver | 0:4788e1df7b55 | 141 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 142 | _remoteControl.write(sec); |
rwcjoliver | 0:4788e1df7b55 | 143 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 144 | _remoteControl.write(day); |
rwcjoliver | 0:4788e1df7b55 | 145 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 146 | _remoteControl.write(mon); |
rwcjoliver | 0:4788e1df7b55 | 147 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 148 | _remoteControl.write(yr); |
rwcjoliver | 0:4788e1df7b55 | 149 | wait_us(spiDelay); |
rwcjoliver | 0:4788e1df7b55 | 150 | _remoteControl.write(255); |
rwcjoliver | 0:4788e1df7b55 | 151 | |
rwcjoliver | 0:4788e1df7b55 | 152 | _remoteControlCS = 1; // DISABLE REMOTE SPI |
rwcjoliver | 0:4788e1df7b55 | 153 | } |
rwcjoliver | 0:4788e1df7b55 | 154 | |
rwcjoliver | 0:4788e1df7b55 | 155 | void Remote::sendError(int error) { |
rwcjoliver | 0:4788e1df7b55 | 156 | |
rwcjoliver | 0:4788e1df7b55 | 157 | bool errorInBuffer = false; |
rwcjoliver | 0:4788e1df7b55 | 158 | |
rwcjoliver | 0:4788e1df7b55 | 159 | for (int index = 0; index < errorIndex; index++) { |
rwcjoliver | 0:4788e1df7b55 | 160 | if (errorBuffer[index] == error) { |
rwcjoliver | 0:4788e1df7b55 | 161 | errorInBuffer == true; |
rwcjoliver | 0:4788e1df7b55 | 162 | break; |
rwcjoliver | 0:4788e1df7b55 | 163 | } |
rwcjoliver | 0:4788e1df7b55 | 164 | } |
rwcjoliver | 0:4788e1df7b55 | 165 | |
rwcjoliver | 0:4788e1df7b55 | 166 | if (errorInBuffer == false) { |
rwcjoliver | 0:4788e1df7b55 | 167 | errorBuffer[errorIndex++] = error; |
rwcjoliver | 0:4788e1df7b55 | 168 | } |
rwcjoliver | 0:4788e1df7b55 | 169 | else { |
rwcjoliver | 0:4788e1df7b55 | 170 | errorInBuffer = false; // reset |
rwcjoliver | 0:4788e1df7b55 | 171 | } |
rwcjoliver | 0:4788e1df7b55 | 172 | |
rwcjoliver | 0:4788e1df7b55 | 173 | sendData(8, errorBuffer[0]); |
rwcjoliver | 0:4788e1df7b55 | 174 | |
rwcjoliver | 0:4788e1df7b55 | 175 | for (int index = 0; index < errorIndex; index++) { |
rwcjoliver | 0:4788e1df7b55 | 176 | errorBuffer[index] = errorBuffer[index + 1]; |
rwcjoliver | 0:4788e1df7b55 | 177 | } |
rwcjoliver | 0:4788e1df7b55 | 178 | errorIndex--; |
rwcjoliver | 0:4788e1df7b55 | 179 | |
rwcjoliver | 0:4788e1df7b55 | 180 | wait_ms(100); |
rwcjoliver | 0:4788e1df7b55 | 181 | } |