-
Notifications
You must be signed in to change notification settings - Fork 0
20241105
Takanobu INAFUKU edited this page Nov 5, 2024
·
7 revisions
サンプルコード
Servo ライブラリを使って、接続した FT90B を動かしてみます。
今回使うサーボモーター(Tower Pro SG90 9g Micro Servo)の仕様

サンプルスケッチ
/* 1105_servo_simple.ino */
#include <Servo.h>
#if (defined(PICO_RP2040))
#define _SRV_OUTPIN 0
#else
#define _SRV_OUTPIN 9
#endif
Servo srv1;
int angle = 0;
void setup() {
pinMode(_SRV_OUTPIN, OUTPUT);
// 指定可能なパルス幅の範囲が異なる場合は初期化時に指定する。
// サーボモーター(FEETECH FT90B)の初期化。
srv1.attach(_SRV_OUTPIN, 500, 2500);
// サーボモーター(Tower Pro SG-90)の初期化。
// srv1.attach(_SRV_OUTPIN, 500, 2400);
srv1.write(angle);
Serial.begin(57600);
}
void loop() {
srv1.write(angle);
Serial.print("Angle: ");
Serial.println(angle);
// 2秒間隔で30°ずつ動かす。180°まで行ったら0°に戻す.
angle += 30;
if (angle > 180) angle = 0;
delay(2000);
}シリアル通信を使って、接続した FT90B を任意の角度に動かしてみます。
サンプルスケッチ
/* 1105_servo_with_serial */
#include <Servo.h>
#if (defined(PICO_RP2040))
#define _SRV_OUTPIN 0
#else
#define _SRV_OUTPIN 9
#endif
Servo srv1;
int angle = 90;
unsigned long tick = 0;
const byte numChars = 64;
char receivedChars[numChars];
bool newData = false;
void setup() {
pinMode(_SRV_OUTPIN, OUTPUT);
// 指定可能なパルス幅の範囲が異なる場合は初期化時に指定する。
// サーボモーター(FEETECH FT90B)の初期化。
srv1.attach(_SRV_OUTPIN, 500, 2500);
// サーボモーター(Tower Pro SG-90)の初期化。
// srv1.attach(_SRV_OUTPIN, 500, 2400);
srv1.write(angle);
Serial.begin(57600);
}
void loop() {
recvWithEndMarker();
if (newData == true) {
String tmp_str = String(receivedChars);
String tmp_perms[2] = { "", "" };
int sidx = 0, pidx = 0;
while (true) {
int fidx = tmp_str.indexOf(' ', sidx);
if (fidx != -1) {
String sstr = tmp_str.substring(sidx, fidx);
sidx = fidx + 1;
if (pidx < 2) {
tmp_perms[pidx] = sstr;
pidx ++;
} else {
break;
}
} else {
String rstr = tmp_str.substring(sidx, tmp_str.length());
if (pidx < 2) {
tmp_perms[pidx] = rstr;
}
break;
}
}
Serial.println(tmp_str);
if (tmp_perms[0].length() != 0) {
angle = map(tmp_perms[0].toInt(), 0, 1023, 0, 180);
Serial.print("Raw[0]:");
Serial.print(tmp_perms[0]);
Serial.print(",Angle:");
Serial.println(angle);
srv1.write(angle);
}
newData = false;
}
if ((millis() - tick) > 1000) {
tick = millis();
Serial.println("tick");
}
}
void recvWithEndMarker() {
static byte ndx = 0;
const char endMarker = ';';
char rc;
if (Serial.available()) {
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}
}大抵の市販されているサーボモーターには ホーン と呼ばれる駆動部分に取り付けるパーツがいくつか付属しています。
実際に作品に組み込んで使う場合、単純な角度の動き以外にしたい場合など、これらの付属のホーンをうまく応用するか、必要に応じて治具を自作する必要があります。
モータードライバーモジュール CYTRON MDD3A を使って2台のモーターをシリアル通信で制御してみます(デモのみ)。
サンプルスケッチ
/* 1105_mdd3a.ino */
#if (defined(PICO_RP2040))
#define _PWM1 0
#define _PWM2 1
#define _PWM3 2
#define _PWM4 3
#else
#define _PWM1 9
#define _PWM2 10
#define _PWM3 11
#define _PWM4 12
#endif
unsigned long tick = 0;
const byte numChars = 64;
char receivedChars[numChars];
bool newData = false;
void setup() {
pinMode(_PWM1, OUTPUT);
pinMode(_PWM2, OUTPUT);
pinMode(_PWM3, OUTPUT);
pinMode(_PWM4, OUTPUT);
analogWrite(_PWM1, 0);
analogWrite(_PWM2, 0);
analogWrite(_PWM3, 0);
analogWrite(_PWM4, 0);
Serial.begin(57600);
}
void loop() {
recvWithEndMarker();
if (newData == true) {
String tmp_str = String(receivedChars);
String tmp_perms[2] = { "", "" };
int sidx = 0, pidx = 0;
while (true) {
int fidx = tmp_str.indexOf(' ', sidx);
if (fidx != -1) {
String sstr = tmp_str.substring(sidx, fidx);
sidx = fidx + 1;
if (pidx < 2) {
tmp_perms[pidx] = sstr;
pidx ++;
} else {
break;
}
} else {
String rstr = tmp_str.substring(sidx, tmp_str.length());
if (pidx < 2) {
tmp_perms[pidx] = rstr;
}
break;
}
}
Serial.println(tmp_str);
if (tmp_perms[0].length() != 0) {
int m1 = map(tmp_perms[0].toInt(), 0, 1023, -254, 254);
Serial.print("Raw[0]:");
Serial.print(tmp_perms[0]);
Serial.print(",m1_status:");
Serial.println(m1);
if (m1 < 0) {
analogWrite(_PWM1, m1);
analogWrite(_PWM2, 0);
} else if (m1 == 0) {
analogWrite(_PWM1, 0);
analogWrite(_PWM2, 0);
} else {
analogWrite(_PWM1, 0);
analogWrite(_PWM2, m1);
}
}
if (tmp_perms[1].length() != 0) {
int m2 = map(tmp_perms[1].toInt(), 0, 1023, -254, 254);
Serial.print("Raw[1]:");
Serial.print(tmp_perms[1]);
Serial.print(",m1_status:");
Serial.println(m2);
if (m2 < 0) {
analogWrite(_PWM3, m2);
analogWrite(_PWM4, 0);
} else if (m2 == 0) {
analogWrite(_PWM3, 0);
analogWrite(_PWM4, 0);
} else {
analogWrite(_PWM3, 0);
analogWrite(_PWM4, m2);
}
}
newData = false;
}
if ((millis() - tick) > 1000) {
tick = millis();
Serial.println("tick");
}
}
void recvWithEndMarker() {
static byte ndx = 0;
const char endMarker = ';';
char rc;
if (Serial.available()) {
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}
}2025年度 (後期 / 火曜4・5限)
2024年度 (後期 / 火曜4・5限)
-
Appendix