2015年11月28日 星期六

訓練數學感 79 ─ 25 匹馬

http://4rdp.blogspot.tw/2015/11/79-25.html

有一馬場共 25 匹馬,它們的個別跑速不清楚,只知道每一匹馬都非常平穩固定,跑馬場每次最多只能 5 匹馬下場比賽,請問最少需要比賽幾場,才能分出這 25 匹馬的冠、亞、季軍是那隻馬?

2015年11月24日 星期二

ROSA 系統開發 15 ─ 回覆台大資工系洪士灝教授的提問

http://4rdp.blogspot.tw/2015/11/rosa-15.html

週日晚上,無意間看到台大洪士灝教授在 FB 貼文轉型到 Open Source 的世界來尋寶,個人蠻認同其觀點,正好個人在開發 ROSA (Robot Operation System for Arduino),因此留文請教洪教授對 ROSA 的看法,教授留言一句話「是否可以用一頁說明這個計畫的目的、優點、製作方法、所需克服的障礙 ?

我把這當作如果未來創業,不管是天使投資人 (只要講得出好點子就會投資你) 還是惡魔投資人 (問一堆問題還是不會投資,然後用你的點子賺錢) 必問的問題,其實這應該要準備一頁 Business Model Canvas 說明,日後再找時間談這個,目前對 ROSA 我以公益看待,在此不談商業模式。

經過兩天沉思後,答覆教授的問題如下:

2015年11月21日 星期六

ROSA 系統開發 14 ─ Control meArm by IR

http://4rdp.blogspot.tw/2015/11/rosa-14-control-mearm-by-ir.html

紅外線遙控能用於 meArm 嗎?答案是可以的,考量許多玩家沒有 mBot 紅外線遙控器,因此另外準備一隻遙控器以及能與 Arduino 相接的紅外線接收器,如上圖所示。

// (C) 2015, Bridan Wang, CC BY-NC-SA 3.0 TW
// http://4rdp.blogspot.tw/search/label/ROSA%20(Arduino)

const byte IR_CODE[][18] PROGMEM = {
//  X, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, *, #,up,dn,rt,lf,ok
    0,22,25,13,12,24,94, 8,28,90,82,66,74,70,21,67,68,64,
    0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
};

void (*FUNC_JUMP[])(void) = {
  FUNC_N,            // none
  FUNC_1,            // 1
  FUNC_N, // FUNC_2, // 2
  FUNC_3,            // 3
  FUNC_4,            // 4
  FUNC_N, // FUNC_5, // 5
  FUNC_6,            // 6
  FUNC_N, // FUNC_7, // 7
  FUNC_N, // FUNC_8, // 8
  FUNC_N, // FUNC_9, // 9
  FUNC_N, // FUNC_0, // 0
  FUNC_S,            // *
  FUNC_P,            // #
  FUNC_N, // FUNC_U, // up
  FUNC_N, // FUNC_D, // down
  FUNC_R,            // right
  FUNC_L,            // left
  FUNC_N, // FUNC_K  // ok
};

void PROCESS_10ms(void){
  IR_CHECK();

  if (A_IN(A4) < 200){   // right X
    if (servo_set[2] > 120) servo_set[2]--;
  }
  else if (A_IN(A4) >= 800){
    if (servo_set[2] < 160) servo_set[2]++;
    else servo_hold[2] = 255;
  }
  else
    servo_hold[2] = 0;

  if (A_IN(A0) < 200){   // left Y
    if (servo_set[4] > 60) servo_set[4]--;
  }
  else if (A_IN(A0) >= 800) {
    if (servo_set[4] < 150) servo_set[4]++;
  }
  if (A_IN(A1) < 200){   // left X
    if (servo_set[1] != 0) servo_set[1]--;
  }
  else if (A_IN(A1) >= 800){
    if (servo_set[1] < 180) servo_set[1]++;
  }
  if (A_IN(A3) < 200){   // right Y
    if (servo_set[3] > 60) servo_set[3]--;
  }
  else if (A_IN(A3) >= 800) {
    if (servo_set[3] < 150) servo_set[3]++;
  }
}

byte pre_ir;
byte ir_code;
byte step_no = 0;

