2023年2月10日 星期五

Android Studio - Aneng AN9002 藍牙低功耗(BLE)手機程式(一百零四)

Android Studio - Aneng AN9002 藍牙低功耗(BLE)手機程式(一百零四):

筆者終於用手機成功讀取 Aneng AN9002 藍牙數字萬用錶(Bluetooth Digital Multimeter / DMM)資料,並顯示讀取到 AN9002 的數據,初版程式是非常簡單,暫未能完備所有原廠的 APK 功能,但程式是可以升級,將來還可以加入不同的功能,而且還學習了不少新的知識,特別是 Samsung Galaxy M33 5G 手機,因為是 Android 12(Snow Cone / 2021)版本,很多新的功能和限制都要適應,也碰到很多挫折,最終都能夠解決,這就是最大的得著!

Aneng AN9002 藍牙低功耗(BLE)手機程式 APK
  • 操作系統:Windows 7 64-bit 版本
  • 開發環境:Android Studio 4.0.1 版本
  • 測試手機:Samsung Galaxy M33 5G
  • 測試手機系統版本:Android 12(Snow Cone / 2021)
  • 原程式:C:\Development\Development_Android\Android_Project\DIY-Android-121-17 BLEDMM bugworkshop AN9002 20230123
  • 程式:C:\Development\Development_Android\Android_Project\DIY-Android-121-17 BLEDMM bugworkshop AN9002 20230123

藍牙低功耗(BLE)掃描編程步驟:
  • 開啟藍牙啟用權,掃描藍牙設備,連接 Aneng AN9002 藍牙數字萬用錶 Device Address。
  • 接收 Aneng AN9002 藍牙數字萬用錶傳送的 11字節(11Byte)資料。
  • 解讀 11字節(11Byte)資料。
  • 顯示解讀 Aneng AN9002 藍牙數字萬用錶的讀數。

DMMActivity.java - Decode Reading Data:

    private static int[] hexInt = {0x41,0x21,0x73,0x55,0xA2,0xC1,0x32,0x71,0x66,0xAA,0x3B} ;

    private static int[] hexROR = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15} ;

    public static String Int2ArrayToDMM(byte[] byteArray) {

        s_MeterValue = "";

        s_MeterRaw ="";

        int y0 = 0;

        int y1 = 0;

        int sData_MSB =0;

        int sData_LSB =0;

        int sData = 0;

        int[] segDigit = {0,0,0,0,0,0,0,0,0,0,0,0};

        int[] funDigit = {0,0,0,0,0,0,0,0,0,0,0,0};

        for (int x=0; x < byteArray.length; x++) {

            y0 =  byteArray[x] & 0xFF ;

            y1 =  hexInt[x] & 0xFF ;

            int aData = (y0 ^ y1)  ;

            sData_MSB =(hexROR[aData & 0x0F]) <<4 ;

            if (x>3) {

                int segData_LSB = hexROR[aData & 0x0F];

                int segData_MSB = sData_LSB << 4;

                sData = segData_MSB + segData_LSB;

                segDigit[x] = sData;

                if (x > 3 && x < 8) {

                    if (x==4 && sData > 127) sData = sData & 0x7F;  // The first Segment without .

                    s_MeterValue = s_MeterValue + digitDMM(sData);

                }            }

            sData_LSB =hexROR[(aData & 0xF0)>>4] ;

            sData = sData_MSB + sData_LSB;

            funDigit[x] = sData;

            s_MeterRaw = s_MeterRaw + (String.format("%02X", y0)) + " ";

        }

        functionDMM(segDigit);

        String gethex = hex5.toString();

        return gethex;

    }


