STM32 - Encoder programmeren met timers

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
Ik ben momenteel bezig met het programmeren van mijn op zelf ontwikkelde PCB in STM32CubeIDE. De PCB is uitgerust met een STM32F103CBT6 microcontroller en een 16 MHz kristaloscillator. Op de PCB zijn 4 rotary encoders aangesloten, waarbij elke encoder is toegewezen aan een specifieke timer (encoder 1 op timer1, encoder 2 op timer2, enzovoort). Mijn doel is om de encoder te programmeren, zodat ik de draairichting kan detecteren. Ik wil de gedetecteerde draairichting vervolgens registreren als een knopinput. Bijvoorbeeld, links draaien wordt button 1 en rechts draaien wordt button 2. Deze input wordt vervolgens in een game gekoppeld aan een specifieke functie.

Op de PCB zijn ook 16 drukknoppen geschakeld in een button matrix, die al correct functioneren en input verzenden via hid reports. Echter, ik heb moeite met het gebruik van timers voor de encoders. Wanneer ik de encoderpinnen eenvoudig als GPIO-input instel en programmeer, werken ze wel correct. Maar in deze configuratie heb ik last van onjuiste input / jumping tussen pinnen. Online is mij geadviseerd om de encoders op de timers aan te sluiten. Is er iemand die mij verder kan helpen of meer informatie kan geven?

Als er meer info nodig is hoor ik het graag.

Iracing Profiel - Twitch - Youtube

Beste antwoord (via joeyl94 op 16-11-2023 21:26)


  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 14:40
Je krijgt pas een periode elapsed interrupt als je 65535 keer aan de encoder hebt gedraaid.
Je moet volgens hid gaan werken en regelmatig pollen en de status opsturen, interrupts hierop zal niet goed werken.

Alle reacties


Acties:
  • +1 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 14:40
Heb je last van contact bouncing op de timers? Als ik het goed herinner hebben de timers hier filters voor.

IC1F zou in het TIMx_CCMR1 moeten zitten. Maar ook via cube zou je deze moeten kunnen instellen.
Je moet wellicht ook even kijken naar de prescaler van de timer hoe snel de timer deze filters evalueert.

Acties:
  • 0 Henk 'm!

  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
Excuus, nee ik heb last van bouncing als ik onderstaande code gebruik. Ik wil juist timers gaan gebruiken om dit te verhelpen. Maar ik weet niet hoe ik de timers moet instellen en programmeren om de gewenste resulstaat te krijgen

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    for (int i = 0; i < ROT_BUTTONS; i++) {
        uint8_t currentPinState = HAL_GPIO_ReadPin(rotaryPorts[i], rotaryPins[i]);

        if (currentPinState != debounceState[i]) {
            // Wacht op een stabiele staat voordat de waarde wordt bijgewerkt
            debounceState[i] = currentPinState;
            HAL_Delay(DEBOUNCE_DELAY);
            currentPinState = HAL_GPIO_ReadPin(rotaryPorts[i], rotaryPins[i]);

            if (currentPinState != stableState[i]) {
                // Update de stabiele staat
                stableState[i] = currentPinState;
                buttonReport.buttons |= (currentPinState == GPIO_PIN_RESET) << i;
            }
        }
    }

[ Voor 42% gewijzigd door joeyl94 op 10-11-2023 16:45 ]

Iracing Profiel - Twitch - Youtube


Acties:
  • +1 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 14:40
De timers zijn edge sensitive, dus als je encoders flinkt klapperen is dat lastig.
Je kunt wel iets doen met die filters die ik noemde. Dat is ongeveer hetzelfde als wat je daar hebt geschreven.
De inputs moeten dan ten minste x ticks hoog zijn.

Hoe zit je applicatie er nu uit? Gebruik je polling? Gebruik je gpio interrupts?

Acties:
  • +1 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik ben verre van een expert op dit vlak, maar bij een encoder denk ik aan een interrupt en niet aan een timer? Of is dat een andere terminologie? En is het niet handiger de debouncing in hardware (zoveel mogelijk) te doen?

Ik zie hier dan wel weer timers gebruikt worden.

