古人智慧

Just Do it!
上士聞道,勤而行之;中士聞道,若存若亡;下士聞道,大笑之。不笑,不足以爲道。
~ 道德經 41

「實現夢想不是追逐成功,而是在於賦予生命意義,人生中的每個決定與聲音都有其重要含義。」"The key to realizing a dream is to focus not on success but on significance — and then even the small steps and little victories along your path will take on greater meaning."
電視名人-歐普拉·溫芙蕾(OPRAH WINFREY)

搜尋此網誌

Translation

2018年6月6日 星期三

[STM32F4x] OpenOCD install on MacOS

單片機MCU的價格不斷下降內含Flash與RAM,開發的工具也越來越成熟與穩定,隨著IOT興起推動MCU的熱潮!!!
手上剛好有一片STM32F407的核心板子,正好可以進入ARM 32bits MCU的世界。
STM32系列是很廣泛被使用在各領域的MCU,內含Cotex-M1到M7的ARM 32bits CPU,是值得深入學習的晶片系列。
在淘寶買到的核心板與Jtag
單片機MCU的價格不斷下降內含FlashRAM,開發的工具也越來越成熟與穩定,隨著IOT興起推動MCU的熱潮!!!
手上剛好有一片STM32F407的核心板子,正好可以進入ARM 32bits MCU的世界。
STM32系列是很廣泛被使用在各領域的MCU,內含Cotex-M1到M7的ARM 32bits CPU,是值得深入學習的晶片系列。

在淘寶買到的核心板與Jtag

<zu’zh

OpenOCD 安裝 installation


Regis-MacPro:~ regis$ brew update

Already up-to-date.

Regis-MacPro:~ regis$ brew install openocd
結果

==> Installing dependencies for open-ocd: libusb, libusb-compat, libftdi, hidapi

==> Installing open-ocd dependency: libusb

==> Downloading https://homebrew.bintray.com/bottles/libusb-1.0.22.high_sierra.b

######################################################################## 100.0%

==> Pouring libusb-1.0.22.high_sierra.bottle.tar.gz

🍺  /usr/local/Cellar/libusb/1.0.22: 29 files, 514.8KB

==> Installing open-ocd dependency: libusb-compat

==> Downloading https://homebrew.bintray.com/bottles/libusb-compat-0.1.5_1.high_

######################################################################## 100.0%

==> Pouring libusb-compat-0.1.5_1.high_sierra.bottle.tar.gz

🍺  /usr/local/Cellar/libusb-compat/0.1.5_1: 14 files, 94.3KB

==> Installing open-ocd dependency: libftdi

==> Downloading https://homebrew.bintray.com/bottles/libftdi-1.4.high_sierra.bot

######################################################################## 100.0%

==> Pouring libftdi-1.4.high_sierra.bottle.1.tar.gz

🍺  /usr/local/Cellar/libftdi/1.4: 19 files, 164.3KB

==> Installing open-ocd dependency: hidapi

==> Downloading https://homebrew.bintray.com/bottles/hidapi-0.8.0-rc1.high_sierr

######################################################################## 100.0%

==> Pouring hidapi-0.8.0-rc1.high_sierra.bottle.2.tar.gz

🍺  /usr/local/Cellar/hidapi/0.8.0-rc1: 17 files, 131.2KB

==> Installing open-ocd

==> Downloading https://homebrew.bintray.com/bottles/open-ocd-0.10.0.high_sierra

######################################################################## 100.0%

==> Pouring open-ocd-0.10.0.high_sierra.bottle.1.tar.gz

🍺  /usr/local/Cellar/open-ocd/0.10.0: 632 files, 4.7MB
首先,尋找interface\是否有J-Link的設定檔。但是,如何找到這個interface\的folder?

sudo find / |grep interface/jlink.cfg
出現在這裡!!!

/usr/local/Cellar/open-ocd/0.10.0/share/openocd/scripts/interface/jlink.cfg
再來就下命令來連上STM32F4核心板

Regis-MacPro:50_openocd regis$ openocd -f interface/jlink.cfg -f target/stm32f4x.cfg
結果成功透過J-Link連上STM32F4核心板

Open On-Chip Debugger 0.10.0

Licensed under GNU GPL v2

For bug reports, read

 http://openocd.org/doc/doxygen/bugs.html

Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.

adapter speed: 2000 kHz

adapter_nsrst_delay: 100

jtag_ntrst_delay: 100

none separate

cortex_m reset_config sysresetreq

Info : No device selected, using first device.

Info : J-Link V9 compiled Jun  2 2222 22:22:22

Info : Hardware version: 9.40

Info : VTarget = 3.192 V

Info : clock speed 2000 kHz

Info : JTAG tap: stm32f4x.cpu tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)

Info : JTAG tap: stm32f4x.bs tap/device found: 0x06413041 (mfg: 0x020 (STMicroelectronics), part: 0x6413, ver: 0x0)

Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
到這裡就成功把OpenOCD執行,並開通port 4444接收telnet來連線執行命令。

測試 Test

打開另一個terminal終端,輸入以下telnet指令

telnet localhost 4444
出現Open On-Chip Debugger,表示連上

Trying ::1...

telnet: connect to address ::1: Connection refused

Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

Open On-Chip Debugger

> poll

background polling: on

TAP: stm32f4x.cpu (enabled)
help指令了解更多
> help
adapter_khz [khz]
      With an argument, change to the specified maximum jtag speed.  For
      JTAG, 0 KHz signifies adaptive  clocking. With or without argument,
      display current setting. (command valid any time)
adapter_name
      Returns the name of the currently selected adapter (driver) (command
      valid any time)
adapter_nsrst_assert_width [milliseconds]
      delay after asserting SRST in ms (command valid any time)
adapter_nsrst_delay [milliseconds]
      delay after deasserting SRST in ms (command valid any time)
add_help_text command_name helptext_string
      Add new command help text; Command can be multiple tokens. (command
      valid any time)
add_script_search_dir <directory>
      dir to search for config files and scripts (command valid any time)
add_usage_text command_name usage_string
      Add new command usage text; command can be multiple tokens. (command
      valid any time)
arm
      ARM command group (command valid any time)
  arm core_state ['arm'|'thumb']
        display/change ARM core state
  arm disassemble address [count ['thumb']]
        disassemble instructions 
  arm mcr cpnum op1 CRn CRm op2 value
        write coprocessor register
  arm mrc cpnum op1 CRn CRm op2
        read coprocessor register
  arm reg
        display ARM core registers
  arm semihosting ['enable'|'disable']
        activate support for semihosting operations
  arm semihosting_fileio ['enable'|'disable']
        activate support for semihosting fileio operations
array2mem arrayname bitwidth address count
      convert a TCL array to memory locations and write the 8/16/32 bit
      values
bindto [name]
      Specify address by name on which to listen for incoming TCP/IP
      connections (command valid any time)
bp <address> [<asid>]<length> ['hw'|'hw_ctx']
      list or set hardware or software breakpoint
command
      core command group (introspection) (command valid any time)
  command mode [command_name ...]
        Returns the command modes allowed by a  command:'any', 'config', or
        'exec'.  If no command isspecified, returns the current command
        mode.  Returns 'unknown' if an unknown command is given. Command
        can be multiple tokens. (command valid any time)
  command type command_name [...]
        Returns the type of built-in command:'native', 'simple', 'group',
        or 'unknown'. Command can be multiple tokens. (command valid any
        time)
cortex_m
      Cortex-M command group
  cortex_m maskisr ['auto'|'on'|'off']
        mask cortex_m interrupts
  cortex_m reset_config ['srst'|'sysresetreq'|'vectreset']
        configure software reset handling (command valid any time)
  cortex_m vector_catch ['all'|'none'|('bus_err'|'chk_err'|...)*]
        configure hardware vectors to trigger debug entry
dap
      DAP command group
  dap apcsw [sprot]
        Set csw access bit 
  dap apid [ap_num]
        return ID register from AP (default currently selected AP)
  dap apreg ap_num reg [value]
        read/write a register from AP (reg is byte address of a word
        register, like 0 4 8...)
  dap apsel [ap_num]
        Set the currently selected AP (default 0) and display the result
  dap baseaddr [ap_num]
        return debug base address from MEM-AP (default currently selected
        AP)
  dap info [ap_num]
        display ROM table for MEM-AP (default currently selected AP)
  dap memaccess [cycles]
        set/get number of extra tck for MEM-AP memory bus access [0-255]
  dap ti_be_32_quirks [enable]
        set/get quirks mode for TI TMS450/TMS570 processors (configuration
        command)
