2018年12月18日 星期二

android藍牙app的裝置搜尋與信號排序

搜尋藍牙的過程是一個非同步過程
因此需要用回呼函數來處理系統找到的藍牙裝置
以下程式是裝置搜尋回呼函數,每找到一項裝置就呼叫addDevice將資料加入裝置與信號強度的列表變數中
    private BluetoothAdapter.LeScanCallback mLeScanCallback =
    new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            addDevice(device, rssi);
                        }
                    });

                }
            });
        }
    };




但在addDevice程序中,裝置資料與rssi資料是分開存放在deviceList與devRssiValues這兩個列表中
因此為了讓顯示裝置列表的時候能夠根據信號強度排序
需要以下做法
1.先讓信號雜湊列表devRssiValues進行排序,雜湊格式是 Address:Value
2.然後雙迴圈先依序取出信號列表的位址值
3.再到裝置列表中找到該筆裝置資料
4.將裝置資料複製一份到列表的尾巴
5.刪除舊位置的裝置資料
等到信號列表中的資料跑過一遍之後,所有裝置列表的資料就會根據信號強度排序了

        // dahai: sort the deviceList
        devRssiValues = sortByComparator(devRssiValues, true);
//        Log.d("UUS-BLE:devRssiValues", devRssiValues.toString());
//        List tmpDeviceList = deviceList;
        for(Map.Entry entry : devRssiValues.entrySet()) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            for(int i=0; i<deviceList.size(); i++){
                if(deviceList.get(i).getAddress().equals(key)){
                    deviceList.add(deviceList.get(i));
                    deviceList.remove(i);
                }
            }

        }
        Log.d("UUS-BLE:deviceList", deviceList.toString());

2018年12月17日 星期一

android studio如果遇到app不能連線起動(Error while Installing APK),可能是這樣...

訊息如下:
Launching app
...
java.io.IOException: Connection reset by peer
Error while Installing APK

則可以到
Preference -> Build, Execution, Deployment -> Debugger -> Android Debug Bridge(ADB)
把 Use libusb backend取消
就可以連線了

這個方法是來自於這個啟示
https://stackoverflow.com/questions/42781934/android-error-while-installing-apks

內文提到
如果Android Studio有不能安裝app的情形則則需取消 Instant Run的功能
但我找不到相關設定,可能是因為版本更新的關係,因此我嘗試上述的方法就成功了

2018年11月14日 星期三

tinker board chromium壞掉記

解法在這裡
https://tinkerboarding.co.uk/forum/thread-1735-page-2.html

wget https://snapshot.debian.org/archive/debian-security/20180701T015633Z/pool/updates/main/c/chromium-browser/chromium_67.0.3396.87-1~deb9u1_armhf.deb
sudo dpkg -i chromium_67.0.3396.87-1~deb9u1_armhf.deb
sudo apt-mark hold chromium



2018年11月13日 星期二

chromium kiosk mode on raspberry pi

在樹莓派
使用者目錄下的這個檔案裡面放檔案路徑
就可以開機自動執行
~/.config/lxsession/LXDE-pi/autostart

裡面要自動執行的程式必須給絕對路徑

2018年10月7日 星期日

system workbench for STM32 一款基於eclipse的stm32整合開發環境,以及STM32CubeMX一款STM32系列程式碼產生器

STM32 CubeMX

System Workbench for STM32(SW4STM32)

下載與安裝都很無腦,到官網下載後就可以安裝。

CubeMX以點選功能的方式快速佈置微控器的功能
要記得要去設定Debug功能,否則到了SW4STM32要跑線上除錯的時候會找不到硬體
CubeMX產生程式碼之後會問是否要打開IDE,
在Win32平台,選擇確定會順利打開SW4STM32
在MacOS平台,無法找到,必須單獨打開SW4STM32然後把專案資料import進來

先按錘子編譯專案
再按瓢蟲進入除錯模式

第一次執行瓢蟲要做以下修改,硬體除錯模式才會正常運作
點選 Debug As -> 1 AC6 STM32 C/C++ Application

然後再點選 Debug Configurations...

到 Debugger 中 Configuration Script 區塊 將 generator options展開
將Reset Mode改為 Software system reset
這樣除錯功能才能正常

2018年9月25日 星期二

ghdl,一款開源的vhdl模擬器以及gtkwave,一款開源的波形觀察器,一個二位元全加法器的實作

參考來源:https://ghdl.readthedocs.io/en/latest/using/QuickStartGuide.html

先說載點:
ghdl:
https://ghdl.readthedocs.io/en/latest/getting/Releases.html
gtkwave:
https://sourceforge.net/projects/gtkwave/files/

然後根據ghdl的說明檔,先來實作一份加法器
ghdl quick start guide:
https://github.com/ghdl/ghdl/blob/master/doc/using/QuickStartGuide.rst#a-full-adder

步驟:
用文字編輯器撰寫vhdl
存檔並且副檔名為.vhd或是.vhdl
vhdl內的entity名稱不一定要與檔名一樣
先用ghdl -a [vhdl檔]
再用ghdl -e [entity名稱] ,elaborate這個entity但我不知道什麼是elaborate
最後ghdl -r [entity名稱],跑這個vhdl,但是如果直接跑會沒有結果產生
因此需要製作testbench,testbench也是一段vhdl程式,他與一班vhdl差別在沒有port,是用來產生輸入信號以及檢查輸出是否為預期