[ Voor 22% gewijzigd door RobIII op 10-11-2023 18:14 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • +1 Henk 'm!

  • Damic
  • Registratie: September 2003
  • Laatst online: 06:36

Damic

Tijd voor Jasmijn thee

@RobIII ja maar die timers kunnen in Encoder modus gezet worden, dus hardware doet al het filteren.
STM32 Timers can be configured in encoder mode and do most of the "heavy lifting".
En als ik verder lees zien ik dat het dan een timer 3 interrupt word :)

@joeyl94 ik zou dus die link van RobIII eens een kijkje geven ;)

Al wat ik aanraak werk niet meer zoals het hoort. Damic houd niet van zijn verjaardag


Acties:
  • 0 Henk 'm!

  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
Thanks voor jullie input! Ik ga vanavond dat linkje eens goed bestuderen en die filter bekijken! Keep you updated!

Iracing Profiel - Twitch - Youtube


Acties:
  • +1 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 14:40
In de reference manual (14.3.16) staat ook een stuk over de encoder modus.
Maar in de basis komt het erop neer dat je de timer op encoder modus zet.
De prescaler op bijvoorbeeld 6399, als je HCLK 64 is krijg je een 10 kHz tick in de timer (nodig voor de filters)
Stel je wilt dat de inputs dan ten minste 1 ms vast staan voor een capture, dan zet je filter op 10.

prescalers division ratio is denk ik niet wat je zoekt, dan triggert hij elke n edge pas en ga je stappen missen.

En je kunt de encoder waarde lezen in het timer register. De velocity moet je zelf nog bepalen met wat wrapping subtracts.

Je hoeft trouwens geen timer te gebruiken, wat je nu doet is ook prima haalbaar met software polling zoals je nu al doet. Hier beschrijven ze hoe dat bijvoorbeeld kan:
Digital Debounce Filter
The digital filter is made up of a single 16 bit integer variable into which you shift the current state of the input pin:

state=(state<<1) | digitalRead(CLK_PIN) | 0xe000;

This is a very compact filter - each time round the loop a new bit is shifted left (at bit 0). The "or" action with 0xe000 defines the number of iterations i.e. the top 3 bits are blocked off leaving the rest as useful inputs. The idea is that you test for the state 0xf000 which can only occur if there was a sequence of 1 0000 0000 0000 inputs meaning that the signal has been stable for 12 iterations around the loop i.e. not bouncing around

[ Voor 4% gewijzigd door jeroen3 op 10-11-2023 20:21 ]


Acties:
  • 0 Henk 'm!

  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
Ik ben inmiddels aan het spelen met de timers met hulp van de linkjes en google/chatgpt en heb inmiddels het volgende. De code geeft geen foutmeldingen, maar de pcb geeft ook geen input. De button matrix werkt wel gewoon dus aan de hid reports ligt het niet. De code maakt nu wel gebruik van de timers als het goed is. dus we blijven nog even doorspelen.

De timers heb ik zo ingesteld nu:
Afbeeldingslocatie: https://tweakers.net/i/iTEeP6hFHaPF0ElKEjQ1t4UsbH4=/x800/filters:strip_exif()/f/image/pljkvEDE0TDe2LGuIwOIIbO3.png?f=fotoalbum_large

En hier heb ik een paar stukken van de code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
void HAL_TIM_PeriodElapsedCallback_TIM1(TIM_HandleTypeDef *htim);
void HAL_TIM_PeriodElapsedCallback_TIM2(TIM_HandleTypeDef *htim);
void HAL_TIM_PeriodElapsedCallback_TIM3(TIM_HandleTypeDef *htim);
void HAL_TIM_PeriodElapsedCallback_TIM4(TIM_HandleTypeDef *htim);

TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim4;

volatile uint8_t encoderState[ROT_BUTTONS] = {0};
void HandleEncoderInterrupt(GPIO_TypeDef* rotaryPorts[], uint16_t rotaryPins[], volatile uint8_t encoderState[], int encoderIndex);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM1_Init();
    MX_TIM2_Init();
    MX_TIM3_Init();
    MX_TIM4_Init();
    MX_USB_DEVICE_Init();

    // Start Timers
    HAL_TIM_Base_Start_IT(&htim1);
    HAL_TIM_Base_Start_IT(&htim2);
    HAL_TIM_Base_Start_IT(&htim3);
    HAL_TIM_Base_Start_IT(&htim4);

    while (1) {
        SCANALL();
        HAL_Delay(50);
    }
}

