Steuerung der Drehzahl eines DC-Motors über PWM mit Arduino Giga R1 WiFi und Arduino Giga Display Shield

Ich stelle folgenden Code zur Verfügung zur Steuerung eines Gleichstrommotors über PWM. In meinem Fall ist der PWM-Pin mit dem Motion Controller von Faulhaber verbunden. Demnächst möchte ich die zuletzt eingestellte Geschwindigkeit auf einer SD-Karte speichern. Ich poste ein Demo-Video zum Anschauen.

#include "DIALOG.h"

static int DrehzahlPin = 9;      
static int g_SliderValue = 0;    
static int g_NumTicks = 80;      
static int g_SliderWidth = 50;   
static WM_HWIN hSlider = 0;

#define ID_BUTTON (GUI_ID_USER + 0)

static int g_Locked = 1; // Startzustand: gesperrt (1 = gesperrt, 0 = entsperrt)
static int lastValidPWM = 127.5; // Speichert den letzten PWM-Wert

static int _MySliderDrawSkin(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo) {
    return SLIDER_DrawSkinFlex(pDrawItemInfo);
}

static void _SetSliderState(int lock) {
    if (lock) {
        WM_DisableWindow(hSlider);
    } else {
        WM_EnableWindow(hSlider);
    }
}

static void _cbChildWinSlider(WM_MESSAGE * pMsg) {
    int Value;
    char acBuffer[32];
    static WM_HWIN hButton;
    static int lastValidValue = 0;

    switch (pMsg->MsgId) {
        case WM_CREATE:
            hSlider = SLIDER_CreateEx(0, 380, 800, 100,
                                    pMsg->hWin, WM_CF_SHOW,
                                    SLIDER_CF_HORIZONTAL, GUI_ID_SLIDER0);
            SLIDER_SetRange(hSlider, -500, 500);
            SLIDER_SetNumTicks(hSlider, g_NumTicks);
            SLIDER_SetValue(hSlider, 0);
            SLIDER_SetWidth(hSlider, g_SliderWidth);
            SLIDER_SetSkin(hSlider, _MySliderDrawSkin);
            
            hButton = BUTTON_CreateEx(300, 250, 200, 80, pMsg->hWin, WM_CF_SHOW, 0, ID_BUTTON);
            BUTTON_SetText(hButton, g_Locked ? "RPM-Gesperrt" : "RPM-Entsperrt");
            
            _SetSliderState(g_Locked);
            break;

        case WM_PAINT: {
            GUI_SetBkColor(GUI_WHITE);
            GUI_Clear();
            GUI_SetFont(&GUI_FontD60x80);
            GUI_SetColor(GUI_BLACK);

            Value = g_Locked ? lastValidValue : g_SliderValue;
            sprintf(acBuffer, "%d RPM", Value);
            
            int textWidth = GUI_GetStringDistX(acBuffer); 
            int xPos = (LCD_GetXSize() - textWidth) / 2;
            
            GUI_DispStringAt(acBuffer, xPos, 100);

            GUI_SetFont(&GUI_Font32B_1);
            GUI_DispString("RPM");

            // Ticks zeichnen
            int y0 = 380;
            int width = 847;
            int height = 100;

            int tickThickness = 4;
            int shortTickLength = 10;
            int longTickLength = 20;

            GUI_SetColor(GUI_BLACK);
            for (int i = 0; i <= g_NumTicks; i++) {
                int x = (width - g_SliderWidth) * i / g_NumTicks;
                int currentTickLength = (i % 5 == 0) ? longTickLength : shortTickLength;
                
                for (int t = 0; t < tickThickness; t++) {
                    GUI_DrawLine(x + t, y0, x + t, y0 + currentTickLength);
                }
                for (int t = 0; t < tickThickness; t++) {
                    GUI_DrawLine(x + t, y0 + height - currentTickLength, x + t, y0 + height);
                }
            }
            break;
        }

        case WM_NOTIFY_PARENT: {
            int Id = WM_GetId(pMsg->hWinSrc);
            int NCode = pMsg->Data.v;

            if (Id == GUI_ID_SLIDER0 && NCode == WM_NOTIFICATION_VALUE_CHANGED) {
                if (!g_Locked) {
                    lastValidValue = SLIDER_GetValue(hSlider);
                    g_SliderValue = lastValidValue;
                    // PWM-Wert berechnen und speichern
                    lastValidPWM = (lastValidValue <= 0) ? 
                                 (int)((lastValidValue + 500) / 500.0 * 127.5) : 
                                 (int)(lastValidValue / 500.0 * 127.5 + 127.5);
                }
                WM_InvalidateWindow(pMsg->hWin);
            }
            else if (Id == ID_BUTTON) {
                switch (NCode) {
                    case WM_NOTIFICATION_RELEASED:
                        g_Locked = !g_Locked;
                        BUTTON_SetText(pMsg->hWinSrc, g_Locked ? "RPM-Gesperrt" : "RPM-Entsperrt");
                        _SetSliderState(g_Locked);
                        WM_InvalidateWindow(pMsg->hWin);
                        break;
                }
            }
            break;
        }

        default:
            WM_DefaultProc(pMsg);
            break;
    }
}

void setup() {
    Serial.begin(9600);
    delay(100);
    pinMode(DrehzahlPin, OUTPUT);
    
    GUI_Init();
    LCD_ROTATE_SetSel(1);
    WM_MULTIBUF_Enable(1);
    
    WM_CreateWindowAsChild(0, 0, LCD_GetXSize(), LCD_GetYSize(),
                         WM_HBKWIN, WM_CF_SHOW, _cbChildWinSlider, 0);
}

void loop() {
    if (!g_Locked) {
        // Im entsperrten Zustand: aktuellen Sliderwert verwenden
        int v = g_SliderValue;
        if (v < -500) v = -500;
        if (v > 500) v = 500;
        
        lastValidPWM = (v <= 0) ? (int)((v + 500) / 500.0 * 127.5) 
                              : (int)(v / 500.0 * 127.5 + 127.5);
    }
    // Im gesperrten Zustand: letzten PWM-Wert weiterverwenden
    analogWrite(DrehzahlPin, lastValidPWM);
    Serial.println(lastValidPWM);

    GUI_Exec();
}

Video kann ich nicht posten….

Und wo ist das Problem? Beispiel aus SD Lib nehmen, lernen, umbauen, nutzen.
Link zu DIALOG.h bitte

Suchmaschine kaputt?
"Arduino DIALOG.h"

Wo möglich schon = nix gefunden.
Hätte ich ein ARM Controller müsste es nicht suchen.

[OT]

Codevorschlag:
Mach Dir zwei(drei) Konstanten für die Verwendung im Code:

constexpr int minSlider {-500};
constexpr int maxSlider {500};
constexpr int valSlider {500};

und im Code ersetzt Du Deine 2 Zeilen:
constrain(v,minSlider,maxSlider);

und überall für die 500 bei der Berechnung nimmst Du valSlider.

1 Like

wo zu Int wen Byte reicht?

Dazu

Na ja Int mit Komma :wink:

"Mit Integer ([ˈɪnteɡɐ], englisch [ˈɪntɪdʒə], für ganze Zahl; von lateinisch numerus integer) wird in der Informatik ein Datentyp bezeichnet, der ganzzahlige Werte speichert."

Guter Vorschlag!

Ja, ich weiß – manchmal denkt man beim Schreiben nicht daran….mitte von 255 halt :smiley: