• 概要
  • 画角の狭いカメラでは任意の向きで撮影したいものです。
    RaspberryPi3BにPWM制御のサーボモータを2個取り付けて、カメラの向きを変えられるようにします。
  • 確認
  • GPIOを確認します。
    pi@raspberrypi:~ $ pinout
    ,--------------------------------.
    | oooooooooooooooooooo J8     +====
    | 1ooooooooooooooooooo        | USB
    |                             +====
    |      Pi Model 3B  V1.2         |
    |      +----+                 +====
    | |D|  |SoC |                 | USB
    | |S|  |    |                 +====
    | |I|  +----+                    |
    |                   |C|     +======
    |                   |S|     |   Net
    | pwr        |HDMI| |I||A|  +======
    `-| |--------|    |----|V|-------'
    
    Revision           : a02082
    SoC                : BCM2837
    RAM                : 1GB
    Storage            : MicroSD
    USB ports          : 4 (of which 0 USB3)
    Ethernet ports     : 1 (100Mbps max. speed)
    Wi-fi              : True
    Bluetooth          : True
    Camera ports (CSI) : 1
    Display ports (DSI): 1
    
    J8:
       3V3  (1) (2)  5V
     GPIO2  (3) (4)  5V
     GPIO3  (5) (6)  GND
     GPIO4  (7) (8)  GPIO14
       GND  (9) (10) GPIO15
    GPIO17 (11) (12) GPIO18
    GPIO27 (13) (14) GND
    GPIO22 (15) (16) GPIO23
       3V3 (17) (18) GPIO24
    GPIO10 (19) (20) GND
     GPIO9 (21) (22) GPIO25
    GPIO11 (23) (24) GPIO8
       GND (25) (26) GPIO7
     GPIO0 (27) (28) GPIO1
     GPIO5 (29) (30) GND
     GPIO6 (31) (32) GPIO12
    GPIO13 (33) (34) GND
    GPIO19 (35) (36) GPIO16
    GPIO26 (37) (38) GPIO20
       GND (39) (40) GPIO21
    
    For further information, please refer to https://pinout.xyz/
    
    これではPWMがどれかわかりません。
    公式サイトのドキュメントを見てみます。

    PWM0 が GPIO12 と GPIO18 に、 PWM1 が GPIO13 と GPIO19 に割り当てられています。
    WiringPi の時に作ったプログラムに合わせて、GPIO18 と GPIO13 を使うことにします。
  • 配線
  • 実配線とモータの組み立てはこちらを参考にしてください。


  • プログラム
  • goto.c
    // gcc -o goto goto.c -lpigpio -lpthread
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pigpio.h>
    #include <unistd.h>
    
    #define RA  13
    #define DEC 18
    
    int main(int ac, char *av[])
    {
        int ra  = 0;
        int dec = 0;
        int err = 0;
    
        if(ac == 2){
          if(strcmp(av[1],"home") == 0){
            ra = dec = 0;
          }else{
            err = 1;
          }
        }else if(ac == 3){
          ra   = atoi(av[1]);
          dec  = atoi(av[2]);
          ra   = (ra  < -90 || ra  > 90) ? 0 : ra;
          dec  = (dec < 0   || dec > 90) ? 0 : dec;
        }else{
            err = 1;
        }
    
        if(err == 1){
          printf("usage:%s ra dec\n ra:-90~90 rec:0~90\n",av[0]);
          exit(1);
        }
    
        int ret = gpioInitialise();
        if (ret < 0)
        {
            return ret;
        }
        else
        {
            int pwm_ra  = 1500 + 10 * ra;
            int pwm_dec = 1500 - 10 * dec;
    
            gpioServo(RA , pwm_ra);
            gpioServo(DEC, pwm_dec);
            sleep(1);
            gpioTerminate();
        }
    
        return ret;
    }
    
  • 実行
  • 1回実行
    sudo ./goto home
    
    7回実行
    demo.sh
    #!/bin/sh
    sudo ./goto 30 60
    sudo ./goto home
    sudo ./goto 30 60
    sudo ./goto home
    sudo ./goto 30 60
    sudo ./goto home
    sudo ./goto 30 60
    sudo ./goto home
    sudo ./goto 30 60
    sudo ./goto home
    sudo ./goto 30 60
    sudo ./goto home
    sudo ./goto 30 60
    sudo ./goto home
    

  • 参考
  • 参考までに、WringPiではこんな感じでした。
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <wiringPi.h>
    #include <unistd.h>
    
    #define BASE_CLOCK 192
    #define MIN_WIDTH  630 //usec
    #define MAX_WIDTH 2500 //usec
    #define SG90_ANGLE 180
    #define RA 13
    #define DEC 18
    
    int main(int ac, char *av[])
    {
      int pwm_range = 4000;
      int pwm_clock = atoi(av[1]);
      int pwm_min = (MIN_WIDTH * BASE_CLOCK) / (pwm_clock * 10);
      int pwm_max = (MAX_WIDTH * BASE_CLOCK) / (pwm_clock * 10);
      int wait    =  12 * 3600 /(pwm_max - pwm_min) * 1000000;
    //  int wait    =  12 * 3600 /(pwm_max - pwm_min) * 1000;
    
    
      int ra  = atoi(av[2]);
      int pwm_ra  =  pwm_min + (pwm_max - pwm_min) / SG90_ANGLE * (90 - ra);
    
      int dec = atoi(av[3]);
      int pwm_dec =  pwm_min + (pwm_max - pwm_min) / SG90_ANGLE * (90 - dec);
    
      if (wiringPiSetupGpio() == -1) {
        printf("cannot setup gpio.");
        return 1;
      }
    
      pinMode(RA,  PWM_OUTPUT);
      pinMode(DEC, PWM_OUTPUT);
      pwmSetMode(PWM_MODE_MS);
      pwmSetClock(pwm_clock);
      pwmSetRange(pwm_range);
    
      pwmWrite(DEC, pwm_dec);
      pwmWrite(RA, pwm_ra);
    
      return 0;
    }