AndroidThings发射红外信号

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

原理:当红外发射管以38KHz频率闪烁时,红外接收端可以接收到信号。通过闪烁时长的不同,可以解析出不同的信号。

因为时间精度高,不可能通过Thread.sleep()实现。

AndroidThings支持的几种通信协议中,SPI(AT关于SPI的官方文档)比较合适(输出信号为例:CLK输出时钟,MOSI输出0/1数据),因为可以自主控制MOSI端口的高低电平,配置好对应的发射频率,就可以实现红外发射。

故使用SPI协议的输出端,修改输出频率为38KHz的整数倍,控制高低电平达到发射红外信号的目的。

以乐高PF的红外文档为模板(图片截图自乐高文档,侵删):

AndroidThings发射红外信号_第1张图片

建立一个工具类,配置参数:

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 = ArrayList().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 = ArrayList().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 = ArrayList().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()
        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):

AndroidThings发射红外信号_第2张图片

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

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

你可能感兴趣的:(AndroidThings发射红外信号)