Você está na página 1de 6

/* AnalogReadSerial Reads an analog input on pin 0, prints the result to the serial monitor This example code is in the

public domain. */ #include "AFMotor.h" // Input/Output Port Definitions for I/O and Motor Control #define SCANPIN 2 #define CONTROLPIN 19 #define MOTORPORT 3 // Constants used to calculate speeds of DC Motor #define PI 3.1415 #define N_STORED_VALUES 16 #define NBITS 255 #define MAXRPM 30 #define DEG_PER_VAL 22.5 #define SCALE 360/60*MAXRPM/NBITS // Global variables used throughout the program AF_DCMotor dcmotor(MOTORPORT, MOTOR12_64KHZ); double vin[20]; double vArray[N_STORED_VALUES]; int currentDirection = FORWARD; int speed, maxV; // Function to setup serial port and I/O ports void setup() { // set serial communication with 9600 baud rate Serial.begin(9600); speed = 55; dcmotor.setSpeed(speed); // Set the default state of the pins. Two digital input pins used to control t he software with pushbuttons. // Both digital input pins are active low. pinMode(SCANPIN, INPUT); digitalWrite(SCANPIN, HIGH); // enable internal pullup resistor pinMode(CONTROLPIN, INPUT); digitalWrite(CONTROLPIN, HIGH); // enable internal pullup resistor Serial.println("Self-Adjusting Antenna"); } // Scan function. Rotates the receiver in a full circle while reading in 20 volt age values during the rotation. // Remembers the maximum voltage read during the scan and returns the receiver t o the orientation that reads in // a voltage that is 180mV within the maximum. void scan() { int i, theta, count; double omega, wait; int e; // The default scan speed is 55. This is the slowest we can rotate the receive

r. Any lower speed cannot overcome // the initial inertia to begin rotating. int scanSpeed = 55; Serial.println("Start Scan!\n"); maxV = 0; dcmotor.setSpeed(scanSpeed); // omega is the speed in radians per second, calculated from the scan speed in bits and a scale factor. omega = (double) scanSpeed*SCALE; Serial.println(omega); // The wait variable holds the amount of time in milliseconds we should wait 2 0 measurements from the full 360 deg. wait = (double) DEG_PER_VAL/omega*1000; Serial.println(wait); dcmotor.run(FORWARD); // This for loop reads the voltage into an array and tests the input to the st ored maximum voltage. If the new value // is greater, it becomes the max voltage. for(i=0; i < N_STORED_VALUES; i++) { vArray[i] = analogRead(A0); Serial.println(vArray[i]); if(vArray[i] > maxV) { maxV = vArray[i]; // new maximum voltage found } delay(wait); } Serial.println(maxV); dcmotor.run(RELEASE); delay(1000); // Now we run backwards and do not stop until the input voltage is 180 mV with in the determined maximum voltage maxV. dcmotor.run(BACKWARD); while(e >= 9) { e = abs(analogRead(A0) - maxV); count = count + 1; if(count == 1000) e = 0; } // At this point, we should be near the optimal orientation. dcmotor.run(RELEASE); delay(2000); } // The main loop function. There are two controlling switches that put the progr am into various modes, depending on the // order switches are pressed. When the scan pin is pressed, the system performs a scan. When the control pin is pressed, // the system goes into control mode where the P or PID controller maintains the orientation in an optimal direction. While

