讀取 Futaba 2.4G 接收機 Channel 信號..
Code:
unsigned long TransmitterThrottle=0;
unsigned long TransmitterCH4=0;
void setup()
{
Serial.begin(9600);
pinMode ( 9, INPUT);
pinMode (10, INPUT);
clearLCD();
}
void CheckTransmitter()
{
TransmitterThrottle = (pulseIn (9, HIGH, 200000))/10;
TransmitterCH4 = (pulseIn (10, HIGH, 200000));
}
void loop()
{
CheckTransmitter();
clearLCD (); // 清除 LCD 畫面
Serial.print ("pulse= ");
Serial.print (TransmitterThrottle, DEC);
Serial.print (" CH4: ");
Serial.print (TransmitterCH4, DEC );
delay(100);
}
// ===== clear the LCD =====
void clearLCD()
{
Serial.print(12, BYTE);
}
輸出數值:
中立: 1509 ~ 1514
至左: 1381 ~ 1388
至右: 1633 ~ 1639
要先搞清楚這些數值的 跳動 原因 ...
~ 待續 ~
讀取 Futaba 2.4G 接收機油門信號..
Futaba FF9 2.4G 發射器
Futaba R617FS 2.4G 接收器
Arduino Pin 9 連接 接收器 pin 3 信號
11.1V 鋰電 和 Arduino 共地 (GND)
執行結果:顯示數值
油門最低點 110
油門最高點 191
Code:
unsigned long TransmitterThrottle=0;
void setup()
{
pinMode (9, INPUT);
Serial.begin(57600);
Serial.println("System Ready~");
}
void CheckTransmitter()
{
TransmitterThrottle = (pulseIn (9, HIGH, 200000))/10;
}
void loop()
{
CheckTransmitter();
Serial.print ("pulse: ");
Serial.println (TransmitterThrottle);
delay (200);
}
Stepper motor 步進馬達的控制:
把老舊的 彩色印表機拆了,
發現裡面有一顆步進馬達,
使用 Arduino 接上馬達的4條線,
我使用了 pin 9~12,
輕易控制馬達前進後退和速度..
Code:
#include
const int stepsPerRevolution = 100;
Stepper myStepper(stepsPerRevolution, 9,10,11,12);
void setup() {
myStepper.setSpeed(100);
Serial.begin(9600);
}
void loop() {
Serial.println("clockwise");
myStepper.step(stepsPerRevolution * 10);
delay(500);
Serial.println("counterclockwise");
myStepper.step(-stepsPerRevolution * 10 );
delay(500);
}
影片:
無刷馬達的控制..
使用材料:
Align ESC BL15X
Align BL250 Brushless motor
動作說明:
提升馬達速度, 降低馬達速度, 暫停..
Code:
#include
Servo myservo;
void setSpeed(int speed)
{
int val = map(speed, 0, 100, 0, 180);
myservo.write(val);
}
void setup()
{
Serial.begin(115200);
myservo.attach(9);
}
void loop()
{
Serial.println("System Ready !!! Hit the 1 ");
do{ if ( Serial.read() == '1' ) break; } while(1);
int speed;
Serial.println("Throttle up");
for(speed = 37; speed <= 90; speed += 1) { setSpeed(speed); Serial.println(speed); delay(100); } setSpeed(30); delay(1000); Serial.println("Throttle down"); for(speed = 90; speed > 37; speed -= 1) {
setSpeed(speed);
Serial.println(speed);
delay(100);
}
Serial.println("waiting for 5 sec...");
setSpeed(30);
delay(5000);
}
//=============================
另外也可以用程式..取代使用遙控器油門設定電變(ESC)的方式
例如電變的 緩啟動, 煞車模式, 截止電壓...等..
依照不同廠商生產不同的電變而有所差異..
Code:
// 程式設定ESC 狀態
void AdjustESC ()
{
//plug ESC Battery first, when ESC start music ready, enter "1" in serial window
Serial.println("Enter Setup Mode");
do{ if ( Serial.read() == '1' ) break;
setSpeed(90);
} while(1);
delay ( 2000 );
setSpeed(30);
// waiting for ESC edit mode music and into brake edit mode,
// then enter "1" in serial window
Serial.println("Break Mode - soft Brake");
do{ if ( Serial.read() == '1' ) break; } while(1);
setSpeed(50);
Serial.println("Electronic Timing -Mid timing");
do{ if ( Serial.read() == '1' ) break; } while(1);
setSpeed(50);
Serial.println("Battery Protection - High cut off voltage protection");
do{ if ( Serial.read() == '1' ) break; } while(1);
setSpeed(30);
Serial.println("Aircraft Mode - normal airplane");
do{ if ( Serial.read() == '1' ) break; } while(1);
setSpeed(30);
Serial.println("Throttle response speed - Quick speed");
do{ if ( Serial.read() == '1' ) break; } while(1);
setSpeed(90);
Serial.println("BEC output voltage - 5.5V");
do{ if ( Serial.read() == '1' ) break; } while(1);
setSpeed(50);
}
影片:
Wii Motion Plus
任天堂革命性的產品,
自己實作了一次,
這也算是窮人的陀螺儀吧..
//========= Arduino Code ========= #include <Wire.h> byte data[6]; //six data bytes int yaw, pitch, roll; //three axes int yaw0, pitch0, roll0; //calibration zeroes int startTag=0xDEAD; void wmpOn(){ Wire.beginTransmission(0x53); //WM+ starts out deactivated at address 0x53 Wire.send(0xfe); //send 0x04 to address 0xFE to activate WM+ Wire.send(0x04); Wire.endTransmission(); //WM+ jumps to address 0x52 and is now active } void wmpSendZero(){ Wire.beginTransmission(0x52); //now at address 0x52 Wire.send(0x00); //send zero to signal we want info Wire.endTransmission(); } void calibrateZeroes(){ for (int i=0;i<10;i++){ wmpSendZero(); Wire.requestFrom(0x52,6); for (int i=0;i<6;i++){ data[i]=Wire.receive(); } yaw0+=(((data[3]>>2)<<8)+data[0])/10; //average 10 readings for each zero pitch0+=(((data[4]>>2)<<8)+data[1])/10; roll0+=(((data[5]>>2)<<8)+data[2])/10; } /*Serial.print("Yaw0:"); Serial.print(yaw0); Serial.print(" Pitch0:"); Serial.print(pitch0); Serial.print(" Roll0:"); Serial.println(roll0);*/ } void receiveData(){ wmpSendZero(); //send zero before each request (same as nunchuck) Wire.requestFrom(0x52,6); //request the six bytes from the WM+ for (int i=0;i<6;i++){ data[i]=Wire.receive(); } yaw=(((data[3]>>2)<<8)+data[0]); //see http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus pitch=(((data[4]>>2)<<8)+data[1]); //for info on what each byte represents roll=(((data[5]>>2)<<8)+data[2]); } void setup(){ Serial.begin(115200); //Serial.println("WM+ tester"); Wire.begin(); wmpOn(); //turn WM+ on calibrateZeroes(); //calibrate zeroes delay(1000); } void loop(){ receiveData(); //receive data and calculate yaw pitch and roll Serial.write((unsigned byte*)&startTag, 2); //see diagram on randomhacksofboredom.blogger.com Serial.write((unsigned byte*)&pitch0, 2); //for info on which axis is which Serial.write((unsigned byte*)&yaw0, 2); Serial.write((unsigned byte*)&roll0, 2); Serial.write((unsigned byte*)&pitch, 2); Serial.write((unsigned byte*)&yaw, 2); Serial.write((unsigned byte*)&roll, 2); delay(10); } //================= End
//========= Processing Code =========
// 劃出波形
import processing.serial.*;
// Globals
int g_winW = 820; // Window Width
int g_winH = 600; // Window Height
boolean g_dumpToFile = false; // Dumps data to c:\\output.txt in a comma seperated format (easy to import into Excel)
boolean g_enableFilter = false; // Enables simple filter to help smooth out data.
cDataArray pitch0 = new cDataArray(200);
cDataArray yaw0 = new cDataArray(200);
cDataArray roll0 = new cDataArray(200);
cDataArray pitch = new cDataArray(200);
cDataArray yaw = new cDataArray(200);
cDataArray roll = new cDataArray(200);
cGraph g_graph = new cGraph(10, 190, 800, 400);
Serial g_serial;
PFont g_font;
void setup()
{
size(g_winW, g_winH, P2D);
println(Serial.list());
g_serial = new Serial(this, "COM3", 115200, 'N', 8, 1.0); //enter COM port of
g_font = loadFont("AVGmdBU-30.vlw"); //of arduino here
textFont(g_font, 20);
// This draws the graph key info
strokeWeight(1.5);
stroke(255, 0, 0); line(20, 440, 35, 440);
stroke(0, 255, 0); line(20, 460, 35, 460);
stroke(0, 0, 255); line(20, 480, 35, 480);
stroke(255, 0, 0); line(20, 500, 35, 500);
stroke(0, 255, 0); line(20, 520, 35, 520);
stroke(0, 0, 255); line(20, 540, 35, 540);
fill(0, 0, 0);
text("pitch0", 40, 450);
text("yaw0", 40, 470);
text("roll0", 40, 490);
text("pitch", 40, 510);
text("yaw", 40, 530);
text("roll", 40, 550);
//text("current raw", 180, 430);
//text("current deg/s", 320, 430);
if (g_dumpToFile)
{
// This clears deletes the old file each time the app restarts
byte[] tmpChars = {'\r', '\n'};
saveBytes("c:\\output.txt", tmpChars);
}
}
void draw()
{
// We need to read in all the avilable data so graphing doesn't lag behind
while (g_serial.available() >= 2*6+2)
{
processSerialData();
}
strokeWeight(1);
fill(255, 255, 255);
g_graph.drawGraphBox();
strokeWeight(1.5);
stroke(255, 0, 0);
g_graph.drawLine(pitch0, 0, 16384);
stroke(0, 255, 0);
g_graph.drawLine(yaw0, 0, 16384);
stroke(0, 0, 255);
g_graph.drawLine(roll0, 0, 16384);
stroke(255, 0, 0);
g_graph.drawLine(pitch, 0, 16384);
stroke(0, 255, 0);
g_graph.drawLine(yaw, 0, 16384);
stroke(0, 0, 255);
g_graph.drawLine(roll, 0, 16384);
}
// This reads in one set of the data from the serial port
void processSerialData()
{
int inByte = 0;
int curMatchPos = 0;
int[] intBuf = new int[2];
intBuf[0] = 0xAD;
intBuf[1] = 0xDE;
while (g_serial.available() < 2); // Loop until we have enough bytes
inByte = g_serial.read();
// This while look looks for two bytes sent by the client 0xDEAD
// This allows us to resync the server and client if they ever
// loose sync. In my testing I haven't seen them loose sync so
// this could be removed if you need to, but it is a good way to
// prevent catastrophic failure.
while(curMatchPos < 2)
{
if (inByte == intBuf[curMatchPos])
{
++curMatchPos;
if (curMatchPos == 2)
break;
while (g_serial.available() < 2); // Loop until we have enough bytes
inByte = g_serial.read();
}
else
{
if (curMatchPos == 0)
{
while (g_serial.available() < 2); // Loop until we have enough bytes
inByte = g_serial.read();
}
else
{
curMatchPos = 0;
}
}
}
while (g_serial.available() < 2*6); // Loop until we have a full set of data
// This reads in one set of data
{
byte[] inBuf = new byte[2];
int pitch0_cur, yaw0_cur, roll0_cur, pitch_cur, yaw_cur, roll_cur;
g_serial.readBytes(inBuf);
// Had to do some type conversion since Java doesn't support unsigned bytes
pitch0_cur = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
g_serial.readBytes(inBuf);
yaw0_cur = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
g_serial.readBytes(inBuf);
roll0_cur = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
g_serial.readBytes(inBuf);
pitch_cur = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
g_serial.readBytes(inBuf);
yaw_cur = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
g_serial.readBytes(inBuf);
roll_cur = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
pitch0.addVal(pitch0_cur);
yaw0.addVal(yaw0_cur);
roll0.addVal(roll0_cur);
pitch.addVal(pitch_cur);
yaw.addVal(yaw_cur);
roll.addVal(roll_cur);
if (g_dumpToFile) // Dump data to a file if needed
{
String tempStr;
tempStr = pitch0_cur + "," + yaw0_cur + "," + roll0_cur + "," + pitch_cur + "," + yaw_cur + "," + roll_cur + "\r\n";
FileWriter file;
try
{
file = new FileWriter("c:\\output.txt", true); //bool tells to append
file.write(tempStr, 0, tempStr.length()); //(string, start char, end char)
file.close();
}
catch(Exception e)
{
println("Error: Can't open file!");
}
}
/*
print(pitch0_cur); print(" "); print(yaw0_cur); print(" "); print(roll0_cur); print(" ");
print(pitch_cur); print(" "); print(yaw_cur); print(" "); println(roll_cur);
*/
}
}
// This class helps mangage the arrays of data I need to keep around for graphing.
class cDataArray
{
float[] m_data;
int m_maxSize;
int m_startIndex = 0;
int m_endIndex = 0;
int m_curSize;
cDataArray(int maxSize)
{
m_maxSize = maxSize;
m_data = new float[maxSize];
}
void addVal(float val)
{
if (g_enableFilter && (m_curSize != 0))
{
int indx;
if (m_endIndex == 0)
indx = m_maxSize-1;
else
indx = m_endIndex - 1;
m_data[m_endIndex] = getVal(indx)*.5 + val*.5;
}
else
{
m_data[m_endIndex] = val;
}
m_endIndex = (m_endIndex+1)%m_maxSize;
if (m_curSize == m_maxSize)
{
m_startIndex = (m_startIndex+1)%m_maxSize;
}
else
{
m_curSize++;
}
}
float getVal(int index)
{
return m_data[(m_startIndex+index)%m_maxSize];
}
int getCurSize()
{
return m_curSize;
}
int getMaxSize()
{
return m_maxSize;
}
}
// This class takes the data and helps graph it
class cGraph
{
float m_gWidth, m_gHeight;
float m_gLeft, m_gBottom, m_gRight, m_gTop;
cGraph(float x, float y, float w, float h)
{
m_gWidth = w;
m_gHeight = h;
m_gLeft = x;
m_gBottom = g_winH - y;
m_gRight = x + w;
m_gTop = g_winH - y - h;
}
void drawGraphBox()
{
stroke(0, 0, 0);
rectMode(CORNERS);
rect(m_gLeft, m_gBottom, m_gRight, m_gTop);
}
void drawLine(cDataArray data, float minRange, float maxRange)
{
float graphMultX = m_gWidth/data.getMaxSize();
float graphMultY = m_gHeight/(maxRange-minRange);
for(int i=0; i<data.getCurSize()-1; ++i)
{
float x0 = i*graphMultX+m_gLeft;
float y0 = m_gBottom-((data.getVal(i)-minRange)*graphMultY);
float x1 = (i+1)*graphMultX+m_gLeft;
float y1 = m_gBottom-((data.getVal(i+1)-minRange)*graphMultY);
line(x0, y0, x1, y1);
}
}
}
//================= End
RGB Led 1W
關鍵一:
Arduino Mini
腳位接到數位IO腳 3, 5, 6, 9, 10, 11 才能做輸出.. !!!
關鍵二:
此 RGB LED circuit 標示錯誤 - 負極..實際上要接 +正極,
R/G/B 接 Digital Pin, 共4線.. 不須接地線.
影片:
程式碼:
int R_ledPin = 9;
int G_ledPin = 10;
int B_ledPin = 11;
int ledPin = 13;
// val 255 = off
int R_val=254;
int G_val=254;
int B_val=254;
void setup()
{
pinMode(ledPin, OUTPUT);
pinMode( R_ledPin, OUTPUT);
pinMode( G_ledPin, OUTPUT);
pinMode( B_ledPin, OUTPUT);
Serial.begin ( 9600 );
analogWrite ( R_ledPin, R_val );
analogWrite ( G_ledPin, G_val );
analogWrite ( B_ledPin, B_val );
delay ( 1000 );
}
int dir=0;
int color = 0;
int offset = 5;
void loop()
{
digitalWrite(ledPin, HIGH);
switch ( color )
{
case 0: analogWrite ( R_ledPin, R_val ); break;
case 1: analogWrite ( G_ledPin, R_val ); break;
case 2: analogWrite ( B_ledPin, R_val ); break;
}
if ( dir == 0 )
{
if ( R_val - offset > 0 )
{
R_val -= offset;
}
else
{
R_val = 0;
dir = 1;
}
}
if ( dir == 1 )
{
if ( R_val + offset < 255 )
{
R_val += offset;
}
else
{
R_val = 254;
dir = 0;
if ( color + 1 < 3 ) color ++;
else color = 0;
}
}
//delay ( 300 );
clearLCD (); // 清除 LCD 畫面
// 輸出數值到 LCD
Serial.print ( "R= ");
Serial.print ( R_val, DEC );
Serial.print ( "\n");
}
// ===== clear the LCD =====
void clearLCD()
{
Serial.print(12, BYTE);
}
Part 4 - 控制 servo 轉動的速度, 而且要轉動的 Smooth
原始碼如下:
#include <Servo.h>
Servo myservo; // create servo object to control a servo
void setup()
{
Serial.begin(9600);
myservo.attach(9);
}
int pulse =2450;
int dir=1;
int offset=1;
void loop()
{
myservo.writeMicroseconds( pulse );
if ( pulse + offset >= 2450 ) dir = -1;
else if ( pulse - offset <= 600 ) dir = 1;
pulse += ( offset * dir);
Serial.println ( pulse, DEC );
}
arduino Mini 的學習之路..( Part -3 )
課目: 伺服馬達的控制 ( PWM )
Hitec HSR-8498HB 伺服馬達 ( 腳位接線圖 )
我這個實驗使用的是 Hitec HSR-8498HB 伺服馬達.
目前使用驅動模式選擇第一種已經成功.
這個馬達總共有3種模式,
1. Standard Pulse Mode (Pulse width 550 to 2450 Microseconds)
角度計算式 Servo Angle (degrees) = (Pulse Width (•S) – 1500) / 10
2. Extended Pulse Mode. (Pulse width 50 to 200 Microseconds) (未完成)
3. Serial Mode. (Pulse width 416 Microseconds) (未完成)
馬達的說明文件連結:
http://robosavvy.com/Builders/i-Bot/HSR8498HB%20Servo.pdf
^^ 上面影片的程式範例:
#include <Servo.h>
Servo myservo; // create servo object to control a servo
void setup()
{
Serial.begin( 19200 );
myservo.attach(9); //連接 Servo 信號到 Digital Pin 9
}
int angleVal=550;
void loop()
{
myservo.writeMicroseconds( angleVal ); //Pulse width 550 to 2450 Microseconds = Standard Pulse Mode
if ( angleVal + 100 <= 2450 )
{
angleVal += 100;
delay ( 1000 );
}
else angleVal = 550;
delay ( 300 );
int readdata=0;
readdata = myservo.read ();
Serial.println ( readdata );
}
arduino Mini 的學習之路..( Part -2 )
看了網頁上的一些前輩教學,( http://accrochages.drone.ws/en/node/90 )
接續我的 Arduino Part -1 ,
應用了 Processing 實現了圖形化的數據顯示,
因為開始複雜化了.. 2 x 16 LCD 不敷使用了
上面的曲線就是光敏電阻傳回來的數值.
接下來 Project 越來越精彩了... 敬請期待~
arduino Mini 的學習之路..( Part -1 )
使用 Mini USB 供應 5V電壓.
16 x 2 LCD 顯示 光敏電阻的數值.
~~ 安裝教學 Step By Step ~~
1. 先安裝電腦 Driver:
Download USBtoTTL Driver "CDM20600.exe",
下載連結 http://www.ftdichip.com/Drivers/VCP.htm
2. 將USB線插入電腦:
這時候打開工作管理員,
確認 COM PORT 的使用和驅動無誤( 使用的 PORT依情況會不同 ),
3. 執行 Arduino 0018:
設定 Tools->Board ( Arduino Mini )
設定 Tools->Serial Port ( COM 3)
4. 光感測器接線:
黑 - GND
紅 - 5V
白 - 信號 ( 接到 Arduino 的 digital pin 0 )
5. Parallax LCD接線:
GND
5V
RX (接到 Arduino 的 TX)
~~ 使用材料 ~~
1. Arduino Mini.
2. USBtoTTL Board.
3. USB Cable.
4. 光感測器
5. LED
6. 麵包板.
7. Parallax LCD
// 程式碼 //
int ledPin = 13; // LED connected to digital pin 13
int PhotoSPin = 0; // Photosensitive connected to digital pin 0
int Analog_val =0; // Photosensitive Val
void setup()
{
Serial.begin ( 9600 );
pinMode(ledPin, OUTPUT); // LED
pinMode(PhotoSPin, INPUT); // Photosensitive
}
void loop()
{
digitalWrite(ledPin, HIGH); // set the LED on
delay(Analog_val); // wait for a second
digitalWrite(ledPin, LOW); // set the LED off
delay(Analog_val); // wait for a second
Analog_val = analogRead(PhotoSPin); //讀取 光敏電阻 的數值
clearLCD (); // 清除 LCD 畫面
//===== 輸出數值到 LCD =====
Serial.print ( "Val= ");
Serial.print ( Analog_val, DEC );
Serial.print ( "\n");
}
// ===== clear the LCD =====
void clearLCD()
{
Serial.print(12, BYTE);
}


