Files
BA_DIY_Power_PCB/main/menu.c
2025-02-09 23:10:59 +01:00

394 lines
13 KiB
C

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "esp_log.h"
#include "ssd1306.h"
#include "sdkconfig.h"
#include "parsed_pins.h"
#include "freertos/task.h"
#include "freertos/FreeRTOS.h"
#include "driver/gpio.h"
#include "GPIO.h"
#include "menu.h"
#include "esp_timer.h"
#include "mcpwm.h"
#include "ADC.h"
#include "functions.h"
/*############################################*/
/*############## Display-Setup ###############*/
/*############################################*/
static SSD1306_t dev;
void configure_OLED()
{
i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, -1);
ESP_LOGI("OLED", "Panel is 128x64");
ssd1306_init(&dev, 128, 64);
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text_x3(&dev, 0, "Power", 5, false);
ssd1306_display_text_x3(&dev, 4, " PCB", 4, false);
vTaskDelay(2000 / portTICK_PERIOD_MS);
ssd1306_clear_screen(&dev, false);
}
/*############################################*/
/*############ Internal Encoder ##############*/
/*############################################*/
//Variablen
static volatile int enc_in_counter = 0;
static volatile int64_t last_interrupt_time = 0;
static volatile uint16_t last_interrupt_time_but = 0;
static volatile bool enc_in_button_flag = false;
static volatile uint8_t last_state = 0;
static void IRAM_ATTR enc_in_isr_handler(void *arg) {
static uint64_t last_interrupt_time = 0;
// Aktueller Zustand der Pins lesen
uint8_t current_state = (gpio_get_level(CONFIG_IN_ENC_A_GPIO) << 1) | gpio_get_level(CONFIG_IN_ENC_B_GPIO);
uint64_t interrupt_time = esp_timer_get_time();
// Zustandswechsel-Logik (FSM) ohne starre Entprellzeit
if (current_state != last_state) {
// Nur wenn der Wechsel signifikant verzögert ist (gute Flanke)
if ((interrupt_time - last_interrupt_time) > CONFIG_IN_ENCODER_DEBOUNCE_TIME) {
if ((last_state == 0b01 && current_state == 0b11) ||
(last_state == 0b10 && current_state == 0b00)) {
enc_in_counter++; // Vorwärtsdrehen
} else if ((last_state == 0b10 && current_state == 0b11) ||
(last_state == 0b01 && current_state == 0b00)) {
enc_in_counter--; // Rückwärtsdrehen
}
last_state = current_state; // Zustand aktualisieren
last_interrupt_time = interrupt_time;
}
}
}
static void IRAM_ATTR enc_in_but_isr_handler(void *arg) {
uint64_t interrupt_time = esp_timer_get_time();
// Entprellung: Verhindert die Erfassung von Störungen aufgrund von Prellung
if (interrupt_time - last_interrupt_time_but > (CONFIG_IN_ENCODER_DEBOUNCE_TIME*1000)) { // Entprellungszeit
last_interrupt_time_but = interrupt_time; // Entprellzeit zurücksetzen
if (gpio_get_level(CONFIG_IN_ENC_BUT_GPIO)) {
enc_in_button_flag = true;
}
}
}
void config_internal_Encoder(){
ESP_ERROR_CHECK(gpio_isr_handler_add(CONFIG_IN_ENC_A_GPIO, enc_in_isr_handler, NULL));
ESP_ERROR_CHECK(gpio_isr_handler_add(CONFIG_IN_ENC_B_GPIO, enc_in_isr_handler, NULL));
ESP_ERROR_CHECK(gpio_isr_handler_add(CONFIG_IN_ENC_BUT_GPIO, enc_in_but_isr_handler, NULL));
}
/*############################################*/
/*############### Menu-Setup #################*/
/*############################################*/
typedef enum {
MAIN_MENU,
CONFIGURE_MENU,
MORE_INFO_MENU
} MenuState;
typedef enum {
MCPWM_MODE,
BLDC_MODE,
DC_BRUSHED_MODE,
MODE_COUNT
}OperationMode;
const char *mode_names[] = {
"MCPWM ",
"BLDC ",
"DC Brush"
};
const char *OutCombi_names[]= {
"+U -V",
"+U -W",
"+V -W",
"+V -U",
"+W -U",
"+W -V",
" +U ",
" +V ",
" +W "
};
typedef enum {
STATE_ACTIVE,
STATE_DEAKTIVE,
STATE_UV,
STATE_OC
} BridgeState;
const char *state_names[] = {
"Active ",
"Deaktive ",
"UV ",
"RFE set(OC)"
};
//Globalevariablen
volatile MenuState current_menu = MAIN_MENU;
volatile OperationMode current_mode = MCPWM_MODE;
volatile BridgeState current_bridge_state = STATE_DEAKTIVE;
volatile OutCombis current_out_combi = OUT_U_V;
volatile bool ShouldState = false; //false==deaktive
int cursor_position = 0;
int max_cursor_pos = 0;
bool in_editing = false;
char display_message[100]; // Puffer für die Nachricht
bool flag;
uint16_t PWM_Frequency = 0;
static void check_button_pressed(){
if (enc_in_button_flag){
enc_in_button_flag=false;
switch (current_menu){
case MAIN_MENU:
switch(cursor_position){
case 0:
current_mode = (current_mode+1)% MODE_COUNT;
break;
case 1:
ShouldState = !ShouldState;
if(ShouldState){
start_mcpwm_output();
}else{
stop_mcpwm_output();
}
break;
case 2:
current_menu = CONFIGURE_MENU;
enc_in_counter=0;
break;
case 3:
current_menu = MORE_INFO_MENU;
enc_in_counter=0;
break;
case 4:
current_out_combi =(current_out_combi+1)%6;
stop_mcpwm_output();
configure_mcpwm_output(current_out_combi);
ShouldState = false;
break;
default:
snprintf(display_message, sizeof(display_message), "ERROR");
ssd1306_display_text(&dev, 7, display_message, strlen(display_message), false);
break;
}
break;
case CONFIGURE_MENU:
switch(cursor_position){
case 0:
if(in_editing){
set_mcpwm_frequency(enc_in_counter*1000);
in_editing = false;
enc_in_counter= cursor_position;
}else{
in_editing = true;
enc_in_counter = get_frequency()/1000;
}
break;
case 1:
if(in_editing){
set_mcpwm_duty((float)enc_in_counter);
in_editing = false;
enc_in_counter = cursor_position;
}else{
in_editing = true;
enc_in_counter = (int)get_duty();
}
break;
case 3:
current_menu = MAIN_MENU;
enc_in_counter=0;
break;
}
break;
case MORE_INFO_MENU:
current_menu = MAIN_MENU;
enc_in_counter=0;
break;
default:
ESP_LOGE("Error","Not yet programmed");
break;
}
}
}
static void getset_bridge_state(){
bool RFE_Pulled = !(gpio_get_level(CONFIG_RFE_GPIO));
if (RFE_Pulled){
current_bridge_state=STATE_OC;
}else if(!ShouldState){
current_bridge_state=STATE_DEAKTIVE;
}else{
current_bridge_state=STATE_ACTIVE;
}
}
static void render_main_menu(){
max_cursor_pos = 4;
//Mode
snprintf(display_message, sizeof(display_message), "Mode: %s", mode_names[current_mode]);
ssd1306_display_text(&dev, 1, display_message, strlen(display_message), cursor_position == 0);
//ShouldState Started oder Stopped
snprintf(display_message, sizeof(display_message), "%s", ShouldState ? "Started" : "Stopped");
ssd1306_display_text(&dev, 2, display_message, strlen(display_message), cursor_position == 1);
//Configure_Menu
snprintf(display_message, sizeof(display_message), "Configure ->");
ssd1306_display_text(&dev, 3, display_message, strlen(display_message), cursor_position == 2);
//More_Info_Menu
snprintf(display_message, sizeof(display_message), "Sensor Info ->");
ssd1306_display_text(&dev, 4, display_message, strlen(display_message), cursor_position == 3);
//Output Selection
snprintf(display_message, sizeof(display_message), "Out: %s",OutCombi_names[current_out_combi]);
ssd1306_display_text(&dev, 5, display_message, strlen(display_message), cursor_position == 4);
//State
getset_bridge_state();
snprintf(display_message, sizeof(display_message), "State: %s",state_names[current_bridge_state]);
ssd1306_display_text(&dev, 6, display_message, strlen(display_message), true);
/*snprintf(display_message, sizeof(display_message), "cursor: %i %s",cursor_position,enc_in_button_flag ?"in" : "out");
ssd1306_display_text(&dev, 7, display_message, strlen(display_message), true);
*/}
static void render_config_menu(){
max_cursor_pos = 3;
switch(current_mode){
case MCPWM_MODE:
//Titel
snprintf(display_message, sizeof(display_message), "Conf. MCPWM");
ssd1306_display_text(&dev, 1, display_message, strlen(display_message), false);
//Frequenz
if(in_editing && cursor_position == 0){
snprintf(display_message, sizeof(display_message), "PWMFreq.:%ikHz", enc_in_counter);
ssd1306_display_text(&dev, 2, display_message, strlen(display_message), true);
set_mcpwm_frequency(enc_in_counter*1000);
}else{
snprintf(display_message, sizeof(display_message), "PWMFreq.:%lukHz", (get_frequency()/1000));
ssd1306_display_text(&dev, 2, display_message, strlen(display_message), cursor_position == 0);
}
//Duty cycle
if(in_editing && cursor_position == 1){
snprintf(display_message, sizeof(display_message), "Duty: %.1f%%", (float)enc_in_counter);
ssd1306_display_text(&dev, 3, display_message, strlen(display_message), cursor_position == 1);
set_mcpwm_duty((float)enc_in_counter);
}else{
snprintf(display_message, sizeof(display_message), "Duty: %.1f%%", get_duty());
ssd1306_display_text(&dev, 3, display_message, strlen(display_message), cursor_position == 1);
}
//Todzeit
snprintf(display_message, sizeof(display_message), "DeadTime: %ins", CONFIG_DEAD_TIME_PWM);
ssd1306_display_text(&dev, 4, display_message, strlen(display_message), cursor_position == 2);
//Back
snprintf(display_message, sizeof(display_message), "Back");
ssd1306_display_text(&dev, 5, display_message, strlen(display_message), cursor_position == 3);
//State
getset_bridge_state();
snprintf(display_message, sizeof(display_message), "State: %s",state_names[current_bridge_state]);
ssd1306_display_text(&dev, 6, display_message, strlen(display_message), true);
break;
default:
break;
}
}
static void render_info_menu(){
max_cursor_pos = 1;
switch(current_mode){
case MCPWM_MODE:
//cur_U & Hall_A
snprintf(display_message, sizeof(display_message), "U:%ldmA H_A:%c", get_current_ASC712(CONFIG_I_SENSE_U_ADC),get_Hall(CONFIG_HALL_A_GPIO)?'1':'0');
ssd1306_display_text(&dev, 1, display_message, strlen(display_message), false);
//cur_V & Hall_B
snprintf(display_message, sizeof(display_message), "V:%ldmA H_B:%c", get_current_ASC712(CONFIG_I_SENSE_V_ADC),get_Hall(CONFIG_HALL_B_GPIO)?'1':'0');
ssd1306_display_text(&dev, 2, display_message, strlen(display_message), false);
//cur_W & Hall_C
snprintf(display_message, sizeof(display_message), "W:%ldmA H_C:%c", get_current_ASC712(CONFIG_I_SENSE_W_ADC),get_Hall(CONFIG_HALL_C_GPIO)?'1':'0');
ssd1306_display_text(&dev, 3, display_message, strlen(display_message), false);
//Bridge Current & Speed
snprintf(display_message, sizeof(display_message), "B:%ldmA SP.:%frpm", get_current_bridge(CONFIG_I_SENSE_ADC), get_speed_AB());
ssd1306_display_text(&dev, 4, display_message, strlen(display_message), false);
//Bridge Voltage & Torque
snprintf(display_message, sizeof(display_message), "U_in:%ldmV Torq.:%ldmV", get_voltage_in(), get_torque());
ssd1306_display_text(&dev, 5, display_message, strlen(display_message), false);
//Left/right
snprintf(display_message, sizeof(display_message), "Dir.:%s",
(get_direction() == -1) ? "Error" :
(get_direction() == 0) ? "Right" : "Left");
ssd1306_display_text(&dev, 6, display_message, strlen(display_message), false);
//Back
snprintf(display_message, sizeof(display_message), "Back");
ssd1306_display_text(&dev, 7, display_message, strlen(display_message), true);
break;
default:
break;
}
}
MenuState last_menu = MAIN_MENU; // Initialisiere mit dem Startmenü
void menu_loop(){
if(!in_editing){
if (enc_in_counter<0){
enc_in_counter = max_cursor_pos;
}
if (enc_in_counter> max_cursor_pos){
enc_in_counter =0;
}
cursor_position = enc_in_counter;
}
if (current_menu != last_menu) {
ssd1306_clear_screen(&dev, false); // Clear the screen on menu change
last_menu = current_menu; // Update to the new menu state
}
switch (current_menu)
{
case MAIN_MENU:
render_main_menu();
break;
case CONFIGURE_MENU:
render_config_menu();
break;
case MORE_INFO_MENU:
render_info_menu();
default:
break;
}
check_button_pressed();
}