// Function to handle Timer 4 interrupt
void HAL_TIM_PeriodElapsedCallback_TIM4(TIM_HandleTypeDef *htim) {
    if (htim == &htim4) {
        HandleEncoderInterrupt(rotaryPorts, rotaryPins, encoderState, 3);
        SendButtonReport();
    }
}

void HandleEncoderInterrupt(GPIO_TypeDef* rotaryPorts[], uint16_t rotaryPins[], volatile uint8_t encoderState[], int encoderIndex) {
    // Read the current state of the encoder pin
    uint8_t encoderValue = HAL_GPIO_ReadPin(rotaryPorts[encoderIndex], rotaryPins[encoderIndex]);

    // Process the encoder value and update the buttonReport
    encoderState[encoderIndex] = (encoderState[encoderIndex] << 1) | encoderValue;

    if (encoderState[encoderIndex] == 0x00 || encoderState[encoderIndex] == 0xFF) {
        // Stable state detected, update the buttonReport
        buttonReport.buttons |= (encoderValue == GPIO_PIN_RESET) << encoderIndex;
    }
}

[ Voor 4% gewijzigd door joeyl94 op 10-11-2023 21:29 ]

Iracing Profiel - Twitch - Youtube


Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 14:40
Je krijgt pas een periode elapsed interrupt als je 65535 keer aan de encoder hebt gedraaid.
Je moet volgens hid gaan werken en regelmatig pollen en de status opsturen, interrupts hierop zal niet goed werken.

Acties:
  • 0 Henk 'm!

  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
jeroen3 schreef op vrijdag 10 november 2023 @ 21:31:
Je krijgt pas een periode elapsed interrupt als je 65535 keer aan de encoder hebt gedraaid.
Je moet volgens hid gaan werken en regelmatig pollen en de status opsturen, interrupts hierop zal niet goed werken.
Thanks voor je hulp, dat wordt enorm gewaardeerd! _/-\o_
Ik heb nu de code aangepast met een polling code. maar ik weet nu niet precies hoe ik de timers in de ioc moet instellen om het correct te laten werken?

de code heb ik nu als volgt:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
uint16_t previousEncoder1Value = 0;
uint8_t encoder1State = 0;
uint16_t previousEncoder2Value = 0;
uint8_t encoder2State = 0;
uint16_t previousEncoder3Value = 0;
uint8_t encoder3State = 0;
uint16_t previousEncoder4Value = 0;
uint8_t encoder4State = 0;

// Functie voor het pollen van encoders
void pollEncoders(void) {
    // Lees de huidige waarde van elke encoder
    uint16_t encoder1Value = TIM1->CNT;
    uint16_t encoder2Value = TIM2->CNT;
    uint16_t encoder3Value = TIM3->CNT;
    uint16_t encoder4Value = TIM4->CNT;

    // Detecteer de draairichting voor encoder 1
    int16_t encoder1Delta = encoder1Value - previousEncoder1Value;
    if (encoder1Delta > 0) {
        // Clockwise rotation for encoder 1
        buttonReport.buttons |= (1 << 0);
    } else if (encoder1Delta < 0) {
        // Counterclockwise rotation for encoder 1
        buttonReport.buttons |= (1 << 1);
    }

    // Detecteer de draairichting voor encoder 2
    int16_t encoder2Delta = encoder2Value - previousEncoder2Value;
    if (encoder2Delta > 0) {
        // Clockwise rotation for encoder 2
        buttonReport.buttons |= (1 << 2);
    } else if (encoder2Delta < 0) {
        // Counterclockwise rotation for encoder 2
        buttonReport.buttons |= (1 << 3);
    }

    // Detecteer de draairichting voor encoder 3
    int16_t encoder3Delta = encoder3Value - previousEncoder3Value;
    if (encoder3Delta > 0) {
        // Clockwise rotation for encoder 3
        buttonReport.buttons |= (1 << 4);  // Set Button 2
    } else if (encoder3Delta < 0) {
        // Counterclockwise rotation for encoder 3
        buttonReport.buttons |= (1 << 5);  // Set Button 3
    }

    // Detecteer de draairichting voor encoder 4
    int16_t encoder4Delta = encoder4Value - previousEncoder4Value;
    if (encoder4Delta > 0) {
        // Clockwise rotation for encoder 4
        buttonReport.buttons |= (1 << 6);  // Set Button 4
    } else if (encoder4Delta < 0) {
        // Counterclockwise rotation for encoder 4
        buttonReport.buttons |= (1 << 7);  // Set Button 5
    }

    // Stel de vorige waarde in voor de volgende iteratie
    previousEncoder1Value = encoder1Value;
    previousEncoder2Value = encoder2Value;
    previousEncoder3Value = encoder3Value;
    previousEncoder4Value = encoder4Value;

    // Send the report with button statuses
    buttonReport.report_id = 1;
    USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&buttonReport, sizeof(buttonReport));
}

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USB_DEVICE_Init();
    MX_TIM1_Init();
    MX_TIM2_Init();
    MX_TIM3_Init();
    MX_TIM4_Init();

    // Initialize encoder states
    encoder1State = (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) << 1) | HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9);
    encoder2State = (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) << 1) | HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
    encoder3State = (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) << 1) | HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
    encoder4State = (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) << 1) | HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);

    while (1) {
        SCANBUTTONS();
        pollEncoders();
        HAL_Delay(50);
    }
}

