AndroidThings發射紅外信號

原文地址:https://blog.csdn.net/luhanglei/article/details/82496986

原理:當紅外發射管以38KHz頻率閃爍時,紅外接收端可以接收到信號。通過閃爍時長的不同,可以解析出不同的信號。

因爲時間精度高,不可能通過Thread.sleep()實現。

AndroidThings支持的幾種通信協議中,SPI(AT關於SPI的官方文檔)比較合適(輸出信號爲例:CLK輸出時鐘,MOSI輸出0/1數據),因爲可以自主控制MOSI端口的高低電平,配置好對應的發射頻率,就可以實現紅外發射。

故使用SPI協議的輸出端,修改輸出頻率爲38KHz的整數倍,控制高低電平達到發射紅外信號的目的。

以樂高PF的紅外文檔爲模板(圖片截圖自樂高文檔,侵刪):

建立一個工具類,配置參數:

import com.google.android.things.pio.SpiDevice

object Util {
    /**
     * 每字節代表一次閃爍,當紅外發射管以38KHz閃爍的時候,接收管才能收到信號
     * one byte per cycle, 1/38K second
     */
    val frequency = 38000 * 8
    val bitsPerWord = 8
    val bitJustification = SpiDevice.BIT_JUSTIFICATION_MSB_FIRST

    /**
     * 一次閃爍的信號,時長1/38K秒
     * one cycle of IR
     * 11110000
     */
    val IR = 0xf0.toByte()

    /**
     * 一次不閃爍的信號,時長1/38K秒
     * one cycle of PAUSE
     * 00000000
     */
    val PAUSE = 0.toByte()

    /**
     * 在樂高PF的文檔裏,一次低位(0)由6個IR和10個pause組成
     * In LEGO Power Functions RC document, Low bit consists of 6 cycles of IR and 10 “cycles” of pause
     */
    val LOW_BIT: ArrayList<Byte> = ArrayList<Byte>().apply {
        for (i in 1..6) {
            add(IR)
        }
        for (i in 1..10) {
            add(PAUSE)
        }

    }

    /**
     * 在樂高PF的文檔裏,一次高位(1)由6個IR和21個pause組成
     * In LEGO Power Functions RC document, high bit of 6 cycles IR and 21 “cycles” of pause
     */
    val HIGHT_BIT: ArrayList<Byte> = ArrayList<Byte>().apply {
        for (i in 1..6) {
            add(IR)
        }
        for (i in 1..21) {
            add(PAUSE)
        }
    }

    /**
     * 在樂高PF的文檔裏,開始或停止位由6個IR和39個pause組成
     * In LEGO Power Functions RC document, start bit of 6 cycles IR and 39 “cycles” of pause
     */
    val START_AND_STOP_BIT: ArrayList<Byte> = ArrayList<Byte>().apply {
        for (i in 1..6) {
            add(IR)
        }
        for (i in 1..39) {
            add(PAUSE)
        }
    }
}

然後組裝命令發射即可:

import android.app.Activity
import android.content.ContentValues.TAG
import android.os.Bundle
import android.util.Log
import com.google.android.things.pio.PeripheralManager
import com.google.android.things.pio.SpiDevice
import java.io.IOException

/**
 * 使用SPI的MOSI口作爲輸出
 * Use the MOSI port of the SPI as the output
 */
class MainActivity : Activity() {
    private val SPI_DEVICE_NAME: String = "SPI0.0"
    private lateinit var mSPIDevice: SpiDevice


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        try {
            val manager: PeripheralManager = PeripheralManager.getInstance()
            mSPIDevice = manager.openSpiDevice(SPI_DEVICE_NAME)
            configureSpiDevice(mSPIDevice)

            //init and send order
            val order = initOrder()
            mSPIDevice.write(order, order.size)

        } catch (e: IOException) {
            Log.w(TAG, "Unable to access SPI device", e);
        }

    }

    /**
     * 拼接命令DEMO,樂高的命令由開始標誌+3段命令+校驗位+結束標誌組成
     * Lego's order consists of START_BIT + Nibble1 + Nibble2 + Nibble3 + LRC + STOP_BIT
     * LRC(4 bit) = 0xF xor Nibble 1 xor Nibble 2 xor Nibble 3
     */
    private fun initOrder(): ByteArray {
        val nibble1 = 0b0100
        val nibble2 = 0b1010
        val nibble3 = 0b0000
        val lrc = 0xff.xor(nibble1).xor(nibble2).xor(nibble3)
        val signal = ArrayList<Byte>()
        signal.addAll(Util.START_AND_STOP_BIT)
        signal.addAll(if (nibble1.and(0b1000) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble1.and(0b0100) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble1.and(0b0010) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble1.and(0b0001) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble2.and(0b1000) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble2.and(0b0100) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble2.and(0b0010) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble2.and(0b0001) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble3.and(0b1000) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble3.and(0b0100) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble3.and(0b0010) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (nibble3.and(0b0001) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (lrc.and(0b1000) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (lrc.and(0b0100) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (lrc.and(0b0010) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(if (lrc.and(0b0001) != 0) Util.HIGHT_BIT else Util.LOW_BIT)
        signal.addAll(Util.START_AND_STOP_BIT)
        return signal.toByteArray()
    }

    override fun onDestroy() {
        super.onDestroy()
        try {
            if (::mSPIDevice.isInitialized) {
                mSPIDevice.close()
            }
        } catch (e: IOException) {
            Log.w(TAG, "Unable to access SPI device", e);
        }
    }

    @Throws(IOException::class)
    fun configureSpiDevice(device: SpiDevice) {
        device.setMode(SpiDevice.MODE0)
        device.setFrequency(Util.frequency)
        device.setBitsPerWord(Util.bitsPerWord)
        device.setBitJustification(Util.bitJustification)
    }
}

接線圖(我用的樹莓派3B):

完整代碼包:https://github.com/Yangwoqizuo/Android-Things-IR

原文地址:https://blog.csdn.net/luhanglei/article/details/82496986

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章