diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index d218cfa..2caa7ed 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "main.cpp" "motordrivers.cpp" "motorctl.cpp" "config.cpp" "joystick.cpp" +idf_component_register(SRCS "main.cpp" "motordrivers.cpp" "motorctl.cpp" "config.cpp" "joystick.cpp" "buzzer.cpp" INCLUDE_DIRS ".") diff --git a/main/buzzer.cpp b/main/buzzer.cpp new file mode 100644 index 0000000..9046cd1 --- /dev/null +++ b/main/buzzer.cpp @@ -0,0 +1,95 @@ +#include "buzzer.hpp" +#include "config.hpp" + +static const char *TAG_BUZZER = "buzzer"; + +//============================ +//========== init ============ +//============================ +//define gpio pin as output, initialize queue +void buzzer_t::init(){ + //define buzzer pin as output + gpio_pad_select_gpio(gpio_pin); + gpio_set_direction(gpio_pin, GPIO_MODE_OUTPUT); + //create queue + beepQueue = xQueueCreate( 20, sizeof( struct beepEntry ) ); +} + + +//============================= +//======== constructor ======== +//============================= +//copy provided config parameters to private variables, run init function +buzzer_t::buzzer_t(gpio_num_t gpio_pin_f, uint16_t msGap_f){ + ESP_LOGI(TAG_BUZZER, "Initializing buzzer"); + //copy configuration parameters to variables + gpio_pin = gpio_pin_f; + msGap = msGap_f; + //run init function to initialize gpio and queue + init(); +}; + + +//============================ +//=========== beep =========== +//============================ +//function to add a beep command to the queue +void buzzer_t::beep(uint8_t count, uint16_t msOn, uint16_t msOff){ + //create entry struct with provided data + struct beepEntry entryInsert = { + count = count, + msOn = msOn, + msOff = msOff + }; + + // Send a pointer to a struct AMessage object. Don't block if the + // queue is already full. + //struct beepEntry *entryInsertPointer; + //entryInsertPointer = &entryInsertData; + ESP_LOGW(TAG_BUZZER, "Inserted object to queue - count=%d, msOn=%d, msOff=%d", entryInsert.count, entryInsert.msOn, entryInsert.msOff); + //xQueueGenericSend( beepQueue, ( void * ) &entryInsertPointer, ( TickType_t ) 0, queueSEND_TO_BACK ); + xQueueSend( beepQueue, ( void * )&entryInsert, ( TickType_t ) 0 ); +} + + +//============================== +//======== processQueue ======== +//============================== +void buzzer_t::processQueue(){ + //struct for receiving incomming events + struct beepEntry entryRead = { }; + + //loop forever + while(1){ + ESP_LOGD(TAG_BUZZER, "processQueue: waiting for beep command"); + + //if queue is ready + if( beepQueue != 0 ) + { + // wait for a queue entry to be available indefinetely if INCLUDE_vTaskSuspend is enabled in the FreeRTOS config + // otherwise waits for at least 7 weeks + if( xQueueReceive( beepQueue, &entryRead, portMAX_DELAY ) ) + { + ESP_LOGW(TAG_BUZZER, "Read entry from queue: count=%d, msOn=%d, msOff=%d", entryRead.count, entryRead.msOn, entryRead.msOff); + + //beep requested count with requested delays + for (int i = entryRead.count; i--;){ + //turn on + ESP_LOGD(TAG_BUZZER, "turning buzzer on"); + gpio_set_level(gpio_pin, 1); + vTaskDelay(entryRead.msOn / portTICK_PERIOD_MS); + //turn off + ESP_LOGD(TAG_BUZZER, "turning buzzer off"); + gpio_set_level(gpio_pin, 0); + vTaskDelay(entryRead.msOff / portTICK_PERIOD_MS); + } + //wait for minimum gap between beep events + vTaskDelay(msGap / portTICK_PERIOD_MS); + } + }else{ //wait for queue to become available + vTaskDelay(50 / portTICK_PERIOD_MS); + } + } +} + + diff --git a/main/buzzer.hpp b/main/buzzer.hpp new file mode 100644 index 0000000..ce6c2c6 --- /dev/null +++ b/main/buzzer.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include + +extern "C" +{ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_log.h" +} + +#include "freertos/queue.h" + + + +//=================================== +//========= buzzer_t class ========== +//=================================== +//class which blinks a gpio pin for the provided count and durations. +//- 'processQueue' has to be run in a separate task +//- uses a queue to queue up multiple beep commands +class buzzer_t { + public: + //--- constructor --- + buzzer_t(gpio_num_t gpio_pin_f, uint16_t msGap_f = 200); + + //--- functions --- + void processQueue(); //has to be run once in a separate task, waits for and processes queued events + void beep(uint8_t count, uint16_t msOn, uint16_t msOff); + //void clear(); (TODO - not implemented yet) + //void createTask(); (TODO - not implemented yet) + + //--- variables --- + uint16_t msGap; //gap between beep entries (when multiple queued) + + private: + //--- functions --- + void init(); + + //--- variables --- + gpio_num_t gpio_pin; + + struct beepEntry { + uint8_t count; + uint16_t msOn; + uint16_t msOff; + }; + + //queue for queueing up multiple events while one is still processing + QueueHandle_t beepQueue = NULL; + +}; + + + diff --git a/main/config.cpp b/main/config.cpp index 9dfd362..47494d8 100644 --- a/main/config.cpp +++ b/main/config.cpp @@ -68,3 +68,6 @@ evaluatedJoystick joystick(configJoystick); //create global evaluated switch instance for button next to joystick gpio_evaluatedSwitch buttonJoystick(GPIO_NUM_33, true, false); //pullup true, not inverted (switch to GND use pullup of controller) + +//create buzzer object on pin 12 with gap between queued events of 100ms +buzzer_t buzzer(GPIO_NUM_12, 100); diff --git a/main/config.hpp b/main/config.hpp index bf9b5f3..da35463 100644 --- a/main/config.hpp +++ b/main/config.hpp @@ -5,6 +5,7 @@ #include "joystick.hpp" #include "gpio_evaluateSwitch.hpp" +#include "buzzer.hpp" //create global controlledMotor instances for both motors @@ -16,3 +17,6 @@ extern evaluatedJoystick joystick; //create global evaluated switch instance for button next to joystick extern gpio_evaluatedSwitch buttonJoystick; + +//create global buzzer object +extern buzzer_t buzzer; diff --git a/main/main.cpp b/main/main.cpp index 510007e..97e95ed 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -14,8 +14,6 @@ extern "C" } -#include "motordrivers.hpp" -#include "motorctl.hpp" #include "config.hpp" //tag for logging @@ -39,6 +37,20 @@ void task_motorctl( void * pvParameters ){ +//====================================== +//============ buzzer task ============= +//====================================== +//TODO: move the task creation to buzzer class (buzzer.cpp) +//e.g. only have function buzzer.createTask() in app_main +void task_buzzer( void * pvParameters ){ + ESP_LOGI("task_buzzer", "Start of buzzer task..."); + //run function that waits for a beep events to arrive in the queue + //and processes them + buzzer.processQueue(); +} + + + //================================= //=========== app_main ============ //================================= @@ -62,13 +74,19 @@ extern "C" void app_main(void) { //esp_log_level_set("joystickCommands", ESP_LOG_DEBUG); - - //---------------------------------------------- //--- create task for controlling the motors --- //---------------------------------------------- xTaskCreate(&task_motorctl, "task_motor-control", 2048, NULL, 5, NULL); + //------------------------------ + //--- create task for buzzer --- + //------------------------------ + xTaskCreate(&task_buzzer, "task_buzzer", 2048, NULL, 5, NULL); + + //beep at startup + buzzer.beep(3, 70, 50); + while(1){ @@ -79,8 +97,11 @@ extern "C" void app_main(void) { //--- testing button --- if (buttonJoystick.risingEdge){ ESP_LOGI(TAG, "button pressed, was released for %d ms", buttonJoystick.msReleased); + buzzer.beep(2, 100, 50); + }else if (buttonJoystick.fallingEdge){ ESP_LOGI(TAG, "button released, was pressed for %d ms", buttonJoystick.msPressed); + buzzer.beep(1, 200, 0); }