Android Things之脈沖寬度調(diào)制(PWM)

上一篇文章講了Android Things之閃爍的LED燈俱饿,不明白的請(qǐng)查看http://www.reibang.com/p/09a6a66a339c

本節(jié)內(nèi)容講PWM如何進(jìn)行控制驻啤,在講之前先了解一些概念

  • 頻率計(jì)算公式(f=1/T)坎背,f代表頻率逊桦,單位是HZ郑象;1代表1秒绿语;T是周期
  • 總周期属百,一個(gè)完整脈寬(沖)所耗費(fèi)的總時(shí)間
  • 工作周期记劝,通電周期相對(duì)總周期的比例

電路連接圖

電路連接圖

獲取開(kāi)發(fā)板名稱(chēng)

請(qǐng)看這里http://www.reibang.com/p/09a6a66a339c

獲取PWM引腳名稱(chēng),為PWM0

    /**
     * Return the preferred PWM port for each board.
     */
    public static String getPWMPort() {
        switch (getBoardVariant()) {
            case DEVICE_EDISON_ARDUINO:
                return "IO6";
            case DEVICE_EDISON:
                return "GP12";
            case DEVICE_JOULE:
                return "PWM_0";
            case DEVICE_RPI3:
                return "PWM0";
            case DEVICE_IMX6UL_PICO:
                return "PWM7";
            case DEVICE_IMX6UL_VVDN:
                return "PWM3";
            case DEVICE_IMX7D_PICO:
                return "PWM1";
            default:
                throw new IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE);
        }
    }

連接到PWM引腳并初始化配置

//聲明設(shè)備管理器對(duì)象
PeripheralManagerService service = new PeripheralManagerService();

//獲取PWM引腳名稱(chēng)
String pinName = BoardDefaults.getPWMPort();
//連接PWM引腳
Pwm pwm = service.openPwm(pinName);
//初始化屬性族扰,包括頻率和工作周期
pwm.setPwmFrequencyHz(50);
pwm.setPwmDutyCycle(1);
//可以獲取pwm
mPwm.setEnabled(true);

動(dòng)態(tài)改變PWM

    /**
     * 脈沖寬度增長(zhǎng)步長(zhǎng)
     */
    private static final double PULSE_CHANGE_PER_STEP_MS = 0.2;
    /**
     * 最小脈沖周期
     */
    private static final double MIN_ACTIVE_PULSE_DURATION_MS = 1;
    /**
     * 最大脈沖周期
     */
    private static final double MAX_ACTIVE_PULSE_DURATION_MS = 2;

    /**
     * 工作周期是否在增長(zhǎng)
     */
    private boolean mIsPulseIncreasing = true;
    private static final int INTERVAL_BETWEEN_STEPS_MS = 10000;
private Runnable mChangePWMRunnable = new Runnable() {
        @Override
        public void run() {
            //調(diào)整脈沖工作周期厌丑,但是要在限制的最大值和最小值之內(nèi)
            if (mIsPulseIncreasing) {
                mActivePulseDuration += PULSE_CHANGE_PER_STEP_MS;
            } else {
                mActivePulseDuration -= PULSE_CHANGE_PER_STEP_MS;
            }
            // 控制在限制范圍之內(nèi)
            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;
            }
                //改變pwm的工作周期,要在[0, 100]內(nèi)取值
                mPwm.setPwmDutyCycle(100 * mActivePulseDuration / PULSE_PERIOD_MS);
                //重復(fù)改變
                mHandler.postDelayed(this, INTERVAL_BETWEEN_STEPS_MS);
        }
}

完整代碼

import android.os.Build;

import com.google.android.things.pio.PeripheralManagerService;

import java.util.List;

@SuppressWarnings("WeakerAccess")
public class BoardDefaults {
    private static final String DEVICE_EDISON_ARDUINO = "edison_arduino";
    private static final String DEVICE_EDISON = "edison";
    private static final String DEVICE_JOULE = "joule";
    private static final String DEVICE_RPI3 = "rpi3";
    private static final String DEVICE_IMX6UL_PICO = "imx6ul_pico";
    private static final String DEVICE_IMX6UL_VVDN = "imx6ul_iopb";
    private static final String DEVICE_IMX7D_PICO = "imx7d_pico";
    private static String sBoardVariant = "";

    /**
     * Return the preferred PWM port for each board.
     */
    public static String getPWMPort() {
        switch (getBoardVariant()) {
            case DEVICE_EDISON_ARDUINO:
                return "IO6";
            case DEVICE_EDISON:
                return "GP12";
            case DEVICE_JOULE:
                return "PWM_0";
            case DEVICE_RPI3:
                return "PWM0";
            case DEVICE_IMX6UL_PICO:
                return "PWM7";
            case DEVICE_IMX6UL_VVDN:
                return "PWM3";
            case DEVICE_IMX7D_PICO:
                return "PWM1";
            default:
                throw new IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE);
        }
    }

    private static String getBoardVariant() {
        if (!sBoardVariant.isEmpty()) {
            return sBoardVariant;
        }
        sBoardVariant = Build.DEVICE;
        // For the edison check the pin prefix
        // to always return Edison Breakout pin name when applicable.
        if (sBoardVariant.equals(DEVICE_EDISON)) {
            PeripheralManagerService pioService = new PeripheralManagerService();
            List<String> gpioList = pioService.getGpioList();
            if (gpioList.size() != 0) {
                String pin = gpioList.get(0);
                if (pin.startsWith("IO")) {
                    sBoardVariant = DEVICE_EDISON_ARDUINO;
                }
            }
        }
        return sBoardVariant;
    }
}
import android.app.Activity;
import com.google.android.things.pio.PeripheralManagerService;
import com.google.android.things.pio.Pwm;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import java.io.IOException;