debug_level number
      Sets the verbosity level of debugging output. 0 shows errors only; 1
      adds warnings; 2 (default) adds other info; 3 adds debugging.
      (command valid any time)
drscan tap_name [num_bits value]* ['-endstate' state_name]
      Execute Data Register (DR) scan for one TAP.  Other TAPs must be in
      BYPASS mode.
dump_image filename address size
echo [-n] string
      Logs a message at "user" priority. Output message to stdout. Option
      "-n" suppresses trailing newline (command valid any time)
exit
      exit telnet session
fast_load
      loads active fast load image to current target - mainly for profiling
      purposes
fast_load_image filename address ['bin'|'ihex'|'elf'|'s19'] [min_address [max_length]]
      Load image into server memory for later use by fast_load; primarily
      for profiling (command valid any time)
find <file>
      print full path to file according to OpenOCD search rules (command
      valid any time)
flash
      NOR flash command group (command valid any time)
  flash bank bank_id driver_name base_address size_bytes chip_width_bytes
            bus_width_bytes target [driver_options ...]
        Define a new bank with the given name, using the specified NOR
        flash driver. (configuration command)
  flash banks
        Display table with information about flash banks. (command valid
        any time)
  flash erase_address ['pad'] ['unlock'] address length
        Erase flash sectors starting at address and continuing for length
        bytes.  If 'pad' is specified, data outside that range may also be
        erased: the start address may be decreased, and length increased,
        so that all of the first and last sectors are erased. If 'unlock'
        is specified, then the flash is unprotected before erasing.
  flash erase_check bank_id
先到這裡,下次再研究深入些。

2018年5月13日 星期日

[母親節] 西瓜盆花~~

2018母親節這天,老大一早人不見蛋,應該會女友了。。。
晚上抱回這一盆西瓜裝一堆花,只有他老媽才會開心吧~~~

看看成果

2018年5月6日 星期日

[Altera Cyclone IV] 開發板 Quartus II & ModelSim installation

這幾天整理工作室,將工具、零件、Arduino、ESP8266等分類與歸位。
在角落發現這片FPGA開發板,估計應該是3年多前買的。。。
上網找相關資料,現在AI領域已經不再以GPU爲重點。FPGAASIC將引領風潮~~~
嗯,看來要再把這片開發板拿來深入學習。。。。
在網上查到資料,Intel在2015將Altera併購,而且開發軟件工具QuartusII已經升級到17.1. 立馬下載Linux的版本並安裝到我Ubuntu16.04 LTS 64bit系統。這套開發軟件包約7GB,我花了將近2小時下載,安裝過程算是順利。
當QuartusII在我Ubuntu跑起來,真是感動阿。。。馬上把點亮LED的範例輸入並compile成功!正當陶醉時,準備把code下載到Cyclone IV卻發現認不到USB的下載器!!!
還好網上神人多,Google就可以找到方法,記錄如下:

lsusb

cd /etc/udev/rules.d

sudo nano 51-usbblaster.rules
把這行輸入並存檔

ATTR{idVendor}=="09fb", ATTR{idProduct}=="6001", MODE="666"
然後下指令建立這USB下載器的node

sudo udevadm control --reload-rules
再來觀察log確定USB下載器是否正確被load

dmesg | tail
因爲沒及時將訊息存下,無法分享。
當一切都OK,準備學習更多Verilog!
但是,過程發現一個很好用的工具ModelSim竟然無法被啓動,終於花了2天找到解決方案,這問題是發生在這套ModelSim是用32bits環境,但是我Ubuntu是64bits,缺了一些32bits的library,只要裝好一切OK,太帥了!!!
ModelSim需要的32bits安裝

