스테퍼 모터 구동 방법

작성자: Colton Parks, 마지막 수정자: BenH [2016년 9월 1일]

소개:

이 기사는 초보자가 스테퍼 모터의 작동 방식과 스테퍼를 구동하는 방법에 대한 이해를 돕기 위해 작성되었습니다. 스테퍼 모터 제어는 광범위한 주제이며 이 기사는 초보자가 시작하는 데 도움이 될 것입니다. 두 가지 유형의 스테퍼(양극 및 단극)가 있습니다.

양극 모터:

image

양극 스테퍼 모터에는 4개의 전선과 2개의 코일이 있습니다. 이 모터를 회전시키려면 코일을 통해 전류를 보내야 합니다. 각 전선을 하이와 로우로 구동이 가능해야 합니다. 전류를 구동하여 스테퍼를 회전시키는 방법은 다음과 같습니다.

이렇게 동작하는 이유를 이해하기 위해 4개의 스텝만 있는 간단한 스테퍼를 고려해 보십시오. 첫 번째 스텝에서는 자석을 첫 번째 코일에 맞게 정렬시킵니다. 다음 스텝에서는 자석을 90도 회전시킵니다. 첫 번째 코일에 전류를 역방향으로 보내면 자기 극성을 반전시킵니다. 반대편 코일이 연결되지만, 중심의 자석에 대해 반대인 자기장을 생성합니다.

물론, 대부분의 스테퍼 모터에는 4개 이상의 스텝이 있습니다. 표준 스테퍼 모터는 회전당 200 스텝일 것입니다. 이런 방식으로 모터를 회전시키는 것을 풀 스테핑(full-stepping)이라고 합니다. 풀 스테핑이 잘 동작하면 하프 스테핑(Half-stepping)은 매우 간단합니다. 두 코일을 통해 전류를 동시에 보내면, 분해능은 두 배가 됩니다.

스테퍼 모터 구동기는 코일을 통과하는 전류를 변조하는 마이크로스테핑을 사용할 수도 있습니다. 일반적인 모터 제어기는 풀 스텝당 16 마이크로스텝을 구현할 수 있습니다. 일부 칩은 전류 변조를 처리하지만, 구형 칩은 구동하는 스테퍼에 맞게 "튜닝"되어야 합니다. 마이크로스테핑은 풀 스텝을 최대 256 마이크로스텝으로 더 분할하여 일반적인 200 스텝 모터를 51,200 스텝 모터로 만듭니다. 또한 마이크로스테핑은 모터의 잡음을 줄여서 모터를 더 부드럽고 효율적으로 동작하게 만듭니다.

image
풀 스텝 1과 2 사이의 하프 스텝

코일의 전류를 제어하는 방법:

권선을 통해 전류를 제어하는 가장 일반적인 구성은 H 브리지를 사용하는 것입니다. H 브리지는 각 전선을 하이 또는 로우로 만들 수 있는 트랜지스터 4개 세트입니다. 트랜지스터 대신 MOSFET을 사용할 수도 있지만, 배선이 약간 다릅니다. 이 구성도는 H 브리지를 통해 각 방향으로 전류를 보낼 수 있는 방법을 보여줍니다. 해당 경로에 있는 트랜지스터를 켜기만 하면 됩니다.

같은 쪽에 있는 두 트랜지스터를 동시에 켜서는 안 됩니다. 그러면 전원에서 접지로 낮은 저항 경로가 만들어져 단락이 발생합니다. 또한 트랜지스터가 켜졌다가 꺼지는 데 시간이 걸릴 수 있습니다. 코일을 통과하는 전류를 급격히 전환하는 것에 대해 잘 모르는 경우에는 그렇게 하지 않는 것이 좋습니다.

image

아직 완성된 것은 아닙니다. 모터가 회전하면 전압을 생성합니다. 트랜지스터를 보호하기 위해 플라이백 다이오드를 배치하는 것이 좋습니다.

이렇게 하면 모터에서 고전압이 발생하여 트랜지스터 또는 심지어 구동기까지 손상시키는 것을 방지할 수 있습니다. 스테퍼 모터를 구동하는 전압이 MCU에서 출력되는 전압보다 높은 경우 PNP 트랜지스터를 제어하기 위해 다른 트랜지스터를 추가해야 합니다.

추가한 NPN 트랜지스터를 켜면, PNP 트랜지스터의 베이스(핀 1)로 전류가 흘러나가서 PNP 트랜지스터를 켭니다. 이제 모든 NPN 트랜지스터의 베이스에 전류 제한 저항기만 있으면 됩니다.

다 됐습니다! 이 H 브리지는 권선 중 하나를 통해 흐르는 전류를 제어합니다. 권선이 두 개 있으므로 이 회로를 두 배로 만들어야 합니다.

이제 필요한 부품의 정확한 수량을 파악할 수 있습니다. 이중 H 브리지의 사용이 스테퍼 모터를 구동하는 유일한 방법은 아닙니다. 이런 이중 H 브리지가 내장된 스테퍼 모터 구동기를 구매할 수도 있지만, 구동기는 일반적으로 MOSFET과 다른 기술들을 사용합니다. BOM 개수를 줄이거나 때로는 기능을 늘리고 싶다면 스테퍼 모터 구동기를 살펴보는 것이 좋습니다. 규격서를 참조하여 칩에서 제공하는 기능을 확인해야 합니다. 칩에 따라 트랜지스터와 다이오드만 제공하는 경우도 있고, 코일을 통해 전류를 완전히 제어하는 경우도 있습니다.

마이크로스테핑:

마이크로스테핑에서는 트랜지스터에 펄스 폭 변조 신호를 전송합니다. 이는 모터 코일에서 전류를 제어하는 간단한 방법입니다. 사전에 선택된 PWM 값이 사인파 룩업 테이블에 저장되며, 일반적으로 20kHz ~ 40kHz의 PWM 주파수가 선택됩니다. 20kHz 이하 주파수는 인간의 귀로 들을 수 있습니다. 트랜지스터의 효율성을 높이고 전력 손실을 줄이기 위해 주파수를 40kHz 미만으로 유지합니다. PWM 신호가 하이면, 전류는 트랜지스터를 통해 흐르고, PWM 신호가 로우면, 전류는 다이오드를 통해 흐릅니다. 이는 마이크로스테핑을 매우 대략적으로 구현한 것이지만, 일반적인 동작 방식을 보여줍니다. MOSFET을 사용하는 모터 구동기는 모터 전류의 감소 또는 감쇠 속도를 제어할 수 있습니다. 구동기의 전류 파형은 다음과 더 유사합니다.

image

구동하는 모터에 맞게 빠른 감쇠 기간과 느린 감쇠 기간을 수동으로 최적화해야 합니다. 일부 신형 칩은 감지하는 전류에 따라 감쇠 기간을 자동으로 조정하지만, 구형 칩은 최적화(또는 튜닝)해야 할 수 있습니다.

트랜지스터 기초:

트랜지스터는 전류 제어식 전류 제한 소자입니다. 트랜지스터에는 베이스, 콜렉터, 이미터라는 세 가지 핀이 있습니다 (b, c, e로 표시됨).

NPN 트랜지스터:

NPN 트랜지스터는 대부분 MOSFET으로 대체되었지만, 여전히 일부 응용 분야에서는 트랜지스터를 더 선호할 수도 있습니다. NPN 트랜지스터는 정전기 방전(ESD)에 취약하지 않으며 작은 전압으로 사용할 수 있습니다. 가장 큰 단점은 MOSFET만큼 많은 전류를 밀어낼 수도 없고 그만큼 효율적이지도 않다는 것입니다. 5mA가 공급되는 TIP120을 사용하여 60V 부하를 최대 5A까지 제어할 수 있습니다 (구체적인 동작 특성은 규격서 참조).

다음은 일반적인 소신호 NPN 트랜지스터입니다. 베이스에서 이미터로 작은 전류가 흐를 때, 콜렉터에서 이미터로 더 큰 전류가 흐를 수 있습니다. 이 트랜지스터는 전류 기반 소자로 기억해야 합니다.

