diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..34efa57 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/include/FlatCar.h b/include/FlatCar.h new file mode 100644 index 0000000..0b2a2f0 --- /dev/null +++ b/include/FlatCar.h @@ -0,0 +1,54 @@ +#ifndef FLATCAR_H +#define FLATCAR_H + +extern bool canSniffState; +extern int USER_INPUT; +extern float SPEED; +extern float RPS; +extern unsigned long speedUpdate; +extern int brakeVal; +extern int throttleVal; +extern float targetRunTime; // In minutes when selected by the user +extern unsigned long runTime; // Target run time of user in millis +extern unsigned long currentTime; +extern unsigned long DIGITAL_UPDATE; // How often Digital sensors should be updated +extern unsigned long digitalElapsed; +extern unsigned long digitalLast; +extern unsigned long WHEEL_UPDATE; +extern unsigned long wheelElapsed; +extern unsigned long wheelLast; +extern unsigned long ANALOG_UPDATE; +extern unsigned long analogElapsed; +extern unsigned long analogLast; +extern long randomAnalog; +extern unsigned long CAN_UPDATE; +extern unsigned long canElapsed; +extern unsigned long canLast; +extern unsigned long CAN_SNIFF_UPDATE; +extern unsigned long canSniffElapsed; +extern unsigned long canSniffLast; + +extern bool wheelStatus; // Used to store current wheel sensor status + +extern const int WHEEL_SPEED_PINS[]; +extern int START_SWITCH_PIN; +extern int BRAKE_1_PIN; +extern int TRACTIVE_PIN; +extern int THROTTLE_1_PIN; +extern int THROTTLE_2_PIN; + +extern const int NUM_WHEEL_SPEED_PINS; + + +void menuSelect(); +void canSetup(); +void pinSetup(); +void canSniff(); +void menuInit(); +void runPrograms(); +void staticTest(); +void variableTest(); +void randomTest(); +void simTest(); + +#endif diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..a13d034 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,14 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:teensy41] +platform = teensy +board = teensy41 +framework = arduino diff --git a/src/FlatCar.cpp b/src/FlatCar.cpp new file mode 100644 index 0000000..8e13d2e --- /dev/null +++ b/src/FlatCar.cpp @@ -0,0 +1,416 @@ +#include "FlatCar.h" +#include + +FlexCAN_T4 CORE_CAN; +FlexCAN_T4 AUX_CAN; + + +bool canSniffState = false; +int USER_INPUT = 0; +float SPEED = 0.0; +float RPS = 0.0; +unsigned long speedUpdate = 0; +int brakeVal = 0; +int throttleVal = 0; +float targetRunTime = 0.0; +unsigned long runTime = 0; +unsigned long currentTime = 0; +unsigned long DIGITAL_UPDATE = 0; +unsigned long digitalElapsed = 0; +unsigned long digitalLast = 0; +unsigned long WHEEL_UPDATE = 0; +unsigned long wheelElapsed = 0; +unsigned long wheelLast = 0; +unsigned long ANALOG_UPDATE = 0; +unsigned long analogElapsed = 0; +unsigned long analogLast = 0; +long randomAnalog = 0; +unsigned long CAN_UPDATE = 0; +unsigned long canElapsed = 0; +unsigned long canLast = 0; +unsigned long CAN_SNIFF_UPDATE = 0; +unsigned long canSniffElapsed = 0; +unsigned long canSniffLast = 0; +bool wheelStatus = false; + +const int WHEEL_SPEED_PINS[] = {2, 3, 4, 5}; +int START_SWITCH_PIN = 26; +int BRAKE_1_PIN = 27; +int TRACTIVE_PIN = 9; +int THROTTLE_1_PIN = 37; +int THROTTLE_2_PIN = 38; +const int NUM_WHEEL_SPEED_PINS = sizeof(WHEEL_SPEED_PINS) / sizeof(WHEEL_SPEED_PINS[0]); + + +void canSetup() { + CORE_CAN.begin(); + CORE_CAN.setBaudRate(250000); + AUX_CAN.begin(); + AUX_CAN.setBaudRate(250000); +} + + +void pinSetup() { + for (int i = 0; i < NUM_WHEEL_SPEED_PINS; i++) { + pinMode(WHEEL_SPEED_PINS[i], OUTPUT); + Serial.print("WHEEL SPEED PIN "); + Serial.print(WHEEL_SPEED_PINS[i]); + Serial.println(" INITIALIZED"); + } + + pinMode(START_SWITCH_PIN, OUTPUT); + Serial.print("SWITCH PIN: "); + Serial.print(START_SWITCH_PIN); + Serial.println(" INITIALIZED"); + + pinMode(BRAKE_1_PIN, OUTPUT); + Serial.print("BRAKE 1 PIN "); + Serial.print(BRAKE_1_PIN); + Serial.println(" INITIALIZED"); + + pinMode(TRACTIVE_PIN, OUTPUT); + Serial.print("TRACTIVE PIN "); + Serial.print(TRACTIVE_PIN); + Serial.println(" INITIALIZED"); + + pinMode(THROTTLE_1_PIN, OUTPUT); + Serial.print("THROTTLE 1 PIN "); + Serial.print(THROTTLE_1_PIN); + Serial.println(" INITIALIZED"); + + pinMode(THROTTLE_2_PIN, OUTPUT); + Serial.print("THROTTLE 2 PIN "); + Serial.print(THROTTLE_2_PIN); + Serial.println(" INITIALIZED"); + + Serial.println("ALL PINS INITIALIZED"); +} + +void canSniff() { + CAN_message_t msg; + if (CORE_CAN.read(msg)) { + Serial.print("[CORE CAN] ID: "); + Serial.print(msg.id); + Serial.print(" LENGTH: "); + Serial.print(msg.len); + Serial.print(" DATA: "); + for (uint8_t i = 0; i < msg.len; i++) { + Serial.print(msg.buf[i]); + Serial.print(" "); + } + Serial.println(); + } + + if (AUX_CAN.read(msg)) { + Serial.print("[AUX CAN] ID: "); + Serial.print(msg.id); + Serial.print(" LENGTH: "); + Serial.print(msg.len); + Serial.print(" DATA: "); + for (uint8_t i = 0; i < msg.len; i++) { + Serial.print(msg.buf[i]); + Serial.print(" "); + } + Serial.println(); + } + canSniffLast = millis(); +} + +void menuInit() { + Serial.println("WELCOME TO FLATCAR"); + Serial.println("START MENU:"); + Serial.println("1) STATIC VALUE TEST"); + Serial.println("2) VARIABLE VALUE TEST"); + Serial.println("3) RANDOM VALUE TEST"); + Serial.println("4) RUN SIM"); + Serial.println("5) EXIT"); +} + +void menuSelect() { + menuInit(); + + Serial.println("WAITING FOR INPUT"); + Serial.print("SELECTION: "); + while (!Serial.available()) { + // Wait for serial input + } + USER_INPUT = Serial.read() - '0'; + Serial.println(USER_INPUT); + + Serial.print("TARGET RUN TIME (MIN): "); + while (!Serial.available()) { + // Wait for serial input + } + targetRunTime = Serial.parseFloat(); + Serial.println(targetRunTime); + + Serial.print("TOGGLE CAN SNIFF (1/0): "); + while (!Serial.available()) { + // Wait for serial input + } + canSniffState = (Serial.read() == '1'); + Serial.println(canSniffState); + + switch (USER_INPUT) { + case 1: + Serial.println("SELECTED: STATIC VALUE TEST"); + Serial.print("TARGET RUN TIME (MIN): "); + Serial.println(targetRunTime); + break; + case 2: + Serial.println("SELECTED: VARIABLE VALUE TEST"); + Serial.print("TARGET RUN TIME (MIN): "); + Serial.println(targetRunTime); + break; + case 3: + Serial.println("SELECTED: RANDOM VALUE TEST"); + Serial.print("TARGET RUN TIME (MIN): "); + Serial.println(targetRunTime); + break; + case 4: + Serial.println("SELECTED: RUN SIM"); + Serial.print("TARGET RUN TIME (MIN): "); + Serial.println(targetRunTime); + break; + case 5: + Serial.println("EXITING..."); + break; + default: + Serial.println("INVALID CHOICE"); + break; + } +} + +void runPrograms() { + switch (USER_INPUT) { + case 1: + Serial.println(">>>STARTING STATIC VALUE TEST<<<"); + staticTest(); + break; + case 2: + Serial.println(">>>STARTING VARIABLE VALUE TEST<<<"); + variableTest(); + break; + case 3: + Serial.println(">>>STARTING RANDOM VALUE TEST<<<"); + randomTest(); + break; + case 4: + simTest(); + break; + } +} + +void startSequence() { + digitalWrite(START_SWITCH_PIN, HIGH); + digitalWrite(TRACTIVE_PIN, HIGH); +} + +void motorCAN() { + return; +} + +void BMSCAN() { + return; +} + +void staticTest() { + startSequence(); + for (int i = 0; i < 4; i++) { + digitalWrite(WHEEL_SPEED_PINS[i], HIGH); + } + analogWrite(BRAKE_1_PIN, 127); + analogWrite(THROTTLE_1_PIN, 127); + analogWrite(THROTTLE_2_PIN, 127); + + Serial.println("<<>>"); + while (Serial.available()) { + // wait for Serial input + } +} + +void updateTimes() { + // Update all times to get current elapse times + currentTime = millis(); + digitalElapsed = currentTime - digitalLast; + analogElapsed = currentTime - analogLast; + wheelElapsed = currentTime - wheelLast; + canElapsed = currentTime - canLast; + canSniffElapsed = currentTime - canSniffLast; + +} + +void updateRates() { + DIGITAL_UPDATE = 1000; + ANALOG_UPDATE = 100; + WHEEL_UPDATE = 350; // Wheel update value for 10 mph initial start + CAN_UPDATE = 100; + brakeVal = 0; + throttleVal = 0; + SPEED = 10; + speedUpdate = 5000; + CAN_SNIFF_UPDATE = 15; +} + +void variableTest() { + startSequence(); + updateRates(); + runTime = currentTime + (targetRunTime * 60000); + + updateTimes(); + + Serial.println("VARIABLE TEST INITALIZED"); + Serial.print("TARGET_RUN_TIME: "); + Serial.println(targetRunTime); + Serial.print("RUN_TIME: "); + Serial.println(runTime); + Serial.print("CURRENT_TIME: "); + Serial.println(currentTime); + + while (currentTime < runTime) { + + updateTimes(); + + if (canSniffElapsed >= CAN_SNIFF_UPDATE && canSniffState) { + canSniff(); + canLast = millis(); + } + + if (currentTime >= speedUpdate) { + SPEED++; + RPS = (SPEED * 1.4667) / (3.141592653589793 * 1.33333333); + WHEEL_UPDATE = 1 / (RPS / 10); + if (SPEED == 120) { + SPEED = 0; + } + speedUpdate += 5000; + } + + if (digitalElapsed > DIGITAL_UPDATE) { + digitalWrite(TRACTIVE_PIN, HIGH); + digitalWrite(START_SWITCH_PIN, HIGH); + + digitalLast = millis(); + } + + if (analogElapsed > ANALOG_UPDATE) { + // Writes values to pins + analogWrite(BRAKE_1_PIN, brakeVal); + analogWrite(THROTTLE_1_PIN, throttleVal); + analogWrite(THROTTLE_2_PIN, 255 - throttleVal); + + // Incriment +1 each cycle + brakeVal++; + throttleVal++; + + // Resets values at 255 + if (brakeVal == 255) { + brakeVal = 0; + } + if (throttleVal == 255) { + throttleVal = 0; + } + + // Updates last run time + analogLast = millis(); + } + if (wheelElapsed > WHEEL_UPDATE) { + if (wheelStatus == 0) { + for (int i = 0; i < 4; i++) { + digitalWrite(WHEEL_SPEED_PINS[i], HIGH); + } + wheelStatus = 1; + } + if (wheelStatus == 1) { + for (int i = 0; i < 4; i++) { + digitalWrite(WHEEL_SPEED_PINS[i], LOW); + } + wheelStatus = 0; + } + wheelLast = millis(); + } + + // if (canElapsed > CAN_UPDATE) { + + // CAN_LAST = millis(); + // } + // else { + // CURRENT_TIME = millis(); + // } + } +} + +void randomTest() { + startSequence(); + updateRates(); + runTime = currentTime + (targetRunTime * 60000); + + updateTimes(); + + Serial.println("VARIABLE TEST INITALIZED"); + Serial.print("TARGET_RUN_TIME: "); + Serial.println(targetRunTime); + Serial.print("RUN_TIME: "); + Serial.println(runTime); + Serial.print("CURRENT_TIME: "); + Serial.println(currentTime); + + while (currentTime < runTime) { + + updateTimes(); + + if (canSniffElapsed >= CAN_SNIFF_UPDATE && canSniffState) { + canSniff(); + Serial.println("CAN SNIFFED!"); + canLast = millis(); + } + + if (digitalElapsed > DIGITAL_UPDATE) { + digitalWrite(TRACTIVE_PIN, HIGH); + digitalWrite(START_SWITCH_PIN, HIGH); + + digitalLast = millis(); + } + if (analogElapsed > ANALOG_UPDATE) { + randomAnalog = random(0, 255); + + analogWrite(BRAKE_1_PIN, randomAnalog); + + randomAnalog = random(0, 255); + analogWrite(THROTTLE_1_PIN, randomAnalog); + analogWrite(THROTTLE_2_PIN, 255 - randomAnalog); + + analogLast = millis(); + } + if (wheelElapsed > WHEEL_UPDATE) { + if (wheelStatus == 0) { + for (int i = 0; i < 4; i++) { + digitalWrite(WHEEL_SPEED_PINS[i], HIGH); + } + wheelStatus = 1; + } + if (wheelStatus == 1) { + for (int i = 0; i < 4; i++) { + digitalWrite(WHEEL_SPEED_PINS[i], LOW); + } + wheelStatus = 0; + } + wheelLast = millis(); + } + Serial.println("<<>>"); + Serial.println(currentTime / 1000); + + // if (canElapsed > CAN_UPDATE) { + + // CAN_LAST = millis(); + // } + // else { + // CURRENT_TIME = millis(); + // } + } +} + +void simTest() { + startSequence(); + return; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..d23ba43 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,15 @@ +#include +#include +#include "FlatCar.h" + +void setup() { + Serial.begin(9600); + Serial.println("Serial Port Intialized"); + canSetup(); + pinSetup(); +} + +void loop() { + menuSelect(); + runPrograms(); +} \ No newline at end of file diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html