sudo apt-get install libc6:i386 libX11.so.6:i386 libxext6:i386 libxft2:i386 lib32ncurses5 libstdc++6:i386
如果發生source code的字型很小,那就要用這個方式解決,因爲在menu bar找不到設定。
Modelsim screenshot
I ran into this too in Ubuntu 16.04 LTS with modelsim 10.5 ASE. I fixed it as follows:

Open ~/.modelsim (use "nano ~/.modelsim" in terminal)
Find: PrefDefault = ... textFontV2 {Verdana 12} (the name of the font may differ)
Change 12 to -12, so it will looks like this: textFontV2 {Verdana -12}
Save ~/.modelsim (Ctrl+O and then Enter)
Reopen modelsim

2018年5月2日 星期三

[iRobot] Roomba 860 UART connect test

2年前家裡買這台掃地機iRobot Roomba 860

開始使用時覺得新鮮,但是總覺得他跑的路徑都怪怪的,不是很有效率與邏輯。However,這幾年就過了沒想這麼多。今天,女主人反映860的邊刷斷了,就是這個

《800系列的邊刷》
看來只能買新的,我就在想這台機器是否有機會升級韌體。Google很多資訊似乎需要買一台Firmware 升級器 OSMO,仔細看了一下,這版號是2012-08-22-1754!!! 似乎很舊了~~
但是,我這台860到底Firmware版號是多少? 如何check?
好問題,開始動手解決問題。。。

資料搜集

1.iRobot有無特殊接口?
2.如果有,要如何讀取?
資料顯示,iRobot在面板上有個隱藏的接口,在把手下面,有個橡皮蓋打開就出現。

《翻開把手》

《翻開橡皮蓋》

《細部觀察接口》

工具與設備

1.PC
2.Uart轉USB
3.單芯線

《Uart轉USB》

實驗過程

找到接口定義後分析,這接口應該是UART(串口),就依定義把先接好,如下圖。
因為找不到這種特殊接頭,雖然可以用PS/2接頭改造,但是我手上還是沒這種接頭,只好用克難式用單芯線來取代。

《用單芯線來接》

《插入接頭剛好》
當線接好之後,把Uart-USB插入PC,打開Uart terminal設定
Baudrate: 115200
Data bits: 8
Parity: None
Stop bits: 1
Flow control: None
然後連上Uart port,按下iRobot中間的啟動鍵,可以從Terminal看到開機訊息如下:

看來,我這台Firmware版本是比較新,應該不需要升級。

後續

其實開可以下命令給iRobot,我查到資料是有一份iRobot® Roomba 500 Open Interface (OI) Specification,有寫Python code透過USB下command,這部分下次有空再分享。

2018年4月29日 星期日

[Robot] 全3D打印 履帶機器人DIY

坦克車履帶傳動系統是個很棒的設計,可以在複雜與惡劣的地形上快速行進,用在robot上應該是適用的。
最近在Thingiverse看到一個神人作品SMARS作品是可以全3D打印的履帶與機身, 而且使用的小型馬達N20剛好手上有,真是太棒了,可以解解這種傳動系統的渴。。。

作品背景說明

要啟動一個項目,電控板是核心,有幾點必須考慮:
1.PCB尺寸
2.有多少GPIO可以控制外接模塊或馬達
3.operation電壓
再來就是周邊模塊的選擇,例如直流DC馬達要搭配馬達驅動板。
遙控器是相當麻煩的部分,我是選擇用jjRobots公司搭配OSC協議透過Wifi UDP傳送,OSC主要訴求是即時傳送與接收,這對遙控車是非常必要的選擇。
之前做4足Spider用HTML來控制,就非常不順暢卡卡的,甚至會突然HTML package會漏掉。
最後,電源系統設計,從電池電壓、尺寸與重量,DC-DC降壓板的電流輸出,這些都足以讓項目卡關,難以持續。
從上述的分析,很容易瞭解這次為何選擇TinyPlan。這片TinyPlan是以ESP8266為核心,並搭載兩顆2.4v 750F電容式快充鋰電池,串聯起來可以提供4.8v,1C放電。並提供8個GPIO,4根pin接馬達驅動板,2根接UltraSonic sensor綽綽有餘,是個非常好的選擇。

作品展示

零件表與設備工具

BOM list:

設備:

