Fortsetzung der Diskussion von duty cycle messen eines PWM-Signals bei 20kHz:
@agmue
Wie es scheint hast du das MCPWM ziemlich im Griff! Ich verzweifle mittlerweile fast bei einem Thema und zwar möchte ich den High-Wert von einem PWM-Signal messen.
Der Aufbau ist im groben so, dass auf einem GPIO ein PWM Signal erzeugt wird und (über ein paar widerstände dgl.) das gleiche PWM Signal wieder auf einen weiteren GPIO gelesen wird.
Das ganze sollte ja nicht schwierig sein jedoch bei einem Duty-Cycle von <10% benötigt man einen Interrupt o.ä. um genau am richtigen Zeitpunkt zu messen, da man ohne ansonsten mit Sicherheit erst irgend wann mal den High wert erwischt.
hier mal mein Code:
#include <driver/mcpwm.h>
#include <soc/mcpwm_struct.h>
#include <driver/adc.h>
#include <esp_adc_cal.h>
static esp_adc_cal_characteristics_t adc_chars;
int test;
static void IRAM_ATTR isr_handler(void *arg){
test++;
}
static void A_TaskCP(void *arg) {
Serial.printf("initializing mcpwm gpio and adc for CP-PWM...\n");
//######################### Initialisieren Sie den ADC-Kanal
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_11);
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &adc_chars);
//######################### PWM Signal mit MCPWM
// Hier wird der Ausgangspin für das PWM-Signal konfiguriert
mcpwm_pin_config_t pin_pwm_config;
pin_pwm_config.mcpwm0a_out_num = 32;
// MCPWM-Zuweisung
mcpwm_set_pin(MCPWM_UNIT_0, &pin_pwm_config);
// Hier wird der PWM-Signalgenerator konfiguriert
mcpwm_config_t pwm_config;
pwm_config.frequency = 1000; // 1kHz
pwm_config.cmpr_a = 10; // Duty-Cycle von 50%
pwm_config.counter_mode = MCPWM_UP_COUNTER;
pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
mcpwm_isr_register(MCPWM_UNIT_0, isr_handler, NULL, ESP_INTR_FLAG_IRAM, NULL); //Set ISR Handler
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);
// Starten des PWM-Signals
mcpwm_start(MCPWM_UNIT_0, MCPWM_TIMER_0);
// vTaskDelete(NULL);
while (1) {
//Serial.printf("\r\nTASK CP");
vTaskDelay(1000 / portTICK_PERIOD_MS); // verzögere den Task um 1000ms
}
}
static void A_Task1(void *arg) {
while (1) {
// ADC-Messwert abfragen
uint32_t raw_value = adc1_get_raw((adc1_channel_t)ADC1_CHANNEL_7);
// Berechnen des Spannungswerts aus dem ADC-Messwert
uint32_t adcRead = esp_adc_cal_raw_to_voltage(raw_value, &adc_chars);
Serial.printf("\r\nADC Read-Val %d", adcRead);
Serial.printf("\r\nInterrupt Test %d", test);
vTaskDelay(1000 / portTICK_PERIOD_MS); // verzögere den Task um 1000ms
}
}
void setup() {
Serial.begin(115200);
Serial.println("\nStart Setup.......");
xTaskCreate(A_TaskCP, "Task_CP_ReadWrite", 4096, NULL, 5, NULL);
xTaskCreate(A_Task1, "Task_1_Normal_Operation", 4096, NULL, 5, NULL);
}
void loop() {}
Laut meiner Recherche sollte es doch genügen, dass man lediglich die Funktion mcpwm_isr_register() einfügt um den Interrupt auszuführen jedoch passiert das einfach nicht!
Was mache ich falsch?
Bitte um unterstützung.
Vielen DANK!