Embedded Programming‎ > ‎Examples‎ > ‎

Workshop Code

#include <superSerial.h>

// Boolean values
#define TRUE 1
#define FALSE 0

// Hardware Pin Information
#define POT_PIN 3
#define PHOTO_PIN 1
#define M1_PWM 3
#define M1_DIR 12
#define BUTTON 5
#define SYNC 2
#define LISTEN 4

// Output Bounds
#define OUT_MAX 255
#define OUT_MIN -255

// Timer Variables
unsigned long startTime, stopTime, now, lastTime, duration;

// PID Variables
double Setpoint, Input, Output, sampleTime, potVal, Last;
double P, I, D;
double Error, vError, Integral;
double timeChange, runTime;
double Kp, Ki, Kd;

// Setpoint achivement variables
#define P_ERR_MAX 10
#define V_ERR_MAX 2
int n, nReq = 30;


int choice;
int threshold = 250;
// Program Setup
void setup() {
 
  // Set serial communication baud rate
  Serial.begin(115200);
 
  // Initialize the Motor pins as output and turn them off
  pinMode (M1_PWM,OUTPUT); digitalWrite (M1_PWM,LOW);
  pinMode (M1_DIR,OUTPUT); digitalWrite (M1_DIR,LOW);
 
  pinMode (SYNC,OUTPUT);
  pinMode (LISTEN,INPUT);
 
  analogWrite (M1_PWM, 0);
 
  // Initialize and set default time length for the code
  duration = 5000; // How long to PID for in milli-seconds
}

void loop(){
  menu();
  choice = sSerial.readInt();
  switch(choice){
    case 1:
      digitalWrite(SYNC, HIGH);
      PID();
      while(digitalRead(LISTEN)!=HIGH){}
      break;
    case 2:
      Serial.println(readPot());
      break;
    case 3:
      while(analogRead(BUTTON)!=0){
        Serial.println(readPot());
      }
      break;
    case 4:
      Serial.println(readPhoto());
      break;
    case 5:
      while(analogRead(BUTTON)!=0){
        Serial.println(readPhoto());
      }
      break;
    case 6:
      digitalWrite(M1_DIR,HIGH);
      analogWrite(M1_PWM,150);
      while(readPhoto()<=threshold){}
      Serial.println(readPot());
      Setpoint = readPot();          //setpoint is global
      PID();
      break;
    default:
      break;
  }
}

void menu(){
  Serial.println("What would you like to do?");
  Serial.println(" ");
  Serial.println("1. Run PID");
  Serial.println("2. Read Pot (Instantaneous)");
  Serial.println("3. Read Pot (Continuous)");
  Serial.println("4. Read Photo (Instantaneous)");
  Serial.println("5. Read Photo (Continuous)");
  Serial.println("6. Run until readPhoto reaches threshold then PID to pot position"); //skeleton must have set PID values and remove questions at beginning
}

int readPot(){
  return analogRead(POT_PIN);


int readPhoto(){
  return analogRead(PHOTO_PIN);


// Main portion of the code
void PID() {
  // Ask for the Set Point value
  Serial.println();
  Serial.println("What would you like the Set Point to be?");
  Setpoint = sSerial.readFloat();
  Serial.print("Setpoint: ");
  Serial.println(Setpoint,0);
  Serial.println();
 
  // Ask for the PID gain values
  Serial.print("Kp?  ");
  Kp = sSerial.readFloat();
  Serial.println(Kp,3);
  Serial.print("Ki?  ");
  Ki = sSerial.readFloat();
  Serial.println(Ki,3);
  Serial.print("Kd?  ");
  Kd = sSerial.readFloat();
  Serial.println(Kd,3);
  Serial.println();  
   
  // Report back the PID value
  Serial.print("Kp: ");
  Serial.print(Kp,3);
  Serial.print(" Ki: ");
  Serial.print(Ki,3);
  Serial.print(" Kd: ");
  Serial.println(Kd,3);
  Serial.println();
 
  // Start of the PID code
  startTime = millis();
  lastTime = millis();
  stopTime = startTime;
  timeChange = 0;
  Integral = 0;
  n = 0;
  Last = analogRead (POT_PIN);
 
  // Runs the PID code for a set duration
  while ( n < nReq && (stopTime-startTime) < duration) {
    Input = analogRead (POT_PIN);
 
    Output = ComputePID();
 
    /*
    // Since output can be between -255 to 255, set the motor direction.
    // You may need to change LOW <-> HIGH depending on your pot/motor setup.
    // Do so if you see the turntable running the wrong direction.
    */
    if (Output > 0) {
      digitalWrite(M1_DIR,HIGH);
    }
    else {
      digitalWrite(M1_DIR,LOW);
    }
 
    analogWrite(M1_PWM,abs(Output));
 

      Serial.print("Pot Value: ");
      Serial.print(Input,3);
      Serial.print("          Drive: ");
      Serial.print(Output,3);
      Serial.print("          dt: ");
      Serial.println((timeChange)/1000,3);
 
    // Check the ending Criterion
    if ( abs(Error) < P_ERR_MAX && abs(vError) < V_ERR_MAX) { n++; }
  
    stopTime = millis();
  }
 
  runTime = (stopTime - startTime);
  runTime = runTime/1000;
 
  if ( n == nReq ) {
    Serial.print ("Setpoint has been REACHED!  Time (sec): ");
    Serial.println (runTime,3);
  }
  else {
    Serial.print ("Setpoint was NEVER reached! :(  Time (sec): ");
    Serial.println (runTime,3);
  }
 
  analogWrite(M1_PWM,0);
}


// Meat and Bone of the PID alogorithm computation - Look at Lecture notes
double ComputePID() {
  now = micros();
 
  timeChange = now-lastTime;
  Error = Setpoint-Input;
  vError = Error-Last;
  Integral = Integral + Error;
 
  P = Error * Kp;
  I = Integral * Ki * (timeChange/1000000);
  D = vError * Kd / (timeChange/1000000);
 
  Output = P + I + D;
 
  if (Output > OUT_MAX) Output = OUT_MAX;
  else if (Output < OUT_MIN) Output = OUT_MIN;
 
  lastTime = now;
  Last = Error;
 
return Output;
}

Comments