Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // PID setting menu demo with Rotary encoder
- // and autosave function
- // Pressing the button starts or stops the output (Built in LED)
- // A long press on the button enters the setting, then you can switch there by a short press on the button
- // The values can be changed with the encoder
- // You can exit the setting by long pressing
- // The values are saved automatically
- // It also has a built-in auto-save function, but it only works if a sufficiently large capacity is connected to the 5V supply voltage.
- #include <LiquidCrystal_I2C.h>
- #include <Rotary.h>
- #include <EEPROM.h>
- #include <PID_v1.h>
- #define button A0 // Rotary encoder button
- #define led 13 // Built in LED
- #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // bit operation macro
- #define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
- float Ucc = 0; // Microcontroller supply voltage
- unsigned long currentMillis=0;
- unsigned long previousMillis=0;
- unsigned int value=0; // This is just an example value to have something on the display
- bool Run=false;
- byte menu=0;
- unsigned long lastDebounceTime = 0;
- unsigned long debounceDelay = 50;
- unsigned long longPressDelay = 1000;
- bool readingButton;
- bool buttonShort=false;
- bool buttonLong=false;
- bool buttonShortPress=false;
- bool buttonLongPress=false;
- bool reading=true;
- bool setting=false;
- double Setpoint, Input, Output;
- double Kp=1, Ki=0.05, Kd=0.25;
- PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
- //LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
- LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
- Rotary r = Rotary(9, 8); // define rottary encoder and pins
- void setup() {
- ADMUX = (0 << ADLAR) | (1 << REFS0) | (14 << MUX0) ; // ADC settings
- sbi(ADCSRA, ADSC); // ADC conversion start
- Serial.begin(115200);
- Serial.println("Start ...");
- lcd.init(); // initialize the lcd
- lcd.backlight();
- pinMode(button, INPUT_PULLUP);
- pinMode(led, OUTPUT);
- r.begin(true);
- EEPROM.get(0, Kp);
- EEPROM.get(4, Ki);
- EEPROM.get(8, Kd);
- if (Kp<0){ // For an empty EEPROM, these will be the default values
- Kp=1;
- Ki=0.05;
- Kd=0.25;
- }
- while(bit_is_set(ADCSRA,ADIF)){
- Ucc=(1024*1.1)/(ADCL+256*ADCH ); // Calculation of the Microcontroller supply voltage
- sbi(ADCSRA, ADSC);
- }
- Serial.println(Ucc);
- delay(500); // Waiting for a power-on transient
- while(bit_is_set(ADCSRA,ADIF)){
- Ucc=(1024*1.1)/(ADCL+256*ADCH );
- sbi(ADCSRA, ADSC);
- }
- Serial.println(Ucc);
- delay(500); // expecting the supply voltage to be measured for sure
- lcd.clear();
- disp(); // Print on the display
- Serial.println("..");
- myPID.SetMode(AUTOMATIC);
- }
- void loop() {
- while(bit_is_set(ADCSRA,ADIF)){
- Ucc=(1024*1.1)/(ADCL+256*ADCH );
- sbi(ADCSRA, ADSC);
- }
- if (Ucc<4) { // Supply voltage check
- lcd.noBacklight();
- digitalWrite(led, LOW);
- save();
- digitalWrite(led, HIGH);
- }
- unsigned char result = r.process(); // Encoder check
- myPID.Compute();
- pressButton(); // Button check
- if (setting==false) { // Normal mode
- if (buttonShort==true and readingButton==HIGH){
- reading=false;
- buttonShort=false;
- Serial.println("Short Press"); // The button has been pressed short time
- if (Run==false) {
- Run=true;
- digitalWrite(led,HIGH);
- Serial.println("Start");
- } else {
- Run=false;
- digitalWrite(led,LOW);
- Serial.println("Stop");
- }
- disp();
- }
- } else { // Settings
- if (buttonShort==true and readingButton==HIGH){
- reading=false;
- buttonShort=false;
- Serial.println("Short Press");
- menu++;
- if (menu==4) menu=1;
- disp();
- }
- if (result == DIR_CCW) {
- setplus();
- myPID.SetTunings(Kp,Ki,Kd);
- disp();
- }
- if (result == DIR_CW) {
- setminus();
- myPID.SetTunings(Kp,Ki,Kd);
- disp();
- }
- }
- if (buttonLong==true){
- reading=false;
- buttonLong=false;
- Serial.println("Long Press"); // The button has been pressed long time
- if (setting==true) {
- setting=false;
- menu=0;
- Serial.println("Normal");
- save();
- } else {
- setting=true;
- menu=1;
- Serial.println("Setting");
- }
- disp();
- }
- currentMillis = millis();
- if (currentMillis - previousMillis >= 1000) { // Timer every 1 second due to display refresh
- previousMillis = currentMillis;
- tick();
- }
- }
- void setplus() { // Increase value
- Serial.print(menu);
- Serial.print(" ");
- Serial.println(Kp);
- if (menu==1) {
- Kp=Kp+0.01;
- if (Kp>10) Kp=10;
- }
- if (menu==2) {
- Ki=Ki+0.01;
- if (Ki>10) Ki=10;
- }
- if (menu==3) {
- Kd=Kd+0.01;
- if (Kd>10) Kd=10;
- }
- }
- void setminus() { // Decrease value
- if (menu==1) {
- Kp=Kp-0.01;
- if (Kp<0) Kp=0;
- }
- if (menu==2) {
- Ki=Ki-0.01;
- if (Ki<0) Ki=0;
- }
- if (menu==3) {
- Kd=Kd-0.01;
- if (Kd<0) Kd=0;
- }
- }
- void tick() {
- value++;
- disp();
- }
- void disp() {
- if (menu==0) {
- lcd.setCursor(0,0);
- if (Run==false) {
- lcd.print("Waiting ");
- } else {
- lcd.print("Running ");
- }
- lcd.setCursor(10,0);
- if (value<10) lcd.print(" ");
- if (value<100) lcd.print(" ");
- if (value<1000) lcd.print(" ");
- if (value<10000) lcd.print(" ");
- lcd.print(value);
- }
- if (menu==1) {
- lcd.setCursor(0,0);
- lcd.print(" Kp ");
- }
- if (menu==2) {
- lcd.setCursor(0,0);
- lcd.print(" Ki ");
- }
- if (menu==3) {
- lcd.setCursor(0,0);
- lcd.print(" Kd ");
- }
- lcd.setCursor(0,1);
- lcd.print(Kp);
- lcd.print(" ");
- lcd.setCursor(6,1);
- lcd.print(Ki);
- lcd.print(" ");
- lcd.setCursor(12,1);
- lcd.print(Kd);
- lcd.print(" ");
- }
- void pressButton() {
- readingButton = digitalRead(button);
- if (readingButton==LOW and reading==true) {
- if ((millis() - lastDebounceTime) > debounceDelay) { // Check the prell time
- buttonShort=true;
- }
- if ((millis() - lastDebounceTime) > longPressDelay) {
- buttonLong=true;
- buttonShort=false;
- }
- }// else {
- if (readingButton==HIGH) {
- lastDebounceTime=millis();
- reading=true;
- }
- }
- void save() {
- EEPROM.put(0,Kp);
- EEPROM.put(4,Ki);
- EEPROM.put(8,Kd);
- }
- /*
- Alternative function
- When pressed for a long time, it does not enter automatically, but waits for the button to be released
- void pressButton() {
- readingButton = digitalRead(button);
- if (readingButton==LOW ) { // meg van nyomva a gomb
- if ((millis() - lastDebounceTime) > debounceDelay) {
- buttonShort=true;
- }
- if ((millis() - lastDebounceTime) > longPressDelay) {
- buttonLong=true;
- buttonShort=false;
- }
- } else { // nincs megnyomva a gomb
- lastDebounceTime=millis();
- if (buttonShort==true) {
- buttonShortPress=true;
- buttonShort=false;
- }
- if (buttonLong==true) {
- buttonLongPress=true;
- buttonLong=false;
- }
- }
- if (buttonShortPress==true) {
- buttonShortPress=false;
- Serial.println("Short Press");
- }
- if (buttonLongPress==true) {
- reading=true;
- lastDebounceTime=millis();
- buttonLongPress=false;
- Serial.println("Long Press");
- }
- }
- */
- // END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement