AndroidThing初探

AndroidThings

搭梯子访问:https://developer.android.com/things/index.html

为了抢攻智能家电市场,Google 14 日推出全新物联网平台“Android Things”的开发者预
览版本。未来不只是手机,Android 可能将透过喇叭、监视器和路由器等家电,占据家中每个
角落。
可用于打印机、门锁、烤箱、灯泡、插座等
Android Things 的前身为在 2015 年 5 月发布的物联网平台 Brillo,不过至今并未受
到开发者大量采用。Google 强调,新推出的 Android Things 除了承袭 Brillo 的功
能,还加入 Android 开发者熟悉的工具,包含 Android Studio、Android SDK、
Google Play 服务和 Google 云端平台,提供整套打造 Android 智能联网设备所需工具,
让任何 Android 开发者都能轻松打造物联网服务。
只要你有能力打造出 App,你就能打造出一个设备。──Google

硬件

现在支持以下3款硬件:

1)Intel Edison
2)NXP Pico
3)Raspberry Pi 3
我使用的是树莓派3,拿到板子首先需要在安卓开发者网站下载预览版镜像。地址为:https://developer.android.com/things/preview/download.html
接下来将8G内存以上的高速TF卡放入读卡器,插入电脑,我使用的是OS X系统,给树莓派刷入
系统的步骤与Linux类似使用终端运行以下命令:
dd bs=4m if=iot_rpi3.img of=/dev/disk2
其中iot_rpi3.img   表示系统镜像所在的目录,我的就在当前目录所以就直接写文件名就OK
接着/dev/disk2是TF在文件系统上的位置。
稍等5分钟左右,系统写入完成,拔下读卡器,将TF卡放入树莓派上电开机。
Paste_Image.png
Paste_Image.png

第一印象

接入显示器开机,开机画面后并没有看到我们熟悉的安卓系统界面。而是在一个AndroidThings
的背景图后显示了已经获取的IP地址。对于AndroidThings来说显示屏不是必须的,无显示器
一样可以工作,使用鼠标试用了一下,界面不是很流畅。
值得一提的是系统开机后虽然并没有可供操作的选项,但是当你编写的带UI的程序运行到系统后
是有界面的,与普通app运行基本没有差别。
Paste_Image.png

使用IIC驱动12864OLED屏幕

拿到板子不久又购买了一块12864的OLED屏幕和一个DHT11温湿度传感器,然后对OLED屏幕开
始折腾。
要操作点阵显示屏,也就是写数据和写命令!让屏幕休眠、让屏幕滚动之类的操作,就要向屏幕
写命令;要让屏幕显示内容,就要写数据。 怎样让屏幕知道你发送的东西是数据还是命令?有
的屏幕有类似D/C(Data/Command)这样的引脚,说明是通过高低电平来区分,有的屏幕是向屏
幕写入特定的值来区分。 点阵屏内部都有一个驱动芯片,这个驱动芯片就负责按照程序的要
求,在某一个点来进行操作。所谓的初始化就是这个驱动芯片的初始化,初始化中注意两个地
方:
一个是复位!这个非常重要,如果没有完全复位,可能导致屏幕不稳定、显示乱码等畸形问题!
另一个就是初始化代码!这个初始化代码一般都是一些16进制数,可以在显示屏的规格书之类的文档里面找到,可以通过“写命令”的方式能够把初始化代码发送给显示屏。
完成了这些步骤,就可以让它显示你想要的东西了!

上代码

//以下代码中不包括字码,因为我的屏幕本身不带字库,所以需要用软件提码得到,具体购买屏幕时一般会附带提码软件
package com.donute.iot_android.utils;

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

import java.io.IOException;

/**
 * Created by zhouyufei on 2017/1/16.
 */

public class OledUtil {
    private I2cDevice device;
    private static final int Brightness=0xCF;

    public OledUtil(I2cDevice device) {
        this.device = device;
        initOled();
        clearScreen();
    }
    public void initOled(){
        oledCmd((byte)0xae);//--turn off oled panel
        oledCmd((byte)0x00);//---set low column address
        oledCmd((byte)0x10);//---set high column address
        oledCmd((byte)0x40);//--set start line address  Set Mapping RAM Display Start Line ((byte)0x00~(byte)0x3F)
        oledCmd((byte)0x81);//--set contrast control register
        oledCmd((byte) Brightness); // Set SEG Output Current Brightness
        oledCmd((byte)0xa1);//--Set SEG/Column Mapping     (byte)0xa0×óÓÒ·´ÖÃ (byte)0xa1Õý³£
        oledCmd((byte)0xc8);//Set COM/Row Scan Direction   (byte)0xc0ÉÏÏ·´Öà (byte)0xc8Õý³£
        oledCmd((byte)0xa6);//--set normal display
        oledCmd((byte)0xa8);//--set multiplex ratio(1 to 64)
        oledCmd((byte)0x3f);//--1/64 duty
        oledCmd((byte)0xd3);//-set display offset   Shift Mapping RAM Counter ((byte)0x00~(byte)0x3F)
        oledCmd((byte)0x00);//-not offset
        oledCmd((byte)0xd5);//--set display clock divide ratio/oscillator frequency
        oledCmd((byte)0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
        oledCmd((byte)0xd9);//--set pre-charge period
        oledCmd((byte)0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
        oledCmd((byte)0xda);//--set com pins hardware configuration
        oledCmd((byte)0x12);
        oledCmd((byte)0xdb);//--set vcomh
        oledCmd((byte)0x40);//Set VCOM Deselect Level
        oledCmd((byte)0x20);//-Set Page Addressing Mode ((byte)0x00/(byte)0x01/(byte)0x02)
        oledCmd((byte)0x02);//
        oledCmd((byte)0x8d);//--set Charge Pump enable/disable
        oledCmd((byte)0x14);//--set((byte)0x10) disable
        oledCmd((byte)0xa4);// Disable Entire Display On ((byte)0xa4/(byte)0xa5)
        oledCmd((byte)0xa6);// Disable Inverse Display On ((byte)0xa6/a7)
        oledCmd((byte)0xaf);//--turn on oled panel
    }
    private void oledCmd(int i) {
        try {
            device.writeRegByte(0x00,(byte)i);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void oledData(int data) {
        try {
            device.writeRegByte(0x40,(byte)(data));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void oledData(int[] data) {
        try {
            for (int i=0;i<data.length;i++){
                device.writeRegByte(0x40,(byte)(data[i]));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /***************功能描述:显示6*8一组标准ASCII字符串  显示的坐标(x,y),y为页范围0~7****************/
    public void oled6x8(int x,int y,char ch[])
    {
        int c=0,i=0,j=0;
        for (int k=0;k<ch.length;k++){
            c =ch[j]-32;
            if(x>126){
                x=0;
                y++;
            }
            OLED_Set_Pos(x,y);
            for(i=0;i<6;i++)
                oledData(CodeTab.F6x8[c][i]);
            x+=6;
            j++;
        }
    }
    /*******************功能描述:显示8*16一组标准ASCII字符串  显示的坐标(x,y),y为页范围0~7****************/
    public void oled8x16(int x,int y,char ch[])
    {
        int c=0,i=0,j=0;
        for (int k=0;k<ch.length;k++){
            c =ch[j]-32;
            if(x>120){
                x=0;
                y++;
            }
            OLED_Set_Pos(x,y);
            for(i=0;i<8;i++)
                oledData(CodeTab.F8X16[c*16+i]);
            OLED_Set_Pos(x,y+1);
            for(i=0;i<8;i++)
                oledData(CodeTab.F8X16[c*16+i+8]);
            x+=8;
            j++;
        }
    }
    /*****************功能描述:显示16*16点阵  显示的坐标(x,y),y为页范围0~7****************************/
    public void oled16x16(int x,int y,int N,int[] codeTab)
    {
        char wm=0;
        int adder=32*N;
        OLED_Set_Pos(x , y);
        for(wm = 0;wm < 16;wm++)
        {
            oledData(codeTab[adder]);
            adder += 1;
        }
        OLED_Set_Pos(x,y + 1);
        for(wm = 0;wm < 16;wm++)
        {
            oledData(codeTab[adder]);
            adder += 1;
        }
    }
    /***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
    public void drawBmp(int x0,int y0,int x1,int y1,char BMP[])
    {
         int j=0;
         int x,y;
        if(y1%8==0)
            y=y1/8;
        else
            y=y1/8+1;
        for(y=y0;y<y1;y++)
        {
            OLED_Set_Pos(x0,y);
            for(x=x0;x<x1;x++)
            {
                oledData(BMP[j++]);
            }
        }
    }

    /*********************OLED 设置坐标************************************/
    public void OLED_Set_Pos(int x, int y)
    {
        oledCmd(0xb0+y);
        oledCmd(((x&0xf0)>>4)|0x10);
        oledCmd((x&0x0f)|0x01);
    }

    /*****************************清除屏幕显示内容************************************/
    public void clearScreen(){
        int y,x;
        for(y=0;y<8;y++)
        {
            oledCmd((byte) (0xb0+y));
            oledCmd((byte) 0x01);
            oledCmd((byte) 0x10);
            for(x=0;x<128;x++){
                int[] b={0};
                oledData(b);
            }
        }
    }
}

Paste_Image.png
Paste_Image.png

使用GPIO驱动DHT11

因为之前有使用GPIO驱动继电器工作的经历,继电器接在3.3V正常工作,接在5V下无法驱动。
在尝试了驱动DHT11的时候很久一直没有成功,起初以为跟最开始驱动继电器的时候一样,电压问题,然后后来仔细核对代码,查看时序图,发现在AndroidThings系统下读取一次GPIO值耗时就在270us左右,而dht11的时序图中电平转换时间都是在100us以下,所以在java下使用GPIO不能捕捉到如此短时间内的电平变化,无法获取到温湿度值。
以下是代码:
package com.donute.iot_android.utils;


import android.util.Log;

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by zhouyufei on 2017/1/5.
 */

public class TemperatureUtil {
    private Gpio gpio;
    private LoopThread thread;
    private float temp=0.0f;
    private float humi=0.0f;
    private static TemperatureUtil temperatureUtil;

    private TemperatureUtil(Gpio gpio) {
        this.gpio = gpio;
        thread=new LoopThread();
        thread.start();
    }
    public static TemperatureUtil init(Gpio gpio){
        if (temperatureUtil==null){
            temperatureUtil=new TemperatureUtil(gpio);
        }
        return temperatureUtil;
    }
    public void destory(){
        if (thread!=null){
            thread.interrupt();
            thread=null;
        }
    }
    private void calculate(List<Integer> integers){
        Log.d("tem","长度:"+integers.size()+"    "+integers+"");
    }
    public float getTemp(){
        return temp;
    }
    public float getHumi(){
        return humi;
    }
    class LoopThread extends Thread{
        @Override
        public void run() {
            super.run();
            while (!isInterrupted()){
                List<Integer> list=new ArrayList<>();
                try {
                    gpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_HIGH);
                    gpio.setActiveType(Gpio.ACTIVE_HIGH);
                    Thread.sleep(10);
                    gpio.setValue(false);
                    Thread.sleep(2);
                    gpio.setValue(true);
                    gpio.setDirection(Gpio.DIRECTION_IN);
                    gpio.setActiveType(Gpio.ACTIVE_HIGH);
                    while (!gpio.getValue()){
                        Log.d("gpio","low");
                        continue;
                    }
                    while (gpio.getValue()){
                        Log.d("gpio","high");
                        continue;
                    }
                    long l3=System.nanoTime();

                    while (list.size()<40){
                        int j=0;
                        while (!gpio.getValue()){
                            Log.d("gpio","low");
                            continue;
                        }
                        while (gpio.getValue()){
                            Log.d("gpio","high");
                            j=j+1;
                            if (j>100)
                                break;
                        }
                        Log.e("value of j",j+"");
                        if (j<8)
                            list.add(0);
                        else
                            list.add(1);
                    }
                    calculate(list);
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容