2016年1月28日 星期四

How to measure and calibrate Low-speed internal oscillator on STM32F0

1. RTC是經常拿來當作喚醒源的一種應用, 為了節省成本, 通常都是使用內部的RC震盪來當作
    起始源, 因此對內部的RC震盪進行校正就很重要了, 底下的範例就是在STM32F0系列上來進
    行校正的測試程式.

2. 測試程式主要是參考ST的原始文件Low-speed internal oscillator measurement(AN4067)來寫
    的, 當然除了內部的RC校正, 也可以對外部的石英震盪進行校正, 但目前還是先測試最常使
    用的內部RC校正.

3. 從文件上的Figure14可以看到校正的原理:



  • 將TIM14設定為input capture mode.
  • TIM14_RTC_CLK: TIM14 Channel 1 is connected to RTC input clock.  RTC input clock can be LSE, LSI or HSE/div128, 目前設定為LSI.
  • 接著利用input capture方式, 計算出LSI的數值.
  • 根據User期待喚醒的時間數值參數和LSI計算出最後的wake up counter, 並設定好RTC.


4. 簡易的測試方式:
  • 可以在RTC_IRQHandler()裡面加上GPIO Toggle, 來確定校正是否成功.

  • 從下圖Logic analyzer的波形上可以看到, 跟我們期待的10msec toggle比起來, 9.992msec已經相當接近10msec了.

5. Test Code Link: 可以參考rtc.c & rtc.h


2016年1月26日 星期二

STM32F0_F3 I2C Master Driver Code

1. STM32F0週邊的架構和F3非常相似, 因此許多的Driver幾乎都是可以共用的, 底下要介紹的是
    I2C Master Driver Code.

2. 測試的硬體是使用STM32F072B Discovery Board + MPU6050 Sensor Board, I2C Clock =
    400KHz.

3. 首先下載i2c_master.c & i2c_master.h, 並把它加入專案內.




4. 加入後, 接著就可以進行i2c init 和 read/write測試了, 如下面程式碼所示, 使用i2c write 對
    mpu6050 初始化, 接著再使用i2c read 讀取 mpu6050 chip id.

  /* I2C Init */
  I2C_Master_Init();
  
  /* I2C Test (mpu6050) */ 
  uint8_t i2c_tmp = 0;
  
  // Reset device.
  i2c_tmp = 0x80;
  I2C_Write(0xD0, 0x6B, &i2c_tmp, 0x01);
  
  // Delay some time
  for(int i=0; i<2000; i++){__asm("nop");}      
  
  // Wake up chip.
  i2c_tmp = 0x00;
  I2C_Write(0xD0, 0x6B, &i2c_tmp, 0x01);
  
  // Read chip id
  I2C_Read(0xD0, 0x75, &i2c_tmp, 0x01);

5. 可以從MPU6050 Datasheet看到, mpu6050 chip id的位址在0x75, 且chip id固定為0x68, 因此代表 i2c init 及 read chip id皆正常.

6. Logic analyzer 波形圖:
  • I2C Write: (Reset device.)
  • I2C Write: (Wake up chip.)
  • I2C Read: (Read chip id.)

2016年1月24日 星期日

dyson AM09 開箱

1. 這幾天台灣真是冷爆了, 於是先預訂了dyson的AM09, 這是將冷風和暖氣合一的機器, 且體積
    不大, 剛好dyson又在促銷滿五千折五百, 所以立馬就下訂了, 運氣很好地剛好就在最冷的週
    六送來了.


2. 體積不大, 內容物蠻精簡的, 除了主機外, 還有遙控器和底座及說明書而已.






3. 插頭挺特殊的, 少見的圓形.


4. 組裝完成.




5. 遙控器可以磁吸在頂部, 還蠻方便的設計.


2016年1月18日 星期一

這是一條不歸路啊~~~~~

    偶然整理照片, 看到一年半前買stm32f051 discovery board時, 大女兒以為是玩具拿在懷裡的照片, 只能說以後別走這條不歸路啊~~~~~~


STM32F072B Discovery Board unboxing + FreeRTOS v8.2.3 + USB_VCP_HID

1. 最近在露天買了一張stm32f072b discovery board, 基本上stm32f072 = stm32f051 + usb,  而在研
    究了一下之後, 也順手將FreeRTOS v8.2.3和USB Virtual Com-Port & HID移植完畢, 接著會將
    移植的過程簡單的描述一下.



2. main flow:
  • 基本上就是先對LED & USB 來做Init.
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
  
  RCC_ClocksTypeDef RCC_Clocks;
  RCC_GetClocksFreq(&RCC_Clocks);
  
  /* Steup Hardware. */
  prvSetupHardware();
  
  /* Create task. */
  vAltStartTask1Tasks( mainCREATOR_TASK_PRIORITY);    //Task1
  vAltStartTask2Tasks( mainCREATOR_TASK_PRIORITY);    //Task2
  
  /* Start the scheduler. */
  vTaskStartScheduler();
 
  /* Will only get here if there was not enough heap space to create the idle task. */
  return 0;
}

static void prvSetupHardware( void )
{
  /* LED Init. */
  STM_EVAL_LEDInit(LED3);
  STM_EVAL_LEDInit(LED4);
  STM_EVAL_LEDInit(LED5);
  STM_EVAL_LEDInit(LED6);
  
  STM_EVAL_LEDOff(LED3);
  STM_EVAL_LEDOff(LED4);
  STM_EVAL_LEDOff(LED5);
  STM_EVAL_LEDOff(LED6);
  
  /* USB VCP or HID Init. */
  USB_Init();
}
  • USB VCP & HID的切換在usb_define.h裡面去做選擇.
 
  • Task1: 就是固定每100msec去Toggle LED3而已.
//Task1
static portTASK_FUNCTION( vTask1FunctionTask, pvParameters )           
{
        portTickType xLastWakeTime;
          
 /* Just to stop compiler warnings. */
 ( void ) pvParameters;
        xLastWakeTime = xTaskGetTickCount();

 for( ;; )
 {
          Task1Task_Counter++;
          STM_EVAL_LEDToggle(LED3);  
          vTaskDelayUntil( &xLastWakeTime, ( 100 / portTICK_RATE_MS ) );
 }
}


  • Task2: 固定每200msec會去Toggle LED6外, 還會根據usb_define選擇的結果來輸出VCP or HID測試信號.
//Task2
static portTASK_FUNCTION( vTask2FunctionTask, pvParameters )             
{        
        portTickType xLastWakeTime;
        
 /* Just to stop compiler warnings. */
 ( void ) pvParameters;
        
        xLastWakeTime = xTaskGetTickCount();
 for( ;; )
 {
          Task2Task_Counter++;
          STM_EVAL_LEDToggle(LED6); 

          #ifdef HIDRAW 
            for(int i=0;i<32;i++)
              HID_Buffer[i] = i;
            USBD_HID_SendReport (&USB_Device_dev, HID_Buffer, 32); 
            PrevXferDone = 0;
          #endif
              
          #ifdef VirtualComPort  
            memset(VCP_Buffer,0x00,sizeof(VCP_Buffer));
            sprintf(VCP_Buffer, "$,HelloWorld:%d\r\n", vcp_counter++); 
            USBD_VCP_SendReport(&USB_Device_dev, CDC_IN_EP, (uint8_t*)&VCP_Buffer[0], strlen(VCP_Buffer)); 
          #endif
                        
          vTaskDelayUntil( &xLastWakeTime, ( 200 / portTICK_RATE_MS ) );
 }
}

3. Test Flow:  當我們利用usb_define.h來切換VCP/HID的時候, 程式會根據切換的結果來做不同
    的Init, 因此在裝置管理員上看到的裝置也不相同.

#ifdef HIDRAW
#define USBD_VID                          0x0483
#define USBD_PID                          0x5750

#define USBD_LANGID_STRING                0x409
#define USBD_MANUFACTURER_STRING          "STMicroelectronics"

#define USBD_PRODUCT_FS_STRING            "Custome HID"

#define USBD_CONFIGURATION_FS_STRING      "HID Config"
#define USBD_INTERFACE_FS_STRING          "HID Interface"
#endif

#ifdef VirtualComPort
  #define USBD_VID                        0x0483
  #define USBD_PID                        0x5740

  /** @defgroup USB_String_Descriptors
    * @{
    */ 
  #define USBD_LANGID_STRING              0x409
  #define USBD_MANUFACTURER_STRING        "STMicroelectronics"

  #define USBD_PRODUCT_FS_STRING          "STM32 Virtual ComPort in FS Mode"

  #define USBD_CONFIGURATION_FS_STRING    "VCP Config"
  #define USBD_INTERFACE_FS_STRING        "VCP Interface"
#endif 



  • HID:  假設我們要測試HID, 可以利用BusHound這套軟體來測試, 它可以針對特定裝置來側錄輸出入的log, 如下圖, 可以看到系統新增出一個HID-compliant device, 透過Hardware ID(VID/PID)可以確認這就是我們目前在使用的stm32f072 discovery board.


  •  從log上看到和我們程式的結果符合, 固定每200msec輸出0x00~0x1f這32個bytes.



  • VCP:
    • 燒錄程式後, 先確認目前ST VCP的編號是多少? (ex: COM14)

    • 可以使用Putty來觀察結果, 設定如下.

    • 接著就可以看到如下圖的結果:


    • Test Video:



4. Test Code Link:

2016年1月12日 星期二

How to Enable MPU6050 Orientation from DMP on STM32F4

1. 最近開始在研究平衡車和空拍機的方案, 發現目前幾乎都是InvenSense mpu6050的天下,
    最主要的原因是因為InvenSense的sensor有內建算法, 因此對於沒有算法team的公司而言,
    使用I家的產品自然成為首選.

2. 現在這個範例是使用mpu6050 sensor board + stm32f401 discovery board + processing來示範,
    主要的流程如下:

  • STM32F401透過I2C來Init MPU6050 DMP, 並透過I2C來讀取MPU6050算出來的Orientation資料.
  • STM32F401透過Virtual Com-Port將Orientation傳送給PC上的Processing軟體.
  • Processing根據Orientation的數據來轉動小飛機.

