Skip to content
This repository has been archived by the owner on Feb 4, 2023. It is now read-only.

Commit

Permalink
Add PWM_StepperControl example
Browse files Browse the repository at this point in the history
Credits of `Paul van Dinther` (https://github.com/dinther)
  • Loading branch information
khoih-prog committed Jan 22, 2023
1 parent 5feec22 commit 5abb928
Showing 1 changed file with 11 additions and 241 deletions.
252 changes: 11 additions & 241 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
* [Examples](#examples)
* [ 1. PWM_Multi](examples/PWM_Multi)
* [ 2. PWM_Single](examples/PWM_Single)
* [ 3. multiFileProject](examples/multiFileProject). **New**
* [ 3. multiFileProject](examples/multiFileProject)
* [ 4. PWM_StepperControl](examples/PWM_StepperControl). **New**
* [Example PWM_Multi](#example-PWM_Multi)
* [Debug Terminal Output Samples](#debug-terminal-output-samples)
* [1. PWM_Single on PORTENTA_H7_M7](#1-PWM_Single-on-PORTENTA_H7_M7)
Expand Down Expand Up @@ -133,7 +134,7 @@ The catch is **your function is now part of an ISR (Interrupt Service Routine),
## Prerequisites

1. [`Arduino IDE 1.8.19+` for Arduino](https://github.com/arduino/Arduino). [![GitHub release](https://img.shields.io/github/release/arduino/Arduino.svg)](https://github.com/arduino/Arduino/releases/latest)
2. [`ArduinoCore-mbed mbed_portenta core 3.4.1+`](https://github.com/arduino/ArduinoCore-mbed) for Arduino **Portenta_H7** boards, such as **Portenta_H7 Rev2 ABX00042, etc.**. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-mbed.svg)](https://github.com/arduino/ArduinoCore-mbed/releases/latest)
2. [`ArduinoCore-mbed mbed_portenta core 3.5.4+`](https://github.com/arduino/ArduinoCore-mbed) for Arduino **Portenta_H7** boards, such as **Portenta_H7 Rev2 ABX00042, etc.**. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-mbed.svg)](https://github.com/arduino/ArduinoCore-mbed/releases/latest)

---
---
Expand Down Expand Up @@ -446,250 +447,18 @@ void setup()

1. [PWM_Multi](examples/PWM_Multi)
2. [PWM_Single](examples/PWM_Single)
3. [**multiFileProject**](examples/multiFileProject) **New**
3. [multiFileProject](examples/multiFileProject)
4. [**PWM_StepperControl**](examples/PWM_StepperControl) **New**


---
---

### Example [PWM_Multi](examples/PWM_Multi)

```cpp
#if !( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) )
#error For Portenta_H7 only
#endif

#define _PWM_LOGLEVEL_ 1

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "Portenta_H7_PWM.h"

#define LED_ON LOW
#define LED_OFF HIGH

// Can't use same TimerIndex again, e.g., the D1 and D2, using TIM1, can't be use concurrently
// That's why D0, D1, D3, D4 and D6 (using TimerIndex 8, 1, HRTIM and 3) are OK together

// Only OK for D0, D1, D2, D4 and D5, PA_0C(D15/A0), PA_1C(D16/A1),
// D3, D6, D7, D8, D9, D10, D11, D12, D13, D14, D17(PC_2C/A2), D18(PC_3C/3), PC2(D19/A4) LEDG, LEDB not OK
#define pinD0 D0 // PH15 / TIM8_CH3N
#define pinD1 D1 // PK1 / TIM1_CH1, TIM8_CH3
#define pinD2 D2 // PJ11 / TIM1_CH2, TIM8_CH2N
#define pinD3 D3 // PG7 / HRTIM_CHE2
#define pinD4 D4 // PC7 / TIM3_CH2, TIM8_CH2, HRTIM_CHA2
#define pinD5 D5 // PC6 / TIM3_CH1, TIM8_CH1, HRTIM_CHA1, LPTIM3_OUT
#define pinD6 D6 // PA8 / HRTIM_CHB2 (TIM1_CH1, TIM8_BKIN2)

// See https://www.st.com/resource/en/datasheet/stm32h747xi.pdf, Table 7, page 53
// Can't use pins with same TIMx. For example,
// pinD1 and pinD2, using same TIM1, can't be used at the same time
// pinD4 and pinD5, using same TIM3, can't be used at the same time
// pinD3 and pinD6 are using HRTIM, can't be used at the same time and the minimum freq must be ~770Hz
uint32_t pins[] = { pinD0, pinD1, pinD3, pinD5 };

#define NUM_OF_PINS ( sizeof(pins) / sizeof(uint32_t) )

float dutyCycle[] = { 50.0f, 50.0f, 50.0f, 50.0f };

float freq[] = { 1000.0f, 2500.0f, 4000.0f, 5000.0f };
https://github.com/khoih-prog/Portenta_H7_PWM/blob/5feec228d068702edb8fe20557e13bb02f9cbc3e/examples/PWM_Multi/PWM_Multi.ino#L10-L251

float curDutyCycle[] = { 50.0f, 50.0f, 50.0f, 50.0f };

float curFreq[] = { 1000.0f, 2500.0f, 4000.0f, 5000.0f };

mbed::PwmOut* pwm[] = { NULL, NULL, NULL, NULL };

void startAllPWM()
{
digitalWrite(LEDG, LED_ON);
digitalWrite(LEDB, LED_OFF);
digitalWrite(LEDR, LED_OFF);

for (uint8_t index = 0; index < NUM_OF_PINS; index++)
{
PWM_LOGERROR7("Freq = ", freq[index], ", \tDutyCycle % = ", dutyCycle[index], ", \tDutyCycle = ", dutyCycle[index] / 100, ", \tPin = ", pins[index]);

// setPWM(mbed::PwmOut* &pwm, pin_size_t pin, float frequency, float dutyCycle)
setPWM(pwm[index], pins[index], freq[index], dutyCycle[index]);
}
}

void restoreAllPWM()
{
digitalWrite(LEDG, LED_ON);
digitalWrite(LEDB, LED_OFF);
digitalWrite(LEDR, LED_OFF);

for (uint8_t index = 0; index < NUM_OF_PINS; index++)
{
curFreq[index] = freq[index];
curDutyCycle[index] = dutyCycle[index];

// setPWM(mbed::PwmOut* &pwm, pin_size_t pin, float frequency, float dutyCycle)
setPWM(pwm[index], pins[index], freq[index], dutyCycle[index]);
}
}

void changeAllPWM()
{
digitalWrite(LEDG, LED_OFF);
digitalWrite(LEDB, LED_ON);
digitalWrite(LEDR, LED_OFF);

for (uint8_t index = 0; index < NUM_OF_PINS; index++)
{
curFreq[index] = freq[index] * 2;
curDutyCycle[index] = dutyCycle[index] / 2;

// setPWM(mbed::PwmOut* &pwm, pin_size_t pin, float frequency, float dutyCycle)
setPWM(pwm[index], pins[index], curFreq[index], curDutyCycle[index]);
}
}

void stopAllPWM()
{
digitalWrite(LEDG, LED_OFF);
digitalWrite(LEDB, LED_OFF);
digitalWrite(LEDR, LED_ON);

for (uint8_t index = 0; index < NUM_OF_PINS; index++)
{
curFreq[index] = 1000.0f;
curDutyCycle[index] = 0.0f;

//stopPWM(mbed::PwmOut* &pwm, pin_size_t pin)
stopPWM(pwm[index], pins[index]);
}
}

void printLine()
{
Serial.println(F("\n=========================================================================================================="));
}

void printPulseWidth()
{
static uint32_t num = 0;

if (num++ % 50 == 0)
{
printLine();

for (uint8_t index = 0; index < NUM_OF_PINS; index++)
{
Serial.print(F("PW (us) ")); Serial.print(index); Serial.print(F("\t"));
}

printLine();
}

if (num > 1)
{
for (uint8_t index = 0; index < NUM_OF_PINS; index++)
{
if (pwm[index])
{
if ( (pins[index] == pinD3) || (pins[index] == pinD6) )
{
// Using HRTIM => fake by calculating PW
Serial.print( (10000 * curDutyCycle[index]) / curFreq[index] ); Serial.print(F("\t\t"));
}
else
{
Serial.print((float) pwm[index]->read_pulsewitdth_us()); Serial.print(F("\t\t"));
}
}
}

Serial.println();
}
}

#define PRINT_INTERVAL 10000L
#define CHANGE_INTERVAL 20000L

void check_status()
{
static unsigned long checkstatus_timeout = 0;
static unsigned long changePWM_timeout = 0;

static bool PWM_orig = true;
static uint32_t count = 0;

// Print every PRINT_INTERVAL (10) seconds.
if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))
{
printPulseWidth();
checkstatus_timeout = millis() + PRINT_INTERVAL;
}

if ( (millis() > changePWM_timeout) && (millis() > CHANGE_INTERVAL) )
{

if (PWM_orig)
{
if (count++ %2 == 0)
{
Serial.println("Stop all PWM");
stopAllPWM();
}
else
{
Serial.println("Change all PWM");

changeAllPWM();

PWM_orig = !PWM_orig;
}
}
else
{
Serial.println("Restore all PWM");
restoreAllPWM();

PWM_orig = !PWM_orig;
}
changePWM_timeout = millis() + CHANGE_INTERVAL;
}
}

void setup()
{
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
pinMode(LEDR, OUTPUT);

digitalWrite(LEDG, LED_OFF);
digitalWrite(LEDB, LED_OFF);
digitalWrite(LEDR, LED_OFF);

for (uint8_t index = 0; index < NUM_OF_PINS; index++)
{
pinMode(pins[index], OUTPUT);
digitalWrite(pins[index], LOW);
}

Serial.begin(115200);
while (!Serial);

delay(100);

Serial.print(F("\nStarting PWM_Multi on ")); Serial.println(BOARD_NAME);
Serial.println(PORTENTA_H7_PWM_VERSION);

// Automatically retrieve TIM instance and channel associated to pin
// This is used to be compatible with all STM32 series automatically.

startAllPWM();
}

void loop()
{
check_status();
}
```
---
---

Expand All @@ -702,7 +471,7 @@ The following is the sample terminal output when running example [PWM_Single](ex

```cpp
Starting PWM_Single on PORTENTA_H7_M7
Portenta_H7_PWM v2.0.2
Portenta_H7_PWM v2.0.3
[PWM] Freq = 5000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 5

========
Expand Down Expand Up @@ -736,9 +505,8 @@ Restore PWM
The following is the sample terminal output when running example [**PWM_Multi**](examples/PWM_Multi) on **Portenta_H7** to demonstrate how to start multiple PWM channels, then stop, change, restore the PWM settings on-the-fly.
```cpp

Starting PWM_Multi on PORTENTA_H7_M7
Portenta_H7_PWM v2.0.2
Portenta_H7_PWM v2.0.3
[PWM] Freq = 1000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 0
[PWM] Freq = 2500.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 1
[PWM] Freq = 4000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 3
Expand Down Expand Up @@ -816,7 +584,7 @@ Submit issues to: [Portenta_H7_PWM issues](https://github.com/khoih-prog/Portent
3. Rewrite the library to fix bug and to permit to start, stop, modify, restore PWM settings on-the-fly
4. Optimize library code by using `reference-passing` instead of `value-passing`
5. Convert to `h-only` style

6. Add example [PWM_StepperControl](https://github.com/khoih-prog/Portenta_H7_PWM/examples/PWM_StepperControl) to demo how to control Stepper Motor using PWM

---
---
Expand All @@ -826,11 +594,13 @@ Submit issues to: [Portenta_H7_PWM issues](https://github.com/khoih-prog/Portent
Many thanks for everyone for bug reporting, new feature suggesting, testing and contributing to the development of this library.

1. Thanks to [GitChris3004](https://github.com/GitChris3004) for reporting, investigating the bug in [No PWM-Output signals #1](https://github.com/khoih-prog/Portenta_H7_PWM/issues/1), which is fixed and leading to v2.0.0.
2. Thanks to [Paul van Dinther](https://github.com/dinther) for proposing new way to use PWM to drive Stepper-Motor in [Using PWM to step a stepper driver #16](https://github.com/khoih-prog/RP2040_PWM/issues/16), leading to v2.0.3


<table>
<tr>
<td align="center"><a href="https://github.com/GitChris3004"><img src="https://github.com/GitChris3004.png" width="100px;" alt="GitChris3004"/><br /><sub><b>GitChris3004</b></sub></a><br /></td>
<td align="center"><a href="https://github.com/dinther"><img src="https://github.com/dinther.png" width="100px;" alt="dinther"/><br /><sub><b>Paul van Dinther</b></sub></a><br /></td>
</tr>
</table>

Expand Down

0 comments on commit 5abb928

Please sign in to comment.