Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

@tomato_sugar

AndroidThings & Raspberry Pi3 で猫用扇風機を作る(6)

2017年11月18日、19日に実施された「東北Tech道場 郡山道場 第8回」の作業内容の続きをまとめます。

LチカのプログラムをCatFansに移植したので、今度はこれを使って扇風機のファンを回します。それからができたら、サーボモータを回す処理を追加します。

1. 扇風機のファンを回す

前回のプログラムのピン名を
String pinName = "BCM6";
から
String pinName = "BCM23";
に変更するだけで、扇風機のファンが回ります。また、メソッド名を次のように変え、コメントも書き換えました。

BlinkRunnable → turnFan

こんな感じでファンが回っています。ちなみに写真の猫は我が家のライトです。(^^)
30.jpg

2. サーボを回す

サーボモータを動かしてみます。Lチカのサンプルプログラムにはサーボモータを動かすプログラム(PWM sample)も入っているので、今回はそれを使うことにしました。扇風機のファンとは逆で、猫がいなければサーボを回し、猫がいたらサーボを止めます。

(1) Lチカのプログラムの移植

(i) mChangePWMRunnableメソッドとPWMメソッドの追加

「Simple PIO」のcom.example.androidthings.simplepioの中のonCreateメソッドとmChangePWMRunnableメソッドを参考に次のようなメソッドを追加する。

CatFansActivity.java
    private Pwm mPwm;
    private boolean mIsPulseIncreasing = true;
    private double mActivePulseDuration;

    // Parameters of the servo PWM
    private static final double MIN_ACTIVE_PULSE_DURATION_MS = 0.8;
    private static final double MAX_ACTIVE_PULSE_DURATION_MS = 2.3;
    private static final double PULSE_PERIOD_MS = 20;  // Frequency of 50Hz (1000/20)

    // Parameters for the servo movement over time
    private static final double PULSE_CHANGE_PER_STEP_MS = 0.08;
    :
    :
    //サーボモータの処理
    private void mChangePWMRunnable(boolean onoff){
            // Exit Runnable if the port is already closed
            if (mPwm == null) {
                Log.w(TAG, "Stopping runnable since mPwm is null");
                return;
            }

            // Change the duration of the active PWM pulse, but keep it between the minimum and
            // maximum limits.
            // The direction of the change depends on the mIsPulseIncreasing variable, so the pulse
            // will bounce from MIN to MAX.
            if (mIsPulseIncreasing) {
                mActivePulseDuration += PULSE_CHANGE_PER_STEP_MS;
            } else {
                mActivePulseDuration -= PULSE_CHANGE_PER_STEP_MS;
            }

            // Bounce mActivePulseDuration back from the limits
            if (mActivePulseDuration > MAX_ACTIVE_PULSE_DURATION_MS) {
                mActivePulseDuration = MAX_ACTIVE_PULSE_DURATION_MS;
                mIsPulseIncreasing = !mIsPulseIncreasing;
            } else if (mActivePulseDuration < MIN_ACTIVE_PULSE_DURATION_MS) {
                mActivePulseDuration = MIN_ACTIVE_PULSE_DURATION_MS;
                mIsPulseIncreasing = !mIsPulseIncreasing;
            }

            Log.d(TAG, "Changing PWM active pulse duration to " + mActivePulseDuration + " ms");

            try {

                // Duty cycle is the percentage of active (on) pulse over the total duration of the
                // PWM pulse
                if(onoff){
                    mPwm.setPwmDutyCycle(100 * mActivePulseDuration / PULSE_PERIOD_MS);
                }

            } catch (IOException e) {
                Log.e(TAG, "Error on PeripheralIO API", e);
            }
        }


    private void PWM(){
        //サーボモータの処理
        PeripheralManagerService service = new PeripheralManagerService();
        try {
            String pinName = "PWM0";
            mActivePulseDuration = MIN_ACTIVE_PULSE_DURATION_MS;

            mPwm = service.openPwm(pinName);

            // Always set frequency and initial duty cycle before enabling PWM
            mPwm.setPwmFrequencyHz(1000 / PULSE_PERIOD_MS);
            mPwm.setEnabled(true);

            // Post a Runnable that continuously change PWM pulse width, effectively changing the
            // servo position
            Log.d(TAG, "Start changing PWM pulse");
            mChangePWMRunnable(false);
        } catch (IOException e) {
            Log.e(TAG, "Error on PeripheralIO API", e);
        }
    }

Lチカと同じようにピンは固定にするので、
String pinName = "PWM0";
とする。
ラズパイのピン名は基本BCM~になるが、サーボモータのみPWM0、PWM1となる。また、サーボモータはパルス幅で回転する位置が決まり、パルス幅はパルス波の周期とデューティー比で求まる。

(ii) onCreateメソッドの修正

OnCreateメソッドの最後に
PWM();
を追加。

(iii) onDestroyメソッドの修正

onDestroyメソッドを次のように修正。

CatFansActivity.java
    protected void onDestroy() {
        :
        :
        //サーボ
        // Remove pending Runnable from the handler.
        mChangePWMRunnable(false);
        // Close the PWM port.
        Log.i(TAG, "Closing port");
        try {
            mPwm.close();
        } catch (IOException e) {
            Log.e(TAG, "Error on PeripheralIO API", e);
        } finally {
            mPwm = null;
        }
    }

(iv) onPictureTakenの修正

onPictureTakenメソッドを次のように修正する。

CatFansActivity.java
    private void onPictureTaken(final byte[] imageBytes) {
                :
                :
                        if (annotations != null) {
                            //猫画像なら
                            if (annotations.containsKey("cat") == true) {
                                if (annotations.get("cat") >= 0.8F) {
                                    // イメージをfirebaseにアップロードする
                                    log.child("timestamp").setValue(ServerValue.TIMESTAMP);
                                    log.child("image").setValue(imageStr);
                                    log.child("annotations").setValue(annotations);

                                    mChangePWMRunnable(false);
                                    turnFan(true);
                                    Log.d(TAG, "Turn the fan");
                                } else {
                                    mChangePWMRunnable(true);
                                    turnFan(false);
                                    Log.d(TAG, "Stop the fan");
                                }
                            }
                            else {
                                mChangePWMRunnable(true);
                                turnFan(false);
                                Log.d(TAG, "Stop the fan");
                            }
                        }
                    } catch (IOException e) {
                        Log.e(TAG, "Cloud Vison API error: ", e);
                    }
                }
            });
        }
    }

(v) 実行確認

以下のように扇風機のファンの下につけたサーボが、猫がいなければ回り、猫がいたら止まる。

31.jpg

第8回はまだ続きます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?