ふるお〜と!- FullAuto

AI・ロボットが普及しBI(ベーシックインカム)が早急に実現されることを願う元ニートのブログ

ふるお〜と!-FullAuto

LinuxとArudinoでサーボモータ(ServoMotor)[MG996R]を動かしてみた

環境

OS: Ubuntu18.04
HW:Arduino Mega 2560
Servo Motor : MG996R
Power Supply : 5V

※MG996RはUSBのみの電力だと動作が不安定になった。ということで外部電源5Vを供給。
IDE: Software | Arduino

事前準備

USBポートのデバイスファイルにアクセスするためのコマンド

$  sudo usermod -a -G dialout `whoami`

書き込み・実行もできるようしておく。

$ sudo chmod 755 /dev/ttyACM0 

結線

f:id:nullpo24:20210710131245p:plain

Arduino側の実装

#include <Servo.h>
 
 Servo servo;
 
void setup(){

   //デフォルトはmin:544, max:2400
   servo.attach(7, 500, 2500); 

  // シリアルポートを9600 bps[ビット/秒]で初期化 
  Serial.begin(9600);
}
 
void loop(){
  int inputchar;
  
  inputchar = Serial.read();
 
  if(inputchar != -1 ){
    switch(inputchar){
      case 'o':
          // 読み込みデータが o の場合
          // step one revolution  in one direction:
          servo.write(180);
          delay(500);
          break;
      case 'p':  
          // 読み込みデータが p の場合
          // step one revolution in the other direction:
          servo.write(0);
          delay(500);
          break;
      case 'q':  
          // 読み込みデータが q の場合
          // step one revolution in the other direction:
          servo.write(90);
          delay(500);
          break;
    }
  } else {

  }
}

MG996Rは他のサーボモータと同様に0°(500us) 180°(2500us)としてパルス幅が決められている。

Linux側の実装

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

#define SERIAL_PORT "/dev/ttyACM0" //Arduinoのシリアル通信用deviceファイル名

int main(int argc, char *argv[])
{
    unsigned char buf[255];
    int val;
    int fd;
    struct termios tio;
    int baudRate = B9600;
    int i;
    int len;
    int ret;
    int size;

    fd = open(SERIAL_PORT, O_RDWR);
    if (fd < 0) {
        printf("open error\n");
        return -1;
    }

    tio.c_cflag += CREAD;               // 受信有効
    tio.c_cflag += CLOCAL;              // ローカルライン(モデム制御なし)
    tio.c_cflag += CS8;                 // データビット:8bit
    tio.c_cflag += 0;                   // ストップビット:1bit
    tio.c_cflag += 0;                   // パリティ:None

    cfsetispeed( &tio, baudRate );
    cfsetospeed( &tio, baudRate );

    cfmakeraw(&tio);                    // RAWモード

    tcsetattr( fd, TCSANOW, &tio );     // デバイスに設定を行う

    ioctl(fd, TCSETS, &tio);            // ポートの設定を有効にする

    // 送信処理ループ
    while(1) {
        // ターミナルで入力を待つ。
        printf("o:180 p:0>");
        fgets(buf, 255, stdin);
        val=atoi(buf);
        write(fd, buf, sizeof(buf));
        if(buf[0] == 'q') break;
    }

    close(fd);                              // デバイスのクローズ
    return 0;
}

実行

ターミナル上で、上記のmain.cをコンパイルして実行。

$  gcc main.c -o main
$ ./main
# 180°動かす
o/p/q?>o
# 0°動かす
o/p/q?>p
# 90°動かして終了
o/p/q?>q

実際に動かしてみると0~200°ぐらい動いてしまっている。
パチものだろうか🤔 そういうときは

servo.attach(7, 500, 2500); 

のminとmax値を狭めるとオッケー

関連

nullpo24.hatenablog.com