Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <JC_Button.h>
- #include <Event.h>
- #include <Timer.h>
- #include <PID_v1.h>
- #include <SPI.h>
- #include <LiquidCrystal.h>
- //set LCD pinout for Arduino Uno (you can set anything you want here):
- const int rs = 13, en = 12, d4 = 7, d5 = 6, d6 = 5, d7 = 4;
- LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
- bool enabled = true;
- //Define variables we'll be connecting to
- double Setpoint, Input, Output;
- double CurrentTemp;
- //Define the aggressive and conservative Tuning Parameters
- double aggKp=20, aggKi=0, aggKd=1;
- double consKp=20, consKi=1, consKd=1;
- //Specify the links and initial tuning parameters
- PID ctrl(&Input, &Output, &Setpoint, aggKp, aggKi, aggKd, DIRECT);
- //I think I Don't need to explain this :D
- #define TEMP_MIN 100
- #define TEMP_MAX 500
- // Defining pins functions
- #define SENSOR_PIN A0
- #define CONTROL_PIN 9
- #define ROTARY_1_PIN A3
- #define ROTARY_2_PIN A4
- #define BUTTON_PIN A5
- #define LCD_LIGHT_PIN 11
- #define LCD_CONTRAST_PIN 10
- // Rotary encoder stuff
- bool lastRot = false;
- int8_t accel;
- #define PULLUP true
- #define INVERT true
- #define DEBOUNCE_MS 20
- #define LONG_PRESS 1500
- Button btn(BUTTON_PIN, DEBOUNCE_MS, PULLUP, INVERT);
- // Timer
- Timer t;
- #define ROTARY_CHECK_INTERVAL 3
- int8_t rotaryCheckTimer = NO_TIMER_AVAILABLE;
- #define LCD_REDRAW_INTERVAL 100
- int8_t LCDRedrawTimer = NO_TIMER_AVAILABLE;
- #define PID_UPDATE_INTERVAL 100
- int8_t PIDUpdateTimer = NO_TIMER_AVAILABLE;
- #define ADC_SAMPLE_INTERVAL 50
- int8_t ADCSampleTimer = NO_TIMER_AVAILABLE;
- //Nice degree symbol :)
- byte DegreeSymbol[8] = {
- 0b00110,
- 0b01001,
- 0b01001,
- 0b00110,
- 0b00000,
- 0b00000,
- 0b00000,
- 0b00000
- };
- byte Fire1[8] = {
- 0b00000,
- 0b00010,
- 0b00001,
- 0b00110,
- 0b00011,
- 0b01001,
- 0b00001,
- 0b00011
- };
- byte Fire2[8] = {
- 0b00000,
- 0b00000,
- 0b00101,
- 0b01000,
- 0b10001,
- 0b01000,
- 0b10001,
- 0b11010
- };
- byte Fire3[8] = {
- 0b01100,
- 0b01000,
- 0b01010,
- 0b11010,
- 0b11000,
- 0b11000,
- 0b11111,
- 0b01111
- };
- byte Fire4[8] = {
- 0b00110,
- 0b00011,
- 0b10011,
- 0b10011,
- 0b00011,
- 0b00111,
- 0b11110,
- 0b11100
- };
- void setup() {
- lcd.begin(16, 2);
- Serial.begin(115200);
- //This ones makes new character for LCD
- lcd.createChar(0, DegreeSymbol);
- lcd.createChar(1, Fire1);
- lcd.createChar(2, Fire2);
- lcd.createChar(3, Fire3);
- lcd.createChar(4, Fire4);
- //analogReference(INTERNAL);
- pinMode(SENSOR_PIN, INPUT);
- pinMode(CONTROL_PIN, OUTPUT);
- pinMode(LCD_LIGHT_PIN, INPUT);
- pinMode(ROTARY_1_PIN, INPUT_PULLUP);
- pinMode(ROTARY_2_PIN, INPUT_PULLUP);
- pinMode(BUTTON_PIN, INPUT_PULLUP);
- digitalWrite(LCD_LIGHT_PIN, HIGH);
- //tell the PID to range between 0 and the full window size
- ctrl.SetOutputLimits(0, 255);
- ctrl.SetSampleTime(PID_UPDATE_INTERVAL);
- t.every(ROTARY_CHECK_INTERVAL, RotaryCheck);
- t.every(PID_UPDATE_INTERVAL, PIDUpdate);
- t.every(LCD_REDRAW_INTERVAL, LCDRedraw);
- t.every(ADC_SAMPLE_INTERVAL, ADCSample);
- // Initial temp
- Setpoint = 320;
- Enable();
- }
- // Rotary encoder with acceleration
- void RotaryCheck()
- {
- bool newRot = digitalRead(ROTARY_1_PIN);
- if (!newRot && lastRot)
- {
- if (!digitalRead(ROTARY_2_PIN))
- {
- Setpoint += accel;
- if (Setpoint > TEMP_MAX)
- Setpoint = TEMP_MAX;
- }
- else
- {
- Setpoint -= accel;
- if (Setpoint < TEMP_MIN)
- Setpoint = TEMP_MIN;
- }
- if (accel < 20)
- accel += 10;
- }
- else if (accel > 1)
- accel -= 1;
- lastRot = newRot;
- }
- void PIDUpdate()
- {
- Input = CurrentTemp;
- double gap = abs(Setpoint-Input); //distance away from setpoint
- if (gap < 20)
- ctrl.SetTunings(consKp, consKi, consKd);
- else
- ctrl.SetTunings(aggKp, aggKi, aggKd);
- ctrl.Compute();
- analogWrite(CONTROL_PIN, 255-Output);
- }
- void LCDRedraw()
- {
- lcd.clear();
- if (Output != 0)
- {
- lcd.setCursor(0,0);
- lcd.print((char)1);
- lcd.print((char)2);
- lcd.setCursor(0,1);
- lcd.print((char)3);
- lcd.print((char)4);
- }
- lcd.setCursor(6,0);
- lcd.print("Set: ");
- lcd.print(Setpoint, 0);
- lcd.print((char)0);
- lcd.print("C");
- lcd.setCursor(6,1);
- lcd.print("Cur: ");
- lcd.print(CurrentTemp, 0);
- lcd.print((char)0);
- lcd.print("C");
- lcd.display();
- }
- unsigned long start;
- // max 5
- #define ADC_MULTISAMPLING 5
- #define ADC_MULTISAMPLING_SAMPLES (1 << ADC_MULTISAMPLING)
- // 7.1 ms
- void ADCSample()
- {
- analogWrite(CONTROL_PIN, 255);
- delayMicroseconds(300);
- // Filter ADC by multisampling
- int adc = 0;
- for (int i = 0; i < ADC_MULTISAMPLING_SAMPLES; ++i)
- adc += analogRead(SENSOR_PIN);
- adc = adc >> ADC_MULTISAMPLING;
- // Apply quadratic equation to get temperature
- double temp = -0.0013*adc*adc + 1.696*adc - 59.284;
- // Additional temperature filtering
- CurrentTemp += (temp-CurrentTemp)*0.05;
- analogWrite(CONTROL_PIN, 255-Output);
- }
- void Enable()
- {
- pinMode(LCD_LIGHT_PIN, OUTPUT);
- ctrl.SetMode(AUTOMATIC);
- enabled = true;
- }
- void Disable()
- {
- pinMode(LCD_LIGHT_PIN, INPUT);
- ctrl.SetMode(MANUAL);
- Output = 0;
- enabled = false;
- }
- void loop() {
- t.update();
- btn.read();
- if (btn.wasPressed())
- {
- if (enabled)
- Disable();
- else
- Enable();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement