348 lines
13 KiB
C
348 lines
13 KiB
C
|
|
#include "functions.h"
|
|
adc_cali_handle_t cali_handle= NULL;
|
|
|
|
/*############################################*/
|
|
/*############### GPIO-Setup #################*/
|
|
/*############################################*/
|
|
void configure_GPIO_dir(const char *TAG)
|
|
{
|
|
/* reset every used GPIO-pin */
|
|
gpio_reset_pin(CONFIG_HIN_U_GPIO);
|
|
gpio_reset_pin(CONFIG_HIN_V_GPIO);
|
|
gpio_reset_pin(CONFIG_HIN_W_GPIO);
|
|
|
|
gpio_reset_pin(CONFIG_LIN_U_GPIO);
|
|
gpio_reset_pin(CONFIG_LIN_V_GPIO);
|
|
gpio_reset_pin(CONFIG_LIN_W_GPIO);
|
|
|
|
gpio_reset_pin(CONFIG_HALL_A_GPIO);
|
|
gpio_reset_pin(CONFIG_HALL_B_GPIO);
|
|
gpio_reset_pin(CONFIG_HALL_C_GPIO);
|
|
|
|
//gpio_reset_pin(CONFIG_IN_ENC_A_GPIO);
|
|
gpio_reset_pin(CONFIG_IN_ENC_B_GPIO);
|
|
gpio_reset_pin(CONFIG_IN_ENC_BUT_GPIO);
|
|
//gpio_reset_pin(CONFIG_BUTTON_GPIO);
|
|
|
|
|
|
gpio_reset_pin(CONFIG_EXT_ENC_LEFT_GPIO);
|
|
gpio_reset_pin(CONFIG_EXT_ENC_RIGHT_GPIO);
|
|
gpio_reset_pin(CONFIG_RFE_GPIO);
|
|
|
|
/* Set the GPIO as a push/pull output */
|
|
gpio_set_direction(CONFIG_HIN_U_GPIO, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(CONFIG_HIN_V_GPIO, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(CONFIG_HIN_W_GPIO, GPIO_MODE_OUTPUT);
|
|
|
|
gpio_set_direction(CONFIG_LIN_U_GPIO, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(CONFIG_LIN_V_GPIO, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(CONFIG_LIN_W_GPIO, GPIO_MODE_OUTPUT);
|
|
|
|
gpio_set_direction(CONFIG_HALL_A_GPIO, GPIO_MODE_INPUT);
|
|
gpio_set_direction(CONFIG_HALL_B_GPIO, GPIO_MODE_INPUT);
|
|
gpio_set_direction(CONFIG_HALL_C_GPIO, GPIO_MODE_INPUT);
|
|
|
|
//gpio_set_direction(CONFIG_IN_ENC_A_GPIO, GPIO_MODE_INPUT);
|
|
gpio_set_direction(CONFIG_IN_ENC_B_GPIO, GPIO_MODE_INPUT);
|
|
gpio_set_direction(CONFIG_IN_ENC_BUT_GPIO, GPIO_MODE_INPUT);
|
|
//gpio_set_direction(CONFIG_BUTTON_GPIO, GPIO_MODE_INPUT);
|
|
|
|
|
|
gpio_set_direction(CONFIG_EXT_ENC_LEFT_GPIO, GPIO_MODE_INPUT);
|
|
gpio_set_direction(CONFIG_EXT_ENC_RIGHT_GPIO, GPIO_MODE_INPUT);
|
|
gpio_set_direction(CONFIG_RFE_GPIO, GPIO_MODE_INPUT);
|
|
ESP_LOGI(TAG, "GPIO dirs configured for DIY power PCB");
|
|
}
|
|
/*############################################*/
|
|
/*################ ADC-Setup #################*/
|
|
/*############################################*/
|
|
adc_oneshot_unit_handle_t configure_ADC1()
|
|
{
|
|
adc_oneshot_unit_handle_t adc1_handle;
|
|
|
|
// ADC1 Initialisierung
|
|
adc_oneshot_unit_init_cfg_t init_config = {
|
|
.unit_id = ADC_UNIT_1,
|
|
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
|
};
|
|
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc1_handle));
|
|
|
|
// Kanal-Konfiguration
|
|
adc_oneshot_chan_cfg_t config = {
|
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
.atten = ADC_ATTEN_DB_12,
|
|
};
|
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, CONFIG_TORQUE_ADC, &config));
|
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, CONFIG_U_SENSE_ADC, &config));
|
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, CONFIG_I_SENSE_U_ADC, &config));
|
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, CONFIG_I_SENSE_V_ADC, &config));
|
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, CONFIG_I_SENSE_W_ADC, &config));
|
|
|
|
// Kalibrierung initialisieren
|
|
adc_cali_line_fitting_config_t cali_config = {
|
|
.atten = ADC_ATTEN_DB_12,
|
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
};
|
|
|
|
esp_err_t ret = adc_cali_create_scheme_line_fitting(&cali_config, &cali_handle);
|
|
if (ret == ESP_OK) {
|
|
ESP_LOGI("ADC", "ADC-Kalibrierung erfolgreich initialisiert");
|
|
} else {
|
|
ESP_LOGW("ADC", "ADC-Kalibrierung nicht möglich, Rohwerte werden verwendet");
|
|
cali_handle = NULL; // Keine Kalibrierung verfügbar
|
|
}
|
|
|
|
return adc1_handle;
|
|
}
|
|
|
|
uint32_t read_voltage(adc_oneshot_unit_handle_t adc1_handle, int channel) {
|
|
int adc_raw = 0;
|
|
int voltage_calibrated = 0; // Verwende int für die Kalibrierungsfunktion
|
|
uint32_t voltage = 0; // Konvertiere später zu uint32_t
|
|
|
|
// ADC-Rohwert lesen
|
|
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, channel, &adc_raw));
|
|
|
|
// Kalibrierung anwenden, falls verfügbar
|
|
if (cali_handle) {
|
|
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(cali_handle, adc_raw, &voltage_calibrated));
|
|
voltage = (uint32_t) voltage_calibrated; // Konvertiere zu uint32_t
|
|
} else {
|
|
voltage = adc_raw; // Fallback auf Rohwert
|
|
}
|
|
|
|
return voltage;
|
|
}
|
|
// Funktion zur Umrechnung in spezifische Spannung
|
|
uint32_t get_voltage_in(adc_oneshot_unit_handle_t adc1_handle)
|
|
{
|
|
uint32_t adc_voltage = read_voltage(adc1_handle, CONFIG_U_SENSE_ADC);
|
|
ESP_LOGI("ADC", "ADC%d:voltage:%ld", CONFIG_U_SENSE_ADC, adc_voltage);
|
|
// Beispielhafte Umrechnung; Wert an eigene Anwendung anpassen
|
|
uint32_t voltage_in = adc_voltage / 0.0909;
|
|
return voltage_in;
|
|
}
|
|
|
|
int32_t get_current_ASC712(adc_oneshot_unit_handle_t adc1_handle, int ADC_pin)
|
|
{
|
|
int32_t adc_voltage = read_voltage(adc1_handle,ADC_pin);
|
|
int32_t current = (adc_voltage -2500)*5.405;
|
|
ESP_LOGI("ADC", "ADC%d:voltage:%ldcurrent%ld", ADC_pin, adc_voltage, current);
|
|
return current;
|
|
}
|
|
|
|
uint32_t get_torque(adc_oneshot_unit_handle_t adc1_handle)
|
|
{
|
|
uint32_t adc_voltage =read_voltage(adc1_handle,CONFIG_TORQUE_ADC);
|
|
uint32_t torque = adc_voltage/33;
|
|
|
|
return torque;
|
|
}
|
|
int32_t get_current_bridge(adc_oneshot_unit_handle_t adc1_handle, int ADC_pin){
|
|
int32_t adc_voltage = read_voltage(adc1_handle,ADC_pin);
|
|
ESP_LOGI("CurrentBridge", "ADC:%ld",adc_voltage);
|
|
int32_t current = ((adc_voltage- 142)/6.77)/0.007;
|
|
return current;
|
|
}
|
|
|
|
/*############################################*/
|
|
/*############## Display-Setup ###############*/
|
|
/*############################################*/
|
|
SSD1306_t *configure_OLED(const char *TAG)
|
|
{
|
|
static SSD1306_t dev;
|
|
//int center, top, bottom;
|
|
//char lineChar[20];
|
|
|
|
i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
|
|
ESP_LOGI(TAG, "Panel is 128x64");
|
|
ssd1306_init(&dev, 128, 64);
|
|
ssd1306_clear_screen(&dev, false);
|
|
ssd1306_contrast(&dev, 0xff);
|
|
ssd1306_display_text_x3(&dev, 0, "Hello", 5, false);
|
|
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
|
ssd1306_clear_screen(&dev, false);
|
|
return &dev;
|
|
}
|
|
/*############################################*/
|
|
/*################ PWM-Setup #################*/
|
|
/*############################################*/
|
|
|
|
void set_PWM_Timer()
|
|
{
|
|
ledc_timer_config_t ledc_timer = {
|
|
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
|
.timer_num = LEDC_TIMER_0,
|
|
.duty_resolution = LEDC_TIMER_10_BIT,
|
|
.freq_hz = CONFIG_FREQ_PWM_HIN,
|
|
.clk_cfg = LEDC_AUTO_CLK
|
|
};
|
|
esp_err_t err = ledc_timer_config(&ledc_timer);
|
|
if (err != ESP_OK) {
|
|
printf("Fehler beim Konfigurieren des LEDC-Timers: %s\n", esp_err_to_name(err));
|
|
return;
|
|
}
|
|
|
|
}
|
|
void set_PWM()
|
|
{
|
|
ledc_channel_config_t ledc_channel_HIN_U =
|
|
{
|
|
.speed_mode = LEDC_HIGH_SPEED_MODE, // Gleicher Modus wie beim Timer
|
|
.channel = LEDC_CHANNEL_0, // Kanal 0 verwenden
|
|
.timer_sel = LEDC_TIMER_0, // Timer 0 zuweisen
|
|
.intr_type = LEDC_INTR_DISABLE, // Keine Interrupts
|
|
.gpio_num = CONFIG_HIN_U_GPIO,
|
|
.duty = 0, //
|
|
.hpoint = 0 // Start des PWM-Signals
|
|
};
|
|
ledc_channel_config(&ledc_channel_HIN_U); // Kanal konfigurieren
|
|
ledc_channel_config_t ledc_channel_HIN_V =
|
|
{
|
|
.speed_mode = LEDC_HIGH_SPEED_MODE, // Gleicher Modus wie beim Timer
|
|
.channel = LEDC_CHANNEL_1, // Kanal 0 verwenden
|
|
.timer_sel = LEDC_TIMER_0, // Timer 0 zuweisen
|
|
.intr_type = LEDC_INTR_DISABLE, // Keine Interrupts
|
|
.gpio_num = CONFIG_HIN_V_GPIO,
|
|
.duty = 0, //
|
|
.hpoint = 0 // Start des PWM-Signals
|
|
};
|
|
ledc_channel_config(&ledc_channel_HIN_V); // Kanal konfigurieren
|
|
ledc_channel_config_t ledc_channel_HIN_W =
|
|
{
|
|
.speed_mode = LEDC_HIGH_SPEED_MODE, // Gleicher Modus wie beim Timer
|
|
.channel = LEDC_CHANNEL_2, // Kanal 0 verwenden
|
|
.timer_sel = LEDC_TIMER_0, // Timer 0 zuweisen
|
|
.intr_type = LEDC_INTR_DISABLE, // Keine Interrupts
|
|
.gpio_num = CONFIG_HIN_W_GPIO,
|
|
.duty = 0, //
|
|
.hpoint = 0 // Start des PWM-Signals
|
|
};
|
|
ledc_channel_config(&ledc_channel_HIN_W); // Kanal konfigurieren
|
|
}
|
|
void pwmStart(int PWM_CH, int Duty){
|
|
ledc_set_duty(LEDC_HIGH_SPEED_MODE,PWM_CH, Duty);
|
|
ledc_update_duty(LEDC_HIGH_SPEED_MODE,PWM_CH);
|
|
}
|
|
|
|
void pwmStop(int PWM_CH){
|
|
ledc_stop(LEDC_HIGH_SPEED_MODE, PWM_CH, 0);
|
|
}
|
|
void pwmStopAll(){
|
|
ledc_stop(LEDC_HIGH_SPEED_MODE, HIN_U_CH, 0);
|
|
ledc_stop(LEDC_HIGH_SPEED_MODE, HIN_V_CH, 0);
|
|
ledc_stop(LEDC_HIGH_SPEED_MODE, HIN_W_CH, 0);
|
|
gpio_set_level(CONFIG_LIN_U_GPIO, 0);
|
|
gpio_set_level(CONFIG_LIN_V_GPIO, 0);
|
|
gpio_set_level(CONFIG_LIN_W_GPIO, 0);
|
|
}
|
|
|
|
|
|
void U_V_start(int duty)
|
|
{
|
|
//HIN_V und LIN_U abschalten
|
|
pwmStop(HIN_V_CH);
|
|
gpio_set_level(CONFIG_LIN_U_GPIO, 0);
|
|
//HIN_U und LIN_V einschalten
|
|
pwmStart(HIN_U_CH, duty);
|
|
gpio_set_level(CONFIG_LIN_V_GPIO, 1);
|
|
}
|
|
void V_U_start(int duty)
|
|
{
|
|
//HIN_U und LIN_V abschalten
|
|
pwmStop(HIN_U_CH);
|
|
gpio_set_level(CONFIG_LIN_V_GPIO, 0);
|
|
//HIN_V und LIN_U einschalten
|
|
pwmStart(HIN_V_CH, duty);
|
|
gpio_set_level(CONFIG_LIN_U_GPIO, 1);
|
|
}
|
|
void U_W_start(int duty)
|
|
{
|
|
//HIN_W und LIN_U abschalten
|
|
pwmStop(HIN_W_CH);
|
|
gpio_set_level(CONFIG_LIN_U_GPIO, 0);
|
|
//HIN_U und LIN_V einschalten
|
|
pwmStart(HIN_W_CH, duty);
|
|
gpio_set_level(CONFIG_LIN_V_GPIO, 1);
|
|
}
|
|
void W_U_start(int duty)
|
|
{
|
|
//HIN_U und LIN_W abschalten
|
|
pwmStop(HIN_U_CH);
|
|
gpio_set_level(CONFIG_LIN_W_GPIO, 0);
|
|
//HIN_U und LIN_V einschalten
|
|
pwmStart(HIN_W_CH, duty);
|
|
gpio_set_level(CONFIG_LIN_U_GPIO, 1);
|
|
}
|
|
void V_W_start(int duty)
|
|
{
|
|
//HIN_U und LIN_W abschalten
|
|
pwmStop(HIN_W_CH);
|
|
gpio_set_level(CONFIG_LIN_V_GPIO, 0);
|
|
//HIN_U und LIN_V einschalten
|
|
pwmStart(HIN_V_CH, duty);
|
|
gpio_set_level(CONFIG_LIN_W_GPIO, 1);
|
|
}
|
|
|
|
void W_V_start(int duty)
|
|
{
|
|
//HIN_U und LIN_W abschalten
|
|
pwmStop(HIN_V_CH);
|
|
gpio_set_level(CONFIG_LIN_W_GPIO, 0);
|
|
//HIN_U und LIN_V einschalten
|
|
pwmStart(HIN_W_CH, duty);
|
|
gpio_set_level(CONFIG_LIN_V_GPIO, 1);
|
|
}
|
|
|
|
/*############################################*/
|
|
/*############### MCPWM-Setup ################*/
|
|
/*############################################*/
|
|
void set_mcpwm_U_V(){
|
|
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, CONFIG_HIN_U_GPIO);
|
|
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, CONFIG_LIN_U_GPIO);
|
|
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1A, CONFIG_HIN_V_GPIO);
|
|
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1B, CONFIG_LIN_V_GPIO);
|
|
|
|
mcpwm_config_t pwm_config_U = {
|
|
.frequency = 20000,
|
|
.cmpr_a = 50.0,
|
|
.cmpr_b = 50.0,
|
|
.counter_mode = MCPWM_UP_DOWN_COUNTER,
|
|
.duty_mode = MCPWM_DUTY_MODE_0,
|
|
};
|
|
//Initialisierung von Halbbrücke U (Timer 0)
|
|
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config_U);
|
|
mcpwm_config_t pwm_config_V = {
|
|
.frequency = 20000,
|
|
.cmpr_a = 50.0,
|
|
.cmpr_b = 50.0,
|
|
.counter_mode = MCPWM_UP_DOWN_COUNTER,
|
|
.duty_mode = MCPWM_DUTY_MODE_0,
|
|
};
|
|
//Initialisierung von Halbbrücke V (Timer 1)
|
|
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &pwm_config_V);
|
|
mcpwm_sync_enable(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_SELECT_TIMER0_SYNC, 13);
|
|
|
|
//Totzeit für Halbbrücke U
|
|
mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 50, 50);//50ns steigende Flanke, 50ns fallende Flanke
|
|
//Totzeit für Halbbrücke V
|
|
mcpwm_deadtime_enable(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, 50, 50);
|
|
}
|
|
/*############################################*/
|
|
/*################## MISC ####################*/
|
|
/*############################################*/
|
|
//Ausgelagert in Preprocessing python program, generate_pins_header.py
|
|
void parse_3pins(const char *TAG, const char *pin_string, int *pins) {
|
|
int pin_count = 0; // Jetzt ein Integer, keine Null-Pointer-Dereferenzierung
|
|
char *token;
|
|
char *pin_list = strdup(pin_string); // Kopie der String-Option
|
|
|
|
token = strtok(pin_list, ",");
|
|
while (token != NULL && pin_count < 3) { // maximal 3 Pins
|
|
pins[pin_count] = atoi(token); // Umwandlung in Integer
|
|
pin_count++;
|
|
token = strtok(NULL, ",");
|
|
}
|
|
free(pin_list); // Speicher freigeben
|
|
} |