ich versuche mit einem NodeMCU ESP8266 einen DRV8316REVM anzusteuern und nutze hierzu die Arduino-IDE. In meinem Code generiere ich sinussignale, die ich als PWM-Signal ausgebe. Ich habe 3 LEDs angeschlossen, die auch ihre helligkeit verändern, aber nach ein paar Zyklen bleibt die helligkeit der drei LEDs konstant und ich glaube, dass das Programm neu gestartet wird.
Hier ist mein bisheriger Code:
1
#include<math.h>
2
#include<Ticker.h>
3
4
constintsinTableLength=256;
5
constfloatpi=3.14159;
6
constintpwmPin_U=D1;
7
constintpwmPin_V=D2;
8
constintpwmPin_W=D3;
9
constintpwmFrequency=1000;// PWM-Frequenz in Hertz
10
11
intsinTable[sinTableLength];
12
volatileintpwmIndex=0;// Index der Sinustabelle
13
Tickerticker;
14
15
voidsetup(){
16
17
Serial.begin(115200);
18
19
for(inti=0;i<sinTableLength;i++){
20
floatradian=(float)i/sinTableLength*2*pi;
21
sinTable[i]=round(sin(radian)*127.0+128);// Skalierung auf den Bereich von 0 bis 255
22
}
23
24
pinMode(pwmPin_U,OUTPUT);
25
pinMode(pwmPin_V,OUTPUT);
26
pinMode(pwmPin_W,OUTPUT);
27
analogWriteFreq(pwmFrequency);
28
29
// Ticker einrichten
30
ticker.attach_ms(1000/pwmFrequency,updatePWM);// Timer für die PWM-Aktualisierung einrichten
Warum so kompliziert mit floats, wenn du dann doch wieder die PWM damit beschreibst?
Hinterlege die Sinustabelle im Flash und lies sie direkt aus, um die PWM damit zu beschreiben.
Eine 3-Phasen Tabelle kannst du aus meinem FU-Projekt plündern oder du lässt dir eine Phase im Internet errechnen:
https://www.mikrocontroller.net/articles/3-Phasen_Frequenzumrichter_mit_AVR
Beachte dabei, das mein Projekt zwei verschiedene Kurven unterstützt. Einmal puren Sinus und einmal die für BLDC besseren 'Popokurven'.
Die Sinus Generatoren im Netz machen immer puren Sinus.
Warum so kompliziert mit floats, wenn du dann doch wieder die PWM damit
beschreibst?
Hinterlege die Sinustabelle im Flash und lies sie direkt aus, um die PWM
damit zu beschreiben.
Eine 3-Phasen Tabelle kannst du aus meinem FU-Projekt plündern oder du
lässt dir eine Phase im Internet errechnen:
https://www.mikrocontroller.net/articles/3-Phasen_Frequenzumrichter_mit_AVR
Beachte dabei, das mein Projekt zwei verschiedene Kurven unterstützt.
Einmal puren Sinus und einmal die für BLDC besseren 'Popokurven'.
Die Sinus Generatoren im Netz machen immer puren Sinus.
Vielen Dank für die Hilfe. Ich habe den Code so angepasst, dass es für U, V und W ein eigenes Array gibt (120° verschoben). Hier ist der neue Code:
1
#include <math.h>
2
#include <Ticker.h>
3
#include <string.h>
4
5
const int pwmPin_U = D2;
6
const int pwmPin_V = D3;
7
const int pwmPin_W = D4;
8
const int pwmFrequency = 100; // PWM-Frequenz in Hertz
Das sind gar keine uint16_t, sondern uint8_t - Jedenfalls ist es vermutlich so gemeint. Allerdings sind da einige '256' drin, die den Wertebereich sprengen. Ich denke, da liegt auch das Problem.
Danke. Ich habe die 256 auf 255 geändert.
Den Typ habe ich auf uint8_t geändert.
Es wird kein Fehler mehr im SerialMonitor angezeigt.
Die LEDs leuchten schön um 120° verschoben nacheinander auf.
Aber nach ein paar Durchgängen (3-4) frieren die LEDs für ca. 1 Sekunde ein und das ganze Programm scheint neu abzulaufen. Also wieder ein paar Durchläufe, bis die LEDs wieder einfrieren.
1
#include <Ticker.h>
2
3
const int pwmPin_U = D2;
4
const int pwmPin_V = D3;
5
const int pwmPin_W = D4;
6
const int pwmFrequency = 600; // PWM-Frequenz in Hertz
Warscheinlich habe ich keine Fehler-Ausgabe mehr bekommen, weil ich die Zeile Serial.begin auskommentiert hatte.
Hier ist das Ergebnis vom Exception Decoder:
1
Exception 4: Level1Interrupt: Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register
2
PC: 0x40000f83
3
EXCVADDR: 0x00000000
4
5
Decoding stack results
6
0x4010015c: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 238
7
0x40201cac: esp_yield() at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 144
8
0x401012b1: _notifyPWM(PWMState*, bool) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_waveform_pwm.cpp line 168
9
0x40203954: _setPWMFreq_weak(uint32_t) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_waveform_pwm.cpp line 208
10
0x4010015c: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 238
11
0x40201cac: esp_yield() at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 144
12
0x401012b1: _notifyPWM(PWMState*, bool) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_waveform_pwm.cpp line 168
13
0x40203b8e: _setPWM_weak(int, uint32_t, uint32_t) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_waveform_pwm.cpp line 343
14
0x4010015c: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 238
15
0x4020140c: std::__detail::__variant::__gen_vtable_impl >::operator=(std::__detail::__variant::_Move_assign_base >&&)::{lambda(auto:1&&, auto:2)#1}&&, std::variant >&)>, std::integer_sequence >::__visit_invoke(std::__detail::__variant::_Move_assign_base >::operator=(std::__detail::__variant::_Move_assign_base >&&)::{lambda(auto:1&&, auto:2)#1}, std::variant >) at c:\users\alex\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0/variant line 1060
16
0x4020fc50: lwip_cyclic_timer at core/timeouts.c line 241
17
0x402026a1: __analogWriteMode(uint8_t, int, bool) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_wiring_pwm.cpp line 79
18
0x402012c2: std::__detail::__variant::__gen_vtable_impl >::swap(std::variant >&)::{lambda(auto:1&&, auto:2)#1}&&, std::variant >&)>, std::integer_sequence >::__visit_invoke(std::variant >::swap(std::variant >&)::{lambda(auto:1&&, auto:2)#1}, std::variant >&) at c:\users\alex\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 357
19
0x4020fc50: lwip_cyclic_timer at core/timeouts.c line 241
20
0x40201047: updatePWM() at C:\Users\alex\Documents\Arduino\OhneFehler/OhneFehler.ino line 54
21
0x402014f4: Ticker::_static_callback() at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\Ticker\src\Ticker.cpp line 135
22
0x40201028: updatePWM() at C:\Users\alex\Documents\Arduino\OhneFehler/OhneFehler.ino line 48
23
0x4020497c: std::_Function_handler ::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\alex\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 268
24
0x40204974: std::_Function_handler ::_M_invoke(std::_Any_data const&) at c:\users\alex\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 289
25
0x40201b26: loop_task(ETSEvent*) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 273
26
0x401000ab: app_entry_redefinable() at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 386
27
0x4010015c: ets_post(uint8, ETSSignal, ETSParam) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\core_esp8266_main.cpp line 238
28
0x40202c39: uart_flush(uart_t*) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\uart.cpp line 587
29
0x40100a10: malloc(size_t) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 912
30
0x40202f80: uart_init(int, int, int, int, int, size_t, bool) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\uart.cpp line 715
31
0x40202ea6: uart_init(int, int, int, int, int, size_t, bool) at C:\Users\alex\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266\uart.cpp line 707
32
0x4020115b: setup() at c:\users\alex\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 303
33
0x4020115b: setup() at c:\users\alex\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.1.0-gcc10.3-e5f9fec\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 303
Also, ich spreche ja null Arduino, aber eine ISR wird normalerweise anders deklariert, nämlich so ähnlich wie:
1
ISR(TIM1_OVF_vect){
2
// code here
3
}
Nach allem, was ich gestern abend so über Interrupts in Arduino gelesen habe, macht ihr das genauso. Es kommt also wahrscheinlich zu einem Überlauf, wenn deine Pseudo ISR zu oft gerufen wird.
Es kann sicher sein, das das bei einem ESP nochmal anders funktioniert, aber der Fehler deutet zumindest auf die ISR hin, wenn ich das richtig lese.