DMMActivity.java - Decode Reading Data:

    private static int[] hexInt = {0x41,0x21,0x73,0x55,0xA2,0xC1,0x32,0x71,0x66,0xAA,0x3B} ;

    private static int[] hexROR = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15} ;

    private static void functionDMM(int[] ai_DMM) {

        s_MeterOpt="";

        s_MeterPre="";

        s_MeterUnit="";

        if((ai_DMM[8] & 0x80) > 0) { s_MeterOpt+="Hold ";    }

        if((ai_DMM[8] & 0x08) > 0) { s_MeterOpt+="MAX ";    }

        if((ai_DMM[8] & 0x04) > 0) { s_MeterOpt+="MIN ";    }

        if((ai_DMM[10] & 0x08) > 0) { s_MeterOpt+="AUTO ";    }

        if((ai_DMM[9] & 0x01) > 0) { s_MeterPre+="M";    }

        if((ai_DMM[9] & 0x02) > 0) { s_MeterPre+="k";    }

        if((ai_DMM[9] & 0x04) > 0) {s_MeterUnit+="Ω";     s_MeterType="Resistance"; return;  }

        if((ai_DMM[8] & 0x40) > 0){s_MeterUnit+="Fahrenheit"; s_MeterPre+="°F";s_MeterType="Temperature"; return;  }

        if((ai_DMM[8] & 0x20) > 0){s_MeterUnit+="Celsius";    s_MeterPre+="°C";s_MeterType="Temperature"; return; }

        if((ai_DMM[9] & 0x08) > 0){s_MeterUnit+="Hertz";      s_MeterPre+="Hz";s_MeterType="Frequency"; return;  }

        if((ai_DMM[9] & 0x90) > 0){s_MeterUnit+="Faraday";    s_MeterPre+="nF"; s_MeterType="Capacitance"; return;  }

        if((ai_DMM[8] & 0x02) > 0){s_MeterUnit+="%";          s_MeterPre+="%"; s_MeterType="Pencentage"; return;  }

        if((ai_DMM[8] & 0x10) > 0){s_MeterUnit+="Diode";      s_MeterType="Diode"; return;  }

        if(ai_DMM[8] == 0)        { s_MeterUnit+="DC";   }

        if((ai_DMM[8] & 0x01) > 0){ s_MeterUnit="AC RMS";    }

        if((ai_DMM[10] & 0x02) > 0){ s_MeterPre += "μA"; return;}

        if((ai_DMM[10] & 0x01) > 0){ s_MeterPre += "mA"; return;}

        if((ai_DMM[10] & 0x10) > 0){ s_MeterPre += "A"; return;}

        int a = ai_DMM[10]>>1;

        if((ai_DMM[10] & 0x80) > 0) {

            if ((ai_DMM[10] & 0x40) > 0) {

                s_MeterPre = "mV";

                return;

            } else

            if((ai_DMM[10]  & 0x80) > 0)  { s_MeterPre = "V";}

        }

    }

    private static String digitDMM(int dig) {

        String s_DMM ="";

        if(dig>127){s_DMM=".";}

        int d7 = dig & 0x7F;

        if(d7==0)   { return s_DMM+"";}

        if(d7==0x7d){ return s_DMM+"0";}

        if(d7==0x05){ return s_DMM+"1";}

        if(d7==0x5b){ return s_DMM+"2";}

        if(d7==0x1f){ return s_DMM+"3";}

        if(d7==0x27){ return s_DMM+"4";}

        if(d7==0x3e){ return s_DMM+"5";}

        if(d7==0x7e){ return s_DMM+"6";}

        if(d7==0x15){ return s_DMM+"7";}

        if(d7==0x7f){ return s_DMM+"8";}

        if(d7==0x3f){ return s_DMM+"9";}

        if(d7==0x77){ return s_DMM+"A";}

        if(d7==0x4c){ return s_DMM+"u";}

        if(d7==0x6a){ return s_DMM+"t";}

        if(d7==0x4e){ return s_DMM+"o";}

        if(d7==0x68){ return s_DMM+"L";}

        return "";

    }


2023年 2月 10日(Fri)天氣報告
氣溫:45.0°F / 7.0°C @ 07:00
風速:每小時 14公里
降雨機會:3%
相對濕度:百分之 85%
天氣:多雲時陰

2023年2月9日 星期四

Android Studio - Aneng AN9002 藍牙低功耗(BLE)LCD 屏資料(一百零三)

Android Studio - Aneng AN9002 藍牙低功耗(BLE)LCD 屏資料(一百零三):

Aneng AN9002 藍牙數字萬用錶(Bluetooth Digital Multimeter / DMM)連接後,Aneng AN9002 藍牙數字萬用錶便會發送 11字節(11Byte)資料,問題是這11字節資料是代表什麼?如何將資料解讀成為有意思的資料,在網上找尋資料和做了實驗,原來是代表 LCD 屏的每 1個顯示的數據,所以首先要有 Aneng AN9002 的 LCD 屏的顯示資料,了解發送資料的結構。

Aneng AN9002 藍牙低功耗 LCD 屏
Aneng AN9002 藍牙低功耗 LCD 屏的顯示資料:

Item

顯示資料

數據

功能顯示

HOLDMAXMINDiodeBuzzer%、℃、℉、Mk、Ω、Hznm、μ、FBT、△、▃、DCACBatteryTRUE RMSAUTOMANUALm、μ、AmV

