Hallo,
ich suche nach Hilfe bei meinem kleinen Projekt, bei dem ich seit fast
einem Jahr nach etlichen versuchen einfach nicht weiter komme.
Ich versuche PWMs mit vorgegebenen Anzahl an Perioden zur Erzeugen, um 8
Stepper Motor an bestimmte Positionen zu fahren.
Wie viele Perioden der Timer für jeden Motor erzeugen soll kriegt der
Controller über eine CAN Botschaft mitgeteilt. Die Botschaft enthält 8
Positionen, die mit den aktuellen Positionen verglichen werden. Sollte
die übersendete Position von der aktuellen Position abweichen, ergibt
sich ein Verfahrweg, der umgerechnet werden kann an die jeweilige Anzahl
an Perioden.
Folgende Timer werden dafür genutzt:
Tim2 mit CH1-CH4, Tim3 mit CH1-CH2 und Tim4 mit CH1-CH2.
Alle PWM sind mit einer festen Frequenz spezifiziert.
Als Mikrocontroller verwende ich einen STM32F103 Blue Pill.
Ich habe die Befürchtung, dass sich die Interrupts gegenseitig im Code
Blockieren. Zumindest stimmen die Positionen nicht 100% nach etwa 24
Stunden.
Da ich kein Experte auf dem Gebiet bin frage ich mich, ob ich das ganze
überhaupt richtig umgesetzt habe.
Callback für die CAN Nachricht:
1 | void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
|
2 | {
|
3 | flag=true; //flag zur Berechnung des Verfahrwegs in der while Schleife
|
4 | recieve_positions(); //Positionen werden in neue_position abgelegt
|
5 | }
|
Ich Polle in meiner Hauptschleife
1 | while(1)
|
2 | {
|
3 | if(flag==true)
|
4 | {
|
5 | motion_calculations(); //// Berechnet den zu fahrenden Weg und Startet PWM Bewegung
|
6 | }
|
7 | }
|
Auschnitt aus motion_calculation():
1 | void motion_calculations()
|
2 | {
|
3 | flag=false;
|
4 | for(uint8_t i=0; i<4; i++)
|
5 | {
|
6 | weg_m[1][i]=(neue_position_m[1][i]-aktuelle_position_m[1][i]); //weg_m enthält die zu erreichende Anzahl der Perioden, um die Position zu erreichen
|
7 | weg_s[1][i]=(neue_position_s[1][i]-aktuelle_position_s[1][i]);
|
8 | }
|
9 | for(uint8_t i=0; i<4; i++)
|
10 | {
|
11 | if (weg_s[1][i] != 0)
|
12 | {
|
13 | switch(i)
|
14 | {
|
15 | case 0:
|
16 | if (weg_s[1][0] >= 0)
|
17 | {
|
18 | HAL_GPIO_WritePin(GPIOA, CWCCW1A_Pin, GPIO_PIN_SET); //Motor dreht rechts
|
19 | }
|
20 | else
|
21 | {
|
22 | HAL_GPIO_WritePin(GPIOA, CWCCW1A_Pin, GPIO_PIN_RESET); //Motor dreht links
|
23 | weg_s[1][0]=abs(weg_s[1][0]); //Bewegungsvorzeichen entfernen
|
24 | }
|
25 | HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1);
|
26 | counter_clock_1s=0;
|
27 | break
|
28 | // Das ganze wird auch noch für alle andern Timer/Motoren gestartet weg_s[1][0] weg_s[1][1] weg_s[1][2] weg_s[1][3] und weg_m[1][0] weg_m[1][1] weg_m[1][2] weg_m[1][3]
|
Nach jeder Periode wird der HAL_TIM_PWM_PulseFinishedCallback
aufgerufen, um die Anzahl der Periode zu inkrementieren, falls die Ziel
Anzahl (weg_s, weg_m) erreicht ist, wird der PWM gestoppt:
1 | void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
|
2 | {
|
3 | if(htim->Instance == TIM2)
|
4 | {
|
5 | if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
|
6 | {
|
7 | if(counter_clock_1s==weg_s[0][0])
|
8 |
|
9 | {
|
10 | HAL_TIM_PWM_Stop_IT(&htim2, TIM_CHANNEL_1);
|
11 | aktuelle_position_s[0][0] = neue_position_s[0][0];
|
12 | }
|
13 | counter_clock_1s++;
|
14 | }
|
15 | }
|
16 |
|
17 | // in diesem Interrupt sind auch alle anderen Interrupts enthalten
|
18 | if(htim->Instance == TIM2)
|
19 | {
|
20 | if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
|
21 | ........
|
PWM Einstellung für Tim2 (anderen Timer sind gleich eingestellt):
1 | /* TIM2 init function */
|
2 | void MX_TIM2_Init(void)
|
3 | {
|
4 | TIM_MasterConfigTypeDef sMasterConfig = {0};
|
5 | TIM_OC_InitTypeDef sConfigOC = {0};
|
6 |
|
7 | htim2.Instance = TIM2;
|
8 | htim2.Init.Prescaler = 17;
|
9 | htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
|
10 | htim2.Init.Period = 4095;
|
11 | htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
12 | htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
13 | if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
|
14 | {
|
15 | Error_Handler();
|
16 | }
|
17 | sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
18 | sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
19 | if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
|
20 | {
|
21 | Error_Handler();
|
22 | }
|
23 | sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
24 | sConfigOC.Pulse = 2095;
|
25 | sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
26 | sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
27 | if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
|
28 | {
|
29 | Error_Handler();
|
30 | }
|
31 | if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
|
32 | {
|
33 | Error_Handler();
|
34 | }
|
35 | if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
|
36 | {
|
37 | Error_Handler();
|
38 | }
|
39 | if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
|
40 | {
|
41 | Error_Handler();
|
42 | }
|
43 | HAL_TIM_MspPostInit(&htim2);
|
44 |
|
45 | }
|
Ist es überhaupt richtig wie ich hier vorgehe? Meine Hoffnung ist, dass
ich hier ein falschen weg gegangen bin und es einen anderen weg gibt.
Über jede Hilfe wäre ich dankbar, weil ich einfach nicht mehr weiter
weiß. Falls doch richtig sein sollte, wäre ich über das Feedback
natürlich auch glücklich, dann muss es wohl an etwas anderem liegen.
Gruß David