Iracing Profiel - Twitch - Youtube


Acties:
  • +1 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 14:40
Zoiets volgens mij:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void init(){
  HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
}

int encoderSteps(TIM_HandleTypeDef *htim){
  uint16_t tim = __HAL_TIM_GET_COUNTER(htim);
  __HAL_TIM_SET_COUNTER(htim, 0); // dan hoef je je geen zorgen te maken over wrapping
  if(tim > 0x7FFF)
    return -(65535 - tim);
  else
    return tim;
}

void polling(){
  int stepsCh1 = encoderSteps(htim1);
  int stepsCh2 = encoderSteps(htim2);
}

test: https://godbolt.org/z/hd8vPfMj1

[ Voor 51% gewijzigd door jeroen3 op 11-11-2023 18:14 . Reden: fix wrapping error in code voorbeeld ]


Acties:
  • +1 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 14:40
Nog een tip overigens, probeer het gebruik van delays te voorkomen.
Om iets regelmatig te doen in de main thread kun je de systick gebruiken.
Voorbeeld:
C:
1
2
3
4
5
6
7
8
while(1){
  const uint32_t interval = 50; // milliseconden
  uint32_t time = HAL_GetTick() + interval;
  if(HAL_GetTick() > time){
    time += interval;
    iets();
  }
}

Je hebt dan exactere polling onafhankelijk van de duur van je code zelf. Moet je code natuurlijk wel <interval duren. (incl usb interrupts ertussendoor) HAL_GetTick wrapt op 32 bit ~42 dagen. Maar deze snippet heeft hier geen last van de += wrapt ook.

Acties:
  • +1 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 14:01
Wat werkt er nu niet aan die encoder modus?
In principe kun je de encoder in software afhandelen, maar eigenlijk ben je dan de timer in encoder modus aan het nabouwen. Dwz, ook in dat geval heb je voor de encoderpinnen een egde interrupt waarin je bepaalt of je vooruit of achteruit gaat tellen.
Met een timer kun je bij een overflow/update interrupt van die 16bits counter eentje met een groter counterbereik maken.
Uiteindelijk moet je denk ik voor je USB HID updates een andere manier/timer gebruiken om de updates weg te sturen, ik kan me voorstellen dat je encoder interrupts sneller binnenkoment dan je USB stack kan bijhouden.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
Ik heb nu een code die werkt met de timers, en ik krijg ook input van de encoder. Maar ik heb hetzelfde probleem als ik de gpio pinnen direct uitlees. De input blijft jumpen tussen de pinnen wanneer de encoder gedraaid wordt.