3D 打印機
3D 結構

設計階段

3D 結構列印與組裝


《用2mm鑽頭通一下比較好安裝》

《TinyPlan+L9113S》

Arduino軟件設計

參考jjRobots的OSC來開發(https://github.com/jjrobots/B-ROBOT_EVO2/tree/master/Arduino)
主程式如下:
/*
   RegisHsu 2018-04-28
   TinyPlan ESP8266 module + L9110S + UltraSound
   Controller jjrobots - www.jjrobots.com

   v01:
      initial version
   v02:
      add UltraDonic sensor
*/

#include <ESP8266WiFi.h>
#include "RHROBOTS_OSC.h"
#include "RHROBOTS_BROBOT.h"

#define BAUDRATE 250000

// TinyPlan Port define
#define PIN_D1 14
#define PIN_D2 12
#define PIN_D3 13
#define PIN_D4 15
#define PIN_D5 16
#define PIN_D6 5
#define PIN_D7 4
#define PIN_D8 2

//N20 Motor pin define
#define MOTOR_M1_S1 PIN_D1
#define MOTOR_M1_S2 PIN_D2
#define MOTOR_M2_S1 PIN_D5
#define MOTOR_M2_S2 PIN_D6

//Ultrasonic sensor pin define
#define ULTRA_TRIG PIN_D3
#define ULTRA_ECHO PIN_D7

// NORMAL MODE PARAMETERS (MAXIMUN SETTINGS)
#define MAX_THROTTLE 2400
#define MAX_STEERING 2400
#define MAX_CONTROL_OUTPUT 1024

uint8_t loop_counter;       // To generate a medium loop 40Hz
uint8_t slow_loop_counter;  // slow loop 2Hz
uint8_t sendBattery_counter; // To send battery status

long timer_old;
long timer_value;
int debug_counter;
float debugVariable;
float dt;

int16_t motor1;
int16_t motor2;

bool newControlParameters = false;
bool modifing_control_parameters = false;

uint8_t mode;  // mode = 0 Normal mode, mode = 1 Pro mode (More agressive)

float throttle;
float steering;
float max_throttle = MAX_THROTTLE;
float max_steering = MAX_STEERING;
float control_output;

// Ultrasonic
volatile long duration;
volatile int distance;
volatile int echo_interr_flag, echo_obstacle;
volatile long t_echo_s, t_echo_e;
long t_auto_last, t_auto_curr;
int echo_trig_sw;

void echo_interr(void)
{
  echo_interr_flag = 1 - echo_interr_flag;
  if (echo_interr_flag)
    t_echo_s = micros();
  else
  {
    t_echo_e = micros();
    duration = t_echo_e - t_echo_s;
    distance = duration * 0.034 / 2;
    if (distance < 12) //12cm
      echo_obstacle = 1;
    else
      echo_obstacle = 0;
  }
}

void echo_trigger(void)
{
  echo_trig_sw = 1;
  // Clears the trigPin
  digitalWrite(ULTRA_TRIG, LOW);
  delayMicroseconds(2);

  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(ULTRA_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(ULTRA_TRIG, LOW);
  echo_interr_flag = 0;
  echo_obstacle = 0;
}

void auto_pilot(void)
{
  t_auto_curr = millis();
  if ((t_auto_curr - t_auto_last) > 80)
  {
    t_auto_last = t_auto_curr;
    //Serial.println("Trig");
    echo_trigger();
  }

  if (echo_obstacle)
  {
    echo_obstacle = 0;
    //Serial.println("obstacle");
    //stop
    setMotorSpeedM1(0);
    setMotorSpeedM2(0);
    delay(800);
    //back
    setMotorSpeedM1(-motor1);
    setMotorSpeedM2(-motor2);
    delay(600);
    //turn left
    setMotorSpeedM1(motor1);
    setMotorSpeedM2(-motor2);
    delay(600);
    //stop
    setMotorSpeedM1(0);
    setMotorSpeedM2(0);
    delay(500);
  }
  setMotorSpeedM1(motor1);
  setMotorSpeedM2(motor2);
}

// Set speed of Stepper Motor1
// tspeed could be positive or negative (reverse)
void setMotorSpeedM1(int16_t tspeed)
{
  if (tspeed >= 0)
  {
    analogWrite(MOTOR_M1_S1, 0);
    analogWrite(MOTOR_M1_S2, tspeed);
  }
  else
  {
    analogWrite(MOTOR_M1_S1, -tspeed);
    analogWrite(MOTOR_M1_S2, 0);
  }
}

// Set speed of Stepper Motor2
// tspeed could be positive or negative (reverse)
void setMotorSpeedM2(int16_t tspeed)
{
  if (tspeed >= 0)
  {
    analogWrite(MOTOR_M2_S1, 0);
    analogWrite(MOTOR_M2_S2, tspeed);
  }
  else
  {
    analogWrite(MOTOR_M2_S1, -tspeed);
    analogWrite(MOTOR_M2_S2, 0);
  }
}

void setup() {
  // put your setup code here, to run once:
  // init motors
  pinMode(MOTOR_M1_S1, OUTPUT);
  pinMode(MOTOR_M1_S2, OUTPUT);
  pinMode(MOTOR_M2_S1, OUTPUT);
  pinMode(MOTOR_M2_S2, OUTPUT);

  //init Ultrasonic sensor
  echo_interr_flag = 0;
  t_auto_last = 0;
  echo_obstacle = 0;
  pinMode(ULTRA_TRIG, OUTPUT); // Sets the trigPin as an Output
  pinMode(ULTRA_ECHO, INPUT_PULLUP); // Sets the echoPin as an Input
  attachInterrupt(digitalPinToInterrupt(ULTRA_ECHO), echo_interr, CHANGE);
  Serial.begin(BAUDRATE); // Serial output to console
  //Regis
  OSC.UDP_Init();

  Serial.println("BROBOT by JJROBOTS v2.2");

  // STEPPER MOTORS INITIALIZATION
  Serial.println("DC motors initialization...");
  // pre-action
  echo_trigger();
  // Little motor vibration to indicate that robot is ready
  setMotorSpeedM1(0);
  setMotorSpeedM2(0);
  for (uint8_t k = 0; k < 3; k++)
  {
    setMotorSpeedM1(1000);
    setMotorSpeedM2(1000);
    //BROBOT.moveServo1(SERVO_AUX_NEUTRO + 5);
    delay(100);
    setMotorSpeedM1(-1000);
    setMotorSpeedM2(-1000);
    //BROBOT.moveServo1(SERVO_AUX_NEUTRO - 5);
    delay(100);
  }
  setMotorSpeedM1(0);
  setMotorSpeedM2(0);

  for (int i = 0; i < 3; i++)
  {
    // pre-action
    echo_trigger();
    delay(200);
  }
  // OSC initialization
  OSC.fadder1 = 0.5;
  OSC.fadder2 = 0.5;

  Serial.println("Let's start...");
  mode = 0;
}

void loop() {

  //Regis
  OSC.MsgRead();  // Read UDP OSC messages
  if (OSC.toggle1 == 1)
  {
    motor1 = -780;
    motor2 = -780;
    auto_pilot();
  }

  if (OSC.newMessage)
  {
    OSC.newMessage = 0;
    //Regis
    if (OSC.page == 1) // Get commands from user (PAGE1 are user commands: throttle, steering...)
    {
      //OSC.newMessage = 0;
      throttle = (OSC.fadder1 - 0.5) * max_throttle;
      // We add some exponential on steering to smooth the center band
      steering = OSC.fadder2 - 0.5;
      if (steering > 0)
        steering = (steering * steering + 0.5 * steering) * max_steering;
      else
        steering = (-steering * steering + 0.5 * steering) * max_steering;

      motor1 = throttle - steering;
      motor2 = throttle + steering;
      motor1 = constrain(motor1, -MAX_CONTROL_OUTPUT, MAX_CONTROL_OUTPUT);
      motor2 = constrain(motor2, -MAX_CONTROL_OUTPUT, MAX_CONTROL_OUTPUT);
      setMotorSpeedM1(motor1);
      setMotorSpeedM2(motor2);
    }
  } // End new OSC message
}

測試


《使用jjRobots的遙控App》

《加上UltraSonic sensor》