From caaa0e0526b0e2d032b34039a61943f287f15623 Mon Sep 17 00:00:00 2001 From: willem Date: Sat, 4 Nov 2023 11:58:52 +0100 Subject: [PATCH] initial --- .gitignore | 5 + include/README | 39 ++++ lib/README | 46 +++++ platformio.ini | 18 ++ src/main.cpp | 530 +++++++++++++++++++++++++++++++++++++++++++++++++ test/README | 11 + 6 files changed, 649 insertions(+) create mode 100644 .gitignore create mode 100644 include/README create mode 100644 lib/README create mode 100644 platformio.ini create mode 100644 src/main.cpp create mode 100644 test/README 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/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..6debab1 --- /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 a 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..b6649a8 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,18 @@ +; 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:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino +lib_deps = + me-no-dev/AsyncTCP@^1.1.1 + madhephaestus/ESP32Servo@^1.1.0 + ottowinter/ESPAsyncWebServer-esphome@^3.1.0 diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..f09de98 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,530 @@ +//make sure to upload with ESP32 Dev Module selected as the board under tools>Board>ESP32 Arduino + +#include +#ifdef ESP32 +#include +#include //by dvarrel +#elif defined(ESP8266) +#include //by dvarrel +#endif +#include //by dvarrel + +#include //by Kevin Harrington +#include +#include + +const char* ssid = "MiniSkidi"; + +#define bucketServoPin 23 + +#define auxServoPin 22 + +Servo bucketServo; +Servo auxServo; +struct MOTOR_PINS +{ + int pinIN1; + int pinIN2; +}; + +std::vector motorPins = +{ + {32, 33}, //RIGHT_MOTOR Pins (IN1, IN2) + {26, 25}, //LEFT_MOTOR Pins + {19, 21}, //ARM_MOTOR pins +}; + +#define UP 1 +#define DOWN 2 +#define LEFT 3 +#define RIGHT 4 +#define ARMUP 5 +#define ARMDOWN 6 +#define STOP 0 + + +#define RIGHT_MOTOR 1 +#define LEFT_MOTOR 0 +#define ARM_MOTOR 2 + +#define FORWARD 1 +#define BACKWARD -1 + +bool horizontalScreen;//When screen orientation is locked vertically this rotates the D-Pad controls so that forward would now be left. +bool removeArmMomentum = false; + + + +AsyncWebServer server(80); +AsyncWebSocket wsCarInput("/CarInput"); + +const char* htmlHomePage PROGMEM = R"HTMLHOMEPAGE( + + + + + + + + + +
+ + +
+