重點:
vhdl檔案必須依照階層關係依序編譯,否則會造成頂端vhdl無法正確解譯

先用文字編輯器把下列程式存檔,檔名為「adder.vhdl」

entity adder is
  -- `i0`, `i1`, and the carry-in `ci` are inputs of the adder.
  -- `s` is the sum output, `co` is the carry-out.
  port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
end adder;

architecture rtl of adder is
begin
  --  This full-adder architecture contains two concurrent assignments.
  --  Compute the sum.
  s <= i0 xor i1 xor ci;
  --  Compute the carry.
  co <= (i0 and i1) or (i0 and ci) or (i1 and ci);
end rtl;

接著把下列測試檔存檔,檔名為「adder_tb.vhdl」

--  A testbench has no ports.
entity adder_tb is
end adder_tb;

architecture behav of adder_tb is
  --  Declaration of the component that will be instantiated.
  component adder
    port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
  end component;

  --  Specifies which entity is bound with the component.
  for adder_0: adder use entity work.adder;
  signal i0, i1, ci, s, co : bit;
begin
  --  Component instantiation.
  adder_0: adder port map (i0 => i0, i1 => i1, ci => ci,
                           s => s, co => co);

  --  This process does the real job.
  process
    type pattern_type is record
      --  The inputs of the adder.
      i0, i1, ci : bit;
      --  The expected outputs of the adder.
      s, co : bit;
    end record;
    --  The patterns to apply.
    type pattern_array is array (natural range <>) of pattern_type;
    constant patterns : pattern_array :=
      (('0', '0', '0', '0', '0'),
       ('0', '0', '1', '1', '0'),
       ('0', '1', '0', '1', '0'),
       ('0', '1', '1', '0', '1'),
       ('1', '0', '0', '1', '0'),
       ('1', '0', '1', '0', '1'),
       ('1', '1', '0', '0', '1'),
       ('1', '1', '1', '1', '1'));
  begin
    --  Check each pattern.
    for i in patterns'range loop
      --  Set the inputs.
      i0 <= patterns(i).i0;
      i1 <= patterns(i).i1;
      ci <= patterns(i).ci;
      --  Wait for the results.
      wait for 1 ns;
      --  Check the outputs.
      assert s = patterns(i).s
        report "bad sum value" severity error;
      assert co = patterns(i).co
        report "bad carry out value" severity error;
    end loop;
    assert false report "end of test" severity note;
    --  Wait forever; this will finish the simulation.
    wait;
  end process;
end behav;

先用
ghdl -a adder.vhdl

再用
ghdl -a adder_tb.vhdl
ghdl -e adder_tb

最後
ghdl -r adder_tb --vcd=adder.vcd

結果會在檔案所在資料夾中看到一個名為adder.vcd的檔案,點開來會自動啟動gtkwave
看到以下畫面:




先在左上的adder_0點一下,接著到左下幾個reg ...都點兩下,結果會在右側波形視窗出現綠線



接著用放大鏡-,一直按一直按,隨著時間刻度慢慢放大,大概到ns間距時,波形開始出現





2018年8月22日 星期三

LED蠟燭實驗

網路這幾天流傳一則影片,有人用Arudino連接一顆0402的SMD LED,然後對著點亮的LED吹氣,最後竟然可以吹熄,過一會又亮起來,如此反覆操作著。
這個作者也在instructables.com上面發表做法,甚至在Arduino官網上也有上頭條,這麼有趣的專題,我也來跟風做做看。

矽二極體每升高一度C,則障壁電壓會下降2.5mV

這是電子學課本一開始就會教的知識,如今可以用在這個小專題上,這個專題利用微小封裝的LED,使得該LED內的二極體接面能夠快速感受到溫度的變化,利用點亮LED時產生的溫度升高與吹氣時帶走溫度這兩者之間的溫差,預計可以獲得一個明顯的障蔽電壓電壓變化,然後搭配Arduino內的ADC將二極體的障壁電壓讀取出來,接著用軟體模擬蠟燭點亮與吹熄的效果。

首先接一個簡單可以點亮發光二極體的電路,一個有限流電阻的發光二極體迴路,發光二極體在迴路中的低側,如此就可以從發光二極體的陽極拉出導線量測電壓。電壓變化如此的小,除了在硬體電路上加以改進外,是否還有其他解法能得知這個微弱變化呢?

為了解決在電壓量測的軟體技巧上使用了累加法,將微小的電壓變化放大出來。當直接讀取單次的ADC數值時,只有看到個位數在跳動,但完全無法得知目前微弱電壓的數值,但是這個跳動的個位數本身就隱含著微弱電壓的訊息,於是我們只要每次讀取固定數量且大量的數據累加起來,就可以將這個隱含的訊息予以放大。這個過程有點像是累進誤差這個概念的反義應用,本來累進誤差是我們不要的,但是如果逆向思考則成為有效的工具。另外,這裡也有另一層意義需要思考,就是單筆ADC數值上的個位數跳動與累加之後產生了明顯的差別,非常貼切地驗證了「見樹不見林」這句話。在解決問題之前我們通常要先觀察問題,而觀察問題的時候則是是需要不斷改變高度甚至是維度,這時候就要依賴數學課教我們的那一堆數學工具來觀察了。