image

달링턴 쌍은 두 개의 트랜지스터로 구성된 패키지입니다. 순방향 전압과 마찬가지로 이득도 두 배가 됩니다.

모든 트랜지스터는 하나의 다이오드와 하나의 종속 전류원으로 간주할 수 있습니다.

종속 전류원을 통과하는 전류는 다이오드를 통과하는 전류(ib)에 β(베타)를 곱한 값입니다. β를 트랜지스터의 이득이라고 합니다. 트랜지스터마다 편차가 매우 크므로 이 값을 신뢰하지 마십시오. 이 모델은 트랜지스터가 포화되지 않은 경우에만 작동합니다. 트랜지스터가 콜렉터-이미터를 통해 흐르는 전류를 더 이상 제한하지 않을 정도로 많은 양의 전류가 베이스를 통해 흐르는 경우 트랜지스터가 포화되었다고 합니다. (트랜지스터를 스위치로 사용하는 경우, 가열과 전력 손실을 방지하려면 트랜지스터를 포화시키거나 꺼야 합니다.)

다이오드는 애노드와 캐소드 간 공칭 전압 강하가 0.7V입니다. 따라서, 베이스와 이미터 간 전압 강하는 0.7V (달링턴의 경우 1.4V)입니다.

image

트랜지스터의 일부분인 다이오드는 접지 제어를 위해 NPN 트랜지스터를 사용해야 하고 전원 제어를 위해 PNP 트랜지스터를 사용해야 하는 이유입니다. 거의 동일한 두 회로를 생각해 보십시오.

첫 번째 회로에서, 3.3V 전원에서 베이스로 흐르는 전류는 트랜지스터를 완전히 포화시킬 정도로 충분하다고 가정합니다 (트랜지스터가 부하의 전류를 제한하지 않음. image). 콜렉터와 이미터 간 아주 작은 0.2V의 전압 강하가 있습니다. 부하에 걸리는 전압은 11.8V입니다. 전류 제한 저항에 걸리는 전압은 2.6V입니다. 이는 저항의 크기를 계산할 때 중요합니다.

두 번째 회로에서, 이론적으로 동일한 전류를 제한하기 위해 동일한 저항을 사용합니다. 그러나 트랜지스터는 베이스와 이미터 사이에서 다이오드처럼 동작하기 때문에, 이미터는 베이스보다 0.7V 더 작아야만 합니다. 2.6V는 이미터에서 가능한 절대 최댓값입니다. 하지만 두 저항의 전압 분배로 인해 이 값은 훨씬 작을 것입니다. 이 시점에 트랜지스터는 전류를 제한하지 않고 전압을 제한합니다. 그럼에도 불구하고, 트랜지스터는 초과 전력을 열로 발산합니다. 부하에 걸리는 전압은 2.6V에 불과합니다.

PNP 트랜지스터:

다음은 회로도에서 볼 수 있는 일반적인 PNP 트랜지스터입니다. 전류가 이미터에서 콜렉터로 흐르기 위해서는 이미터에서 베이스로 전류가 흘러야 한다는 점을 제외하고 NPN 트랜지스터와 비슷합니다. 작은 전류가 다이오드를 통해 흐르면, 이미터와 콜렉터 간에 훨씬 큰 전류가 흐를 수 있습니다.

image

트랜지스터는 하나의 다이오드와 하나의 종속 전류원으로 간주할 수 있습니다. 종속 전류원의 전류는 image입니다. NPN과 마찬가지로, 다이오드는 베이스와 이미터 간에 존재합니다. 다이오드에서는 여전히 0.7V 전압 강하가 있습니다. 방향만 다릅니다.

image

회로에서 트랜지스터를 사용하는 방법은 다음과 같습니다. 트랜지스터를 켜려면, 핀 1은 핀 3보다 0.7V 낮어야 합니다. 트랜지스터를 차단하려면, 핀 1은 VCC와 동일한 전압이어야 합니다. 연산 증폭기로 트랜지스터를 제어할 때 이 점을 유의해야 합니다. 연산 증폭기가 레일 투 레일로 동작하지 않으면, PNP 트랜지스터를 완전히 차단하지 못합니다. 또한 높은 전압을 구동하기 어렵습니다. 3.3V로 12V 전원을 제어하려 한다면, 트랜지스터를 차단시킬 수 없을 것입니다. 3.3V는 항상 12V보다 작습니다. 이것이 일반적으로 PNP 트랜지스터를 소신호 NPN과 함께 사용하는 이유입니다. NPN이 꺼져 있으면, 전류는 다이오드를 통해 흐를 수 없으므로 PNP가 꺼집니다.

image

개별 부품을 선택하는 방법:

다이오드 : 전류 정격이 응용 분야에 적합한 다이오드를 선택합니다. 온에서 오프로 스위칭할 때, 모터의 전류가 다이오드를 통과해야 합니다. 과열을 방지하려면, 순방향 전압이 낮은 다이오드를 찾아보십시오 (마이크로스테핑을 구현하려는 경우 특히 그렇습니다).

트랜지스터 : H 브리지 트랜지스터의 전류 정격도 응용 분야에 적합해야 합니다. 낮은 콜렉터-이미터 포화 전압을 선택하여 과열을 방지할 수 있습니다. 또한 과도 주파수가 높으면 트랜지스터가 활성 상태로 유지되는 시간이 단축되므로 유리할 수 있습니다. 최대 전력 값은 트랜지스터가 소비할 수 있는 전력량을 나타냅니다. 소비 전력이 낮다는 것은 트랜지스터가 스위치로 사용되어야 한다는 것을 의미합니다.

소신호 트랜지스터 : 특별할 것은 없습니다. 살펴볼 가장 큰 특성은 콜렉터-이미터 항복 전압이 모터의 공급 전원보다 높은지 입니다. 과도 주파수는 높을수록 좋습니다. 두 트랜지스터 간의 과도 시간이 누적되어 전체적으로 과도 주파수가 훨씬 낮아집니다.

저항 : 저항은 쉽게 선택할 수 있어야 합니다. 트랜지스터를 통과하는 전류의 일부만 저항을 통과합니다. 또한 두 NPN 저항에는 최소 전압 수준만 걸릴 것입니다. PNP의 베이스에 연결된 저항만 주의하면 됩니다. 트랜지스터를 통과하는 전류량을 알고 있다면, 전압은 기본적으로 모터의 공급 전압입니다. 전력 정격이 ¼와트를 초과하면 대부분의 응용 분야에 충분합니다.

예시 시나리오:

예시 상황을 통해 요구되는 저항 값을 계산하는 방법을 알아보겠습니다. 시나리오는 다음과 같습니다.

모터 : ROB-09238. 12V, 0.33A.

전원 공급 장치 : WSU120-1000

마이크로 컨트롤러 : EFM32GG-STK3700. 이 평가 기판의 논리 레벨은 3.3v입니다. 각 핀은 최대 20mA를 공급할 수 있습니다.

트랜지스터 : 마침 TIP120TIP125 트랜지스터가 몇 개 있어서 H 브리지 구동에 사용할 것입니다. 이들은 5A를 구동할 수 있습니다.

이런! 두 트랜지스터 모두 콜렉터-이미터 포화 전압이 4V인 것 같습니다! 두 트랜지스터를 거치면 모터에는 4V만 인가될 것입니다. 사양을 좀 더 자세히 살펴봐야 할 것 같습니다.

image

규격서가 순간 저를 놀라게 했네요! 제 응용 조건에서의 일반적인 포화 전압은 1V 미만인 것 같습니다. 더 높은 전류 상황에서는 포화 전압이 약 1.2V로 높아집니다. 소신호 NPN의 포화 전압은 일반적으로 0.2V입니다. 달링턴 쌍은 왜 이렇게 높을까요?

image

D 지점에 대해 생각해 보십시오. 첫 번째 트랜지스터가 포화되면, D는 C보다 0.2V 작습니다. 두 번째 트랜지스터에 내장된 다이오드를 떠올려 보십시오. E가 D보다 0.7V 작아야만 전류가 흐릅니다. 전체적으로 E는 C보다 0.9V 작습니다. 이것이 달링턴 쌍의 포화 전압이 더 높은 이유일 것입니다. 회로에서의 전류 흐름을 생각할 때, 과도한 복잡성을 피하기 위해 간단한 사실에 의존하는 것이 가장 좋습니다.

이제 저항과 다이오드가 필요합니다. IN4148 다이오드 몇 개가 있지만, 전류 정격이 응용 조건에 맞지는 않습니다. 하지만 모터를 마이크로 스테핑을 할 계획은 없습니다.

전류 용량을 자세히 살펴보면, 300mA의 순방향 전류를 처리할 수 있다고 규격서에 나옵니다. 또한 1A 서지를 1초 동안 처리할 수 있습니다. 따라서 모터의 전류가 1초 동안 1A를 초과해서는 안 됩니다.

image

H 브리지의 저항 계산:

이제 부품 선택은 거의 끝났으므로 저항에 집중할 차례입니다. 먼저 트랜지스터를 통과하는 전류를 고려해야 합니다.

부하 전류는 0.33A입니다. 따라서 image입니다.

PNP 저항에서 소비되는 전력은 V * I = 10.4 * 0.001 = 10.4mW입니다. 거의 모든 크기의 저항이 가능합니다. DigiKey의 표면 실장 저항 중 가장 작은 전력 정격은 12.5mW입니다.

동작 영역 근처에서의 트랜지스터 이득은 섭씨 25도에서 1000에 가깝습니다.

따라서 트랜지스터의 베이스에 330uA를 공급해야 합니다. 만약을 위해 1mA(필요한 전류의 3배)를 공급하겠습니다. 330mA를 구동하기 때문에 1mA는 신경 쓰지 않겠습니다. 일반적으로 두 배의 전류면 안전합니다.

필요한 전류를 확인했으므로 이제 전압을 살펴보겠습니다.

PNP에는 다이오드가 내장되어 있으므로 B 지점의 전압은 VDD(12V)보다 1.4V 작습니다. 따라서 Vb = 10.6V입니다.

맨 왼쪽에 있는 NPN이 포화되면 콜렉터-이미터 전압은 0.2V가 됩니다. 따라서 Va = 0.2V입니다.

이는 저항에 걸리는 전압이 10.4V라는 것을 의미합니다. 1mA가 저항을 통해 흘러야 합니다.

V = I*R을 사용하면, R = V/I = 10400입니다. 10k 저항이면 충분합니다. 전류를 세 배로 늘렸을 때 이미 이득 허용 오차 범위를 고려했으므로 이 값이 정확할 필요는 없습니다.

image

다음 트랜지스터는 다른 달링턴 쌍입니다. 콜렉터 전류는 330mA입니다. 이득 또한 동작 지점 근처에서 약 1000입니다. 330uA만 필요하지만 허용 오차 범위를 고려하여 1mA로 세 배 늘렸습니다.

D 지점의 전압은 1.4V입니다. MCU는 C 지점에 3.3V를 공급할 수 있습니다. 저항에 걸리는 전압은 1.9V가 됩니다. V = I*R을 사용하면, R = V/I = 1900입니다. 2k2 저항 또는 1k8 저항이면 충분합니다.

image

계산할 마지막 저항은 PNP 트랜지스터를 제어하는 (소신호 트랜지스터의) 저항입니다. 콜렉터 전류는 1mA입니다. 일반적인 소신호 트랜지스터의 이득은 100이며, 낮은 전류에서는 더 낮을 수도 있습니다. 사용하는 트랜지스터의 규격서를 재확인해 보십시오. 이 트랜지스터를 구동하는 데 필요한 전류는 10uA에 불과합니다. 만약을 위해 100uA로 계산하겠습니다. F 지점의 전압은 0.7V입니다. E 지점의 전압은 3.3V입니다. 저항에 걸리는 전압은 2.6V입니다. R = V/I를 사용하면, R = 26k입니다. 20k ~ 50k 사이의 값이면 충분합니다. 여기서는 28k 저항을 사용했습니다.

image

이러한 방식으로 H 브리지를 구성합니다. 제어하려면 전선에 전력을 공급해야 합니다.

경고: 모두 연결되기 전까지는 공급 전압을 켜거나 모터 공급 전압을 VM에 연결하지 마십시오. 핀을 다시 연결하고 전선을 옮길 때, 고전압 전원 공급 장치가 꺼져 있는지 확인하시기 바랍니다. 모든 IC를 매우 쉽게 날려 먹을 수 있습니다. 분명히 말씀 드렸습니다.

핀 1, 핀 3, 핀 2, 핀 4를 차례로 하나씩만 켜서 모터를 회전시킵니다. 또는 역순(4,2,3,1)으로 회전시킵니다. 전원에서 접지로의 경로가 발생하지 않도록, 스위칭 상태일 때 모든 핀을 끄십시오.

H 브리지용 예시 코드:

풀 스텝을 사용하는 예시 코드:

/**************************************************************************//**
 * @file
 * @brief Empty Project
 * @author Energy Micro AS
 * @version 3.20.2
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_system.h"
#include "em_gpio.h"
volatile uint32_t msTicks;
#define TOTAL_STEPS      4
uint32_t STEPS[TOTAL_STEPS] = {0b1000, 0b0010, 0b0100, 0b0001};             //1,3,2,4
uint16_t STEP = 0;
/* ************* Systick Handler ***************** */
void SysTick_Handler(void) {
    msTicks++;
}
/* ************* Delay function ****************** */
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
/* ************* Output to H-bridge ************** */
void setStep(void) {
      GPIO->P[3].DOUTCLR = 0xF;                  //Shut off all pins.
      GPIO->P[3].DOUTSET = STEPS[STEP];          //Output the steps
}
/* ************* Main function ******************* */
int main(void)
{
    CHIP_Init();
    CMU->HFRCOCTRL = 0x30; // Set RC clock to 1 MHz
    CMU->HFPERCLKEN0 =(1<<13); //Enable GPIO clock

    if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;         //Setup SysTick

/* ****************** Setup pushbuttons and H-bridge outputs ****************** */
    GPIO->P[1].MODEH = 0x110;                //Setup RB9 and RB10 as input
    GPIO->P[3].MODEL = 0x5555;               //Setup PD0-PD3 as push pull output. These go directly to the H-bridge
    GPIO->P[3].CTRL = 2;                     //High drivemode
    GPIO->P[3].DOUT = 0x0000;                //They should already be all low.
                                            //H-bridge pins 1,2,3,4 map to pins 3,2,1,0 on port D.
  /* Infinite loop */
  while (1) {
      if(!GPIO_PinInGet(gpioPortB,9)) {                         //If button 0 is pressed
          STEP = (STEP + 1) % TOTAL_STEPS;                      //Increment the step
          setStep();                                            //Output to the H-bridge
      }
      else if(!GPIO_PinInGet(gpioPortB, 10)) {                  //If button 1 is pressed.
          STEP = (STEP + TOTAL_STEPS-1) % TOTAL_STEPS;          //Decrement the step
          setStep();                                            //Output to the H-bridge
      }
      Delay(10);                                                //Short delay to let motor rotate
  }
}

하프 스텝을 사용하는 예시 코드:

/**************************************************************************//**
     * @file
 * @brief Empty Project
     * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_system.h"
#include "em_gpio.h"
volatile uint32_t msTicks;
#define TOTAL_STEPS      8
uint32_t STEPS[TOTAL_STEPS] = {0b1000, 0b1010, 0b0010, 0b0110, 0b0100, 0b0101, 0b0001, 0b1001};   
//1, 1and3, 3, 3and2, 2, 2and4, 4, 4and1

/* ************* Systick Handler ***************** */
void SysTick_Handler(void) {
    msTicks++;
}
/* ************* Delay function ****************** */
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
/* ************* Output to H-bridge ************** */
void setStep(uint32_t STEP) {
      GPIO->P[3].DOUTCLR = 0xF;                                  //Shut off all pins.
      GPIO->P[3].DOUTSET = STEPS[(STEP % TOTAL_STEPS)];          //Output the steps
}
/* ************* Main function ******************* */
int main(void)
{
    CHIP_Init();
    CMU->HFRCOCTRL = 0x30; // Set RC clock to 1 MHz
    CMU->HFPERCLKEN0 =(1<<13); //Enable GPIO clock

    if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;         //Setup millisecond tick counter

    /* ****************** Setup pushbuttons and H-bridge outputs ****************** */
    GPIO->P[1].MODEH = 0x110;                //Setup RB9 and RB10 as input
    GPIO->P[3].MODEL = 0x5555;               //Setup PD0-PD3 as push pull output. These go directly to the H-bridge
    GPIO->P[3].CTRL = 2;                     //High drivemode
    GPIO->P[3].DOUT = 0x0000;                //They should already be all low.
                                            //H-bridge pins 1,2,3,4 map to pins 3,2,1,0 on port D.
int32_t STEP = 0;

  /* Infinite loop */
  while (1) {
      if(!GPIO_PinInGet(gpioPortB,9)) {                         //If button 0 is pressed
          STEP += 1;                                            //Increment the step
          setStep(STEP);                                        //Output to the H-bridge
      }
      else if(!GPIO_PinInGet(gpioPortB, 10)) {                  //If button 1 is pressed.
          STEP -= 1;                                            //Decrement the step
          setStep(STEP);                                        //Output to the H-bridge
      }
      Delay(10);                                                //Short delay to let motor rotate
  }
}

개별 부품 사용에 대한 대안:

먼저, 칩이 제어할 수준을 결정해야 합니다. 스테퍼 구동기는 H 브리지 패키지만큼 간단할 것입니다. 제품군은 점점 더 복잡해지고 있으며, 필요에 따라 정확하게 원하는 제품을 선택할 수 있습니다. 텍사스 인스트루먼트는 다양한 제어 수준의 다양한 구동기를 공급하고 있으며, 어떠한 스텝 모터에도 사용할 수 있는 칩을 보유하고 있을 것입니다. Allegro 또한 다양한 구동기를 보유하고 있습니다. 가장 많은 기능이 내장된 구동기는 Trinamic 칩입니다.

ST마이크로일렉트로닉스 L293D – 채널당 600mA를 구동할 수 있는 쿼드 하프 브리지로, 위의 회로도를 대체할 수 있습니다. 여전히 어떤 핀을 하이 또는 로우로 구동할 지 제어해야 합니다. 아두이노 모터 쉴드와 같은 기판들이 이 종류의 칩을 사용합니다.

TMCSILENTSTEPSTICK – 스텝과 방향으로 제어하는 스테퍼 모터 구동기입니다. Trinamic은 작고 경제적인 패키지로 다양한 기능을 제공합니다. 이 제품은 TMC2100 칩 용 평가 기판으로 최대 1.2A를 구동합니다. 이 칩은 전류 감지를 통해 256 마이크로 스텝 보간이 가능합니다 (조정이 필요하지 않음).

TMC5130-EVAL-KIT – SPI/1선식 UART 또는 스텝과 방향으로 제어하는 스테퍼 모터 구동기입니다. 이 제품은 TMC5130 칩 용 평가 기판으로 이 칩은 스테퍼 모터 구동기 계의 롤스로이스입니다. 이 평가 기판은 모터에 가장 적합한 설정을 결정하는 데 유용합니다. 고전압 VM 라인에 주의하시기 바랍니다.

TMCSILENTSTEPSTICK :

TMC2100용 브레이크아웃 기판이며, Watterott가 3D 인쇄에 사용하기 위해 설계하였습니다. 두 개의 0.11옴 감지 저항을 사용하여 최대 모터 전류를 1.77A RMS로 설정하였습니다. 전위차계를 사용하여 설정 가능한 최대 전류는 1.77A RMS입니다.

image

구매 링크 – DigiKey 웹 사이트

규격서 – TMC2100에 유용한 정보 포함

기판 정보 – 회로도 및 기판 레이아웃을 포함합니다.

깃허브 Trinamic 칩 데이터 – 칩을 이해하는 데 필요한 모든 것이 포함되어 있습니다.

헤더 납땜:

헤더를 기판에 납땜합니다. 설정 입력 3번 핀(CFG3)을 사용하고 싶다면, 먼저 끊어진 부분을 납땜하여 연결합니다(사용자의 99%는 이에 대해 걱정할 필요가 없습니다). 브레드보드에 장착하거나 소켓을 사용할 예정이라면, 아랫면을 위로 향하게 해야 합니다(TOP이라고 적혀 있습니다). 그러면 전위차계를 쉽게 조정할 수 있습니다. (0.5A 이상의) 상당한 양의 모터 전류를 구동할 예정이라면, 노출 비아홀에 열전도성 양면 테이프를 사용하여 소형 방열판을 추가하십시오. 기판 윗면의 비아홀은 TMC2100의 아랫면 및 접지면과 열적 그리고 전기적으로 연결됩니다(칩의 접지와 냉각용으로 사용됩니다).

핀 연결:

경고: 모두 연결되기 전까지는 공급 전압을 켜거나 모터 공급 전압을 VM에 연결하지 마십시오. 핀을 다시 연결하고 전선을 옮길 때, 고전압 전원 공급 장치가 꺼져 있는지 확인하시기 바랍니다. 모든 IC를 매우 쉽게 날려 먹을 수 있습니다. 분명히 말씀 드렸습니다.

칩의 기능 설정은 다음과 같습니다. 전위차계는 모터를 통해 흐르는 전류를 제어합니다. Diag0 및 Diag1은 칩의 진단 출력입니다. 자세한 내용은 TMC2100 규격서를 참조하십시오. Vref는 전위차계의 가운데 핀 전압이며, 모터의 전류를 계산하는 데 사용되는 AIN_REF 핀에 연결되어 있습니다. Trinamic 설정 입력은 3상태로, 핀이 접지되었는지, VCC에 연결되었는지 또는 연결되지 않았는지(오픈) 여부를 감지할 수 있습니다. SilentStepStick에는 4개의 설정 핀이 제공됩니다.

설정 입력 1과 2 : 연결하지 않은 채로 두면 칩의 초기 연결은 CFG1 = 오픈 그리고 CFG2 = 오픈입니다. 나중에 마음이 바뀔 수 있으므로 이 핀들을 영구적으로 연결하지는 마시기 바랍니다.

설정 입력 3 : 칩의 초기 연결은 오픈입니다. 설정 입력을 설정 핀에 연결하려면, 기판의 끊어진 부분을 연결해야 합니다. smd 점퍼 1개는 연결되지 않은 상태일 것입니다. 다른 3개에는 0옴 저항이 이미 납땜되어 있을 것입니다. 현미경을 사용하는 것이 좋지만, 납땜할 부분을 알고 있다면 돋보기를 사용해도 됩니다. (0옴) 0201 저항을 끊어진 부분에 붙여도 되지만 권장하지는 않습니다.

image

헤더 핀에 전원을 공급하더라도 이 핀은 N.C.입니다.

설정 입력 6 : 연결하지 않은 채로 두면 칩의 초기 연결은 오픈입니다. 모터가 고정 토크를 제공할 필요가 있는 애플리케이션이 아니라면 오픈 상태로 두는 것이 좋습니다.

초퍼 설정 핀:

또한 이 기판에서는 다른 몇 개의 설정 핀들도 하드와이어 할 수 있습니다. Mr. Watterott이 나머지 세 핀을 설정 가능한 상태로 남겨 놓은 것 같습니다.

image