30數據(30bits

數字顯示

4x7Segment + 3xDecimal Point

31數據(31bits

總數:

 

62數據(61bits


Aneng AN9002 藍牙數字萬用錶資料例子:
手機接收了 Aneng AN9002 藍牙數字萬用錶傳送來的 11字節(Byte)資料,資料是 1B 84 70 B1 49 CA D8 36 66 AA 3B,11字節(Byte)資料會 OR 資料鍵,得到新資料需要將右轉(03=00000011→C0=11000000 / E4=11100100→27=00100111),然後將 Byte3 到 Byte10 從新組合(Byte3_LSB+Byte4_MSB 組合成新的 Byte),將新組合 Byte 對應出顯示的數字,也將 Byte8 到 Byte10 的數據對應出顯示的功能(20=°C),那麼藍牙數字萬用錶的讀數便是 0016°C。

Aneng AN9002 藍牙低功耗 LCD 屏的顯示資料:

Item

顯示資料

數據

Byte

0  1   2  3  4  5  6   7  8  9  10

11Byte

y0

1B 84 70 B1 49 CA D8 36 66 AA 3B

Raw data = y0

y1

41 21 73 55 A2 C1 32 71 66 AA 3B

Raw Data Key = y1

aData

5A A5 03 E4 EB 0B EA 47 00 00 00

aData=(y0 ^ y1)

sData

5A A5 C0 27 D7 D0 57 E2 00 00 00

sData=RoR

Shift Byte 3

5A A5 C0 2 7D 7D 05 7E 20 00 00 0

Byte3_LSB+Byte4_MSB ~ Byte9_LSB+Byte10_MSB

7-Segment Data

            7D 7D 05 7E 20 00 00

7D=0

7D=0

05=1

7E=6

 

0016°C

20=°C


Aneng AN9002 藍牙低功耗 LCD 屏的功能顯示資料數據:

Function

Byte 8

Byte 9

Byte 10

Byte 8

Byte 9

Byte 10

Auto DC V

0

0

0

0

A

8

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

1 0 1 0

1 0 0 0

Auto AC V RMS

0

1

0

0

8

8

0 0 0 0

0 0 0 1

0 0 0 0

0 0 0 0

1 0 0 0

1 0 0 0

Auto DC mV

0

0

0

0

E

8

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

1 1 1 0

1 0 0 0

Auto AC mV RMS

0

1

0

0

C

8

0 0 0 0

0 0 0 1

0 0 0 0

0 0 0 0

1 1 0 0

1 0 0 0

°C

2

0

0

0

0

0

0 0 1 0

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

°F

4

0

0

0

0

0

0 1 0 0

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

Auto Ω

0

0

0

4

0

8

0 0 0 0

0 0 0 0

0 0 0 0

0 1 0 0

0 0 0 0

1 0 0 0

Auto nF

0

0

9

0

0

8

0 0 0 0

0 0 0 0

1 0 0 1

0 0 0 0

0 0 0 0

1 0 0 0

Auto Hz

0

0

0

8

0

8

0 0 0 0

0 0 0 0

0 0 0 0

1 0 0 0

0 0 0 0

1 0 0 0

Auto DC A

0

0

0

0

3

8

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

0 0 1 1

1 0 0 0

Auto AC A RMS

0

1

0

0

1

8

0 0 0 0

0 0 0 1

0 0 0 0

0 0 0 0

0 0 0 1

1 0 0 0

Auto DC mA

0

0

0

0

3

9

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

0 0 1 1

1 0 0 1

Auto AC mA RMS

0

1

0

0

1

9

0 0 0 0

0 0 0 1

0 0 0 0

0 0 0 0

0 0 0 1

1 0 0 1

Auto DC uA

0

0

0

0

3

A

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

0 0 1 1

1 0 1 0

Auto AC uA RMS

1

0

0

0

1

A

0 0 0 1

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 1

1 0 1 0

Diode

1

0

0

0

8

0

0 0 0 1

0 0 0 0

0 0 0 0

0 0 0 0

1 0 0 0

0 0 0 0

MAX

0

9

0

0

1

2

0 0 0 0

1 0 0 1

0 0 0 0

0 0 0 0

0 0 0 1

0 0 1 0

MIN

0

5

0

0

1

2

0 0 0 0

0 1 0 1

0 0 0 0

0 0 0 0

0 0 0 1

0 0 1 0

NO Auto

0

1

0

0

1

1

0 0 0 0

0 0 0 1

0 0 0 0

0 0 0 0

0 0 0 1

0 0 0 1

Auto

0

1

0

0

1

9

0 0 0 0

0 0 0 1

0 0 0 0

0 0 0 0

0 0 0 1

1 0 0 1

Ω

0

0

0

4

0

8

0 0 0 0

0 0 0 0

0 0 0 0

0 1 0 0

0 0 0 0

1 0 0 0

0

0

0

5

0

8

0 0 0 0

0 0 0 0

0 0 0 0

0 1 0 1

0 0 0 0

1 0 0 0

0

0

0

6

0

8

0 0 0 0

0 0 0 0

0 0 0 0

0 1 1 0

0 0 0 0

1 0 0 0

%

0

2

0

0

0

0

0 0 0 0

0 0 1 0

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

O.L MΩ

0

0

0

5

0

8

0 0 0 0

0 0 0 0

0 0 0 0

0 1 0 1

0 0 0 0

1 0 0 0


2023年 2月 9日(Thu)天氣報告
氣溫:42.0°F / 6.0°C @ 07:00
風速:每小時 0公里
降雨機會:69%
相對濕度:百分之 79%
天氣:多雲