Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
remoteControl.cpp
- Committer:
- rwcjoliver
- Date:
- 2020-03-13
- Revision:
- 0:4788e1df7b55
File content as of revision 0:4788e1df7b55:
#include <mbed.h>
#include "remoteControl.h"
#include "definitions.h"
Remote::Remote(SPI& remoteControl, DigitalOut& remoteControlCS) : _remoteControl(remoteControl), _remoteControlCS(remoteControlCS) {
_remoteControl.format(8,0); // FORMAT SPI AS 8-BIT DATA, SPI CLOCK MODE 0
const long arduinoClock = 16000000;
long spiFrequency = arduinoClock / 4;
_remoteControl.frequency(spiFrequency); // SET SPI CLOCK FREQUENCY
_remoteControlCS = 1; // DISABLE SLAVE
spiDelay = 600; //DELAY BETWEEN SPI TRANSACTIONS (SO ARDUINO CAN KEEP UP WITH REQUESTS)
commsGood = false; // Successful Comms Between Nucleo and Remote Control
commsFailures = 0; // Number of consecutive remote comms failures
errorIndex = 0;
// remoteSwitchStateTicker.attach(this, &Remote::getSwitchStates, 0.2);
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
}
int Remote::sendData(int precursor, int data) {
int response = 0;
_remoteControlCS = 0; // ENABLE REMOTE SPI
// pc.printf("Enabled \r\n");
_remoteControl.write(precursor); // Prepare arduino to receive data
wait_us(spiDelay);
_remoteControl.write(data); // SEND DATA
wait_us(spiDelay);
response = _remoteControl.write(255);
wait_us(spiDelay);
_remoteControlCS = 1; // DISABLE REMOTE SPI
// pc.printf("Disabling\r\n");
return response;
}
void Remote::commsCheck() {
// Send a random number to the controller and expect its square in return for valid operation.
// Random number between 2 and 15. Reply should be the squared, and within the 1 byte size limit of 255 for SPI comms.
// Does not conflict with switch states as they use ASCII A, B C etc which are Decimal 65+
int randomNumber = rand() % (15 - 2 + 1) + 2; // rand()%(max-min + 1) + min inclusive of max and min
int expectedResponse = randomNumber * randomNumber;
int actualResponse = 0;
actualResponse = sendData(1, randomNumber);
// pc.printf("Random Number: %d\r\n", randomNumber);
// pc.printf("Expected: %d\r\n", expectedResponse);
// pc.printf("Actual: %d\r\n", actualResponse);
if (actualResponse == expectedResponse) {
commsGood = true;
commsFailures = 0; // Reset consecutive failure count
}
else
{
// pc.printf("Failed at: \r\n");
// pc.printf("Random Number: %d\r\n", randomNumber);
// pc.printf("Expected: %d\r\n", expectedResponse);
// pc.printf("Actual: %d\r\n", actualResponse);
if (commsFailures++ > 3) { // Increment consecutive failure count
commsGood = false; // Flag comms failure after 3 failures (> 0.3 seconds)
// pc.printf("Remote Comms Failure!\r\n");
}
}
// pc.printf("commsGood: %d\r\n", commsGood);
}
// CONVERT BYTE TO BITS
/*
The received bytes from the remote control uses bitmapping.
Each 0/1 bit represents the on/ off state of a switch.
This function takes each bit and assigned it to a switch variable.
*/
void Remote::ByteToBits(unsigned char character, bool *boolArray)
{
for (int i=0; i < 8; ++i) {
boolArray[i] = (character & (1<<i)) != 0;
}
}
void Remote::getSwitchStates() {
// GET THE SWITCH STATES FROM THE REMOTE CONTROL
bool bitGroupA[8] = {1, 1, 1, 1, 1, 1, 1, 1};
bool bitGroupB[8] = {1, 1, 1, 1, 1, 1, 1, 1};
char slaveReceivedA, slaveReceivedB; // BYTE RECEIVED FROM REMOTE CONTROL
slaveReceivedA = sendData(3, 3);
slaveReceivedB = sendData(4, 4);
throttle = sendData(5, 5);
braking = sendData(6, 6);
ByteToBits(slaveReceivedA, bitGroupA); // CONVERT GROUP A BYTE TO BITS
ByteToBits(slaveReceivedB, bitGroupB); // CONVERT GROUP B BYTE TO BITS
// ASSIGN VARIABLES FROM BIT GROUPS
start = bitGroupA[0];
forward = bitGroupA[1];
park = bitGroupA[2];
reverse = bitGroupA[3];
compressor = bitGroupA[4];
autoStop = bitGroupA[5];
regenBrake = bitGroupA[6];
regenThrottle = bitGroupA[7];
whistle = bitGroupB[0];
innovation = bitGroupB[1];
// pc.printf("Start: %d\n\r", start);
// pc.printf("Forward: %d\n\r", forward);
// pc.printf("Park: %d\n\r", park);
// pc.printf("Reverse: %d\n\r", reverse);
// pc.printf("Compressor: %d\n\r", compressor);
// pc.printf("AutoStop: %d\n\r", autoStop);
// pc.printf("Regen Brake: %d\n\r", regenBrake);
// pc.printf("Regen Throttle: %d\n\r", regenThrottle);
// pc.printf("Whistle: %d\n\r", whistle);
// pc.printf("Innovation: %d\n\r", innovation);
// pc.printf("Throttle: %d\n\r", throttle);
// pc.printf("Brake: %d\n\r", braking);
}
void Remote::setTime(int hr, int min, int sec, int day, int mon, int yr) {
_remoteControlCS = 0;
_remoteControl.write(7);
wait_us(spiDelay);
_remoteControl.write(hr);
wait_us(spiDelay);
_remoteControl.write(min);
wait_us(spiDelay);
_remoteControl.write(sec);
wait_us(spiDelay);
_remoteControl.write(day);
wait_us(spiDelay);
_remoteControl.write(mon);
wait_us(spiDelay);
_remoteControl.write(yr);
wait_us(spiDelay);
_remoteControl.write(255);
_remoteControlCS = 1; // DISABLE REMOTE SPI
}
void Remote::sendError(int error) {
bool errorInBuffer = false;
for (int index = 0; index < errorIndex; index++) {
if (errorBuffer[index] == error) {
errorInBuffer == true;
break;
}
}
if (errorInBuffer == false) {
errorBuffer[errorIndex++] = error;
}
else {
errorInBuffer = false; // reset
}
sendData(8, errorBuffer[0]);
for (int index = 0; index < errorIndex; index++) {
errorBuffer[index] = errorBuffer[index + 1];
}
errorIndex--;
wait_ms(100);
}