Der ESP32 ist ein fettes Teil, aber die (Arduino) Doku / Beispiele sind
bisher dürftig.
Derzeit suche ich eine Möglichkeit am ESP32 ein externes Clock-Signal
auszugeben. Beim AVR ja simpel - Timer einstellen, anschalten, Pin
hüpft.
Beim ESP32 habe ich bisher probiert:
#1 - RepeatTimer aus den beigefügten Arduino Beispielen.
Hebt und senkt im Sekundentakt fein das Bein - am Prescaler drehen geht
auch (40 statt 80 sind 500ms, usw.). Den Zähler (Microsekunden) im
Timer-Call von 1000000 auf 500000 stellen macht das selbe.
Aber enn man zu weit runter geht wird erst die Linie auf dem Oszi
"unscharf" - die Rechtecke verlagern sich periodisch, es entstehen
Geister.
Und ab einem gewissen Punkt kommt einfach nur noch eine Guru Meditation
über UART. (Ich gebe übrigens nix auf der UART aus, nur Pin an/aus).
Vermutlich funkt hier RTOS dazwischen.
#2 - LEDC PWM. Scheinbar auch nicht geeignet so schnelle Signale zu
erzeugen - es werden bisher auch nur 10+ Bit PWM-Frequenzen angeboten.
Mit weniger Bits könnte es gehen.
Hat jemand eine Idee? Das muss doch gehen.
Wenn dir das LEDC-Modul zu langsam ist, probier es mal mit dem
MCPWM-Modul. Das ist eigentlich für die Ansteuerung von Motortreibern
gedacht, sollte aber einen ganzen zacken schneller laufen als das
LEDC-Modul. Keine Ahnung wie schnell genau. Du hast auch nicht gesagt
wie schnell es zuckeln soll. Das was du gemacht hast ist sehr
wahrscheinlich Software-PWM per Interrupt. Da der Guru eingesprungen
ist, tippe ich mal darauf, dass FreeRTOS mit diesem IRQ-Storm nicht klar
kam und sich verschluckt hat.
Was die Timer und andere "spezielle" Peripherie des ESP32 angeht,
vergiss den Arduino-Kram. Selbst das ESP-IDF ist noch dermaßen
unausgegoren und unvollständig, dass es selbst da oft haaresträubend
ist. Wenn du mit dem ESP32 derzeit irgendwas machen willst, was über das
Dimmen einer LED hinausgeht, dann musst du schon mindestens mal das IDF
hernehmen und im Zweifelsfall auch mal einen Blick ins Handbuch werfen
und zur größten Not auch ein paar Register von Hand ziehen. Das geht
aber alles auch aus der Arduino-Umgebung heraus und du musst nicht
komplett auf das IDF umsatteln. Ist in gewisser Weise wie bei den AVRs.
OK, MCPWM ist wieder was neues, auf dem board bei ESP32.com wurde mir
die I2C Clock vorgeschlagen. Kreativ, aber nicht unbedingt das was man
erwartet...
Das mit den IDF Namespaces in Arduino hab ich schon - teilweise -
mitbekommen. Manche Sachen tuns auch 1:1 aus der Dokumentation raus.
Z.B. das hier:
Stefan Z. schrieb:> OK, MCPWM ist wieder was neues
Ja bis vor zwei Monaten gab es den auch noch nicht :D Also im Silizium
war er drin aber eben nirgendwo dokumentiert. Angeblich gibt es auch
noch ein BPWM-, also "Basic PWM-Modul" und angeblich arbeiten sie da
gerade daran. Es gibt also immer was neues und man kann sich quasi alle
paar Monate über ein neues Feature freuen, als hätte man einen neuen
Chip.
Hmm und ich dachte, dass bei € 6,– für das Modul jetzt der Punkt wäre wo
es langsam Resourcen für Normalsterbliche gibt…
Naja lassen wir das gute Stück noch etwas im Regal reifen.
Danke auf jeden Fall!
Stefan Z. schrieb:> Naja lassen wir das gute Stück noch etwas im Regal reifen.
Ich bezweifle ob das z.B. bei den Timern so schnell so viel besser wird.
Dafür gibt es bei dem Teil einfach noch zu viele Baustellen. Der
CAN-Treiber fehlt meines Wissens nach z.B. noch komplett.
Eigentlich ist die Sache nicht so wild. Ein simples PWM-Dingens mit dem
IDF sieht z.B. so aus:
1
#include"driver/mcpwm.h"
2
#include"soc/mcpwm_reg.h"
3
#include"soc/mcpwm_struct.h"
4
5
6
#define GPIO_MCPWM0_0A_OUT 19 //Set GPIO 19 as PWM0A of MCPWM0
pwm_config.cmpr_a=20.0;//duty cycle of PWMxA = 20.0%
18
pwm_config.counter_mode=MCPWM_UP_COUNTER;
19
// set the output polarity
20
// DUTY_MODE_0 means output is 20% high and 80% low, DUTY_MODE_1 means 20% low and 80% high
21
pwm_config.duty_mode=MCPWM_DUTY_MODE_0;
22
23
mcpwm_init(MCPWM_UNIT_0,MCPWM_TIMER_0,&pwm_config);//Configure PWM0A & PWM0B with above settings
24
25
while(1);
26
}
Das hatte ich so in der Art auch selber schonmal am laufen. Funktioniert
an sich ganz gut aber die Angabe des Dutycycles als Float stinkt nach
Fisch. Stelle ich die Frequenz auf 500kHz und Duty-Cycle auf 50% bekomme
ich 3µs Periodendauer und 1µs Impuls auf High, 2µs auf Low. Guckt man in
den Quelltext der mcpwm.c stellt man dann fest, das alle Timer
grundsätzlich auf 1MHz getaktet werden, nur steht das nirgendwo. Das ist
das, was ich oben mit "haaresträubend" meinte.
Wie gesagt: Man kann den ESP32 auch direkt per Register programmieren.
Im IDF selbst wird das auch so gemacht. Man kann sich also einen
prinzipiellen Ablauf in den Funktionen des IDF abschauen. Ich hab mir
mal den Spaß gemacht und so ein Beispiel zusammengetippt/kopiert. Für
einen Überblick über das MCPWM-Modul empfehle ich unbedingt einen Blick
ins (wirklich nicht so schlechte) Reference Manual. Ansonsten viel Spaß
beim Pin togglen.
1
#include"driver/mcpwm.h"
2
#include"soc/mcpwm_struct.h"
3
4
5
#define GPIO_MCPWM1_2B_OUT 19
6
7
voidapp_main()
8
{
9
// configure GPIO for output B of operator 2 of MCPWM module 1
Nice! Vielen Danke!
Ich habs mal in Arduino reingeworfen - macht leider Fehler beim
Kompilieren.
der Fehler hier kommt ständig - was bedeutet er in diesem Kontext?
Hmmm, ich hab es auch selber gerade mal mit Arduino getestet und dem
scheinen die sowohl die Struct-Deklarationen aus dem Header, sowie so
manche Typedefs nicht zu schmecken. Das liegt wohl vermutlich an C++.
Ich bin leider weder bei Arduino, noch bei C++ sonderlich bewandert und
nutze selber nur das IDF. Du könntest auch den Karren von hinten
aufziehen und im IDF das Arduino-Framework einbinden:
https://github.com/espressif/arduino-esp32/blob/master/docs/esp-idf_component.md
Ansonsten müsstest du denke ich die Funktion in eine C-Datei packen und
eine Arduino-Library (in C++) als Wrapper basteln aber da bin ich
ehrlich gesagt der falsche Ansprechpartner. Mit dem IDF funktioniert es
jedenfalls einwandfrei.
Ich werde mal auf Zeit setzen und die Library-Arbeit den Pros
überlassen...
Ging ja dann beim alten ESP auch irgendwann alles recht gut.
Vielen Dank trotzdem!