핀 0, 4 및 5를 다른 상태로 하드와이어 할 수 있습니다. 회로도를 보면 각 핀의 위치를 알 수 있습니다. 초기 연결은, 핀 0과 4는 접지되어 있고 핀 5는 VCC_IO에 연결되어 있습니다.

규격서에는 핀에 대해 다음과 같이 설명되어 있습니다.

전류 계산:

CFG3에 점퍼를 연결하지 않았다면, 구동기는 AIN_REF와 감지 저항을 사용하여 코일을 통과하는 전류를 조정합니다. 이 기판에서는 0.11옴 감지 저항을 사용합니다. Vref 전압은 코일을 통과하는 전류에 비례합니다. 모터를 연결하기 전에 전류를 설정하려면, 모터를 연결하기 전에 기판의 전원을 차단해야 합니다. 모터를 연결하거나 분리할 때 구동기에 전원이 공급되고 있으면 구동기가 손상될 수 있습니다. Vref 핀의 전압을 모니터링합니다. 전류를 낮추려면, 전위차계를 시계 반대 방향으로 돌립니다. 전류를 보정하는 또 다른 방법은 모터가 얼마나 잘 동작하는지 확인하는 것입니다. 모터가 올바르게 동작하지 않을 때까지 전류를 낮춘 다음, 모터가 올바르게 동작할 때까지 전류를 높입니다.

Vref (V) I RMS (A)
2.5 1.74
2.0 1.39
1.5 1.04
1.0 0.70
0.5 0.35

규격서에는 구동기가 구동할 수 있는 최대치가 1.2A RMS(제곱 평균 제곱근)라고 나와 있습니다. 방열판이 제대로 부착되어 있다면 더 많은 전류를 구동할 수도 있습니다.

EFM32 Giant Gecko를 사용한 예시 코드:

/**************************************************************************//**
 * @file
 * @brief Empty Project
 * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_gpio.h"
#include "em_cmu.h"
#include "em_timer.h"
#include "em_emu.h"
volatile uint32_t msTicks;
void SysTick_Handler(void) {
    msTicks++;
}
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
void setDir(bool dir) {
    if(dir) GPIO->P[4].DOUTSET = 1 << 3;
    else GPIO->P[4].DOUTCLR = 1 << 3;
}
bool getPushButton(bool button) {
    return !(GPIO->P[1].DIN & (1 << (button + 9)));
}
/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
/* This code isn't optimized for anything. Rather, it was just proof that i could get the motor spinning and test ou the maximum velocities. If you change the step configuration pins, you
could probably get faster speeds out of the driver. */

int main(void)
{
  /* Chip errata */
  CHIP_Init();
  CMU_ClockEnable(cmuClock_GPIO,true);
  CMU_ClockEnable(cmuClock_TIMER3,true);
  TIMER3->CTRL = 1 << 6;                                                       //Run in debug mode
  TIMER3->ROUTE = (1 << 16) | (1 << 2);                                          //Location 1, CC2 output enable
  TIMER3->CC[2].CTRL = (1 << 10) | 2;                                          //On timer overflow, toggle output. Enable compare output.
  if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;       //Setup system tick handler
  GPIO->P[1].MODEH |= (1 << 4) | (1 << 8);                                       //Enable pushbuttons as inputs (B9, B10)
  GPIO->P[4].MODEL |= 0x4400;                                                    //Enable outputs E2 and E3
  int16_t time_delay = 32767;                                                   //32767 is the largest value for this signed int. If i     increment by one more, it will overflow to -32768. Good.
  /* Infinite loop */
  while (1) {
      if(getPushButton(1)){                                                     //If button one is pressed
          if((time_delay > 0) | (time_delay < -500)) time_delay++;                //Make sure it isn't in the dead zone,     then increment time_delay
      }
      else if(getPushButton(0)) {                                               //If button zero is pressed
          if((time_delay < 0) | (time_delay > 500)) time_delay--;             //Make sure it isn't in the dead zone, then decrement time_delay
      }
      if((time_delay > 32000) | (time_delay < -32000))TIMER3->CMD = 0x2;       //If the time delay is large, i probably wanted to stop the motor entirely.
      else TIMER3->CMD = 0x1;
      if(time_delay < 0) {                                                       //This is not optimized for keeping position absolute. I ignored the direction-to-step transition time here.
          setDir(0);
          TIMER3->TOPB = (time_delay * -1);
      }
      else {
          setDir(1);
          TIMER3->TOPB = time_delay;
      }
  }
}

속도 제어:

모터를 스테핑하는 두 가지 방법을 제시하였습니다. 타이머를 사용하여 모터를 스테핑하는 것을 추천합니다. H 브리지를 사용하는 경우, 타이머 인터럽트 내에서 모터를 스테핑할 수 있습니다. 스텝/방향 구동기를 사용하는 경우, compare/capture 핀을 PWM 모드로 설정하여 핀을 자동으로 토글할 수 있습니다. 모터의 속도는 시간 지연에 따라 결정됩니다. 또한 타이머 오버플로우 시 compare 채널을 토글하거나 PWM 채널을 설정할 수도 있습니다. 타이밍 특성에 대한 자세한 내용은 구동기 규격서를 참조하십시오. 이 경우, 1MHz 클럭으로 구동하면 동작 간에 20 클럭을 기다려야 합니다. 스테핑 방향의 설정 시간은 중요한 값이지만 처음에 간과했습니다. 타이밍 특성을 무시하면 위치를 잃을 수 있습니다. 칩은 모터가 다른 위치에 있다고 생각할 것입니다. 다행히 Trinamic 규격서에 보기 쉽게 나와 있습니다.

속도는 거리를 시간으로 나눈 값이며, 스테퍼 모터에서는 스텝을 시간으로 나눈 값입니다. 회전당 총 스텝 수로 나누어 속도를 계산할 수 있습니다. 여기에는 마이크로 스텝도 포함됩니다. (총 스텝 수 = 모터 스텝 수 * 마이크로 스텝 수)

image

1로 곱할 수 있습니다. 총 스텝당 1 회전을 곱하였습니다.

image

코드에 구현할 경우, 스텝을 증가 또는 감소시킬 시간 간격을 찾아야 합니다. 속도의 함수로써 시간 간격을 구하면

image

여기서 V는 초당 회전 수이며, 시간 간격은 초 단위입니다. 마이크로컨트롤러에서 초는 매우 긴 시간입니다. 초당 클록 수로 곱하는 것이 가장 좋습니다.

image

변수와 연결된 숫자를 무시하면 단위를 확인할 수 있습니다.

image

초당 클럭 수를 주파수라고도 합니다.

image

타이머에서 전치 분주기를 사용하는 경우, 동일한 전치 분주기로 나누어야 합니다. 전치 분주를 하기 전 1초가 1024 클럭이고 1024로 전치 분주하는 경우, 1 클럭은 정확히 1초가 됩니다.

image

이는 매 시간 간격 마다 모터가 스테핑을 하는 한 성립됩니다. (위 코드에서 한 것처럼) 타이머가 오버플로우가 되도록 설정한다면, 2로 나누면 모든 방정식이 성립됩니다 (스테핑에 두 번의 시간 간격이 걸리기 때문이며, 시간 간격을 2로 나누면 이를 되돌립니다.)

전치 분주기는 주로 최고 속도에 따라 달라집니다. 최고 속도를 알고 있다면, 이 방정식을 사용하여 해당 속도를 낼 수 있는 가장 작은 타이머 클럭 수를 계산할 수 있습니다. 최고 속도를 모른다면, 시행착오를 겪으면서 계산해야 합니다. 모터가 비정상적으로 동작할 때까지 시간 간격을 계속 줄입니다. 부하가 최고 속도에 가깝게 증가하면 모터가 스킵할 수 있으므로 주의하십시오. 다양한 모터 속도와 부하를 적용해 보시기 바랍니다.

image