// in this mode, if the scan pin is pressed, the program goes into debug mode wh ere the analog voltage input is simply printed // to the hyperterminal window connected serially. To get out of debug mode and back to controller mode, scan pin should be // pressed again. This ability would be disabled for the product for the end-use r. The end-user would only have access to // begin a scan or begin the control program. void loop() { int i, analogIn, errCount, lowVCount, vAvg, wait; int voltArray[4]; int e[3]; double k, kd, ki, K; // if pin scanPin is 1, we must perform a scan Serial.println("waiting2"); errCount = 0; // If the scan pin is low, call the scan function. if(digitalRead(SCANPIN) == LOW) { scan(); } // If the control pin is low, perform control law else if(digitalRead(CONTROLPIN) == LOW) { Serial.println("Start control system!\n"); delay(2000); speed = 0; // e[0] holds the error between the last voltage input and the current input . These error values get pushed through // the e array from e[0] to e[1] to e[2] to be used in the PID controller. e[0] = e[1] = e[2] = 0; vin[0] = vin[1] = analogRead(A0); // the lowVCount variable keeps count of the number of times in a row the vo ltage is too low. If this number reaches // 15 the controller sends the receiver into a scan to get close to optimal orientation again. lowVCount = 0; // Control software loop while(digitalRead(CONTROLPIN) == HIGH) { analogIn = analogRead(A0); // keep track of the max voltage if(maxV < analogIn) { maxV = analogIn; } // increment the low voltage counter if the input voltage is too low (70% of max) if(analogIn < 0.7*maxV) {

lowVCount++; } else { lowVCount = 0; } // if low voltage 15 times in a row, we perform a scan. if(lowVCount == 15) { scan(); speed = 0; dcmotor.setSpeed(speed); lowVCount = 0; } vin[0] = analogIn; // e = v(k) - v(k-1). Positive e means direction is correct. // compute the error e[2] = e[1]; e[1] = e[0]; e[0] = vin[0] - vin[1]; vin[1] = vin[0]; Serial.println(vin[0]); wait = 500; /* // This is the PID controller used in testing. Kc is the proportional gain, KcKi is the integral gain, KcKd is the derivative gain. // The formula used for PID control is below, where us is the speed. // u(t) = u(t-1) + Kc(e(t) - e(t-1)) + KcKie(t) + KcKd(e(t) - 2e(t-1) + e( t-2)) k = 1; kd = 0.2; ki = 0.6; speed = speed + k*(e[0] - e[1]) + ki*e[0] + kd*(e[0] - 2*e[1] + e[2]); error = (k*(e[0] - e[1]) + ki*e[0] + kd*(e[0] - 2*e[1] + e[2]))/wait; speed = 1000*error + 15; */ // This is the proportional controller used in testing. K is the proportio nal gain. Because of the effect of inertia to begin // rotating the reflector system, we add a constant of 15 to the computed speed. K = 4.4; speed = K*e[0] + 15; // We ensure that the speed is positive (negative speed sending to the mot or ports send max speed). speed = abs(speed); // Threshold on the max speed to ensure forces are not too high so as to p rotect the hardware. if(speed > 55) speed = 85;

dcmotor.setSpeed(speed); // Thresholding on the computed error. If error is low enough, we do not e xpect the system to require rotation if(e[0] > 3) { dcmotor.run(currentDirection); errCount = 0; } else if(e[0] < -3) { errCount = errCount + 1; if(e[0] > -10) { // To determine the direction to run, if the error is large enough neg ative (200mV), then we change direction. if(currentDirection == FORWARD) currentDirection = BACKWARD; else if (currentDirection == BACKWARD) currentDirection = FORWARD; // Since we made a step in the wrong direction, we offset this by rota ting in the opposite direction for a small period of time. dcmotor.setSpeed(55); dcmotor.run(currentDirection); delay(2*wait); dcmotor.setSpeed(speed); dcmotor.run(RELEASE); //delay(wait); errCount = 0; } // dcmotor.run(currentDirection); } else { dcmotor.run(RELEASE); } delay(wait); // The debug mode which prints analog voltage input to the screen if(digitalRead(SCANPIN) == LOW) { dcmotor.run(RELEASE); delay(1000); while(digitalRead(SCANPIN) == HIGH) { analogIn = analogRead(A0); Serial.println(analogIn); } delay(1000); dcmotor.run(RELEASE); } } delay(1000); } else {

dcmotor.run(RELEASE); } }

Você também pode gostar