/**
 * PWM是脈沖寬度調(diào)制
 *
 * 脈沖寬度
 * pulse with
 * alias is duty cycle
 * 定義:脈沖寬度從學(xué)術(shù)角度講就是電流或者電壓隨時(shí)間有規(guī)律變化的時(shí)間寬度
 *
 *
 * Sample usage of the PWM API that changes the PWM pulse width at a fixed interval defined in
 * {@link #INTERVAL_BETWEEN_STEPS_MS}.
 *
 * https://www.zybang.com/question/adcdecbe416f753023406451c9fde1e0.html
 *
 */
public class PWMActivity extends Activity {
    private static final String TAG = PWMActivity.class.getSimpleName();

    // Parameters of the servo PWM
    /**
     * 最小脈沖周期
     */
    private static final double MIN_ACTIVE_PULSE_DURATION_MS = 1;
    /**
     * 最大脈沖周期
     */
    private static final double MAX_ACTIVE_PULSE_DURATION_MS = 2;

    /**
     * 脈沖周期
     */
    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.2;
    private static final int INTERVAL_BETWEEN_STEPS_MS = 10000;

    private Handler mHandler = new Handler();
    private Pwm mPwm;

    /**
     * 脈沖是否在增長(zhǎng)
     */
    private boolean mIsPulseIncreasing = true;

    /**
     * 脈沖周期
     */
    private double mActivePulseDuration;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "Starting PWMActivity");

        PeripheralManagerService service = new PeripheralManagerService();
        try {
            String pinName = BoardDefaults.getPWMPort();
            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.setPwmDutyCycle(mActivePulseDuration);
            mPwm.setEnabled(true);

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Remove pending Runnable from the handler.
        mHandler.removeCallbacks(mChangePWMRunnable);
        // 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;
        }
    }

    private Runnable mChangePWMRunnable = new Runnable() {
        @Override
        public void run() {
            // 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

                Log.e(TAG, String.valueOf(100 * mActivePulseDuration / PULSE_PERIOD_MS));
                mPwm.setPwmDutyCycle(100 * mActivePulseDuration / PULSE_PERIOD_MS);

                // Reschedule the same runnable in {@link #INTERVAL_BETWEEN_STEPS_MS} milliseconds
                mHandler.postDelayed(this, INTERVAL_BETWEEN_STEPS_MS);
            } catch (IOException e) {
                Log.e(TAG, "Error on PeripheralIO API", e);
            }
        }
    };

}

該例子是google官方的例子渔呵,這里給出源碼地址https://github.com/androidthings/sample-simplepio.git

如果文章對(duì)你有幫助怒竿,給我點(diǎn)個(gè)贊吧!~.~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末扩氢,一起剝皮案震驚了整個(gè)濱河市耕驰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌录豺,老刑警劉巖朦肘,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異双饥,居然都是意外死亡媒抠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)咏花,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)趴生,“玉大人,你說(shuō)我怎么就攤上這事昏翰〔源遥” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵矩父,是天一觀的道長(zhǎng)锉桑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)窍株,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任攻柠,我火速辦了婚禮球订,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瑰钮。我一直安慰自己冒滩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布浪谴。 她就那樣靜靜地躺著开睡,像睡著了一般因苹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篇恒,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天扶檐,我揣著相機(jī)與錄音,去河邊找鬼胁艰。 笑死款筑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的腾么。 我是一名探鬼主播奈梳,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼解虱!你這毒婦竟也來(lái)了攘须?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤殴泰,失蹤者是張志新(化名)和其女友劉穎阻课,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體艰匙,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡限煞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了员凝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片署驻。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖健霹,靈堂內(nèi)的尸體忽然破棺而出旺上,到底是詐尸還是另有隱情,我是刑警寧澤糖埋,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布宣吱,位于F島的核電站,受9級(jí)特大地震影響瞳别,放射性物質(zhì)發(fā)生泄漏征候。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一祟敛、第九天 我趴在偏房一處隱蔽的房頂上張望疤坝。 院中可真熱鬧,春花似錦馆铁、人聲如沸跑揉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)历谍。三九已至现拒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間望侈,已是汗流浹背印蔬。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甜无,地道東北人扛点。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像岂丘,于是被迫代替她去往敵國(guó)和親陵究。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,288評(píng)論 25 707
  • 整體思路ESP8266作為T(mén)CP服務(wù)器,,手機(jī)作為T(mén)CP客戶(hù)端,自己使用Lua直接做到了芯片里面,省了單片機(jī),,節(jié)...
    楊奉武閱讀 5,854評(píng)論 0 5
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理奥帘,服務(wù)發(fā)現(xiàn)铜邮,斷路器,智...
    卡卡羅2017閱讀 134,702評(píng)論 18 139
  • 碧空之上寨蹋,倦云若飄絲松蒜, 遙寄一縷,毫末生盤(pán)云已旧。 九天之上疑凡塵聞幾俗秸苗? 咫尺仙心,問(wèn)道天涯…… ————嘿白龍馬
    嘿白龍馬閱讀 292評(píng)論 3 2
  • 轉(zhuǎn)載請(qǐng)注明出處 http://www.reibang.com/p/fc4d4348dc58 (作者:韓棟)本文為譯...
    miraclehen閱讀 34,654評(píng)論 3 42