Add vfd.cpp/hpp with functions to control the VFD via 4 digital pins Add way to test the vfd via SET button (rotate speed level) and START button (toggle motor on/off)
		
			
				
	
	
		
			186 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "control.hpp"
 | |
| 
 | |
| //========================
 | |
| //===== init display =====
 | |
| //========================
 | |
| max7219_t init_display(){
 | |
|     // Configure SPI bus
 | |
|     spi_bus_config_t cfg;
 | |
|     cfg.mosi_io_num = DISPLAY_PIN_NUM_MOSI;
 | |
|     cfg.miso_io_num = -1;
 | |
|     cfg.sclk_io_num = DISPLAY_PIN_NUM_CLK;
 | |
|     cfg.quadwp_io_num = -1;
 | |
|     cfg.quadhd_io_num = -1;
 | |
|     cfg.max_transfer_sz = 0;
 | |
|     cfg.flags = 0;
 | |
|     ESP_ERROR_CHECK(spi_bus_initialize(HOST, &cfg, 1));
 | |
| 
 | |
|     // Configure device
 | |
|     max7219_t dev;
 | |
|     dev.cascade_size = 1;
 | |
|     dev.digits = 8;
 | |
|     dev.mirrored = true;
 | |
|     ESP_ERROR_CHECK(max7219_init_desc(&dev, HOST, MAX7219_MAX_CLOCK_SPEED_HZ, DISPLAY_PIN_NUM_CS));
 | |
|     ESP_ERROR_CHECK(max7219_init(&dev));
 | |
|     //0...15
 | |
|     ESP_ERROR_CHECK(max7219_set_brightness(&dev, 12));
 | |
|     return dev;
 | |
| }
 | |
| 
 | |
| 
 | |
| //========================
 | |
| //===== init encoder =====
 | |
| //========================
 | |
| QueueHandle_t init_encoder(rotary_encoder_info_t * info){
 | |
|     // esp32-rotary-encoder requires that the GPIO ISR service is installed before calling rotary_encoder_register()
 | |
|     ESP_ERROR_CHECK(gpio_install_isr_service(0));
 | |
| 
 | |
|     // Initialise the rotary encoder device with the GPIOs for A and B signals
 | |
|     ESP_ERROR_CHECK(rotary_encoder_init(info, ROT_ENC_A_GPIO, ROT_ENC_B_GPIO));
 | |
|     ESP_ERROR_CHECK(rotary_encoder_enable_half_steps(info, ENABLE_HALF_STEPS));
 | |
| #ifdef FLIP_DIRECTION
 | |
|     ESP_ERROR_CHECK(rotary_encoder_flip_direction(info));
 | |
| #endif
 | |
| 
 | |
|     // Create a queue for events from the rotary encoder driver.
 | |
|     // Tasks can read from this queue to receive up to date position information.
 | |
|     QueueHandle_t event_queue = rotary_encoder_create_queue();
 | |
|     ESP_ERROR_CHECK(rotary_encoder_set_queue(info, event_queue));
 | |
|     return event_queue;
 | |
| }
 | |
| 
 | |
| 
 | |
| //============================
 | |
| //===== display distance =====
 | |
| //============================
 | |
| //display current position in meters from current encoder count
 | |