3. 因此在操作之前, 必須先裝好裝滿Processing以及相關的Library.

  • 接著會出現問你要不要捐錢, 直接點選No Donation, 就會出現Download的標幟.

  • 接著就根據你自己的平台來選擇安裝, 由於我是使用win10 64bit, 因此安裝64bit版本, 選擇後就會下載約100MB左右的壓縮檔.

  • 解壓縮後, 會看到processing.exe, 執行後即可完成安裝.

  • 由於我們在Processing上執行的demo範例必須要使用到toxiclibs這個library, 因此
    我們必須也要到toxiclibs的網站去下載library.
  • 到達下載頁面後, 直接選擇toxiclibs-complete-0020.zip, 即可下載至PC.
  • toxiclibs-complete-0020.zip解壓縮後, 將整個資料夾複製到C:\Users\user\Documents\Processing\libraries資料夾內, 到這邊我們已經完成了PC端軟體的設置.

4. 接下來可以準備相關的硬體, 首先先完成mpu6050 sensor board和stm32f401 discovery board之
    間的連接線路.
  • stm32f401 discovery board :3V ->  mpu6050 sensor board: VCC
  • stm32f401 discovery board :GND -> mpu6050 sensor board: GND 
  • stm32f401 discovery board :PB6 -> mpu6050 sensor board: SCL
  • stm32f401 discovery board :PB9 -> mpu6050 sensor board: SDA

  • 接著將ST-LINKUSB端口分別使用USB CablePC相連, 此時會看到mpu6050 sensor board上的LED亮起, 這樣應該就代表電源沒接錯了, 到此硬體已全部準備完成.

5. Code Flow:
  • STM32F401:
    • 針對硬體上的Init, 其中最重要的是對I2C & USB VCP的初始化, 使用I2C與MPU6050溝通, 使用USB VCP將Orientation data傳給PC.

    • 使用I2C對MPU6050執行初始化, 中間只要有一個步驟不正確, 則會跑到無窮迴圈.
    • 當MPU6050 Init成功後, 便會跑到主迴圈, 此時會不斷地去詢問dmp fifo data是否已完成準備, 若是完成準備的話, 則會一口氣將fifo data全讀回來.
    • 接著便會開始計算Yaw/Roll/Pitch, 並把quaternion透過USB VCP傳送給PC.


  • Processing:
    • 使用Processing開啟程式後, 會看到左上角的Run的符號, 按下即可執行程式.

    • Processing程式中特別需要注意的是要去設定com port的編號, 首先我們先去觀察stm32 virtual com port在裝置管理員上的com port編號是多少, 從下圖可以看到目前是COM8.
    • 接著我們可以先執行Processing端的程式, 可以看到下面的訊息窗會把目前PC上面的所有com port及編號皆列出來, 而我們要找的就是virtual com port對應的編號(ex: COM8), 從下圖看到COM8是第4個.
    • 確定了vcp的編號後, 接著就是去修改processing程式上的com port編號, 如下圖在line 74行的地方, 將vcp number填入Serial.list()[vcp number].


6. Test Flow:
  • 將stm32f401的測試程式燒入到stm32f401 discovery board上.
  • 使用USB Cable將stm32f401 discovery board與PC相連接.
  • 執行Processing程式, 成功的話會看到如下圖的小飛機出現, 此時移動sensor board, 飛機會有相對應的動作出現.

  • Test Video:


7. Test Code Download Link:
    

2016年1月4日 星期一

Atmel SAMG53 Xplained Pro unboxing + FreeRTOS v8.2.3

1. 之前跟Atmel合作案子時用過這張板子, 那時候覺得很類似ST Discovery Board的概念,
    板子上已經內建了ICE, 省去了另外購買ICE的花費, 而這張SAMG53 Xplained Pro也是我
    第一次用到內建CMSIS-DAP的板子, 從淘寶上購買加上運費大概台幣一千塊左右.

2. 外盒包裝採用機器人當作主題, 之前使用過STK600開發板的時候, 也是使用類似像無敵鐵金
    剛的造型, 看來這應該是Atmel開發板的特色.



3. 看來我這片開發板是在馬來西亞製作完成的.




4. 在使用此塊板子之前需先安裝Atmel USB相關的Driver才能夠使用, 下載連結如下:

5. 安裝USB Driver完畢後, 此時就可以透過USB Cable與開發板相接, 此時裝置管理員會新增
    EDBG USB Port出來, 前置工作基本上就準備完成了.


6. 測試程式的編譯軟體是IAR EWARM, 完整測試程式連結如下:

7. 使用IAR EWARM開啟Project後, 需要先設定Device和Debug Tool才能夠正常進入Debug 
     Mode和燒錄.





8. Main Flow:


  • init evb hardware.(init Wdt & Clock & Usart & LED)

  • create task and start the scheduler.
  • toggle LED0 & Print HelloWorld via Usart0.


9. Test Flow:
  • LED Toggle可以透過觀察LED0是否有變化來得知.
  • Usart Output可以透過putty來觀察是否有輸出來得知, putty的設定如下:

  • 設定成功後, 可以看到如下的輸出結果.


10. Test Video: