上拉式磁懸浮

科展用(確定可用)

float kp=0.25 ; //比例

float kd=700 ; //微分

int c = 20 ; //常數

int set = 512 ; //設定點 (介於AnalogRead讀數範圍 0~1023之間)

int now ;

int err,old,output ;

unsigned long t1,t2;

float p,d;

void setup() {

//Serial.begin(9600);

}

void loop() {

now = analogRead(A0);

if(now<20){

analogWrite(3,0);

}else{

t2=micros();

err = now - set ;

p = kp * err ;

d = kd *1000* (now - old)/(t2-t1) ;

output=constrain(p + d ,-127,127);

analogWrite(3,output + 127);

old = now ;

t1=t2;

Serial.print("now=");

Serial.print(now);

Serial.print(" , ");

Serial.print("err=");

Serial.print(err);

Serial.print(" , ");

Serial.print("p=");

Serial.print(p);

Serial.print(" , ");

Serial.print("d=");

Serial.print(d);

Serial.print(" , ");

Serial.println(output+128);

}

}

//Hall effect sensor

int x=21;

int i,j,p1[21],p2[21],timer=0,temp,now,old,error,output,setpoint = 382,total;

unsigned long t,oldt;

float p,d,kp = -0.6,kd = -25;

void setup() {

//Serial.begin(9600);

}

void loop() {

timer =timer % x;

old = now;

p1[timer] = analogRead(A0);

now = p1[timer];

for(i=0;i<x;i++)

{

p2[i] = p1[i];

}

timer++;

for(i=0;i<(x-1);i++)

{

for(j=0;j<10;j++)

{

if(p2[j+1] >= p2[j])

{

temp = p2[j];

p2[j] = p2[j+1];

p2[j+1] = temp;

}

}

}

t = micros(); //紀錄時間(單位:微秒)

error = p2[10] - setpoint ; //設誤差值(error)=現在感應的光度(now)-預設光度(setpoint)

p =kp*error; //設函數(p)=誤差值*對應比例(kp)

d =kd*(now - old)*1000/ (t - oldt); //注三

output = constrain(p+100+d,0,255); //注四

if(now>=762)

output = 0;

analogWrite(3,output); //注五 //更新過去時間(oldt)

/* Serial.print(p2[0]);

Serial.print(" , ");

Serial.print(p2[1]);

Serial.print(" , ");

Serial.print(p2[2]);

Serial.print(" , ");

Serial.print(p2[3]);

Serial.print(" , ");

Serial.print(p2[4]);

Serial.print(" , ");

Serial.print(p2[5]);

Serial.print(" , ");

Serial.print(p2[6]);

Serial.print(" , ");

Serial.print(p2[7]);

Serial.print(" , ");

Serial.print(p2[8]);

Serial.print(" , ");

Serial.print(p2[9]);

Serial.print(" , ");

Serial.print(p2[10]);

Serial.print(" , ");*/

Serial.print( p1[timer]);

Serial.print(" , ");

Serial.println(error);

oldt = t;

total = 0;

}

參考"給邪惡天才的15個危險瘋狂專題"並稍作修改(確定可用)

// Project 13 - Anti-gravity

// 15 Dangerous Projects for the Evil Genius

#define coilPin 3

#define irPin 13

#define sensorPin 0

int A = 2;

// Adjust B to improve stability

int B = 80;

int C = 20;

int D = 1000;

int maxPower = 255;

long powerCountThreshold = 300000;

int objectPresent = 0;

int monitoring = false;

void setup()

{

pinMode(coilPin, OUTPUT);

pinMode(irPin, OUTPUT);

pinMode(sensorPin, INPUT);

Serial.begin(9600);

Serial.println("Ready");

Serial.println("m - toggle monitoring");

Serial.println("B - increase B");

Serial.println("b - decrease B");

}

void loop()

{

static int count = 0;

static int oldPosition = 0;

static int ambient = 0;

static long powerCount = 0;

count ++;

if (count == 1000)

{

ambient = readAmbient();

count = 0;

objectPresent = (powerCount < powerCountThreshold);

powerCount = 0;

}

int raw = analogRead(sensorPin);

// position from top (0) of sensor region to the bottom (650)

int position = raw - ambient;

// positive value means going downwards, negative going upwards

int velocity = position - oldPosition;

int power = position / A + velocity * B + C;

powerCount += power;

oldPosition = position;

// clip

if (power > maxPower) power = maxPower;

if (power < 0) power = 0;

checkSerial();

if (monitoring)

{

Serial.print(position); Serial.print(",");

Serial.println(velocity);

}

analogWrite(coilPin, power * objectPresent);

delayMicroseconds(D);

}

int readAmbient() //todo try speding up delay in micros

{

digitalWrite(irPin, LOW);

// allow time for LED and phototransistor to settle

delayMicroseconds(100);

int ambient = analogRead(sensorPin);

digitalWrite(irPin, HIGH);

return ambient;

}

void checkSerial()

{

if (Serial.available())

{

char ch = Serial.read();

if (ch == 'm')

{

monitoring = ! monitoring;

}

if (ch == 'B')

{

B += 5;

Serial.println(B);

}

if (ch == 'b')

{

B -= 5;

Serial.println(B);

}

}

}