#include <Servo.h>
#include <LiquidCrystal.h>
#include <PID_v1.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // initialize the library with the numbers of thepins interface
Servo myservo; // create servo object to control a servo
int pot_pin = 3; // analog pin used to connect the potentiometer
int spd; // variable to read the value from the analog pin
int curr_pin = 5; // current input pin
int curr;
int set_spd;
int anl_0;
int anl_1;
int anl_2;
int anl_3;
int anl_4;
int anl_5;
int set_screen = 5; //input pin for screen switching
int myscr =0;
float volts = 0;
long previousMillis = 0;
long interval = 500;
const int numReadings = 10; //smoothing averages last 10 readings from current pin
int readings[numReadings]; // array for readings
int index = 0; // the index of the current reading
int total = 0; // the running total
int curr_average = 0;
int curr_average1 = 0;
int curr_average2 = 0;
float curr_average3 = 0;
int top_spd = 0;
int pid_spd = 0;
int mypid = 0;
// ------------ PID setup -------------
double Sensor, Pid_Setting, Pid_Output; //Define the Tuning Parameters for PID
double pid_p, pid_i, pid_d; //Define the Tuning Parameters for PID
PID myPID(&Sensor, &Pid_Output,&Pid_Setting,pid_p,pid_i,pid_d, REVERSE);
// ----------------------------------------
void setup()
{
Serial.begin(9600);
myservo.attach(3); // attaches the servo on pin 9 to the servo object
lcd.begin(20, 4);
pinMode(set_screen, INPUT_PULLUP);
for (int thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0;
myPID.SetMode(AUTOMATIC); //initialize pid
myPID.SetOutputLimits(5, 50); //set maximum output value to max throttle value
myPID.SetSampleTime(10); //compute pid every 10 ms
myPID.SetTunings(.8, 2.5, 0);
}
void loop() {
smooth(); // calls current smoothing algorithym
curr_average1 = curr_average - 122; // subtract out static reading
curr_average3 = curr_average1 / 8.00; // scaling to show actual current
anl_4 = analogRead(4);
volts = (anl_4/34.53);
set_spd = analogRead(pot_pin); // reads the value of the potentiometer (value between 0 and 1023)
// actual reading from hall effect throttle aproximately 200 - 800
spd = map(set_spd, 200, 800, 50, 120); // scale it to use it with the servo (value between 60 and 120)
//200 to 800 is observed input range using hall efffect throttle
Pid_Setting = 7; // hard coded 50 amp current lmit
Sensor = curr_average3;
myPID.Compute();
mypid = Pid_Output;
pid_spd = (spd - Pid_Output);
if (Sensor > 2 ) { spd = pid_spd; }
myservo.write(spd);
anl_0 = analogRead(0);
anl_1 = analogRead(1);
anl_2 = analogRead(2);
anl_3 = analogRead(3);
anl_5 = analogRead(5);
if (digitalRead(set_screen) == 0) myscr = myscr + 1; // switch through the output screens
if (myscr < 0) myscr = 3;
if (myscr > 3) myscr = 0;
unsigned long currentMillis = millis(); // this code gives write data without use of delay
if(currentMillis - previousMillis > interval) { // interval coded above to 500 millis
previousMillis = currentMillis;
switch (myscr) {
case 1: write_data1();
break;
case 2: write_data2();
break;
case 3: write_data3();
break;
default: write_data();
}}}
void write_data() { // these data screens not complete... some duplicates
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Raw Input Spd ");
lcd.print(set_spd);
lcd.setCursor(0, 1);
lcd.print("Set Speed ");
lcd.print(spd);
lcd.setCursor(0, 2);
lcd.print("Volts ");
lcd.print(volts);
lcd.setCursor(13, 2);
lcd.print("Raw ");
lcd.print(mypid);
lcd.setCursor(0, 3);
lcd.print("Curr ");
lcd.print(curr_average3);
//lcd.setCursor(15, 3);
//lcd.print(average3);
}
void write_data1() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Analog 3 Input ");
lcd.print(set_spd);
lcd.setCursor(0, 1);
lcd.print("Set Speed ");
lcd.print(spd);
lcd.setCursor(0, 2);
lcd.print("Volts ");
lcd.print(anl_3);
lcd.setCursor(0, 3);
lcd.print("MPH ");
lcd.print(set_spd);
lcd.setCursor(11, 3);
lcd.print("Curr ");
lcd.print(anl_0);
}
void write_data2() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Analog 4 Input ");
lcd.println(set_spd);
lcd.setCursor(0, 1);
lcd.print("Set Speed ");
lcd.println(spd);
lcd.setCursor(0, 2);
lcd.print("PID Speed ");
lcd.println(pid_spd);
lcd.setCursor(0, 3);
lcd.print("MPH ");
lcd.print(set_spd);
lcd.setCursor(11, 3);
lcd.print("Curr ");
lcd.print(anl_0);
delay(500);
}
void write_data3() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Analog 4 Input ");
lcd.print(set_spd);
lcd.setCursor(0, 1);
lcd.print("Set Speed ");
lcd.print(spd);
lcd.setCursor(0, 2);
lcd.print("Volts ");
lcd.print(anl_3);
lcd.setCursor(0, 3);
lcd.print("MPH ");
lcd.print(set_spd);
lcd.setCursor(11, 3);
lcd.print("Curr ");
lcd.print(anl_0);
}
void smooth() {
total= total - readings[index]; // subtract the last reading:
readings[index] = analogRead(curr_pin); // read from the sensor:
total= total + readings[index]; // add the reading to the total:
index = index + 1; // advance to the next position in the array:
if (index >= numReadings) // if we're at the end of the array...
index = 0; // ...wrap around to the beginning:
curr_average = total / numReadings; // calculate the average:
// send it to the computer as ASCII digits
// Serial.println(curr_average);
//delay(1); // delay in between reads for stability
}