2015年7月9日 星期四

[炊] Risotto, 香菇燉飯初體驗

第一次做燉飯,還蠻好吃的XDD 實作的對像是風味燉飯&絕品濃湯書中的夏季松露野菇燉飯(Mushroom risotto with truffle)。 不過當然沒有那麼多高級材料拉~ 用的都是全聯福利中心可以買到的食材。



另外我用的是一般有蓋子的湯鍋(導熱慢一點米比較不會太快焦掉),紀錄一下過程跟心得摟~

材料

食材

  • 台梗九號米 兩人份 (大約100g 左右)
  • 洋蔥 切丁 一小碗 (大約 10~15g)
  • 蘑菇 切片 3~5 朵 
  • 紅禧菇 去蒂頭 2 朵 (總共約 55g)
  • 新鮮香菇 4 朵 
  • 香菇乾 5 朵 (泡熱水後切片,熱水不要倒掉)

原本食譜上是放牛乾菌菇 5g ,不過這種珍貴的食材不知道哪裡買@@ 所以我用乾貨香菇來替代。

調味


  • 奶油 30g (大約 1/3 條)
  • 鹽巴跟胡椒 少許
  • 起司粉 少許 (書上用乾酪)
  • 雞高湯 300 ml

步驟

1. 潤鍋,中火炒洋蔥至香,加入奶油跟香菇
所謂潤鍋是先用橄欖油把鍋子潤一遍,以免接下來炒食物 & 飯的時候沾鍋。我潤鍋後就加入洋蔥了,等洋蔥炒的差不多時,灑上胡椒,再放入一塊奶油。(食譜上是用無鹽奶油,出於懶惰,我用有鹽的就不再調味了) 等奶油溶化的差不多的時候放入所有香菇。

2. 加入米,拌炒至半透明,再分次加入高湯等待慢慢收汁
生的米還滿快就炒好了,由於米很容易黏在鍋子上,要一直翻炒才行。先加一點高湯,大約加到整個鍋底是溼的(不會黏住米飯即可)。選用台梗九號米是因為書中推荐這種米比較可以耐久翻炒。

3. 加入洗香菇的水,拌炒
香菇水的氣味滿香,對口感滿重要的。雞高湯大約準備 300 ml,每次加入大約 50 ml 總共加入 6 次,慢慢讓米飯收汁,一邊觀察黏度,不要太稀也小心黏在鍋子上焦掉。另外可以交替加入高湯與香菇水。

 4. 不斷試吃,等到適當口感後蓋鍋蓋轉小火,悶煮約3分鐘後,加入胡椒與起司粉,拌勻即可

2014年7月2日 星期三

Desktop Manipulator

Erick and I cooperated and did it in this semester.
We make it from scratch. Erick deal with mechanism design and manufacturing and Im in charge of control.
Our design procedure is followed this flow chart.


Erick cares so many details. One thing we may encounter is that the linkage is quadratic loop equation. When we solve it, two solution will come out that can cause link crossover situation.

Zoom in and see what assembly in detail.







First time test video



2014年6月26日 星期四

Mechanical Experiment Improvement

有幸為母校成大機械系設計一堂機械工程實驗課程 (還有幸今天可以打中文XD)

這堂課的設計目標是因為目前開源硬體非常流行(像是Arduino、Raspberry Pi),售價不斷下降時效能卻大幅提升。我想利用Open-Source的軟體硬體,製作在機械工程中非常重要的PID控制器。


上課的流程是這樣的

在硬體方面,系統架構如下
(實作時的紀錄可以參考: 之前)

最後冠冕堂晃的說


在這堂課程的基礎上,日後可以設計小型的Term Project,利用PID控制馬達來達成應用,像是倒單擺的實踐或是輪型機器人的精準控制等等。


本實驗的核心精神在於利用開源的軟體以及硬體,來實作課程中學到的理論,並且解決其中的問題,讓課堂的學習以及實驗課的操作相輔相成,訓練出實作與理論兼具的機械工程師。




2014年6月23日 星期一

Dillon - Thirteen Thirtyfive

Pretty like this song




Strongest taste
loudest drop
head is filled
the thought, unlocked

you'd be thirteen
i'd be thirty-five
gone to find a place for us to hide


be together but alone
as the need for it has grown

