介紹
設計理念
4. 轉彎部份,有一輪不動一輪動的 定軸轉彎,另一種是兩輪反向的定中心轉彎。
5. 筆跡會沾輪部份,除移動速度放慢,另外底座加個吹風風扇吹乾。
工具
製作過程
使用編碼器精準控制移動的方式
使用 IRS01A IR Sensor 去讀取輪子的移動,輪子內會裝上雷切出來的板子,在板子邊緣有多個洞。
轉 G code 的程式碼參考:
https://github.com/dherrendoerfer/uCNC_controller/blob/master/uCNC_controller/uCNC_gcode.ino
問題
20150502 進度
黃偉峻提供小車機構模組,章國俊兄已經把藍芽控制小車的方式完成,目前可以用藍牙來操縱了,不過真的一跑就歪了,因為還沒用到編碼器。XD,紀錄請見下方影片。
*
https://www.youtube.com/watch?v=uCvYBIGFheU
20150502 進度2
後來把萬向輪上油潤滑之後,車子行進路立刻改善了,直很多了。
裝上遮斷開關,配合車子套件的碼盤。
計劃拿手機或筆電用藍芽和小車連線,指揮小車往前走多少公分、到定點後轉幾度、什麼地方要下筆。
小車接受指令並且自己修正。
20150506
馬爸把前輪換成這個。
原先的輪子在轉向時會因為本身旋轉歸位得時間差,而造成行進路線的誤差。
這個輪子就沒這個問題了。
20150507
用遮蔽膠帶量輪子圓周長:
20150511
車子的操控一整個改善了!
20150513
基本教練:第一課
其實是想要寫一個"口"字....
*
https://www.youtube.com/watch?v=36ZA0ze9PFw
還沒有做到校正的部份
以目前的機構沒有辦法做到精準,所以寫字應該會像是塗鴉。既然是塗鴉,就真的來塗鴉好了。
在手機上亂畫
因為用車子來寫字,也就是要用輪子走到定點,而車子的控制方式不像是CNC可以直接告訴它走到哪一個座標上面,而要轉方向盤、踩油門。
所以用手機計算:把在螢幕圖形的X,Y座標轉成極座標,然後再轉成轉方向盤、踩油門的指令,來控制車子。
用Android手機透過藍芽與Arduino控制的小車連線,讓小車以移動自身位置的方式畫出手機上面的圖形。
圖形可以運用APP以手指頭在螢幕上畫出,或是使用 APP中內建的特殊圖形(在影片中是個玫瑰線)。
目前小車還不能很準確的移動到所望位置,所以影片中的玫瑰線畫完之後首尾沒辦法連起來,差距很大。
手機上面可以同步顯示畫出的進度了
*
https://www.youtube.com/watch?v=oj6462PY5eQ
在2015的 maker faire 過後,完程度大約70%,機構還需要再做修改。看看運動可不可以再精確一點。
這樣的寫字方式,把筆放在兩個輪子之間較為適合。
筆可以做成模組,或可換成滴水的方式,我想在地上寫字啊!
滴水的方式可以參考:
馬達考慮換成扭力更大或自帶編碼器的馬達,或是用步進馬達或是修改舵機(360度旋轉)來用。
另一支的影片:
運作方式
機構
連線與遙控
程式碼
penWriting
//servo control
unsigned char servo = 6;
unsigned char count = 0;
unsigned char i = 0;
unsigned char servoTime = 0;
unsigned char servoValue = 0;
unsigned char flag = 0;
unsigned int secondT = 0;
unsigned int k = 0;
//pen
const unsigned int down = 50;
const unsigned int up = 100;
//motor
int L1 = 9;
int L2 = 7;
int R1 = 10;
int R2 = 8;
//speed and time
int dir = 0;
int speeds = 0;
unsigned long time = 0;
long serialValue = 0;
int length = 0;
unsigned char cmd[400];
void setup()
{
UBRRL=103; //16M baud 9600,8bit UART
UCSRB=0x18; //enable
pinMode(servo,OUTPUT);
digitalWrite(servo,LOW);
//pin for motor
pinMode(L1,OUTPUT);
pinMode(L2,OUTPUT);
pinMode(R1,OUTPUT);
pinMode(R2,OUTPUT);
timer2();
TIMSK &= ~(2 << 6);
digitalWrite(servo,LOW);
time = 300;
penWrite();
penRise();
}
void loop()
{
while(!(UCSRA&(1<<RXC)));
if(UDR == 170)
{
while(!(UCSRA&(1<<RXC)));
if(UDR == 85)
{
while(!(UCSRA&(1<<RXC)));
length = UDR;
length = length << 2;
for (k = 0;k<length;++k)
{
while(!(UCSRA&(1<<RXC)));
cmd[k] = UDR;
while(!(UCSRA&(1<<RXC)));
cmd[++k] = UDR;
while(!(UCSRA&(1<<RXC)));
cmd[++k] = UDR;
while(!(UCSRA&(1<<RXC)));
cmd[++k] = UDR;
}
while(!(UCSRA&(1<<RXC)));
if(UDR != 0xe0)
return;
while(!(UCSRA&(1<<RXC)));
if(UDR != 0x07)
return;
for (k = 0;k<length;++k)
{
dir = (cmd[k] & 0xf0) >> 4;
speeds = (cmd[k] & 0xf) * 17;
time = 0;
time = time | cmd[++k];
time = time << 8 | cmd[++k];
time = time << 8 | cmd[++k];
switch (dir)
{
case 8:
stoprun();
break;
case 0:
gforward();
break;
case 1:
gback();
break;
case 2:
turnLeft();
break;
case 3:
turnRight();
break;
case 4:
gLF();
break;
case 5:
gRF();
break;
case 6:
gLB();
break;
case 7:
gRB();
break;
case 9:
penWrite();
break;
case 10:
penRise();
break;
default: stoprun();
}
}
cmd[0] = UDR;
}
}
}
//timer2 for servo control
void timer2()
{
noInterrupts();
TCCR2 = 0x0f; //CTC,1024
OCR2 = 155;
TIMSK |= (2 << 6);
interrupts();
}
//each interrupt 25hz
ISR(TIMER2_COMP_vect)
{
//two intrupt as a circle
if(secondT == 0)
{
digitalWrite(servo,HIGH);
secondT++;
flag = 0;
}
else
{
secondT = 0;
}
//finished in 10ms
for(count = 0;count<127;count++)
{
if(flag == 1)
{
return;
}
//for(i = 0;i != 120;i++);
delayMicroseconds(76);
if(servoTime == servoValue)
{
digitalWrite(servo,LOW);
flag = 1;
servoTime = 0;
//secondT++;
return;
}
else
{
servoTime++;
}
}
}
//stop
void stoprun()
{
digitalWrite(L1,LOW);
digitalWrite(L2,LOW);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
delay(time);
}
void gforward()
{
//leftmotor
analogWrite(L1,speeds);
digitalWrite(L2,LOW);
//right motor
analogWrite(R1,speeds);
digitalWrite(R2,LOW);
delay(time);
digitalWrite(L1,LOW);
digitalWrite(R1,LOW);
}
//goback
void gback()
{
//leftmotor
analogWrite(L1,speeds);
digitalWrite(L2,HIGH);
//right motor
analogWrite(R1,speeds);
digitalWrite(R2,HIGH);
delay(time);
digitalWrite(L1,LOW);
digitalWrite(L2,LOW);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
}
void turnLeft()
{
analogWrite(L1,speeds);
digitalWrite(L2,HIGH);
analogWrite(R1,speeds);
digitalWrite(R2,LOW);
delay(time);
digitalWrite(L1,LOW);
digitalWrite(L2,LOW);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
}
void turnRight()
{
analogWrite(L1,speeds);
digitalWrite(L2,LOW);
analogWrite(R1,speeds);
digitalWrite(R2,HIGH);
delay(time);
digitalWrite(L1,LOW);
digitalWrite(L2,LOW);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
}
void gLF()
{
analogWrite(L1,speeds/2);
digitalWrite(L2,LOW);
analogWrite(R1,speeds);
digitalWrite(R2,LOW);
delay(time);
digitalWrite(L1,LOW);
digitalWrite(L2,LOW);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
}
void gRF()
{
analogWrite(L1,speeds);
digitalWrite(L2,LOW);
analogWrite(R1,speeds/2);
digitalWrite(R2,LOW);
delay(time);
digitalWrite(L1,LOW);
digitalWrite(L2,LOW);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
}
void gLB()
{
analogWrite(L1,speeds/2);
digitalWrite(L2,HIGH);
analogWrite(R1,speeds);
digitalWrite(R2,HIGH);
delay(time);
digitalWrite(L1,LOW);
digitalWrite(L2,LOW);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
}
void gRB()
{
analogWrite(L1,speeds);
digitalWrite(L2,HIGH);
analogWrite(R1,speeds/2);
digitalWrite(R2,HIGH);
delay(time);
digitalWrite(L1,LOW);
digitalWrite(L2,LOW);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
}
void penWrite()
{
TIMSK |= (2 << 6);
servoValue = 14;
delay(150);
delay(time);
}
void penRise()
{
TIMSK |= (2 << 6);
servoValue = 20;
delay(150);
delay(time);
}
參考資料