MINISKIDI

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bucket: +
+ +
+
AUX: +
+ +
+
+ + + + +)HTMLHOMEPAGE"; + + +void rotateMotor(int motorNumber, int motorDirection) +{ + if (motorDirection == FORWARD) + { + digitalWrite(motorPins[motorNumber].pinIN1, HIGH); + digitalWrite(motorPins[motorNumber].pinIN2, LOW); + } + else if (motorDirection == BACKWARD) + { + digitalWrite(motorPins[motorNumber].pinIN1, LOW); + digitalWrite(motorPins[motorNumber].pinIN2, HIGH); + } + else + { + if(removeArmMomentum) + { + digitalWrite(motorPins[ARM_MOTOR].pinIN1, HIGH); + digitalWrite(motorPins[ARM_MOTOR].pinIN2, LOW); + delay(10); + digitalWrite(motorPins[motorNumber].pinIN1, LOW); + digitalWrite(motorPins[motorNumber].pinIN2, LOW); + delay(5); + digitalWrite(motorPins[ARM_MOTOR].pinIN1, HIGH); + digitalWrite(motorPins[ARM_MOTOR].pinIN2, LOW); + delay(10); + removeArmMomentum = false; + } + digitalWrite(motorPins[motorNumber].pinIN1, LOW); + digitalWrite(motorPins[motorNumber].pinIN2, LOW); + } +} + +void moveCar(int inputValue) +{ + Serial.printf("Got value as %d\n", inputValue); + if(!(horizontalScreen)) + { + switch(inputValue) + { + + case UP: + rotateMotor(RIGHT_MOTOR, FORWARD); + rotateMotor(LEFT_MOTOR, FORWARD); + break; + + case DOWN: + rotateMotor(RIGHT_MOTOR, BACKWARD); + rotateMotor(LEFT_MOTOR, BACKWARD); + break; + + case LEFT: + rotateMotor(RIGHT_MOTOR, BACKWARD); + rotateMotor(LEFT_MOTOR, FORWARD); + break; + + case RIGHT: + rotateMotor(RIGHT_MOTOR, FORWARD); + rotateMotor(LEFT_MOTOR, BACKWARD); + break; + + case STOP: + rotateMotor(ARM_MOTOR, STOP); + rotateMotor(RIGHT_MOTOR, STOP); + rotateMotor(LEFT_MOTOR, STOP); + break; + + case ARMUP: + rotateMotor(ARM_MOTOR, FORWARD); + break; + + case ARMDOWN: + rotateMotor(ARM_MOTOR, BACKWARD); + removeArmMomentum = true; + break; + + default: + rotateMotor(ARM_MOTOR, STOP); + rotateMotor(RIGHT_MOTOR, STOP); + rotateMotor(LEFT_MOTOR, STOP); + break; + } + }else { + switch(inputValue) + { + case UP: + rotateMotor(RIGHT_MOTOR, BACKWARD); + rotateMotor(LEFT_MOTOR, FORWARD); + break; + + case DOWN: + rotateMotor(RIGHT_MOTOR, FORWARD); + rotateMotor(LEFT_MOTOR, BACKWARD); + break; + + case LEFT: + rotateMotor(RIGHT_MOTOR, BACKWARD); + rotateMotor(LEFT_MOTOR, BACKWARD); + break; + + case RIGHT: + rotateMotor(RIGHT_MOTOR, FORWARD); + rotateMotor(LEFT_MOTOR, FORWARD); + break; + + case STOP: + rotateMotor(ARM_MOTOR, STOP); + rotateMotor(RIGHT_MOTOR, STOP); + rotateMotor(LEFT_MOTOR, STOP); + break; + + case ARMUP: + rotateMotor(ARM_MOTOR, FORWARD); + break; + + case ARMDOWN: + rotateMotor(ARM_MOTOR, BACKWARD); + removeArmMomentum = true; + break; + + default: + rotateMotor(ARM_MOTOR, STOP); + rotateMotor(RIGHT_MOTOR, STOP); + rotateMotor(LEFT_MOTOR, STOP); + break; + } + } +} + + +void bucketTilt(int bucketServoValue) +{ + bucketServo.write(bucketServoValue); +} +void auxControl(int auxServoValue) +{ + auxServo.write(auxServoValue); +} + + +void handleRoot(AsyncWebServerRequest *request) +{ + request->send_P(200, "text/html", htmlHomePage); +} + +void handleNotFound(AsyncWebServerRequest *request) +{ + request->send(404, "text/plain", "File Not Found"); +} + +void onCarInputWebSocketEvent(AsyncWebSocket *server, + AsyncWebSocketClient *client, + AwsEventType type, + void *arg, + uint8_t *data, + size_t len) +{ + switch (type) + { + case WS_EVT_CONNECT: + Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); + break; + case WS_EVT_DISCONNECT: + Serial.printf("WebSocket client #%u disconnected\n", client->id()); + moveCar(STOP); + break; + case WS_EVT_DATA: + AwsFrameInfo *info; + info = (AwsFrameInfo*)arg; + if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) + { + std::string myData = ""; + myData.assign((char *)data, len); + std::istringstream ss(myData); + std::string key, value; + std::getline(ss, key, ','); + std::getline(ss, value, ','); + Serial.printf("Key [%s] Value[%s]\n", key.c_str(), value.c_str()); + int valueInt = atoi(value.c_str()); + if (key == "MoveCar") + { + moveCar(valueInt); + } + else if (key == "AUX") + { + auxControl(valueInt); + } + else if (key == "Bucket") + { + bucketTilt(valueInt); + } + else if (key =="Switch") + { + if(!(horizontalScreen)) + { + horizontalScreen = true; + } + else{ + horizontalScreen = false; + } + } + } + break; + case WS_EVT_PONG: + case WS_EVT_ERROR: + break; + default: + break; + } +} + +void setUpPinModes() +{ + + for (int i = 0; i < motorPins.size(); i++) + { + pinMode(motorPins[i].pinIN1, OUTPUT); + pinMode(motorPins[i].pinIN2, OUTPUT); + } + moveCar(STOP); + bucketServo.attach(bucketServoPin); + auxServo.attach(auxServoPin); + auxControl(150); + bucketTilt(140); +} + + +void setup(void) +{ + setUpPinModes(); + Serial.begin(115200); + + WiFi.softAP(ssid ); + IPAddress IP = WiFi.softAPIP(); + Serial.print("AP IP address: "); + Serial.println(IP); + + server.on("/", HTTP_GET, handleRoot); + server.onNotFound(handleNotFound); + + wsCarInput.onEvent(onCarInputWebSocketEvent); + server.addHandler(&wsCarInput); + + server.begin(); + Serial.println("HTTP server started"); + +} + +void loop() +{ + wsCarInput.cleanupClients(); +} \ 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