이 구현의 가장 큰 문제점은 속도가 0일 때로, 무한한 시간을 기다려야 한다는 것입니다. 무한대는 마이크로 컨트롤러로 계산하기에 너무 큰 수입니다. 또한 속도가 0에 가까우면 시간 지연은 매우 길어집니다. 이에 대한 좋은 해결책은 실현 가능한 최저 속도를 찾아서 데드 존을 만드는 것입니다. 저의 칩에서 최대 타이머 값은 16비트 수 입니다. 가장 긴 지연은 65,535 클럭이며, 실현 가능한 최저 속도는 다음과 같습니다.

image

다 되었습니다! 이렇게 하면 프로젝트를 시작할 수는 있지만, 사용하려면 더 많은 작업이 필요합니다. 일정한 속도로 목표 위치에 보내는 것은 매우 쉽습니다. 인터럽트 내에서, 목표 위치가 실제 위치와 같지 않은지 확인하십시오. 그럴 경우, 모터를 스테핑합니다.

속도 제어에 대해 알아보았으므로, 이를 사용하여 제어를 확장할 수 있습니다. 속도를 높이거나 낮추는 기능을 구현해 보십시오. 그런 다음 목표 위치를 설정하고 해당 위치에 도달하도록 속도를 높이거나 낮춰 보시기 바랍니다. 작업이 너무 많은 것처럼 들린다면, 다른 해결책이 있습니다. TMC5130을 사용해 보십시오!

TMC5130 예시 사례:

Trinamic의 스테퍼 구동기인 TMC5130은 다 열거하기 어려울 정도로 많은 기능을 제공합니다. 우선 해당 드라이버는 스텝/방향, SPI 또는 1선식 UART로 제어할 수 있습니다. 스텝/방향 제어를 사용한다면, 칩은 TMC2100과 똑같습니다. 이로 인해 칩에 함께 제공되는 일부 유용한 기능을 상실하게 됩니다. SPI 또는 1선식 UART를 사용한다면, 속도 모드 및 위치 모드에 액세스할 수 있습니다. 두 모드 모두 모터의 위치와 모터의 회전 속도를 알려줍니다. 최대 속도와 가속도를 프로그래밍할 수 있습니다. 칩에 목표 위치를 지정하면, 최대 속도로 가속하였다가 해당 위치에 도달하기 전에 감속합니다.

구동기가 제공하는 주요 기능을 간략히 요약하면 다음과 같습니다.

SpreadCycle – 자동 고속 감쇠. 모터를 튜닝할 필요가 없습니다.
CoolStep – 모터에서 생성되는 전자기장을 사용하여 코일에서 최소 전류를 사용합니다.
StealthChop – 저속에서 모터가 거의 무소음으로 동작합니다.
StallGuard2 – 모터가 멈추면 감지됩니다.
DcStep – 부하가 높으면 속도를 자동으로 낮춥니다.

최근 프로젝트에서 StealthChop, SpreadCycle 및 StallGuard2를 사용했습니다. 칩을 StealthChop과 StallGuard2로 설정하는 방법을 살펴보겠습니다.

가장 먼저 해야 할 일은 기판에 칩을 실장하는 것입니다. TMC5130-EVAL-KIT로 시작하는 것이 좋겠군요. 직접 기판을 만들려 한다면, 자세한 내용은 규격서를 참조하십시오. 여기서 다루기에는 정보가 너무 많습니다. 한 가지만 말씀드리면 핀 29, DRV_ENN_CFG6이 구동기의 인에이블(enable) 핀입니다. 이 핀을 하이에 연결하면, 모든 모터 출력이 플로팅 상태가 됩니다. 모터 출력을 활성화하려면 이 핀을 접지에 연결합니다. 또한 CLK 핀에 클럭을 입력하지 않을 경우, 핀을 접지에 연결해야 합니다. 제 칩은 다음과 같이 연결하였습니다.

번호 유형 연결
TST_MODE 1 DI 접지
CLK 2 DI 외부 클럭 또는 접지
CSN_CFG3 3 DI(tpu) SPI 칩 셀렉트 입력
SCK_CFG2 4 DI(tpu) SPI 클럭
SDI_NAI_ CFG1 5 DI(tpu) SPI 데이터 입력
N.C. 6, 31, 36 사용되지 않는 핀, 이후 버전과의 호환성을 위해 접지에 연결합니다
SDO_NAO_ CFG0 7 DIO(tpu) SPI 데이터 출력
REFL_STEP 8 DI 플로팅
REFR_DIR 9 DI 플로팅
VCC_IO 10 MCU 공급 전압에 연결
SD_MODE 11 DI(pu) 접지
SPI_MODE 12 DI(pu) 플로팅
GNDP 13, 48 전원 접지. 핀 근처 접지면에 연결합니다
DNC. 14, 16, 18,20, 22, 41,43, 45, 47 이 핀들은 연결하지 마십시오. PCB의 연면거리를 늘려 코팅 없이 더 높은 전압을 공급하기 위함입니다
OB1 15 모터 코일 B 출력 1
BRB 17 코일 B의 감지 저항 연결. 감지 저항은 핀 근처 접지에 배치합니다. 최상의 성능을 얻으려면 접지(접지면)에 100nF을 추가하는 것이 좋습니다
OB2 19 모터 코일 B 출력 2
VS 21, 40 모터 공급 전압. (각각의 접지면을 통해) 가장 가까운 GNDP 핀에 짧은 루프로 연결하여 핀 주변 필터링 능력을 제공합니다
ENCN_DCO 23 DIO 접지
ENCB_DCEN_ CFG4 24 DI(tpu) 접지
ENCA_DCIN_ CFG5 25 DI(tpu) 접지
SWN_DIAG0 26 DIO 플로팅
SWP_DIAG1 27 DIO 플로팅
SWSEL 28 DI(pd) 플로팅
DRV_ENN_ CFG6 29 DI 접지 – 토글 스위치 또는 MCU에 연결할 수도 있습니다
AIN_IREF 30 AI 플로팅
GNDA 32 아날로그 접지. 접지면에 연결합니다
5VOUT 33 내부 5V 조정기의 출력. 최상의 성능을 얻으려면 2.2µF 이상의 세라믹 커패시터를 핀 근처 GNDA에 연결합니다. 칩의 VCC 공급을 위한 출력
VCC 34 칩 내부 디지털 회로와 차지 펌프용 5V 전원 입력 470nF 커패시터를 접지(접지면)에 연결합니다. 5VOUT으로 공급할 수도 있습니다. 5VOUT의 잡음을 디커플링하기 위해 2.2옴 또는 3.3옴 저항을 사용하는 것이 좋습니다. 외부 전원을 사용할 경우, VCC는 5VOUT 또는 VCC_IO 중 늦게 켜지는 것보다 빠르거나 동시에 켜져야 합니다
CPO 35 차지 펌프 커패시터 출력
CPI 37 차지 펌프 커패시터 입력. 22nF 50V 커패시터를 사용하여 CPO에 연결합니다
VCP 38 차지 펌프 전압. 100nF 커패시터를 사용하여 VS에 연결합니다
VSA 39 5V 조정기의 아날로그 공급 전압. 일반적으로 VS에 연결합니다. 100nF 필터링 커패시터를 사용합니다
OA2 42 모터 코일 A 출력 2
BRA 44 코일 A의 감지 저항 연결. 감지 저항은 핀 근처 접지에 배치합니다. 최상의 성능을 얻으려면 접지(접지면)에 100nF을 추가하는 것이 좋습니다
OA1 46 모터 코일 A 출력 1
노출된 다이 패드 - 노출된 다이 패드를 접지면에 연결합니다. 접지면으로 열을 전달하기 위해 최대한 많은 비아(via)를 사용합니다. 디지털 회로의 접지 핀 역할을 합니다

레퍼런스 설계에 대한 다른 유용한 정보는 규격서 122페이지에 있습니다. 다음은 평가 기판의 회로도입니다. TMC5130-Eval_v15_01_Schematic.pdf (69.0 KB)

