AndroidThings
搭梯子訪問:https://developer.android.com/things/index.html
為了搶攻智能家電市場含末,Google 14 日推出全新物聯(lián)網(wǎng)平臺“Android Things”的開發(fā)者預
覽版本司抱。未來不只是手機,Android 可能將透過喇叭谚赎、監(jiān)視器和路由器等家電尔崔,占據(jù)家中每個
角落蚓胸。
可用于打印機驱富、門鎖灾螃、烤箱镊讼、燈泡宽涌、插座等
Android Things 的前身為在 2015 年 5 月發(fā)布的物聯(lián)網(wǎng)平臺 Brillo,不過至今并未受
到開發(fā)者大量采用蝶棋。Google 強調(diào)卸亮,新推出的 Android Things 除了承襲 Brillo 的功
能,還加入 Android 開發(fā)者熟悉的工具玩裙,包含 Android Studio嫡良、Android SDK、
Google Play 服務和 Google 云端平臺献酗,提供整套打造 Android 智能聯(lián)網(wǎng)設備所需工具寝受,
讓任何 Android 開發(fā)者都能輕松打造物聯(lián)網(wǎng)服務。
只要你有能力打造出 App罕偎,你就能打造出一個設備很澄。──Google
硬件
現(xiàn)在支持以下3款硬件:
1)Intel Edison
2)NXP Pico
3)Raspberry Pi 3
我使用的是樹莓派3,拿到板子首先需要在安卓開發(fā)者網(wǎng)站下載預覽版鏡像颜及。地址為:https://developer.android.com/things/preview/download.html
接下來將8G內(nèi)存以上的高速TF卡放入讀卡器甩苛,插入電腦,我使用的是OS X系統(tǒng)俏站,給樹莓派刷入
系統(tǒng)的步驟與Linux類似使用終端運行以下命令:
dd bs=4m if=iot_rpi3.img of=/dev/disk2
其中iot_rpi3.img 表示系統(tǒng)鏡像所在的目錄讯蒲,我的就在當前目錄所以就直接寫文件名就OK
接著/dev/disk2是TF在文件系統(tǒng)上的位置。
稍等5分鐘左右肄扎,系統(tǒng)寫入完成墨林,拔下讀卡器赁酝,將TF卡放入樹莓派上電開機。
Paste_Image.png
Paste_Image.png
第一印象
接入顯示器開機,開機畫面后并沒有看到我們熟悉的安卓系統(tǒng)界面旭等。而是在一個AndroidThings
的背景圖后顯示了已經(jīng)獲取的IP地址酌呆。對于AndroidThings來說顯示屏不是必須的,無顯示器
一樣可以工作搔耕,使用鼠標試用了一下隙袁,界面不是很流暢。
值得一提的是系統(tǒng)開機后雖然并沒有可供操作的選項弃榨,但是當你編寫的帶UI的程序運行到系統(tǒng)后
是有界面的菩收,與普通app運行基本沒有差別。
Paste_Image.png
使用IIC驅(qū)動12864OLED屏幕
拿到板子不久又購買了一塊12864的OLED屏幕和一個DHT11溫濕度傳感器鲸睛,然后對OLED屏幕開
始折騰娜饵。
要操作點陣顯示屏,也就是寫數(shù)據(jù)和寫命令腊凶!讓屏幕休眠划咐、讓屏幕滾動之類的操作拴念,就要向屏幕
寫命令钧萍;要讓屏幕顯示內(nèi)容,就要寫數(shù)據(jù)政鼠。 怎樣讓屏幕知道你發(fā)送的東西是數(shù)據(jù)還是命令风瘦?有
的屏幕有類似D/C(Data/Command)這樣的引腳,說明是通過高低電平來區(qū)分公般,有的屏幕是向屏
幕寫入特定的值來區(qū)分万搔。 點陣屏內(nèi)部都有一個驅(qū)動芯片,這個驅(qū)動芯片就負責按照程序的要
求官帘,在某一個點來進行操作瞬雹。所謂的初始化就是這個驅(qū)動芯片的初始化,初始化中注意兩個地
方:
一個是復位刽虹!這個非常重要酗捌,如果沒有完全復位,可能導致屏幕不穩(wěn)定涌哲、顯示亂碼等畸形問題胖缤!
另一個就是初始化代碼!這個初始化代碼一般都是一些16進制數(shù)阀圾,可以在顯示屏的規(guī)格書之類的文檔里面找到哪廓,可以通過“寫命令”的方式能夠把初始化代碼發(fā)送給顯示屏。
完成了這些步驟初烘,就可以讓它顯示你想要的東西了涡真!
上代碼
//以下代碼中不包括字碼分俯,因為我的屏幕本身不帶字庫,所以需要用軟件提碼得到综膀,具體購買屏幕時一般會附帶提碼軟件
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?y3£
oledCmd((byte)0xc8);//Set COM/Row Scan Direction (byte)0xc0é???·′?? (byte)0xc8?y3£
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);
}
/*****************************清除屏幕顯示內(nèi)容************************************/
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驅(qū)動DHT11
因為之前有使用GPIO驅(qū)動繼電器工作的經(jīng)歷,繼電器接在3.3V正常工作讥此,接在5V下無法驅(qū)動拢锹。
在嘗試了驅(qū)動DHT11的時候很久一直沒有成功,起初以為跟最開始驅(qū)動繼電器的時候一樣萄喳,電壓問題卒稳,然后后來仔細核對代碼,查看時序圖他巨,發(fā)現(xiàn)在AndroidThings系統(tǒng)下讀取一次GPIO值耗時就在270us左右充坑,而dht11的時序圖中電平轉(zhuǎn)換時間都是在100us以下,所以在java下使用GPIO不能捕捉到如此短時間內(nèi)的電平變化染突,無法獲取到溫濕度值捻爷。
以下是代碼:
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();
}
}
}
}
}