commit 582860d2abb57a50d409ef00455c61aabb8df785 Author: yorick.geoffre Date: Sun Dec 18 17:23:09 2022 +0100 importing existing files 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/HellMetServo.hpp b/include/HellMetServo.hpp new file mode 100644 index 0000000..a4d328b --- /dev/null +++ b/include/HellMetServo.hpp @@ -0,0 +1,40 @@ +#include +#include "WS2812Manager.hpp" + +class HellMetServo{ +private: + int _origin = 0; + int _movement = 0; + int _pin = -1; + int _start = 0; + float lastAngle = 0; + float _target = 0; + volatile float _angle = 0; + volatile int servoHandle = 0; + bool wasClosing = false; +public: + HellMetServo(int origin, int movement, int pin); + void StartToggle(); + void StartOpen(); + void StartClose(); + bool Step(); + void Disable(); + void Enable(); + int getCurrentAngle(){return _angle;} + int getCurrentTarget(){return _target;} + int getPin(){return _pin;} + int getHandle(){return servoHandle;} +}; + +class HellMetServoManager{ +private: + std::vector topServos = std::vector(); + std::vector bottomServos = std::vector(); + std::vector allServos = std::vector(); + int timingsArray[11] = {20,15,7,1,1,1,1,7,15,20,20}; + void ToggleAll(); +public: + volatile bool in_use = false; + HellMetServoManager(); + static void ToggleAllWrapper(void *classInstance); +}; \ No newline at end of file diff --git a/include/I2CManagement.hpp b/include/I2CManagement.hpp new file mode 100644 index 0000000..91036b3 --- /dev/null +++ b/include/I2CManagement.hpp @@ -0,0 +1,29 @@ +#include +#include +#include + +class I2CDevice{ + protected: + int _writeAddress = 0x00; + int _readAddress = 0xFF; + std::string _name = ""; + public: + int getWriteAddress(){return _writeAddress;} + int getReadAddress(){return _readAddress;} + std::string getname(){return _name;} + virtual bool checkAlive(){return false;} +}; + +class I2CManager{ + protected: + static std::vector _Devices; + static int _pinSCL; + static int _pinSDA; + public: + static void Setup(int pinSDA, int pinSCL); + static void I2CWrite(int address, int value); + static int I2CRead(int address, int size); + static void writeToRegister8bit(int message, int targetRegister, int i2cAddress); + static void registerNewDevice(I2CDevice* device){_Devices.push_back(device);} + static void scanAll(); +}; \ No newline at end of file diff --git a/include/PinDefinitions.hpp b/include/PinDefinitions.hpp new file mode 100644 index 0000000..73e5f13 --- /dev/null +++ b/include/PinDefinitions.hpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +extern SemaphoreHandle_t serial_mutex; + +extern void THREAD_SAFE_PRINTLN(String data); + +enum debugLevel{ + none = 0, + error = 1, + warn = 2, + info = 3, + verbose = 4 //only use as a last resort, it makes things go real bad on the serial port +}; + +#define DEBUGLEVEL debugLevel::info + +#define LOG_ERROR(x) do { if (DEBUGLEVEL >= debugLevel::error) { THREAD_SAFE_PRINTLN(x); } } while (0) + +#define LOG_WARN(x) do { if (DEBUGLEVEL >= debugLevel::warn) { THREAD_SAFE_PRINTLN(x); } } while (0) + +#define LOG_INFO(x) do { if (DEBUGLEVEL >= debugLevel::info) { THREAD_SAFE_PRINTLN(x); }} while (0) + +#define LOG_VERBOSE(x) do { if (DEBUGLEVEL >= debugLevel::verbose) { THREAD_SAFE_PRINTLN(x); }} while (0) \ No newline at end of file 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/include/WS2812Manager.hpp b/include/WS2812Manager.hpp new file mode 100644 index 0000000..1471ea0 --- /dev/null +++ b/include/WS2812Manager.hpp @@ -0,0 +1,15 @@ +#include + +class WS2812Manager{ + private: + Freenove_ESP32_WS2812* strip; + int _ledCount; + void RGBCycleAll(int tempo); + void setAllColor(int R, int G, int B); + void BreatheOutAllColor(int R, int G, int B, int tempo); + void BreatheInAllColor(int R, int G, int B, int tempo); + void BreatheAllColor(int R, int G, int B, int tempo); + public: + WS2812Manager(int ledPin, int ledCount); + static void RunRGB(void *classInstance); +}; \ No newline at end of file diff --git a/include/hmc5883L.hpp b/include/hmc5883L.hpp new file mode 100644 index 0000000..909b4e2 --- /dev/null +++ b/include/hmc5883L.hpp @@ -0,0 +1,24 @@ +#include "I2CManagement.hpp" +#define X 0 +#define Y 1 +#define Z 2 + +class Hmc5883L : I2CDevice{ + protected: + int16_t values[3] = {0,0,0}; + double valuesScaled[3] = {0,0,0}; + double radius = 0; + double azimuth = 0; + double elevation = 0; + double heading = 0; + void readRawValues(); + public: + Hmc5883L(int readAddress, int writeAddress); + void beginUpdateTask(); + void update(); + static void beginUpdateTaskWrapper(void *classInstance); + bool checkAlive() override {return true;} + String getRawValuesWithSeparator(); + String getHeadingValue(){return String(heading);} + String getDebugValues(); +}; \ No newline at end of file diff --git a/include/main.hpp b/include/main.hpp new file mode 100644 index 0000000..b5ba951 --- /dev/null +++ b/include/main.hpp @@ -0,0 +1 @@ +#include "HellMetServo.hpp" \ No newline at end of file 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..59cf52f --- /dev/null +++ b/platformio.ini @@ -0,0 +1,25 @@ +; 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:esp32-c3-devkitm-1] +platform = espressif32 +board = esp32-c3-devkitm-1 +framework = arduino +;board_upload.flash_size=2MB +lib_deps = + khoih-prog/ESP32_C3_ISR_Servo@^1.2.0 + freenove/Freenove WS2812 Lib for ESP32@^1.0.5 +monitor_speed = 460800 +build_flags = + -D ARDUINO_USB_MODE=1 + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D SERIALCONS=USBSerial +;board_build.filesystem = littlefs +;board_build.partitions = minimal.csv \ No newline at end of file diff --git a/src/HellMetServo.cpp b/src/HellMetServo.cpp new file mode 100644 index 0000000..3b90faa --- /dev/null +++ b/src/HellMetServo.cpp @@ -0,0 +1,116 @@ +#include "HellMetServo.hpp" +#include "PinDefinitions.hpp" + +#define USE_ESP32_TIMER_NO 1 +#define TIMER_INTERRUPT_DEBUG 0 +#define ISR_SERVO_DEBUG 0 +#define MIN_MICROS 800 +#define MAX_MICROS 2450 +#define ADDITIONNAL_MOVEMENT_OFFSET 25 + +#include + +HellMetServo::HellMetServo(int origin, int movement, int pin) : _origin(origin), _movement(movement), _pin(pin){ + LOG_INFO("Creating servo on pin" + String(pin)); + servoHandle = ESP32_ISR_Servos.setupServo(pin, MIN_MICROS, MAX_MICROS); + LOG_INFO("Servo Created with handle" + String(servoHandle)); + lastAngle = origin; + _angle = origin; +} + +void HellMetServo::StartToggle(){ + wasClosing ? StartOpen() : StartClose(); +} + +void HellMetServo::StartClose(){ + _start = _origin-_movement; + _target = _origin; + _angle = _start; + wasClosing = true; +} + +void HellMetServo::StartOpen(){ + _start = _origin; + _target = _origin-_movement; + _angle = _start; + wasClosing = false; +} + +bool HellMetServo::Step(){ + if(_angle == _target) return true; + float completion = abs(_target - lastAngle); + _angle += (_angle > _target) ? -1 : 1; + lastAngle = _angle; + if(_angle > 180 || _angle < 0 || !ESP32_ISR_Servos.setPosition(servoHandle, _angle)){ + LOG_ERROR("Error moving servo "+String(_pin)+" to angle "+_angle); + return true; //stop + } + return _angle == _target; +} + +void HellMetServo::Disable(){ + if(!ESP32_ISR_Servos.disable(servoHandle)) + LOG_ERROR("Error disableing servo "+String(_pin)); +} + +void HellMetServo::Enable(){ + if(!ESP32_ISR_Servos.enable(servoHandle)) + LOG_ERROR("Error enabling servo "+String(_pin)); +} + +//HellMetServoManager defintions --------------------------------------------------------------------------------------------------------------------------------------- + +HellMetServoManager::HellMetServoManager(){ + ESP32_ISR_Servos.useTimer(USE_ESP32_TIMER_NO); + + allServos.push_back(new HellMetServo(90+3+ADDITIONNAL_MOVEMENT_OFFSET, (50+ADDITIONNAL_MOVEMENT_OFFSET), GPIO_NUM_3)); //Top right + allServos.push_back(new HellMetServo(78+0+6+ADDITIONNAL_MOVEMENT_OFFSET, (50+ADDITIONNAL_MOVEMENT_OFFSET), GPIO_NUM_2)); //bottom right + allServos.push_back(new HellMetServo(28+4+1-ADDITIONNAL_MOVEMENT_OFFSET, -(50+ADDITIONNAL_MOVEMENT_OFFSET), GPIO_NUM_4)); //bottom left + allServos.push_back(new HellMetServo(28+13-ADDITIONNAL_MOVEMENT_OFFSET, -(50+ADDITIONNAL_MOVEMENT_OFFSET), GPIO_NUM_5)); //top left + //vTaskDelay(100); +} + +void HellMetServoManager::ToggleAll(){ + LOG_INFO("Beginning Toggle for "+String(allServos.size())+" servos"); + for (HellMetServo* servo : allServos) + { + LOG_INFO("Enabling"); + servo->Enable(); + LOG_INFO("Toggling"); + servo->StartToggle(); + } + LOG_INFO("Done enabling servos"); + bool finished = false; + int i = 0; + while(!finished){ + finished = true; + for(HellMetServo* servo : allServos){ + i++; + LOG_WARN("not finished for servo "+String(servo->getHandle())+" angle: "+String(servo->getCurrentAngle())+" target: "+String(servo->getCurrentTarget())); + if(!servo->Step()){ + LOG_INFO("Servo returned false "+String(i)); + finished = false; + } + LOG_INFO("Servo didn't return false "+String(i)); + } + vTaskDelay(10/ portTICK_RATE_MS); + } + LOG_INFO("Done moving servos"); + vTaskDelay(100/ portTICK_RATE_MS); + + for (HellMetServo* servo : allServos) + { + servo->Disable(); + } + LOG_INFO("Toggle done"); +} + +void HellMetServoManager::ToggleAllWrapper(void *classInstance){ + // Get a pointer to the object instance + HellMetServoManager *obj = static_cast(classInstance); + obj->in_use = true; + // Call the object method + obj->ToggleAll(); + obj->in_use = false; + vTaskDelete(NULL); +} \ No newline at end of file diff --git a/src/I2CManagement.cpp b/src/I2CManagement.cpp new file mode 100644 index 0000000..9a9e684 --- /dev/null +++ b/src/I2CManagement.cpp @@ -0,0 +1,54 @@ +#include "I2CManagement.hpp" +#include +#include "PinDefinitions.hpp" + +std::vector I2CManager::_Devices = std::vector(); +int I2CManager::_pinSCL; +int I2CManager::_pinSDA; + +void I2CManager::Setup(int pinSDA, int pinSCL){ + _pinSCL = pinSCL; + _pinSDA = pinSDA; + Wire.setPins(_pinSDA, _pinSCL); + Wire.begin(); +} + +int I2CManager::I2CRead(int address, int size){ + return Wire.requestFrom(address, size); +} + +void I2CManager::I2CWrite(int address, int value){ + Wire.beginTransmission(address); + Wire.write(value); + Wire.endTransmission(); +} + +void I2CManager::writeToRegister8bit(int message, int targetRegister, int i2cAddress){ + Wire.beginTransmission(i2cAddress); // Begins a transmission to the I2C slave + Serial.print(Wire.write(targetRegister)); // ask to write to this register + Serial.print(Wire.write(message)); // set this register's value to the message value (byte) + Wire.endTransmission(true); +} + +void I2CManager::scanAll(){ + Serial.println (); + Serial.println ("I2C scanner. Scanning ..."); + uint8_t count = 0; + + for (uint8_t i = 8; i < 120; i++) + { + Wire.beginTransmission (i); // Begin I2C transmission Address (i) + if (Wire.endTransmission () == 0) // Receive 0 = success (ACK response) + { + Serial.print ("Found address: "); + Serial.print (i, DEC); + Serial.print (" (0x"); + Serial.print (i, HEX); // PCF8574 7 bit address + Serial.println (")"); + count++; + } + } + Serial.print ("Found "); + Serial.print (count, DEC); // numbers of devices + Serial.println (" device(s)."); +} \ No newline at end of file diff --git a/src/PinDefinitions.cpp b/src/PinDefinitions.cpp new file mode 100644 index 0000000..c82a229 --- /dev/null +++ b/src/PinDefinitions.cpp @@ -0,0 +1,14 @@ +#include "PinDefinitions.hpp" + +void THREAD_SAFE_PRINTLN(String data) +{ + + // Wait for the mutex to be available + xSemaphoreTake(serial_mutex, 10); + + // Use the Serial class to send and receive data + Serial.println(data); + + // Release the mutex + xSemaphoreGive(serial_mutex); +} \ No newline at end of file diff --git a/src/WS2812Manager.cpp b/src/WS2812Manager.cpp new file mode 100644 index 0000000..8acb3b8 --- /dev/null +++ b/src/WS2812Manager.cpp @@ -0,0 +1,75 @@ +#include "WS2812Manager.hpp" +#include "PinDefinitions.hpp" + +WS2812Manager::WS2812Manager(int ledPin, int ledCount){ + strip = new Freenove_ESP32_WS2812(ledCount,ledPin); + _ledCount = ledCount; + if(!strip->begin()) + LOG_ERROR("WS2812Manager() error"); + } + +void WS2812Manager::RGBCycleAll(int tempo){ + strip->setBrightness(255); + for (int j = 0; j < 255; j++) { //cycle to blue + for (int i = 0; i < _ledCount; i++) { + strip->setLedColorData(i, strip->Wheel((i * 256 / _ledCount + j) & 255)); + } + LOG_VERBOSE("RGBCycleAll to blue"); + strip->show(); + vTaskDelay(tempo/ portTICK_RATE_MS); + } + for (int j = 255; j > 0; j--) { //cycle back to red + for (int i = 0; i < _ledCount; i++) { + strip->setLedColorData(i, strip->Wheel((i * 256 / _ledCount + j) & 255)); + } + LOG_VERBOSE("RGBCycleAll to red"); + strip->show(); + vTaskDelay(tempo/ portTICK_RATE_MS); + } +} + +void WS2812Manager::setAllColor(int R, int G, int B){ + LOG_VERBOSE(String("setAllColor ")+String(R)+String(G)+String(B)); + esp_err_t error = strip->setAllLedsColor(R,G,B); + if(error != 0){ + LOG_VERBOSE("setAllColor ERROR "+String(error)); + } + //strip->show(); +} + +void WS2812Manager::BreatheInAllColor(int R, int G, int B, int tempo){ + LOG_VERBOSE("BreatheInAllColor"); + LOG_VERBOSE("BreatheInAllColor set color done"); + setAllColor(R,G,B); + for(int i = 0; i < 255; i++){ + strip->setBrightness(i); + LOG_VERBOSE("BreatheInAllColor " + String(i) + +' '+String(R) + ":" +String(G) + ":"+ String(B)); + vTaskDelay(tempo/ portTICK_RATE_MS); + } +} + +void WS2812Manager::BreatheOutAllColor(int R, int G, int B, int tempo){ + LOG_INFO("BreatheOutAllColor"); + LOG_INFO("BreatheOutAllColor set color done"); + for(int i = 254; i > 0; i--){ + setAllColor(R,G,B); + strip->setBrightness(i); + LOG_INFO("BreatheOutAllColor " + String(i) + +' '+String(R) + ":" +String(G) + ":"+ String(B)); + vTaskDelay(tempo/ portTICK_RATE_MS); + } +} + +void WS2812Manager::BreatheAllColor(int R, int G, int B, int tempo){ + BreatheInAllColor(R,B,G,tempo); + BreatheOutAllColor(R,G,B,tempo); +} + +void WS2812Manager::RunRGB(void *classInstance){ + // Get a pointer to the object instance + WS2812Manager *obj = static_cast(classInstance); + while(true){ + obj->RGBCycleAll(10); + } +} \ No newline at end of file diff --git a/src/hmc5883L.cpp b/src/hmc5883L.cpp new file mode 100644 index 0000000..e2812b3 --- /dev/null +++ b/src/hmc5883L.cpp @@ -0,0 +1,67 @@ +#include "hmc5883L.hpp" +#include +#include "PinDefinitions.hpp" + +#define _x valuesScaled[X] +#define _y valuesScaled[Y] +#define _z valuesScaled[Z] + +Hmc5883L::Hmc5883L(int readAddress = 0x1E, int writeAddress = 0x1E){ + _readAddress = readAddress; + _writeAddress = writeAddress; + LOG_INFO("Setting up Hmc5883L"); + I2CManager::writeToRegister8bit(0b01110000, 0x00 , writeAddress ); //Configuration Register A + I2CManager::writeToRegister8bit(0b11100000, 0x01 , writeAddress ); //Configuration Register B + I2CManager::writeToRegister8bit(0b00000000, 0x02 , writeAddress ); //Mode register continuous measurement mode + LOG_INFO("Done setting up Hmc5883L"); +} + +void Hmc5883L::beginUpdateTask(){ + while(true){ + vTaskDelay(100/ portTICK_RATE_MS); + LOG_VERBOSE("reading raw values"); + readRawValues(); + } +} + +void Hmc5883L::beginUpdateTaskWrapper(void *classInstance){ + LOG_INFO("beginUpdateTaskWrapper"); + Hmc5883L *obj = static_cast(classInstance); + obj->beginUpdateTask(); +} + +void Hmc5883L::readRawValues(){ + LOG_VERBOSE("Obtaining raw data"); + Wire.beginTransmission(_readAddress); + Wire.write(0x03); // starting with register 0x03 (Data Output X MSB Register) [HMC5883L datasheet page 11] + Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active. + Wire.requestFrom(_readAddress, 6, 1); // request a total of 3*2=6 registers, and send the stop message + LOG_VERBOSE("Obtained raw data"); + for (int i = 0; i < 3; i++) + { + values[i] = Wire.read() << 8 | Wire.read(); //we read the two registers at the same time, and concat them to get the full uint16_t (2*8) + valuesScaled[i] = ((double)values[i]); + } + LOG_VERBOSE("Concatenated and scaled the data"); + radius = sqrt(pow(valuesScaled[X],2) + pow(valuesScaled[Y],2) + pow(valuesScaled[Z],2)); + azimuth = atan2(valuesScaled[Y], valuesScaled[X]); + elevation = atan2(valuesScaled[Z], sqrt(pow(valuesScaled[X], 2) + pow(valuesScaled[Y], 2))); + heading = atan2(values[Y], values[X]) * 180 / M_PI; + LOG_VERBOSE("Recovered heading: "+String(heading)); + double head = 0; + if (_x > 0) { + heading = 90 - std::atan(_z/_x) * 180/M_PI; + } else if (_x < 0) { + heading = 270 - std::atan(_z/_x) * 180/M_PI; + } else { + if (_z < 0) { + heading = 180.0; + } else { + heading = 0.0; + } + } +} + +String Hmc5883L::getDebugValues(){ + return "X:" + String(_x) + "\nY:" + String(_y) +"\nZ:"+ String(_z); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..b3f37c7 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,73 @@ +#include "main.hpp" +#include "PinDefinitions.hpp" +#include "hmc5883L.hpp" + +#if !defined( ARDUINO_ESP32C3_DEV ) + #error This code is intended to run on the ESP32_C3 platform! Please check your Tools->Board setting. +#endif + +HellMetServoManager* hm; +WS2812Manager* LedManager; +Hmc5883L* magnetometer; +SemaphoreHandle_t serial_mutex = NULL; + +void rtosLoop(void *pvParameter){ + LOG_VERBOSE("rtosloop"); + + if (Serial.available()){ + String str = Serial.readString(); + LOG_INFO(str); + switch(str[0]){ + case 's': //servo + switch(str[1]){ + case 't': //toggle All + if(!hm->in_use) + xTaskCreate(HellMetServoManager::ToggleAllWrapper, "Servo Thread", 4096, hm, 6, NULL); + break; + default: + break; + } + break; + case 'l': //leds + break; + case 'm' : //magnetometer + switch(str[1]){ + case 'r': //read heading + Serial.println(magnetometer->getHeadingValue()); + break; + case 'd': //read debug + Serial.println(magnetometer->getDebugValues()); + break; + default: + break; + } + default: + break; + } + LOG_INFO("rtosloop - serial present"); + Serial.flush(); + } + LOG_VERBOSE("rtosloop - out"); +} + +void setup() { + serial_mutex = xSemaphoreCreateBinary(); + Serial.begin(9600); + I2CManager::Setup(GPIO_NUM_9, GPIO_NUM_8); + Serial.println("Are you alive?"); + while (!Serial.available()); + I2CManager::scanAll(); + magnetometer = new Hmc5883L(0x1E,0x1E); + LOG_INFO("Creating mag thread"); + xTaskCreate(Hmc5883L::beginUpdateTaskWrapper, "magnetometer thread", 4096, magnetometer, 7, NULL); + LOG_INFO("Done creating mag thread"); + Serial.println("Are you alive?"); + LedManager = new WS2812Manager(GPIO_NUM_5,1); + xTaskCreate(WS2812Manager::RunRGB, "RGB thread", 4096, LedManager, 6, NULL); + delay(100); + hm = new HellMetServoManager(); +} + +void loop(){ + rtosLoop(NULL); +} \ 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