바닥면의 패드가 접지면에 열적으로 잘 연결되었는지 확인합니다. 가능하면, 비아를 사용하여 열을 접지면에 전달합니다. CNC 머신으로 2층 기판을 가공할 경우, 칩 아래에 큰 드릴 구멍을 만들고 납땜으로 채워서 접지면에 연결합니다. 바닥면의 패드를 열적으로 연결하지 않을 경우, 그만큼의 전류를 구동할 수 없습니다.

칩을 배치한 후 설정 데이터를 칩에 보내야 합니다. 제 경험은 매우 비효율적이었습니다. 평가 키트의 설정을 알아내서 그걸 제 설정으로 복사하였습니다. 설정이 동작하지 않으면, 어디가 잘못되었는지 모든 레지스터를 확인해야 했습니다. 결국에는, SPI 버스의 클럭 라인이 없는 것이었습니다. 다시 작업한다면, TMC5130 규격서의 110페이지를 참조할 것입니다. 다음은 해당 페이지의 사본입니다. 규격서에서 각 레지스터를 참조하여 작동하는 설정을 확인할 수 있습니다. 참고: 전류 설정을 다시 확인하십시오. 이 초기화는 전류를 최대값으로 설정합니다. 이는 칩 하단으로의 열 방출이 매우 뛰어난 평가 키트를 염두에 두고 설계되었습니다. 고전압으로 칩이 탔을 때 칩을 교체하느라 애를 먹었습니다. 또한, PWMCONF 레지스터 일부로 전류를 높일 수 있습니다. 이 레지스터를 설정하면 모터를 통과하는 전류를 모니터링하거나 칩의 온도를 확인하십시오.

25.1 Initialization Examples
SPI datagram example sequence to enable the driver for step and direction operation and initialize the chopper for spreadCycle operation and for stealthChop at <60 RPM:
SPI send: 0xEC000100C5; // CHOPCONF: TOFF=5, HSTRT=4, HEND=1, TBL=2, CHM=0 (spreadCycle)
SPI send: 0x9000061F0A; // IHOLD_IRUN: IHOLD=10, IRUN=31 (max. current), IHOLDDELAY=6
SPI send: 0x910000000A; // TPOWERDOWN=10: Delay before power down in stand still
SPI send: 0x8000000004; // EN_PWM_MODE=1 enables stealthChop (with default PWM_CONF)
SPI send: 0x93000001F4; // TPWM_THRS=500 yields a switching velocity about 35000 = ca. 30RPM
SPI send: 0xF0000401C8; // PWM_CONF: AUTO=1, 2/1024 Fclk, Switch amplitude limit=200, Grad=1
SPI sample sequence to enable and initialize the motion controller and move one rotation (51200 microsteps) using the ramp generator. A read access querying the actual position is also shown.
SPI send: 0xA4000003E8; // A1 = 1 000 First acceleration
SPI send: 0xA50000C350; // V1 = 50 000 Acceleration threshold velocity V1
SPI send: 0xA6000001F4; // AMAX = 500 Acceleration above V1
SPI send: 0xA700030D40; // VMAX = 200 000
SPI send: 0xA8000002BC; // DMAX = 700 Deceleration above V1
SPI send: 0xAA00000578; // D1 = 1400 Deceleration below V1
SPI send: 0xAB0000000A; // VSTOP = 10 Stop velocity (Near to zero)
SPI send: 0xA000000000; // RAMPMODE = 0 (Target position move)
// Ready to move!
SPI send: 0xADFFFF3800; // XTARGET = -51200 (Move one rotation left (200*256 microsteps)
// Now motor 1 starts rotating
SPI send: 0x2100000000; // Query XACTUAL - The next read access delivers XACTUAL
SPI read; // Read XACTUAL

이것으로 모터가 움직이기 시작하기를 바랍니다. 동작하지 않는다면, SPI 버스 통신을 다시 확인하십시오. 우연히 동일한 SPI 버스에 가속도계가 있어서 해당 부분이 동작하는지 확인했습니다.

StealthChop 설정:

위의 예시에서는 StealthChop을 설정하는 방법도 보여줍니다. 현재 StealthChop을 사용하고 있지 않는 작업 코드에서 세 레지스터를 수정해야 합니다.

GCONF – 0x00: 비트 2를 1로 설정하여 PWM 모드를 활성화합니다.
TPWMTHRS – 0x13: StealthChop이 동작할 속도 상한(시간 지연 하한)을 설정합니다. 이 값을 너무 낮게 설정하지 마십시오. 그렇지 않으면 모터가 전환할 때 갑작스럽게 움직일 수 있습니다. 예시에서는 500을 사용하지만, 저는 5000을 사용했습니다.
PWMCONF – 0x70: StealthChop의 주설정 레지스터입니다. StealthChop이 이상하게 동작하는 경우, 다음 레지스터 설정을 확인해 보십시오.

  • pwm_autoscale 비트를 1로 설정하여 StealthChop을 빠르게 설정할 수 있도록 합니다.
  • 모터에서 계속 잡음이 발생한다면, PWM_FREQ 비트 필드를 높은 주파수로 설정해 보시기 바랍니다.
  • PWM_GRAD 비트 필드는 1 이상으로 설정합니다.
  • PWM_AMPL 필드는 64 이상으로 설정하는 것이 좋습니다. 값이 높을수록 모터 전류가 높습니다.

이 주제에 대해서는 규격서에 자세히 나와 있습니다.

StallGuard2 호밍(homing) 사용:

StallGuard2를 하드 스톱(hard stop)과 함께 사용하는 것은 레퍼런스 스위치보다 설정하는 것이 쉽지 않습니다. 레퍼런스 스위치는 StallGuard2보다 허용 오차 범위가 훨씬 좋습니다. 유사시에는, 여전히 매우 편리한 해결책입니다. 몇 개의 스텝이 큰 차이를 만드는 애플리케이션에서는 이 기능을 사용하지 마십시오. 절대 위치가 중요하지 않은 애플리케이션에서 사용하는 것이 좋습니다.

triWrite(0x27,0)                        //To start, set the motor velocity to 0.
triWrite(0x20,1)                        //Put the chip in velocity mode                                   //Or 2 if other direction
triWrite(0x14,5000)                     //Set the coolStep upper velocity                                 //I suspect lower numbers may work better
triWrite(0x34, (1 << 10))             //Enable stop by stallGuard2                                      //Clear this bit to disable stallGuard2
triWrite(0x6D,(11 << 16))                 //Set Stall Guard Threshold                                       //This field will change if anything else changes. It will also vary from motor to motor. The EVAL kit is nice for this.
triWrite(0x27, 60000)                   //Start a motion                                                  //My application was geared down
Delay(1000)                             //Wait for motor to start                                         //Motor will stop when it stalls
while(triGetVel())                      //Poll vActual, wait for it to be 0                               //Poll the velocity instead of the     flags
triWrite(0x27,0)                        //Set the target velocity to 0                                    //This prevents the motor from moving
triWrite(0x34,0)                        //Clear the sg_stop bit                                           //Alternatively, read the     RAMP_STAT register
/*
To set where "home" is, you need to set xActual. If where you stopped is home, set xActual to 0. In my case, home was +187300 microsteps. So, I set xActual to -187300. Then, I set xTarget to 0. This will send the stepper home once you switch to position mode.
    */
triWrite(0x21,-187300)                  //Set home                                                        //I'm here in reference to home
triWrite(0x2D, 0)                       //Go home                                                         //I want to be here
triWrite(0x20,0)                        //Now set into position mode                                      //Position mode
triWrite(0x27,0x249F0)                  //Set upper velocity limit                                        //This is your upper operating velocity

이러면 충분할 것입니다! 제 프로젝트에서는 위치 모드로 전환하기 전에 xTarget을 xActual로 설정했습니다. 설정한 매크로 때문이었습니다. 이 명령도 마찬가지입니다. 애플리케이션에 따라 속도와 StallGuard 임계값을 변경해야 할 수 있지만, 과정은 동일해야 합니다. sg_stop 비트를 비우면 StallGuard가 꺼집니다. 애플리케이션에서 StallGuard를 계속 켜두려면, 대신 RAMP_STAT 레지스터를 읽어 보시기 바랍니다.