void IR_CHECK() {   // for KEYES IR
  byte i;
  byte j;
  j = ir.key();
  // Serial.print("IR - ");
  // Serial.println(j);
  for (i = 17; i != 0; i--) {
    if (j == pgm_read_byte(&IR_CODE[0][i])) {
      if (pgm_read_byte(&IR_CODE[1][i])==0 || pre_ir!=j) {
        pre_ir = ir_code;
        ir_code = i;
        step_no = 0;
        (*FUNC_JUMP[i])();
break;
      }
    }
  }
  ir.loop();
}

void FUNC_N(void)  // none
{
}

void FUNC_1(void)  // left Y
{
  if (servo_set[4] < 150) servo_set[4]++;
}

void FUNC_4(void)
{
  if (servo_set[4] > 60) servo_set[4]--;
}

void FUNC_3(void)  // right Y
{
  if (servo_set[3] < 150) servo_set[3]++;
}

void FUNC_6(void)
{
  if (servo_set[3] > 60) servo_set[3]--;
}

void FUNC_S(void)  // right X
{
  if (servo_set[2] < 160) servo_set[2]++;
  else servo_hold[2] = 255;
}

void FUNC_P(void)
{
  if (servo_set[2] > 120) servo_set[2]--;
}

void FUNC_R(void)  // left X
{
  if (servo_set[1] != 0) servo_set[1]--;
}

void FUNC_L(void)
{
  if (servo_set[1] < 180) servo_set[1]++;
}

2015年11月18日 星期三

數學之美 4 ─ 解析幾何

http://4rdp.blogspot.tw/2015/11/4.html

數學式與圖形之間有密不可分的關係,這在我專科時才體悟到,後來才知道這門數學稱為解析幾何。

我的工作常常需要分析數值,利用 Curve Fitting 等技巧,求解最近似方程式,這些能力皆是建立在數學方程式與函數曲線之間關聯,非數學愛好者,很難將其聯想在一起。

2015年11月14日 星期六

ROSA 系統開發 13 ─ SERVO 多工同步控制

http://4rdp.blogspot.tw/2015/11/rosa-13-servo.html

前文談過單一伺服馬達驅動,本期續談多顆伺服馬達多工同步控制方法,

// (C) 2015, Bridan Wang, CC BY-NC-SA 3.0 TW
// http://4rdp.blogspot.tw/search/label/ROSA%20(Arduino)

byte servo_set[] = { 0, 90, 90, 90, 90};
byte servo_speed[] = { 0, 5, 1, 5, 5};
byte servo_hold[] = { 0, 0, 0, 0, 0};

void PROCESS_SERVO(void) {
  static byte servo_no;
  byte i;

  if (servo_no == 0 || servo_no > 4) {
    servo_no = 4;
  }

  if (servo_set[servo_no] > servo_angle[servo_no]){
    servo_angle[servo_no] += servo_speed[servo_no];
    if (servo_set[servo_no] < servo_angle[servo_no])
      servo_angle[servo_no] = servo_set[servo_no];
    SERVO_SET(servo_no);
  }
  else if (servo_set[servo_no] < servo_angle[servo_no]){
    servo_angle[servo_no] -= servo_speed[servo_no];
    if (servo_angle[servo_no] > 180)
      servo_angle[servo_no] = servo_set[servo_no];
    SERVO_SET(servo_no);
  }
  else if (servo_hold[servo_no] != 0){
    if (servo_hold[servo_no]!=255) 
      servo_hold[servo_no]--;
    SERVO_SET(servo_no);
  }
  servo_no--;
}

unsigned long  now;

void SYS_TIMER() {
  static byte  tm_10ms = 0;
  static byte  tm_100ms = 0;
  static byte  tm_1sec = 0;

while (millis() - now >= 5) {
now += 5;
tm_10ms++;
tm_100ms++;
tm_1sec++;
    PROCESS_SERVO();
}
if (tm_1sec >= 200) {
tm_1sec -= 200;
PROCESS_1sec();
}
if (tm_100ms >= 20) {
tm_100ms -= 20;
PROCESS_100ms();
}
if (tm_10ms >= 2) {
tm_10ms -= 2;
PROCESS_10ms();
}
}