| void display_current_distance(max7219_t * dev, rotary_encoder_info_t * info){
 | |
|     // --- event based action ---
 | |
|     // Wait for incoming events on the event queue.
 | |
|     // rotary_encoder_event_t event;
 | |
|     // if (xQueueReceive(event_queue, &event, 1000 / portTICK_PERIOD_MS) == pdTRUE)
 | |
|     // {
 | |
|     //     ESP_LOGI(TAG, "Event: position %d, direction %s", event.state.position,
 | |
|     //             event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET");
 | |
|     //     //--- calculate distalce ---
 | |
|     //     distance_mm = event.state.position * (MEASURING_ROLL_DIAMETER * PI / 600); //TODO dont calculate constant factor every time
 | |
|     //     //--- show current position on display ---
 | |
|     //     //sprintf(buf, "%08d", event.state.position);
 | |
|     //     //--- show current distance in cm on display ---
 | |
|     //     sprintf(buf, "%06.1f cm", (float)distance_mm/10);
 | |
|     //     //printf("float num\n");
 | |
|     //     max7219_clear(&dev);
 | |
|     //     max7219_draw_text_7seg(&dev, 0, buf);
 | |
|     // }
 | |
|     // else //no event for 1s
 | |
|     // {
 | |
|     //     // Poll current position and direction
 | |
|     //     rotary_encoder_state_t state;
 | |
|     //     ESP_ERROR_CHECK(rotary_encoder_get_state(&info, &state));
 | |
|     //     ESP_LOGI(TAG, "Poll: position %d, direction %s", state.position,
 | |
|     //             state.direction ? (state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET");
 | |
|     // }
 | |
| 
 | |
|     // Poll current position and direction
 | |
|     rotary_encoder_state_t state;
 | |
|     rotary_encoder_get_state(info, &state);
 | |
|     //--- calculate distalce ---
 | |
|     float distance_mm = state.position * (MEASURING_ROLL_DIAMETER * PI / 600); //TODO dont calculate constant factor every time
 | |
| 
 | |
|     //--- show current position on display ---
 | |
|     char buf[10]; // 8 digits + decimal point + \0
 | |
|     sprintf(buf, "%06.1f cm", (float)distance_mm/10);
 | |
|     //printf("float num\n");
 | |
|     max7219_clear(dev);
 | |
|     max7219_draw_text_7seg(dev, 0, buf);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| //====================
 | |
| //==== variables =====
 | |
| //====================
 | |
| static const char *TAG = "control";
 | |
| char display_buf[10]; // 8 digits + decimal point + \0
 | |
| max7219_t display; //display device
 | |
| QueueHandle_t encoder_queue = NULL; //encoder event queue
 | |
| rotary_encoder_info_t encoder; //encoder device/info
 | |
| 
 | |
| uint8_t count = 0; //count for testing
 | |
| uint32_t timestamp_pageSwitched = 0;
 | |
| bool page = false; //store page number currently displayed
 | |
| bool state = false; //store state of motor
 | |
| 
 | |
|                       
 | |
|            
 | |
| //========================
 | |
| //===== control task =====
 | |
| //========================
 | |
| void task_control(void *pvParameter)
 | |
| {
 | |
|     //initialize display
 | |
|     display = init_display();
 | |
|     //initialize encoder
 | |
|     encoder_queue = init_encoder(&encoder);
 | |
| 
 | |
|     //display startup message
 | |
|     max7219_clear(&display);
 | |
|     ESP_LOGI(TAG, "showing startup message...");
 | |
|     max7219_draw_text_7seg(&display, 0, "ABCDEFGH");
 | |
|     vTaskDelay(pdMS_TO_TICKS(500));
 | |
| 
 | |
| 
 | |
|     //===== loop =====
 | |
|     while(1){
 | |
|         vTaskDelay(20 / portTICK_PERIOD_MS);
 | |
| 
 | |
|         //run handle functions for all switches
 | |
|         SW_START.handle();
 | |
|         SW_RESET.handle();
 | |
|         SW_SET.handle();
 | |
|         SW_PRESET1.handle();
 | |
|         SW_PRESET2.handle();
 | |
|         SW_PRESET3.handle();
 | |
| 
 | |
|         //switch between two display pages
 | |
|         if (esp_log_timestamp() - timestamp_pageSwitched > 1000){
 | |
|             timestamp_pageSwitched = esp_log_timestamp();
 | |
|             page = !page;
 | |
|         }
 | |
|         max7219_clear(&display);
 | |
|         if (page){
 | |
|             //display current position
 | |
|             display_current_distance(&display, &encoder);
 | |
|         } else {
 | |
|             //display counter
 | |
|             sprintf(display_buf, "lvl: %02d", count);
 | |
|             max7219_draw_text_7seg(&display, 0, display_buf);
 | |
|             //count++;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //testing: rotate through speed levels
 | |
|         if(SW_SET.risingEdge){
 | |
|             //rotate count 0-7
 | |
|             if (count >= 7){
 | |
|                 count = 0;
 | |
|             } else {
 | |
|                 count ++;
 | |
|             }
 | |
|             //set motor level
 | |
|             vfd_setSpeedLevel(count);
 | |
|             buzzer.beep(1, 100, 100);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         //testing: toggle motor state
 | |
|         if(SW_START.risingEdge){
 | |
|             state = !state;
 | |
|             vfd_setState(state);
 | |
|             buzzer.beep(1, 500, 100);
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 |