규격서의 81페이지부터 StallGuard2를 설정하는 방법이 나와 있습니다. StallGuard2 기능은 올바르게 보정하는 데 어느 정도 시간이 걸립니다 다른 모터 구동기도 멈춤을 감지할 수 있지만, 이 기능은 매우 인상적입니다. 다른 구동기들도 초과 전류를 감지할 수 있지만, 초과 전류 제한을 설정할 수 있는 구동기는 지금까지 본 적이 없습니다.

단극 모터:

단극 모터는 코일에 센터 탭이 있는 양극 모터입니다. 즉, 전류 제어가 훨씬 쉽습니다. 단점은 코일의 반만 사용할 수 있어서 비효율적이라는 것입니다. 다음과 같이 단극 모터의 전선이 연결됩니다. 모터에 전선이 다섯 개만 있다면, 두 개의 센터 탭 전선이 이미 연결되어 있는 상태입니다.

image

다음은 양극 모터의 스테핑 방식입니다. 양극 모터에서는, 각 핀을 하이 또는 로우로 만들 수 있어야 합니다.

단극 모터에서는, 코일 끝을 접지로 연결하기만 하면 됩니다.

구동하는 회로는 간단합니다.

image

양극 모터와 달리, 인접한 두 트랜지스터를 켜도 터지지 않습니다. 모터를 스테핑하려면 A1, B1, A2, B2 순서로 코일을 켭니다. 모터를 반전시키려면, 순서를 반대로 합니다. 다음은 몇 가지 예시 코드입니다.

풀 스텝을 사용하는 예시 코드:

/**************************************************************************//**
 * @file
 * @brief Empty Project
 * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_system.h"
#include "em_gpio.h"
volatile uint32_t msTicks;
#define TOTAL_STEPS      4
uint32_t STEPS[TOTAL_STEPS] = {0b1000, 0b0010, 0b0100, 0b0001};             //1,3,2,4
uint16_t STEP = 0;
/* ************* Systick Handler ***************** */
void SysTick_Handler(void) {
    msTicks++;
}
/* ************* Delay function ****************** */
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
/* ************* Output to H-bridge ************** */
void setStep(void) {
      GPIO->P[3].DOUTCLR = 0xF;                  //Shut off all pins.
      GPIO->P[3].DOUTSET = STEPS[STEP];          //Output the steps
}
/* ************* Main function ******************* */
int main(void)
{
    CHIP_Init();
    CMU->HFRCOCTRL = 0x30; // Set RC clock to 1 MHz
    CMU->HFPERCLKEN0 =(1<<13); //Enable GPIO clock

    if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;         //Setup SysTick

    /* ****************** Setup pushbuttons and H-bridge outputs ****************** */
    GPIO->P[1].MODEH = 0x110;                //Setup RB9 and RB10 as input
    GPIO->P[3].MODEL = 0x5555;               //Setup PD0-PD3 as push pull output. These go directly to the H-bridge
    GPIO->P[3].CTRL = 2;                     //High drivemode
    GPIO->P[3].DOUT = 0x0000;                //They should already be all low.
                                        //H-bridge pins 1,2,3,4 map to pins 3,2,1,0 on port D.
  /* Infinite loop */
  while (1) {
      if(!GPIO_PinInGet(gpioPortB,9)) {                         //If button 0 is pressed
          STEP = (STEP + 1) % TOTAL_STEPS;                      //Increment the step
          setStep();                                            //Output to the H-bridge
      }
      else if(!GPIO_PinInGet(gpioPortB, 10)) {                  //If button 1 is pressed.
          STEP = (STEP + TOTAL_STEPS-1) % TOTAL_STEPS;          //Decrement the step
          setStep();                                            //Output to the H-bridge
      }
      Delay(10);                                                //Short delay to let motor rotate
  }
}

하프 스텝을 사용하는 예시 코드:

/**************************************************************************//**
 * @file
 * @brief Empty Project
 * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_system.h"
#include "em_gpio.h"
volatile uint32_t msTicks;
#define TOTAL_STEPS      8
uint32_t STEPS[TOTAL_STEPS] = {0b1000, 0b1010, 0b0010, 0b0110, 0b0100, 0b0101, 0b0001, 0b1001};                     //1, 1and3, 3, 3and2, 2, 2and4, 4, 4and1

/* ************* Systick Handler ***************** */
void SysTick_Handler(void) {
    msTicks++;
}
/* ************* Delay function ****************** */
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
/* ************* Output to H-bridge ************** */
void setStep(uint32_t STEP) {
      GPIO->P[3].DOUTCLR = 0xF;                                  //Shut off all pins.
      GPIO->P[3].DOUTSET = STEPS[(STEP % TOTAL_STEPS)];          //Output the steps
}
/* ************* Main function ******************* */
int main(void)
{
 CHIP_Init();
    CMU->HFRCOCTRL = 0x30; // Set RC clock to 1 MHz
    CMU->HFPERCLKEN0 =(1<<13); //Enable GPIO clock

    if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;         //Setup millisecond tick counter

    /* ****************** Setup pushbuttons and H-bridge outputs ****************** */
    GPIO->P[1].MODEH = 0x110;                //Setup RB9 and RB10 as input
    GPIO->P[3].MODEL = 0x5555;               //Setup PD0-PD3 as push pull output. These go directly to the H-bridge
    GPIO->P[3].CTRL = 2;                     //High drivemode
    GPIO->P[3].DOUT = 0x0000;                //They should already be all low.
                                            //H-bridge pins 1,2,3,4 map to pins 3,2,1,0 on port D.
    int32_t STEP = 0;

  /* Infinite loop */
  while (1) {
      if(!GPIO_PinInGet(gpioPortB,9)) {                         //If button 0 is pressed
          STEP += 1;                                            //Increment the step
          setStep(STEP);                                        //Output to the H-bridge
      }
      else if(!GPIO_PinInGet(gpioPortB, 10)) {                  //If button 1 is pressed.
          STEP -= 1;                                            //Decrement the step
          setStep(STEP);                                        //Output to the H-bridge
      }
      Delay(10);                                                //Short delay to let motor rotate
  }
}

코드에서 스텝을 증가 및 감소시키는 방법을 수정했습니다. STEPS 벡터를 재활용하는 대신, 스텝을 설정할 때 현재 위치와 나뉘어진 위치를 계속 추적하였습니다. 이러면 매우 효과적으로 위치를 계속 추적하고 모터를 움직일 수 있습니다. 주의해야 할 유일한 점은 숫자가 언더플로우할 때의 제로 크로싱입니다. 총 스텝 수가 2의 배수이면 괜찮습니다. 또 다른 변경은 STEP을 부호 있는 정수로 선언했지만, 출력을 설정하는 데 사용할 때에는 부호 없는 정수로 호출했습니다. 따라서 출력에 영향을 주지 않으면서 음의 스텝을 계속 추적할 수 있습니다.

단극 모터 구동기는 위 회로도를 대체하거나 스텝/방향으로 제어할 수 있게 해줍니다. 설정이 매우 간단하므로 여기서는 자세히 다루지 않겠습니다. 구동기에 대한 사양은 규격서를 참조하십시오.

기타 자료:
H-bridge secrets – 이 기사에서는 H 브리지 작동 방식을 자세히 설명합니다.
Jones on Stepping Motors – 이 지침서는 1995년 아이오와 대학교의 교수에 의해 작성되었습니다. 이 지침서에는 스테퍼 모터의 원리에 대해 자세히 설명되어 있습니다. 스테퍼 모터 구동을 넘어 원리에 대해 자세히 알아보려면 이 지침서를 읽어 보시기 바랍니다.



영문 원본: How to Drive a Stepper Motor