a cave or a shed
a car or a bed
a hole in the ground
or a burial mound
a bush or a tree
or the aegean sea will do for me

for you i found a vent
in the bottom of a coal mine
just enough space for your hands in the inside

if you go
do let me know

a den or a dessert
perhaps an ink squirt
a cellar, a wishing well, a war
or a guarantee will do for me

for you i found a cell
on the top floor of a prison
just enough space for you to fit your feet in

if you go
please let me know

2014年6月22日 星期日

New Toy - PX4FLOW

I just received the notice that my toy arrived! It is PX4FLOW, you can find more information here: https://pixhawk.org/modules/px4flow

It is highly sensor-integrated device. The device fused optical flow CMOS camera, sonar sensor and gyro.

Besides, its CPU is STM32F4 which I have some experience about this Cortex M4 core. I want to implement some algorithm on it achieving visual odometry.

Test it on qGrouncontrol-pixhawk


ps. PX4FLOW can be bought here: http://goods.ruten.com.tw/item/show?21405213979317

2014年6月20日 星期五

PID Performance Indices

When writing the PID Lab program, I need some indices for evaluate the controller.
There are three useful values:                                                    
  • Rise Time: time duration from 10% to 90% of final value
  • Settling Time: time to approach the final value (within the error band)
  • Time Constant: when output value approaches 63.2% of desired value



It seems Settling time is a good index using in this case because it's not only can estimate the performance but be a stop condition.

But I encounter a strange phenomenon that sometimes it soon to complete controlling and sometimes not. (about 4-1) And the first run is the longest and is prone to find steady state error.

BBB Serial Debug

Just a quick Note
  • J1 = GND (Ground)
  • J2 = CTS
  • J3 = VCC (5V)
  • J4 = RXD (Receive Data)
  • J5 = TXD (Transmit Data)
  • J6 = RTS
And its pin map

2014年6月19日 星期四

Compiling uROSnode

uROSnode
We can find it on Github: https://github.com/openrobots-dev/uROSnode
It is a great work for MCU can run ROS.
https://dl.dropboxusercontent.com/u/2771793/uros/doc/html/pag_demos.html
One great explainition about this project: pdf
ROSCon: http://vimeo.com/66970254

Problem 1:
Compiling ./src/urosUser.c
In file included from ../../include/urosUser.h:45:0,
                 from ./src/urosUser.c:42:
