3rd year levitator

Dependencies:   MovingAverage NOKIA_5110 PinDetect mbed

Files at this revision

API Documentation at this revision

Comitter:
Generic
Date:
Sun Sep 09 18:45:52 2018 +0000
Commit message:
Test

Changed in this revision

MovingAverage.lib Show annotated file Show diff for this revision Revisions of this file
NOKIA_5110.lib Show annotated file Show diff for this revision Revisions of this file
Pattern/Pattern.cpp Show annotated file Show diff for this revision Revisions of this file
Pattern/Pattern.h Show annotated file Show diff for this revision Revisions of this file
PinDetect.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r d7cc9bad311b MovingAverage.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MovingAverage.lib	Sun Sep 09 18:45:52 2018 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/fblanc/code/MovingAverage/#ad69440a9bef
diff -r 000000000000 -r d7cc9bad311b NOKIA_5110.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NOKIA_5110.lib	Sun Sep 09 18:45:52 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Fuzball/code/NOKIA_5110/#9cfce382e741
diff -r 000000000000 -r d7cc9bad311b Pattern/Pattern.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Pattern/Pattern.cpp	Sun Sep 09 18:45:52 2018 +0000
@@ -0,0 +1,42 @@
+#include "Pattern.h"
+
+char pattern1[ROWS][COLUMNS] = {
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x041,0x041,0x07F,0x07F,0x041,0x041,0x00,0x00,0x00,0x01C,0x03E,0x062,0x041,0x041,0x041,0x00,0x07C,0x0E,0x0B,0x09,0x0B,0x0E,0x07C,0x00,0x07F,0x07F,0x06,0x0C,0x018,0x03F,0x07F,0x00,0x00,0x00,0x07F,0x07F,0x08,0x08,0x08,0x07F,0x07F,0x00,0x07C,0x0E,0x0B,0x09,0x0B,0x0E,0x07C,0x00,0x061,0x071,0x049,0x047,0x043,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x07F,0x07F,0x040,0x040,0x040,0x040,0x00,0x07F,0x07F,0x049,0x049,0x049,0x049,0x049,0x00,0x07,0x0F,0x018,0x030,0x060,0x040,0x060,0x030,0x018,0x0F,0x07,0x00,0x00,0x041,0x041,0x07F,0x07F,0x041,0x041,0x00,0x03,0x03,0x03,0x07F,0x07F,0x03,0x03,0x03,0x00,0x07C,0x0E,0x0B,0x09,0x0B,0x0E,0x07C,0x00,0x00,0x03,0x03,0x03,0x07F,0x07F,0x03,0x03,0x03,0x00,0x041,0x041,0x07F,0x07F,0x041,0x041,0x00,0x01C,0x022,0x041,0x041,0x041,0x022,0x01C,0x00,0x07F,0x07F,0x06,0x0C,0x018,0x03F,0x07F},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+char pattern2[ROWS][COLUMNS] = { 
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07F,0x071,0x011,0x011,0x01F,0x00,0x07F,0x011,0x011,0x011,0x011,0x011,0x02A,0x044,0x00,0x07F,0x07F,0x049,0x049,0x049,0x049,0x049,0x00,0x046,0x049,0x049,0x049,0x049,0x031,0x00,0x046,0x049,0x049,0x049,0x049,0x031,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07F,0x07F,0x049,0x049,0x049,0x049,0x049,0x036,0x00,0x07F,0x07F,0x040,0x040,0x040,0x040,0x00,0x03F,0x03F,0x060,0x060,0x060,0x060,0x060,0x03F,0x03F,0x00,0x07F,0x07F,0x049,0x049,0x049,0x049,0x049,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07F,0x07F,0x049,0x049,0x049,0x049,0x049,0x036,0x00,0x03F,0x03F,0x060,0x060,0x060,0x060,0x060,0x03F,0x03F,0x00,0x00,0x03,0x03,0x03,0x07F,0x07F,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x03,0x07F,0x07F,0x03,0x03,0x03,0x00,0x01C,0x022,0x041,0x041,0x041,0x022,0x01C,0x00,0x07F,0x07F,0x06,0x0C,0x018,0x03F,0x07F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x080,0x0C0,0x0E0,0x0F0,0x0F8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x080,0x040,0x020,0x010,0x010,0x090,0x090,0x090,0x010,0x010,0x020,0x040,0x080,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x01C,0x03E,0x07F,0x0FF,0x0FF,0x0FF,0x0FF,0x0FF,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x01F,0x00,0x01F,0x020,0x040,0x080,0x0E,0x01F,0x03F,0x03F,0x03F,0x01F,0x0E,0x080,0x040,0x020,0x01F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+void DisplayPattern(NokiaLcd *lcd, int pattern_num)
+{
+    lcd->ClearLcdMem();
+    lcd->SetXY(0,0);
+
+    for( int i = 0; i < ROWS ; i++ )
+    {
+        for( int j = 0; j < COLUMNS ; j++)
+        {
+            if( pattern_num == 1 )
+            {
+                lcd->SendDrawData(pattern1[i][j]);
+            }
+            else
+            {
+                lcd->SendDrawData(pattern2[i][j]);
+            }
+            
+            
+        }
+    }
+}
diff -r 000000000000 -r d7cc9bad311b Pattern/Pattern.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Pattern/Pattern.h	Sun Sep 09 18:45:52 2018 +0000
@@ -0,0 +1,14 @@
+#ifndef PATTERN_H
+#define PATTERN_H
+
+#include "NOKIA_5110.h"
+
+#define ROWS 6
+#define COLUMNS 84
+
+extern char pattern1[ROWS][COLUMNS];
+extern char pattern2[ROWS][COLUMNS];
+
+void DisplayPattern(NokiaLcd*,int pattern_num);
+
+#endif
diff -r 000000000000 -r d7cc9bad311b PinDetect.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PinDetect.lib	Sun Sep 09 18:45:52 2018 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/AjK/code/PinDetect/#cb3afc45028b
diff -r 000000000000 -r d7cc9bad311b main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Sep 09 18:45:52 2018 +0000
@@ -0,0 +1,663 @@
+#include "mbed.h"
+#include "NOKIA_5110.h"
+#include "PinDetect.h"
+#include "Pattern.h"
+#include "MovingAverage.h"
+
+#define PWM_PERIOD_US 100 //10kHz
+#define MAX_PWM 1.0f //Maximum duty cycle 100%
+#define MIN_PWM 0.0f //Minimum duty cycle 0%
+#define OPEN 17080.0f //No object sensor value
+#define CLOSED 0.1f //Fully obstructed sensor value
+#define REFERENCE 1150.0f //Setpoint (desired) sensor value
+#define MAX_POWER 40.8f //Maximum power watts of coil
+#define MAX_CURRENT 3.5f //Maximum current amps through coil (Used to calculate instantaneous current)
+#define CONST_POWER 4.78f  //Const power drawn by fans and other hardware
+#define COIL_VOLTAGE 12.0f //Voltage of the coil
+
+//-- State variables
+
+#define REF_PARAM 0
+#define KP_PARAM 1
+#define KD_PARAM 2
+
+#define TEST 1
+#define IDLE 2
+#define LEVITATE 3
+#define ERROR 4
+#define CALIBRATION 5
+
+//-- Function prototypes
+void Initialise();
+void Idle();
+void Calibrate();
+void Test();
+void Error();
+void SetRGB(bool,bool,bool);
+void SetState(char);
+void SelectButtonPress();
+void UpButtonPress();
+void DownButtonPress();
+void SelectButtonHeld();
+void UpButtonHeld();
+void DownButtonHeld();
+void UpdateScreen();
+void PDController();
+void Levitate();
+void SetErrorLine(int,char*);
+float RoundDigits(float,int);
+void ResetTime();
+void UpdateTime();
+
+
+//-- Mbed objects
+AnalogIn PosSensor(PC_0);
+AnalogIn AmbSensor(PC_1);
+
+NokiaLcd *Display;
+LcdPins DisplayPins;
+
+PinDetect SelectButton(PB_3);
+PinDetect UpButton(PA_10);
+PinDetect DownButton(PB_5);
+
+Ticker ScreenUpdateTimer;
+Timer CycleTimer;
+
+DigitalOut RedLed(PA_8);
+DigitalOut GreenLed(PA_9);
+DigitalOut BlueLed(PB_10);
+
+MovingAverage <float>AveragePower(10,0.0f);
+MovingAverage <float>AverageCurrent(10,0.0f);
+
+PwmOut CoilPWM(PWM_OUT);
+
+//Variable decleration and initialisation
+
+float ref = 0.0f; //Reference value
+float pos = 0.0f; //Position value
+float amb = 0.0f; //Ambient sensor value
+float err = 0.0f; //Difference between setpoint and measured value
+float prev_err = 0.0f; //Previous error
+float d_err = 0.0f; //Rate of error change
+float duty = 0.0f; //Current duty cycle
+
+float current = 0.0f;
+float power_consumed = 0.0f;
+
+char line_buffer[14];
+
+char error_line_1[14];
+char error_line_2[14];
+char error_line_3[14];
+char error_line_4[14];
+char error_line_5[14];
+
+int state = 0; //State variable
+float T = 0.000016129f; //Cycle time (measured)
+float cycle_t = 0.0f; 
+float open_val = 0.0f;
+
+int seconds = 0;
+int minutes = 0;
+int hours = 0;
+int delay = 260;
+
+int prev_seconds = 0;
+int prev_minutes = 0;
+int prev_hours = 0;
+
+bool levitating = false;
+
+
+volatile float Kp = 11000.0; //Proportional value of PD controller
+volatile float Kd = 65.0f; //Derivative value of PD controller
+volatile float offset = 20.0f; //Control bias
+volatile int selected_parameter = 0;
+
+volatile bool select_button_flag = false;
+volatile bool down_button_flag = false;
+volatile bool up_button_flag = false;
+volatile bool select_button_held_flag = false;
+volatile bool down_button_held_flag = false;
+volatile bool up_button_held_flag = false;
+
+
+int main()
+{
+    Initialise();
+    
+    while(1)
+    {
+        switch(state)
+        {
+            case IDLE:
+                Idle();
+                break;
+            case CALIBRATION:
+                Calibrate();
+                break;
+            case TEST:
+                Test();
+                break;
+            case LEVITATE:
+                Levitate();
+                break;
+            case ERROR:
+                Error();
+                break;
+        }
+    }
+}
+
+void Initialise()
+{
+    DisplayPins.sce  = PB_8;
+    DisplayPins.rst  = PB_9;
+    DisplayPins.dc   = PB_6;
+    DisplayPins.mosi = PA_7;
+    DisplayPins.miso = NC;
+    DisplayPins.sclk = PA_5;
+    Display = new NokiaLcd(DisplayPins);
+    Display->InitLcd();
+    Display->ClearLcdMem();
+    Display->SetXY(0,0);
+    wait(0.1);
+    CoilPWM.period_us(PWM_PERIOD_US);
+    ref = REFERENCE;
+    
+    CoilPWM.period_us(PWM_PERIOD_US);
+    CoilPWM = 0.0f;
+    
+    SelectButton.mode(PullDown);
+    SelectButton.attach_asserted(&SelectButtonPress);
+    SelectButton.attach_asserted_held(&SelectButtonHeld);
+    SelectButton.setSampleFrequency();
+    
+    UpButton.mode(PullDown);
+    UpButton.attach_asserted(&UpButtonPress);
+    UpButton.attach_asserted_held(&UpButtonHeld);
+    UpButton.setSampleFrequency();
+    
+    DownButton.mode(PullDown);
+    DownButton.attach_asserted(&DownButtonPress);
+    DownButton.attach_asserted_held(&DownButtonHeld);
+    DownButton.setSampleFrequency();
+    
+    DisplayPattern(Display,1);
+    
+    
+    SetRGB(true,false,false);
+    wait(0.5);
+    SetRGB(false,true,false);
+    wait(0.5);
+    SetRGB(false,false,true);
+    wait(0.5);
+    SetRGB(true,true,true);
+    wait(2);
+    Display->ClearLcdMem();
+    SetRGB(false,false,false);
+    
+    ScreenUpdateTimer.attach(&UpdateScreen,1);
+    
+    SetState(TEST);
+    
+}
+
+void Levitate()
+{
+    PDController();
+    
+    if( down_button_held_flag && up_button_held_flag && select_button_held_flag )
+    {
+        down_button_held_flag = false;
+        up_button_held_flag = false;
+        select_button_held_flag = false;
+        
+        SetState(CALIBRATION);
+    }
+    
+    
+    if( select_button_held_flag )
+    {
+        select_button_held_flag = false;
+        select_button_flag = false;
+        SetState(IDLE);
+    }    
+}
+
+void PDController()
+{
+    pos = PosSensor.read();
+    pos *= 3461.5f;
+    
+    err = pos - ref;
+    
+    d_err = (err-prev_err)/T;
+    
+    duty = 17*(Kp*err+Kd*d_err)+10000.0f;
+    prev_err = err;
+
+    
+    if( pos < CLOSED || pos > OPEN )
+    {
+        CoilPWM.pulsewidth(0.0f);
+        AveragePower.Insert(0.0f);
+        AverageCurrent.Insert(0.0f);
+    }
+    else
+    {
+        if( duty > PWM_PERIOD_US )
+        {
+            CoilPWM.pulsewidth_us(MAX_PWM*PWM_PERIOD_US);
+            //AveragePower.Insert()
+            AverageCurrent.Insert(MAX_PWM*MAX_CURRENT);
+        }
+        else if( duty < 0.0f )
+        {
+            CoilPWM.pulsewidth_us(0.0f);
+            AveragePower.Insert(0.0f);
+            AverageCurrent.Insert(0.0f);
+        }
+    }
+    
+    
+    
+    wait_us(260); //Delay longer than PWM period needed to ensure the set duty cycle completes atleast one cycle
+}
+
+void Error()
+{
+    CoilPWM = 0.0f;
+    
+    if( select_button_held_flag )
+    {
+        select_button_held_flag = false;
+        select_button_flag = false;
+        SetState(TEST);
+    }
+}
+
+void Test()
+{
+    bool test_passed = false;
+    open_val = 3461.5f*PosSensor.read();
+    amb = 3461.5f*AmbSensor.read();
+    
+    test_passed = ( open_val > amb );
+    
+    Display->ClearLcdMem();
+    Display->SetXY(0,0);
+    
+    if( test_passed )
+    {    
+        Display->DrawString("Test Passed");
+    }
+    else
+    {
+        Display->DrawString("Test Failed");
+    }
+    
+    wait(2);
+    
+    if( test_passed )
+    {
+        SetState(IDLE);
+    }
+    else
+    {
+        SetErrorLine(1,"Error");
+        SetErrorLine(2,"!!!!!!!!!!!!!!");
+        SetErrorLine(3,"Sensor Blocked");
+        SetErrorLine(4,"or");
+        SetErrorLine(5,"Disconnected");
+        SetState(ERROR);
+    }
+}
+
+void Idle()
+{
+    if( select_button_held_flag && down_button_held_flag && up_button_held_flag )
+    {
+        select_button_held_flag = false;
+        down_button_held_flag = false;
+        up_button_held_flag = false;
+        
+        SetState(CALIBRATION);
+    }
+    
+    if( select_button_flag )
+    {
+        select_button_flag = false;
+        SetState(LEVITATE);
+    }
+    
+    CoilPWM = 0.0f;
+}
+
+void Calibrate()
+{
+    CycleTimer.start();
+    
+    if( select_button_held_flag )
+    {
+        select_button_held_flag = false;
+        select_button_flag = false;
+        SetState(IDLE);
+    }
+    
+    if( up_button_held_flag )
+    {
+        up_button_held_flag = false;
+        
+        if( selected_parameter == KP_PARAM )
+            Kp += 10.0f;
+        else if( selected_parameter == KD_PARAM )
+            Kd += 10.0f;
+        else if( selected_parameter == REF_PARAM )
+            ref += 10.0f;
+    }
+    
+    if( down_button_held_flag )
+    {
+        down_button_held_flag = false;
+        
+        if( selected_parameter == KP_PARAM )
+            Kp -= 10.0f;
+        else if( selected_parameter == KD_PARAM )
+            Kd -= 10.0f;
+        else if( selected_parameter == REF_PARAM )
+            ref -= 10.0f;
+    }
+    
+    if( select_button_flag )
+    {
+        select_button_flag = false;
+        
+        if( selected_parameter < 2 )
+            selected_parameter++;
+        else
+            selected_parameter = 0;
+        
+        
+    }
+    
+    if( up_button_flag )
+    {
+        up_button_flag = false;
+        
+        if( selected_parameter == KP_PARAM )
+            Kp += 5.0f;
+        else if( selected_parameter == KD_PARAM )
+            Kd += 5.0f;
+        else if( selected_parameter == REF_PARAM )
+            ref += 5.0f;
+    }
+    
+    if( down_button_flag )
+    {
+        down_button_flag = false;
+        
+        if( selected_parameter == KP_PARAM )
+            Kp -= 5.0f;
+        else if( selected_parameter == KD_PARAM )
+            Kd -= 5.0f;
+        else if( selected_parameter == REF_PARAM )
+            ref -= 5.0f;
+    }
+    
+    PDController();
+    
+    CycleTimer.stop();
+    cycle_t = CycleTimer.read()*1000000.0f;
+    CycleTimer.reset();
+}
+
+void SetRGB(bool r, bool g, bool b)
+{
+    RedLed = (r ? 1 : 0 );
+    GreenLed = (g ? 1 : 0 );
+    BlueLed = (b ? 1 : 0 );
+}
+
+float RoundDigits(float x, int numdigits)
+{ 
+    return ceil(x * pow(10.0f,numdigits))/pow(10.0f,numdigits); 
+}
+
+void SetState(char to_state)
+{
+    Display->ClearLcdMem();
+    Display->SetXY(0,0);
+    CoilPWM = 0.0f;
+    
+    if( to_state == IDLE )
+    {
+        state = IDLE;
+        SetRGB(false,true,false);
+        DisplayPattern(Display,2);
+    }
+    else if( to_state == CALIBRATION)
+    {
+        state = CALIBRATION;
+        SetRGB(true,true,false);
+    }
+    else if( to_state == TEST )
+    {
+        state = TEST;
+        SetRGB(false,true,true);
+        Display->DrawString("Testing");
+    }
+    else if( to_state == ERROR )
+    {
+        SetRGB(true,false,false);
+        Display->DrawString(error_line_1);
+        Display->SetXY(0,1);
+        Display->DrawString(error_line_2);
+        Display->SetXY(0,2);
+        Display->DrawString(error_line_3);
+        Display->SetXY(0,3);
+        Display->DrawString(error_line_4);
+        Display->SetXY(0,4);
+        Display->DrawString(error_line_5);
+        state = ERROR;
+    }
+    else if( to_state == LEVITATE )
+    {
+        Display->DrawString("Levitate");
+        SetRGB(false,false,true);
+        state = LEVITATE;
+    }
+}
+
+void SelectButtonPress()
+{
+    select_button_flag = true;
+}
+
+void UpButtonPress()
+{
+    up_button_flag = true;
+}
+
+void DownButtonPress()
+{
+    down_button_flag = true;
+}
+
+void SelectButtonHeld()
+{
+    select_button_held_flag = true;
+}
+
+void UpButtonHeld()
+{
+    up_button_held_flag = true;
+}
+
+void DownButtonHeld()
+{
+    down_button_held_flag = true;
+}
+
+void UpdateScreen()
+{
+    power_consumed += (CONST_POWER + AverageCurrent.GetAverage()*COIL_VOLTAGE)/1000.0f;
+    
+    if( state == CALIBRATION )
+    {
+        Display->ClearLcdMem();
+        Display->SetXY(0,0);
+        Display->DrawString("Calibrate");
+        
+        Display->SetXY(0,1);
+        sprintf(line_buffer,"Kp=%.2f",Kp);
+        
+        if( selected_parameter == KP_PARAM )
+            Display->DrawChar('>');
+        
+        Display->DrawString(line_buffer);
+        
+        Display->SetXY(0,2);
+        sprintf(line_buffer,"Kd=%.2f",Kd);
+        
+        if( selected_parameter == KD_PARAM )
+            Display->DrawChar('>');
+        
+        Display->DrawString(line_buffer);
+        
+        Display->SetXY(0,3);
+        sprintf(line_buffer,"T=%.2f",ref);
+        
+        if( selected_parameter == REF_PARAM )
+            Display->DrawChar('>');
+        
+        Display->DrawString(line_buffer);   
+        
+        Display->SetXY(0,4);
+        sprintf(line_buffer,"T=%.2fus",cycle_t);
+        Display->DrawString(line_buffer);
+        
+        Display->SetXY(0,5);
+        sprintf(line_buffer,"Pos=%.2f",pos);
+        Display->DrawString(line_buffer);
+    }
+    
+    if( state == LEVITATE )
+    {
+        if( pos < open_val-100)
+        {
+            UpdateTime();
+            levitating = true;
+        }
+        else
+        {
+            prev_seconds = seconds;
+            prev_minutes = minutes;
+            prev_hours = hours;
+            levitating = false;
+            ResetTime();
+        }
+        
+        
+        Display->ClearLcdMem();
+        Display->SetXY(0,0);
+        Display->DrawString("Current:");
+        //Display->SetXY(0,1);
+        current = AverageCurrent.GetAverage();
+        
+        if( current < 0.0f )
+            current = 0.0f;
+        
+        sprintf(line_buffer,"%.2fA",current);
+        Display->DrawString(line_buffer);
+        
+        sprintf(line_buffer,"%.2fkWs",power_consumed);
+        
+        Display->SetXY(0,1);
+        Display->DrawString("Consumption");
+        Display->SetXY(0,2);
+        Display->DrawString(line_buffer);
+        
+        if( levitating )
+        {
+            SetRGB(false,false,true);
+            sprintf(line_buffer,"%dh%dm%ds",hours,minutes,seconds);
+        }
+        else
+        {
+            SetRGB(true,false,true);
+            sprintf(line_buffer,"%dh%dm%ds",prev_hours,prev_minutes,prev_seconds);
+        }
+        
+        Display->SetXY(0,3);
+        Display->DrawString("Time:");
+        //Display->SetXY(0,5);
+        Display->DrawString(line_buffer);
+        
+        Display->SetXY(0,4);
+        Display->DrawString("Airgap:15mm");
+    }
+    
+    
+}
+
+void SetErrorLine(int line,char *message)
+{
+    char *temp;
+    
+    switch(line)
+    {
+        case 1:
+            temp = error_line_1;
+            break;
+        case 2:
+            temp = error_line_2;
+            break;
+        case 3:
+            temp = error_line_3;
+            break;
+        case 4:
+            temp = error_line_4;
+            break;
+        case 5:
+            temp = error_line_5;
+            break;
+    }
+    
+    
+    for(int i = 0; i < 14 ; i++ )
+    {
+        *temp = message[i];
+        temp++;
+    }
+    
+}
+
+void ResetTime()
+{
+    seconds = 0;
+    minutes = 0;
+    hours = 0;
+}
+
+void UpdateTime()
+{
+    if( seconds < 60 )
+        seconds++;
+    else
+    {
+        seconds = 0;
+        
+        if( minutes < 60 )
+            minutes++;
+        else
+        {
+            minutes = 0;
+            hours++;
+        }
+    }
+        
+}
+
diff -r 000000000000 -r d7cc9bad311b mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Sep 09 18:45:52 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9296ab0bfc11
\ No newline at end of file