TouchGFXを使おう10～Servo編～

TouchGFXを使おう～I2C編~の続きとして今回はServoモータを動かします。

STM32CubeIDEを使ってみよう How To STM32CubeIDE 日本語版 (13) PWMでサーボモーター（SERVO)を動かしてみようを元にプログラム作成をします。

https://qiita.com/usashirou/items/2d0fedf59a3cef083b87
# 画面の作成
新規プロジェクトを作成し、画面上にサーボモーターの角度を表示するテキストエリアを作成します。
__Transtation__ を __Servo °__ にし __＋__ を __クリック__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/dc733777-e27e-e92f-b570-6f0cc7cbc6ef.png)

# wildcardの設定
__Wildcard1__ を __クリック__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/892bf3bf-0e6d-f48d-a2e8-30a323b547a4.png)
__＋__ を __クリック__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/f5a9c012-2036-301d-56d4-1d627d5ffcfe.png)
__Initial Value__ を __000__ とします。
__Buffer size__ は __12__ にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/30c0168f-3034-37f9-62f6-b85f66176067.png)
左の __Texts__ を __クリック__ し、文字設定を行います。
__Typographies__ を選択し、__Large__ の __Wildcard Ranges__ を __0-9__ にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/fffb0aa6-a8f6-d7b2-8202-479c859a5090.png)
# pin設定
今回、Timerを使用出来るピンとしてPD15を使用しますが、PWMが使用出来るピンであればほかのピンでも問題ありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/a16f8bce-68dd-2da1-cd17-93d79c7cf95f.png)
コード生成後、__STM32CubeIDE__ で __プロジェクト__ を開き
__PD15__ を __クリック__ し __TIM4_CH4__ を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/69924326-4f72-efba-762c-e7d4f908ef3e.png)
TIM4を開き、__Mode__ を __Internal Clock,Channel4__ を __PWM Generation CH4__ にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/158dc520-f7e8-92e5-3b14-ea31764f9261.png)
__Configuration__ の __Prescaler__ を __５５０、Counter period__ を __１００００__ とします。

__275MHz__ を __50Hz__ にします。
__275MHz/550/10000=50Hz__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/3befaae4-a645-44f8-9986-0f36b055dc54.png)
__Yes__ で進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e7623cd4-3f7a-e30d-ba54-b9496a4412bb.png)
# プログラム
## Duty設定
__ __HAL_TIM_SET_COMPARE__ で __PWM__ を生成します。

__ __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,duty);__
__275MHz/550=500000Hz⇒2us__
__1us__ は __500カウント__ になります。
### dutyの計算式
250+角度*(1000/180)
### 0.5ms 0度
500us/2=2500 counts
### 2.5ms　180度
2500us/2=1250 counts
## Screen1View.cpp
\TouchGFX\gui\src\screen1_screen\Screen1View.cpp
```
#include <gui/screen1_screen/Screen1View.hpp>
#ifndef SIMULATOR
#include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_tim.h"
#include "stm32h7xx_hal_tim_ex.h"
#include "main.h"
#endif
```
### setupScreen内にHAL_TIM_PWM_Startを追加していますが、handleTickEvent内でも宣言しています。
```
void Screen1View::setupScreen()
{
    Screen1ViewBase::setupScreen();
	#ifndef SIMULATOR
    HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
	#endif
}
```

```
void Screen1View::tearDownScreen()
{
    Screen1ViewBase::tearDownScreen();
}
void Screen1View::handleTickEvent()
{
    tickCounter++;
    #ifndef SIMULATOR
    HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
	#endif

	if(tickCounter >= 150)
	{
		touchgfx::Unicode::strncpy(textArea1Buffer,"0", TEXTAREA1_SIZE);
		textArea1.invalidate();
	#ifndef SIMULATOR
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,250);
	#endif
	}
	if(tickCounter >= 300)
	{
	touchgfx::Unicode::strncpy(textArea1Buffer,"30", TEXTAREA1_SIZE);
	#ifndef SIMULATOR
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,417);
	#endif
	textArea1.invalidate();
	}
	if(tickCounter >= 450)
	{
	touchgfx::Unicode::strncpy(textArea1Buffer,"60", TEXTAREA1_SIZE);
	#ifndef SIMULATOR
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,583);
	#endif
	textArea1.invalidate();
	}
	if(tickCounter >= 600)
	{
	touchgfx::Unicode::strncpy(textArea1Buffer,"90", TEXTAREA1_SIZE);
	#ifndef SIMULATOR
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,750);
	#endif
	textArea1.invalidate();
	}
	if(tickCounter >= 750)
	{
	touchgfx::Unicode::strncpy(textArea1Buffer,"120", TEXTAREA1_SIZE);
	#ifndef SIMULATOR
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,917);
	#endif
	textArea1.invalidate();
	}
	if(tickCounter >= 900)
	{
		touchgfx::Unicode::strncpy(textArea1Buffer,"150", TEXTAREA1_SIZE);
	#ifndef SIMULATOR
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,1083);
	#endif
	textArea1.invalidate();
	}
	if(tickCounter >= 1050)
	{
	touchgfx::Unicode::strncpy(textArea1Buffer,"180", TEXTAREA1_SIZE);
	#ifndef SIMULATOR
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,1250);
	#endif
	textArea1.invalidate();
	}
	if(tickCounter >= 1200)
	{
	touchgfx::Unicode::strncpy(textArea1Buffer,"120", TEXTAREA1_SIZE);
	#ifndef SIMULATOR
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,917);
	#endif
	textArea1.invalidate();
	}

	if(tickCounter >= 1350)
	{
	tickCounter = 0;
		touchgfx::Unicode::strncpy(textArea1Buffer,"60", TEXTAREA1_SIZE);
	#ifndef SIMULATOR
	__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,417);
	#endif
	textArea1.invalidate();
	}
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/93286ee2-4983-3801-3dac-b9eaaa484b3b.png)

## Screen1View.hpp
\TouchGFXgui\screen1_screen\Screen1View.hpp
public:

    virtual void handleTickEvent();
protected:
    uint16_t tickCounter;
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/aea190cd-e00e-aa5b-8ffa-b6a9230443b9.png)

## main.h
main.hにexternを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/cb4ac9dc-b82c-ca5b-621f-7f22e92fc72e.png)

以上でコンパイル＆書込みすることでサーボモーターが回ります。