Ik heb de timer als volgt ingesteld nu (counter period op 1 geeft betere input)
Afbeeldingslocatie: https://tweakers.net/i/irsSCShxFzWfcnIIMm6FudjDwdg=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/GosChxN6YlI8V1aAtWYJHMhT.png?f=user_large

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
int16_t prevEncoderValue = 0; // Variabele om vorige encoderwaarde bij te houden

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM1) {
        // Lees de huidige encoderwaarde uit de timerregisters
        int16_t currentEncoderValue = TIM1->CNT;

        // Bepaal de richting van de encoderbeweging
        int16_t encoderDiff = currentEncoderValue - prevEncoderValue;

        if (encoderDiff > 0) {
            // Clockwise rotation detected
            buttonReport.buttons |= (1 << 0); // Simuleer druk op knop 1
        } else if (encoderDiff < 0) {
            // Counterclockwise rotation detected
            buttonReport.buttons |= (1 << 1); // Simuleer druk op knop 2
        }

        if (encoderDiff != 0) {
            buttonReport.report_id = 1;
            USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&buttonReport, sizeof(buttonReport));
        }

        // Werk de vorige encoderwaarde bij
        prevEncoderValue = currentEncoderValue;

        __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);

    }
}

static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_Encoder_InitTypeDef sConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
  sConfig.IC1Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 8;
  sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 15;
  if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */

}

Iracing Profiel - Twitch - Youtube


Acties:
  • +1 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 14:40
De timer draait nu op HCLK, zet er eens wat prescaler in. (Je filter, 8x (1/72MHz) is 111 ns dat helpt niet denk ik)
En heroverweeg of je de interrupt wil gebruiken, je kunt nu niet zien welke kant de encoder op is gedraaid want hij telt maar tot 1.

[ Voor 13% gewijzigd door jeroen3 op 14-11-2023 10:46 ]


  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
Even een update, het werkt! het gebruiken van polling ipv interrupts was inderdaad the way to go! Thanks voor de input, het heeft me goed geholpen! :)

Iracing Profiel - Twitch - Youtube


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 14:01
Misschien wel aardig voor het nageslacht om een stukje code te delen hoe je het nu gedaan hebt...

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
farlane schreef op zaterdag 18 november 2023 @ 14:31:
Misschien wel aardig voor het nageslacht om een stukje code te delen hoe je het nu gedaan hebt...
Excuus, wou ik inderdaad nog plaatsen. Bij deze :)
Ik moet alleen nog spelen met de counter period / prescaler, ik krijg nog te veel input per puls

EDIT: bouncing probleem is opgelost. ik heb de bijgewerkte code bijgevoegd.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
      int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM1_Init();
    MX_TIM2_Init();
    MX_TIM3_Init();
    MX_TIM4_Init();
    MX_USB_DEVICE_Init();

    HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
    HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);
    HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
    HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);

    HAL_TIM_Base_Start_IT(&htim1);
    HAL_TIM_Base_Start_IT(&htim2);
    HAL_TIM_Base_Start_IT(&htim3);
    HAL_TIM_Base_Start_IT(&htim4);

    while (1) {
        // Poll TIM1 encoder
        int16_t currentEncoderValue1 = TIM1->CNT;
        int16_t encoderDiff1 = currentEncoderValue1 - prevEncoderValue1;

        // Handle rollovers
        if (encoderDiff1 > 32767) {
            encoderDiff1 -= 65536;
        } else if (encoderDiff1 < -32768) {
            encoderDiff1 += 65536;
        }

        if (encoderDiff1 > 0) {
            // Clockwise rotation detected
            buttonReport.buttons |= (1 << 0);
        } else if (encoderDiff1 < 0) {
            // Counterclockwise rotation detected
            buttonReport.buttons |= (1 << 1);
        }

        if (encoderDiff1 != 0) {
            buttonReport.report_id = 1;
            USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&buttonReport, sizeof(buttonReport));
        }

        prevEncoderValue1 = currentEncoderValue1;
}
}

static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_Encoder_InitTypeDef sConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
  sConfig.IC1Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 5;
  sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 5;
  if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */

}

[ Voor 17% gewijzigd door joeyl94 op 20-11-2023 13:41 ]

Iracing Profiel - Twitch - Youtube


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 14:01
Thx, maar je post helaas net niet hoe je nu die poll doet. Dat is zo'n beetje de crux van je oplossing ;)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • +1 Henk 'm!

  • joeyl94
  • Registratie: Oktober 2014
  • Laatst online: 12:16

joeyl94

Probleem'n? Poar neem'n!

Topicstarter
farlane schreef op zondag 19 november 2023 @ 20:55:
Thx, maar je post helaas net niet hoe je nu die poll doet. Dat is zo'n beetje de crux van je oplossing ;)
heb de post bijgewerkt, met de hele main void

Iracing Profiel - Twitch - Youtube

Pagina: 1