Hallo,
ich rechne im 1ms Takt meine Motorsteuerung für einen Schrittmotor. Für
eine hohe Dynamik wird dieser mit 256 Mikroschritten betrieben und ich
möchte gerne den Prescaler bei sehr langsamen Drehgeschwindigkeite
setzen.
Zur Info, der Aufbau ist wie eine elektrische Spritze. Wenn der Motor
sich dreht bewegt sich ein Kolben und Wasser wird herausgedrückt. Ohne
Prescaler fließt ansonsten etwa 1 Tropfen pro Sekunde (bei 12µl pro
Fullstep), was zu viel wäre, da hier über eine längere zeit aufsummiert
wird.
Wenn ich den Code zusammenstückle, sieht es etwa so aus (die velocity
sind Mikrosteps pro Sekunde, timerclock sind 100MHz, timer_maxvalue ist
2^16-1):
1 | uint32_t timervaluebuffer = 0;
|
2 | uint32_t prescalervalue = 0;
|
3 |
|
4 | calc_velocitiy(&Motor);
|
5 | //calculate the timer
|
6 | if (Motor->velocity_in_steps == 0)
|
7 | {
|
8 | HAL_TIM_OC_Stop(Motor->handle.htim, TIM_CHANNEL_4);
|
9 | }
|
10 | else
|
11 | {
|
12 | timervaluebuffer = timer_clock / fabsf(Motor->velocity_in_steps);
|
13 | if (timervaluebuffer > timer_maxvalue)
|
14 | {
|
15 | prescalervalue = timervaluebuffer / timer_maxvalue + 1;
|
16 | timervaluebuffer = (timer_clock / ((prescalervalue + 1) * fabsf(Motor->velocity_in_steps)));
|
17 | }
|
18 | HAL_TIM_OC_Start(Motor->handle.htim, TIM_CHANNEL_4);
|
19 | }
|
20 | __HAL_TIM_SET_AUTORELOAD(Motor->handle.htim, timervaluebuffer);
|
21 | __HAL_TIM_SET_PRESCALER(Motor->handle.htim, prescalervalue);
|
22 | return 0;
|
Mein Problem sind die Shadow Register. Natürlich haben sie einen Sinn,
aber bei mir führt das dazu, dass wenn sehr langsame Geschwindigkeiten
angefahren werden (Extrembeispiel 1µStep/s), wird ja weder der Prescaler
noch der Autoreloadwert übernommen, bis ein Update Event passiert, was
im Extremfall eine Sekunde dauern kann.
Mir fällt aber keine gute Logik ein, wann ich beispielsweise "händisch"
einen solchen Event auslösen sollte oder wie ich das sonst irgendwie
umgehen kann.
Ist das Problem verständlich?