./src/urosUser.c: In function 'urosUserParamUpdate':
./src/urosUser.c:353:21: error: 'UrosRpcParam' has no member named 'class'
     urosError(paramp->class != UROS_RPCP_INT, return UROS_ERR_BADPARAM,
                     ^
../../include/urosBase.h:323:50: note: in definition of macro 'urosError'
 #  define urosError(when, action, msgargs) { if (when) { action; } }
                                                  ^
./src/urosUser.c:368:21: error: 'UrosRpcParam' has no member named 'class'
     urosError(paramp->class != UROS_RPCP_INT, return UROS_ERR_BADPARAM,
                     ^
../../include/urosBase.h:323:50: note: in definition of macro 'urosError'
 #  define urosError(when, action, msgargs) { if (when) { action; } }
                                                  ^
./src/urosUser.c:383:21: error: 'UrosRpcParam' has no member named 'class'
     urosError(paramp->class != UROS_RPCP_INT, return UROS_ERR_BADPARAM,
                     ^
../../include/urosBase.h:323:50: note: in definition of macro 'urosError'
 #  define urosError(when, action, msgargs) { if (when) { action; } }
                                                  ^
make: *** [build/obj/urosUser.o] Error 1
Fix:
Find the struct in uROSnode/include/urosRpcCall.h

typedef struct UrosRpcParam {

  uros_rpcparamclass_t      pclass;      /**< @brief Parameter pclass.*/

  union {

    UrosString              string;     /**< @brief XMLRPC string.*/

    int32_t                 int32;      /**< @brief XMLRPC int/i4.*/

    uros_bool_t             boolean;    /**< @brief XMLRPC boolean.*/

    double                  real;       /**< @brief XMLRPC double.*/

    UrosString              base64;     /**< @brief XMLRPC base64.*/

    void                    *mapp;      /**< @brief XMLRPC struct (map pointer).*/ /* TODO */

    struct UrosRpcParamList *listp;     /**< @brief XMLRPC array (list pointer).*/

  }                         value;      /**< @brief Parameter value.*/

} UrosRpcParam;


Then, just change the variable name from class to pclass. The error seems caused by typo.


Problem 2:
/src/lld/lwip/uros_lld_conn.c:784: undefined reference to `netconn_set_sendtimeout'

At first, I think it seems the lwip version caused error.
Change from 1.4.0 to 1.4.1
However, problem still exist.
/../../ext/lwip/src/api/api_lib.c:627: undefined reference to `sys_now'
build/obj/api_msg.o: In function `do_writemore':
/home/kv/rosnode/ChibiOS_2.5.1/demos/uROSnode/demos/turtlesim-chibios+lwip/../../../../ext/lwip/src/api/api_msg.c:1228: undefined reference to `sys_now'
collect2: error: ld returned 1 exit status
make: *** [build/turtlesim.elf] Error 1
Fix:
Then i just do the dirty thing. That I comment sys_now in 
lwip/src/api/api_msg.c
and 
lwip/src/api/api_lib.c
cause they have no instance.

Finally, the compilation is d
one.

st-flash write build/turtlesim.bin 0x08000000
2014-06-19T16:29:51 INFO src/stlink-common.c: Starting verification of write complete
2014-06-19T16:29:54 INFO src/stlink-common.c: Flash written and verified! jolly good!

But it doesn't Run! Obviously, we have different hardware module with their. 



The difficulty then will be porting the peripheral to the STM32F407 which we using Discovery.

I think porting this could be a great help to my robot!

2014年6月18日 星期三

DC Motor Speed PID Control with Arduino

It is a new MechLab for NCKU ME next semester, a PID controller!
Hardware:





Source Code on Github: https://github.com/kvzhao/ME-PIDLab

The crucial part of the PID code is listed below
void loop()
{
    // Run a period to estimate more precise speed
    Motor.Tick();
    // Run for one Second
    delay(SamplingTime);
    Motor.Tock();

    // Read rotation speed from Encoder
    Input = Motor.getSpeedRPS();

    // PID Compute
    PID_Controller.Compute();
    if ((Output-prevOutput) >= oscGap) {
      //Output = prevOutput;
    }
    Motor.setSpeed(Output);
    prevOutput = Output;
    // Show Data
    /*
    Serial.print("Input: ");
    Serial.println(Input);
    Serial.print("Setpoint: "); 
    Serial.println(Setpoint);    
    Serial.print("Error: ");
    Serial.println(error);
    Serial.print("Output: "); 
    Serial.println(Output);*/
    Serial.println(error);
    // wait a little while
    delay(5);
}


My first test result (with KP=98, KI=8, PD=5)
There is almost no steady state error, however overshoot happens.
Next step is to tune the parameters and control the motor smoothly!

Some useful references



2014年6月17日 星期二

2014年2月13日 星期四

Good articles about Arduino and IMU

Kalman filter is the one of the filter, or signal processing technique that lures me.

I wanna make a small system (via Arduino) to implement it and act as the lab material of embedded system tutorial.

Some useful websites and source code listing here :


Besides, here is the Arduino PID lib.

Great article : Faster analogRead()

2014年1月2日 星期四

Syringe Pump v2 : 6 stage step motor set

從去年開始實作了第一版本的Syringe Pump,幫助材料系的Graphene Lab可以從事薄膜等等的實驗。

功能

  • 讀取腳本,批次的控制六顆馬達
  • 手動直接操作

硬體

  • 六個壓克力幫浦臺
  • Seeedurino MCU
  • 6 Steppers 
  • 6 Easy Driver 
軟體
  • Arduino IDE 
  • C# for GUI


  • Stepper
    Easy Driver
    悲劇GUI
  • 設計為自己寫腳本(我們自己定義的語法),讓程式讀取
  • 程式會一行一行解析腳本,然後送出指令
  • 目前支援
    • 控制步伐,轉速,系統待機
    • 支援馬達同步 進行相同指令

整體系統
六個幫浦組


注射針筒

實驗發生的反應槽

利用金箔來測試有沒有振動發生
NOW, We are moving on!

因為這個系統不強健,有很多帶解決的問題(後面詳述)
由於第一版希望學長能盡快開始實驗,很多功能相當簡陋;另外也因為從頭打造,現實會發生的問題沒有考慮到。

將設計第二版 v2 ,這次重點將已系統的可靠度以及汎用性作考量,有以下的修改及加強。

v2 Modification 
  • 電路從麵包版換成自己焊接,留下IC座考慮以後容易更換
  • 設計電源開關,考慮是否需要 Pull-up Resistor
  • 界面首先已Qt4 (or Qt5) 重寫(因為C#檔案已經不見)
  • 界面需要一個LabView版本,考慮外包
    • 讀檔,一行一行parse然後透過UART送出
  • 電路盒子(需屏蔽?)
v2 New Function 
主要在韌體上考慮新功能,讓實驗更容易進行
  • 兩顆馬達同步
  • 待機時不激磁(No holding)
  • 慢進快退,馬達進退速度不同要考慮
  • 設定Home,當實驗結束可以回到固定地點
  • 除了絕對位置以外,提供相對圈數 兩種控制方式












102-2 Courses


理想的課表,1/5選課

第一階段選完,預料之為Parallel programming 看起來滿有趣的,最後應該會把Compiler 退掉。

2014年1月1日 星期三

Shopping List : Robot Hardware

寒假快來了,準備開始實作機器人
打算買一些硬體

  • Vision 
    • Xtion Pro (done)
  • Processor 
  • Wireless Device 
    • Xbee 
    • GPS

最令人好奇的是Cubie2 。價格相當優惠,雙核心的ARM Cortex A7,不知道用來當視覺系統的處理核心是否適合?


2013年12月30日 星期一

Raspicam Code Review

*** This Note is the Code Review of Raspicam Video ***
RASPIVID_STATE : 

PORT_USERDATA : 



MMAL_COMPONENT_T
MMAL_CONNECTION_T
MMAL_POOL_T In void main() :

Initialization Section
  • RASPIVID_STATE  state // is data storage vessel ,資料都從這裡存取
  • MMAL_STATUS_T 
  • MMAL_PORT_T
    • camera_video_port (動態)
    • camera_still_port    (靜態)
    • preview_input_port
    • encoder 
      • encoder_input_port
      • encoder_output_port
signal(SIGINT, singnal_hanlder)
default_status( &state );
  • h = state.height
  • w = state.width
Initiailize window and OpenCV stuff

dstImage = cvCreateImage( cvSize(w,h), IPL_DEPTH_8U, 3) // 3 Channels
  • py, pu, pv        : py 大小 w*h, pu, pv 大小只有 w/2 * h/2 
  • pu_big, pv_big : big u, v 將上面的長寬統一,變為 w * h
由於編碼格式的關係 (planar format - I420),所以所以u, v長度較短,在組合成影像時必須經過內插。

  • 以YUV 4:2:0的方式記錄。 
  • YUV4:2:0並不是說只有U(即Cb), V(即Cr)一定為0,而是指U:V互相援引,時見時隱,也就是說對於每一個行,只有一個U或者V份量,如果一行是4:2:0的話,下一行就是4:0:2,再下一行是4:2:0...以此類推。 

為節省頻寬起見,大多數YUV格式平均使用的每像素位數都少於24位元。
主要的抽樣(subsample)格式有YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和YCbCr 4:4:4。

YUV的表示法稱為A:B:C表示法:
  • 4:4:4表示完全取樣。
  • 4:2:2表示2:1的水平取樣,沒有垂直下採樣。
  • 4:2:0表示2:1的水平取樣,2:1的垂直下採樣。
  • 4:1:1表示4:1的水平取樣,沒有垂直下採樣。
Create Camera

create_camera_component( &state );
重要的  function ,裡面包括了mmal的初始化以及 video_buffer 的 callback function.

raspipreview_create( &state.preview_parameters ) ;

  • if not success : destroy_camera_component( &state )

PORT_USERDATA callback_data; 

camera_video_port = 
state.camera_component -> output[MMAL_CAMERA_VIDEO_PORT]; 

callback_data.pstate = &state; 

VCOS_STATUS_T vcos_status; // what is VCOS?
vcos_status = vcos_semaphore_create( &callback_data.complete_semaphore..);
vcos_assert(...);

這裡將來自camera 的 data pointer 指派給 user 讓 callback function 可以使用
camera_video_port -> userdata = 
(struct MMAL_PORT_USERDATA_T*) & callback_data;

 接下來的事情比較看不懂了,分別是

  • 初始化 timer
  • 開始抓取
  • 將所有的 buffer 送到 video port
  • wait until need to stop
  • disable all connections
  • destroy_encoder_components 
  • cvReleaseImage(IplImages)
之後仔細閱讀在詳述,現在應該把焦點放到 callback function 以及如何加速


In MMAL_COMPONENT_T *crate_camera_component( *state) : 

MMAL_ES_FORMAT_T *format
MMAL_COMPONENT_T *camera;
MMAL_PORT_T *video_port, *still_port, *preview_port; 

function 的流程為 :

  • Create camera component 
    • mmal_create_component(DEFAULT_CAMREA, &camera)
  • Set up camera configuration
    • 可以注意這種config設定的寫法
    • stills_yuv422 = 0; 暗示靜態有另一種編碼?
    • num_preview_video_frame = 3; (preview_video的意思待確定)

  • Set the encode format on the video port
    • format = video_port -> format;
  • Plug the callback to the video port
    • mmal_port_enable(video_port, video_buffer_callback); 
    • then ensure there is enough buffers to avoid dropping frames

  • Set the encode format on the still port 
    • Is still port necessary for video?
  • Create pool of message on video port
    • What is pool ?
  • Enable component

It seems that MMAL is the boardcom wrapper over OpenMAX. (Ref:Stack overflow) 

MMAL API runs over OpenMAX = Media Acceleration (中文/英文)
程式碼可以在Pi提供的userland中找到。
OpenMAX 的 簡介,他包含三層
  • DL (Development Layer) 
    • OpenMAX AL是多媒體應用程式(如Media Player)和平台媒體框架之間的介面。它允許公司開發應用程序方便地移植到不同平台的應用程序(客戶),並支持OpenMAX AL API。 
  • IL (Integration Layer) 
    • OpenMAX IL API透過C語言致力於打造可移植的媒體組件的陣列的平台。 
    • 這些組件可以是來源(source)、匯出(sink)、編解碼器(codec)、過濾器(filter)、分離器(splitter)、混頻器(mixers),或任何其他資料操作。
  • AL (Application Layer)
    • AL功能包括 視頻播放和錄製
    • 音頻播放和錄製
    • 圖像捕捉(攝像機)並顯示
    • 攝影控制
    • 廣播和RDS
    • 基本MIDI播放
    • 元數據(Metadata)的提取和插入

In video_buffer_callback(MMAL_PORT_T *port,                        MMAL_BUFFER_HEADER_T *buffer) : 

PORT_USERDATA *pData = (PORT_USERDATA*) port -> userdata; 

防止錯誤
...  if (pData) 
...  if (buffer -> length)

mmal_buffer_header_mem_lock( buffer ); 

不是很了解Memory lock再做什麼,但常常看到,似乎是重要的技巧。(待查)

OpenCV  here
w = pData-> pstate->width;
h = pData-> pstate->height;
h4 = h >> 2;  // h= h/4 

接下來透過讀取YUV,得到影像,分成兩種情況 (determined by graymode in RASPIVID_STATE)

  • 如果要得到Color map,YUV三者接需要
  • 如果只要用到gray image ,計算Y值即可

mmal_buffer_header_mem_unlock( buffer ); 

There are two algorithm that we want implement on my Pi.

  • Template Matching
  • Optical flow 
為了實踐這兩種演算法我想用ARM提供的NEON SIMD來加速。

在Github上找到了neon的(浮點)加速測試範例 :vfp-test
(浮點運算也很重要,因為optical flow將會用到)
但是可以看得出來,Pi 會產生錯誤訊息 :failed to run and generated an Illegal instruction exception.



Reference : 
補充知識 :

YUV format (Luminance, Chrominance, Chroma)
  • 緊縮格式(packed formats):將Y、U、V值儲存成Macro Pixels陣列,和RGB的存放方式類似。 
  • 平面格式(planar formats):將Y、U、V的三個份量分別存放在不同的矩陣中,Raspicam用的是這種方式。每Y份量,U份量和V份量都是以獨立的平面組織的,也就是說所有的U份量必須在Y分量後面,而V份量在所有的U份量後面,此一格式適用於採樣(subsample)。