2016年2月4日 星期四

use raspberry for voice control

  建議先看一下  http://makezine.com/projects/use-raspberry-pi-for-voice-control/
 
   我的平台是  RPI 2

   OS :     2015-05-05-raspbian-wheezy

   插入買的usb audio device.....

    我是買這一款的

   


      然後check 一下你的usb audio裝置有沒有抓到...


                      cat /proc/asound/cards



    可以看到

        或是輸入  aplay -l  也可以得到一樣的資訊



   可以看到  card 1 :   usb PnP Sound Device....


    安裝一下  alsa 的套件  (Advanced Linux Sound Architecture)

    sudo apt-get install alsa-base alsa-utils

     輸入     alsamixer  可以調整音量

    sudo vi /usr/share/alsa/alsa.conf

       sudo vi   .asoundrc
       
    加入這一行

     pcm.!default sysdefault:Device


       
 
 
          測試一下你的設定有沒有成功.....錄製一下聲音試試

         arecord -vv --duration=7 -fdat ~/test.wav

    或是 播放已經有的wave file

    aplay /usr/share/sounds/alsa/Front_Center.wav


        沒問題之後.....

       安裝其他的套件

        sudo apt-get install libasound2-dev autoconf libtool bison \
swig python-dev python-pyaudio
   
      install    python-pip  tool
   
      curl -O https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
sudo pip install gevent grequests

     安裝  screen  (could save yourself  some heartache)

      sudo apt-get install screen
screen -DR sphinx
      接下來是重頭戲了

      install  SPHINX  

       git clone git://github.com/cmusphinx/sphinxbase.git
cd sphinxbase
git checkout 3b34d87
./autogen.sh
sudo make -j4
    sudo make install

   cd ..

   install  PocketSphinx  

    git clone git://github.com/cmusphinx/pocketsphinx.git
cd pocketsphinx
git checkout 4e4e607
./autogen.sh
sudo make -j4

  sudo make install

cd ..

   update your new library on your system

    sudo ldconfig

    run test

    pocketsphinx_continuous -inmic yes
 
   如果有看到下面的訊息...就代表成功
INFO: ngram_search.c(874): bestpath 0.10 CPU 0.071 xRT
INFO: ngram_search.c(877): bestpath 0.11 wall 0.078 xRT
what
READY....
   INFO: ngram_search.c(874): bestpath 0.10 CPU 0.071 xRT
INFO: ngram_search.c(877): bestpath 0.11 wall 0.078 xRT
what
READY....

 

接下來就是   control all the thing



  先來run 一個已經寫好的範例

    git clone https://github.com/bynds/makevoicedemo
cd makevoicedemo
python main.py

    他的程式會停在 need more input:

   這時候我就說  Turn on the kitchen Light....

   他就秀出來了  

 

   這樣其實代表是辨識成功....

    接下來要動手打造自己的例子....

     要使用  PocketSphix  ..需要三個元素

    1.   dictionary
    2.   grammar file
    3.   init decoder

    step  1 :  dictionry...
                先用編輯器編輯  corpus.txt
                  以他的例子是下面的內容...你也可以改成你自己的...
        
turn on the kitchen light
turn off the kitchen light
turn on the bedroom light
turn off the bedroom light
turn on the roomba
turn off the roomba
roomba clean
roomba go home

接下來要把他上傳到網站...  

  用  web browser ....輸入   http://www.speech.cs.cmu.edu/tools/lmtool-new.html

  網站的畫面如下:


點選左下角的  選擇檔案....  upload your  corpus.txt 

接著按下   Compile Knowledge Base

 然後就會跳轉到下面這個頁面


選擇down    *.tgz.....  以我的例子為言是  TAR0304.tgz

wget http://www.speech.cs.cmu.edu/tools/product/1454753396_20565/TAR0304.tgz

tar -xvf TAR0304.tgz

step  2 :  grammar file...

以他的例子......  grammar.jsgf

#JSGF V1.0;
grammar commands;

<action> = TURN ON      |
        TURN OFF        ;

<object> = KITCHEN LIGHT|
        BEDROOM LIGHT   |
        ROOMBA          ;

public <command> = <action> THE <object> |
                ROOMBA CLEAN             |
                ROOMBA GO HOME           ;

  其實你可以改在 最後....  例如

public <command> = <action> THE <object> |
                ROOMBA CLEAN             |
                LEFT                                    |
                 RIGHT                                |
                ROOMBA GO HOME           ;

step 3 : init decoder
修改  pocket_sphinx_listener.py

self.hmm = 'cmusphinx-5prealpha-en-us-ptm-2.0/'
self.dic = 'dictionary.dic' self.lm = 'language_model.lm' self.grammar = 'grammar.jsgf'
  
改成你剛剛解壓縮完的檔案....副檔名一樣....主檔名不一樣


接下來就是修改他的例子....  main.py

裡面的  hue 和 roomba 和 configuration和 insteon 都不需要....只留 gevent....這個是為了 停留 1秒


然後把裡面的 roomba和  configuration 和 insteon 相關的code 都delete.....

直接看到  run_main 這個函式

def runMain():
 
    # Now we set up the voice recognition using Pocketsphinx from CMU Sphinx.
    pocketSphinxListener = PocketSphinxListener()

    
    while True:
        
  try:
            command = pocketSphinxListener.getCommand().lower()
             if command.startswith('turn'):
                       do_turn_action().....

看到這邊就知道....  command其實就是辨識出來的字串....

 接下來你就是拿它來做判斷...去執行相對應的動作就可以了....