void PROCESS_1sec(void){   // print analog value for debugging
  Serial.print("A0 - ");
  Serial.println(A_IN(A0));
  Serial.print("A1 - ");
  Serial.println(A_IN(A1));
  Serial.print("A2 - ");
  Serial.println(D_IN(A2));

  Serial.print("A3 - ");
  Serial.println(A_IN(A3));
  Serial.print("A4 - ");
  Serial.println(A_IN(A4));
  Serial.print("A5 - ");
  Serial.println(D_IN(A5));
}

void PROCESS_100ms(void){
}

void PROCESS_10ms(void){
  if (A_IN(A4) < 200){   // right X
    if (servo_set[2] > 120) servo_set[2]--;
  }
  else if (A_IN(A4) >= 800){
    if (servo_set[2] < 160) servo_set[2]++;
    else servo_hold[2] = 255;
  } else
    servo_hold[2] = 0;

  if (A_IN(A0) < 200){   // left Y
    if (servo_set[4] > 60) servo_set[4]--;
  }
  else if (A_IN(A0) >= 800) {
    if (servo_set[4] < 150) servo_set[4]++;
  }
  if (A_IN(A1) < 200){   // left X
    if (servo_set[1] != 0) servo_set[1]--;
  }
  else if (A_IN(A1) >= 800){
    if (servo_set[1] < 180) servo_set[1]++;
  }
  if (A_IN(A3) < 200){   // right Y
    if (servo_set[3] > 60) servo_set[3]--;
  }
  else if (A_IN(A3) >= 800) {
    if (servo_set[3] < 150) servo_set[3]++;
  }
}

2015年11月11日 星期三

訓練數學感 78 ─ X+Y 面積和多少?

http://4rdp.blogspot.tw/2015/11/78-xy.html

已知梯形 ABCD 面積 34 平方單位,三角形 BCG 面積 11 平方單位,另外還知道線段 AF 及 ED 各為 1 單位長度,請問三角形 BFG 及 CEG 兩者面積和為多少?(也就是兩個水藍色面積)

2015年11月7日 星期六

ROSA 系統開發 12 ─ SERVO 驅動

http://4rdp.blogspot.tw/2015/11/rosa-12-servo.html

影片來自 MeArm.Joytick

接下來 ROSA 將以 meArm 機械手臂為控制標的,加入伺服馬達驅動控制,

// (C) 2015, Bridan Wang, CC BY-NC-SA 3.0 TW
// http://4rdp.blogspot.tw/search/label/ROSA%20(Arduino)

// SERVO  SG90  pulse = 560 ~ 2000 us (0 ~ 180)
#define MAXus  2000
#define MINus  560
#define GAIN   (MAXus-MINus)/180.0
byte servo_pin[] = { 0, 4, 5, 6, 7};
byte servo_revse[] = { 0, 0, 1, 0, 0};
byte servo_angle[] = { 0, 0, 0, 0, 0};

void SERVO_SET(byte p){   // for SG90
  byte a = servo_angle[p];
  if (a >= 181) return;
  if (servo_revse[p]==1) a = 180 - a;
  D_OUT(servo_pin[p], HIGH);
  delayMicroseconds(GAIN*a+MINus);
  digitalWrite(servo_pin[p], LOW);
}


void PROCESS_10ms(){     // sweep 0 ~90 degree
  static byte dir = 0;
  
  if (dir==0){
    if (++servo_angle[1] >= 90)
      dir = 1;
  } else {
    if (--servo_angle[1] >= 180)
      dir = servo_angle[1] = 0;
  }
  SERVO_SET(1);   // servo 1
}

2015年11月4日 星期三

平方減一速算

http://4rdp.blogspot.tw/2015/11/blog-post.html

1 x 1 - 1 = 0 x 2
2 x 2 - 1 = 1 x 3
3 x 3 - 1 = 2 x 4
4 x 4 - 1 = 3 x 5
5 x 5 - 1 = 4 x 6
6 x 6 - 1 = 5 x 7
7 x 7 - 1 = 6 x 8
8 x 8 - 1 = 7 x 9
9 x 9 - 1 = 8 x 10

上週提出平方數和推導一文,讓我想到一個速算技巧,就如上面的算式表示,為什麼會有這麼規律恆等算式?