Reference : http://makezine.com/projects/use-rasp
berry-pi-for-voice-control/

use usb2ttl to control raspberry or arduino



參考文章是用  raspberry 和 arduino  來做實驗


先從 raspberry 傳送到  arduino

在 arduino 

.寫程式如下 : (可以參考  File->Examples->01.Basics->Blink. )

const int ledPin = 13;

void setup(){
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop(){
  if (Serial.available())  {
     blink(Serial.read() - '0');  // convert the character '1'-'9' to decimal 1-9
  }
  delay(500);
}

void blink(int numberOfTimes){
  for (int i = 0; i < numberOfTimes; i++)  {
    digitalWrite(ledPin, HIGH);
    delay(100);
    digitalWrite(ledPin, LOW);
    delay(100);
  }
}

最主要就是使用  Serial 這個物件

void Serial.begin (9600)  ->  鲍率 9600
bool Serial.available() -> check serial 有沒有message
int Serial.read()      -> 傳回接收到的數字


在Raspberry

use python

sudo vi main.py

#!/usr/bin/python

import serial
ser = serial.Serial('/dev/ttyACM0', 9600)
ser.write('3')

大概就是RPI 傳送  3 出去....



從 arduino 傳送到  raspberry

在 arduino 

void setup(){
  Serial.begin(9600);
}

void loop(){
  Serial.println("Hello, World!");
  delay(1000);
}

多了一個function    :  Serial.println("Hello, World!");

在 raspberry


import serial
ser = serial.Serial('/dev/ttyACM0', 9600)
while 1 :
    ser.readline()</span>

多了一個function    serial .readline()  

執行的結果如下:

'Hello, World!\r\n'
'Hello, World!\r\n'
'Hello, World!\r\n'
...

不過我目前沒有arduino....所以我會用兩個RPI來互相傳送資料試試...



Reference : http://www.seeedstudio.com/recipe/166-basic-pi-lt-gt-arduino-communication-over-usb.html

parse server install on raspberry



按照下面的流程做....

目前遇到的問題如下:


Q1:
node 的版本太舊....須更新 到  v4.1以上


https://nodejs.org/dist/v4.1.2/node-v4.1.2.tar.gz
As advice on ubuntu community on installing the tar.gz the following steps are followed.
$ ./configure
$ make -j4
$ [sudo] make install

然後這邊須注意你的gcc 和 g++.... 如果是4.6.3 版以下...會有compile error

/deps/v8/src/base/platform/mutex.h:36:13: error: variable ‘v8::base::Mutex v8::base::final’ has initializer but incomplete type

須更新到 gcc & g++ 4.8以上

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get install gcc-4.8 g++-4.8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50


Q2:  執行到  npm i parse-server --save 這步....

        有compile error message :   ../lib/kerberos.h:5:27: fatal error: gssapi/gssapi.h: No such file or directory

查了一下google ...

sudo apt-get install libkrb5-dev

然後再執行一次  npm i parse-server --save




Reference : https://github.com/jollen/blog/issues/10

Reference : http://www.appcoda.com.tw/instagram-app-parse-swift/

Reference : http://www.inside.com.tw/2011/03/13/new-tech-nodejs

usb2TTL PL2303 詳細研究



這顆IC 可以把USB 轉成 RS232/RS485等等....

他是採用usb bulk mode...

支援的data format 如下:



看完了datasheet之後...找不到register table.......

不過沒關係...就直接從 linux driver code下手來分析....


首先來看 pl2303_device 這個變數....他會跟linux kernel 註冊function 的進入點...
static struct usb_serial_driver pl2303_device = {
         .driver = {
                 .owner =        THIS_MODULE,
                 .name =         "pl2303",
         },
         .id_table =             id_table,
         .num_ports =            1,
         .bulk_in_size =         256,
         .bulk_out_size =        256,
         .open =                 pl2303_open,
         .close =                pl2303_close,
         .dtr_rts =              pl2303_dtr_rts,
         .carrier_raised =       pl2303_carrier_raised,
         .ioctl =                pl2303_ioctl,
         .break_ctl =            pl2303_break_ctl,
         .set_termios =          pl2303_set_termios,
         .tiocmget =             pl2303_tiocmget,
         .tiocmset =             pl2303_tiocmset,
         .tiocmiwait =           usb_serial_generic_tiocmiwait,
         .process_read_urb =     pl2303_process_read_urb,
         .read_int_callback =    pl2303_read_int_callback,
         .probe =                pl2303_probe,
         .attach =               pl2303_startup,
         .release =              pl2303_release,
         .port_probe =           pl2303_port_probe,
         .port_remove =          pl2303_port_remove,
 };

接下來看  pl2303_open 這個function


Setup termios

static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
         struct usb_serial *serial = port->serial;
         struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
         int result;
 
         if (spriv->quirks & PL2303_QUIRK_LEGACY) {
                 usb_clear_halt(serial->dev, port->write_urb->pipe);
                 usb_clear_halt(serial->dev, port->read_urb->pipe);
         } else {
                 /* reset upstream data pipes */
                 pl2303_vendor_write(serial, 8, 0);
                 pl2303_vendor_write(serial, 9, 0);
         }
 
         /* Setup termios */
         if (tty)
                 pl2303_set_termios(tty, port, NULL);
 
         result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
         if (result) {
                 dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
                         result);
                 return result;
         }
 
         result = usb_serial_generic_open(tty, port);
         if (result) {
                 usb_kill_urb(port->interrupt_in_urb);
                 return result;
         }
 
         return 0;
 }



Reference : PL2303_datasheet

Reference : pl2303_linux_code