Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#include <avr/wdt.h> // Watchdog timer
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <Wire.h>
- #include <LiquidCrystal_I2C.h>
- #include <Rotary.h>
- #include <PID_v1.h>
- #include <EEPROM.h>
- #define GATE 6 // TRIAC gate
- #define encButton 10 // stop/start gomb
- #define FINE 9 // rpm egyesével való állítása kapcsoló
- #define FINE10 8 //
- #define LED 13 //
- #define RELAY 4 // relé
- #define CURRENT A7 // motor áram
- #define PULSE 2 // triac gyújtóimpulzusának a hossza, órajelciklusban
- #define TACHOPULSES 8 // a tacho fordulatonkénti impulzusa
- unsigned int RPM; // mért fordulatszám
- unsigned int count; // tacho impulzus számlálója
- unsigned int lastcount = 0; // a tacho impulzusainak számlálója, a fordulatszám kiszámításához szükséges
- unsigned long lastcounttime = 0; // a tacho impulzusainak ideje
- unsigned long lasttachotime; // a tach impulzus idejének átmeneti tárolása
- unsigned long lastpiddelay = 0; // a motor lágy indításának számlálója
- //unsigned long previousMillis = 0; // a kijelző frissési idejének méréséhez
- //unsigned long lastDebounceTime = 0; // a gomb pergésének idejéhez átmeneti tároló
- const int sampleRate = 1; // A PID szabályozó minavételezési gyakorisága
- const int rpmcorrection = 86; // a perc és a processzor órajele közötti korrekció
- const int lcdinterval = 500; // a kijelző frissítési ideje ms-ban
- const int protection = 2000; // fordulatszám túllépési hiba értéke
- //const int debounceDelay = 50; // a gomb pergésmentesítési ideje
- const int minoutputlimit = 80; // a PID szabályozó kimeneti értékének alsó határa
- const int maxoutputlimit = 540; // a PID szabályozó kimeneti értékének felső határa
- const int mindimminglimit = 80; // a triac gyújtási idejének biztonsági korlátja
- const int maxdimminglimit = 625; // a triac gyújtási idejének biztonsági korlátja
- const int minrpm = 200; // a fordulatszám kiválasztás alsó határa
- const int maxrpm = 9500; // a fordulatszám kiválasztás alsó határa
- const int risetime = 100; // RPM rise time delay in microseconds (risetime x RPM)
- int dimming = 540; // a gyújtásszög kezdeti értéke (fordított érték)
- int counter; // fordulatszám mérés számlálója
- int desiredRPM; // a PID szabályozó kívánt fordulasztám értéke
- int tempcounter = 100; // a motor lágy indításához átmeneti számláló
- byte currentdisplay; // a motor áramának kijelzett értéke
- int current; // motor áramának mért értéke
- //byte relayState = LOW; // a relé állapota
- //byte buttonState; // a gomb állapota
- //byte lastButtonState = HIGH; // a gomb előző állapota
- bool softflag = false; // motor lágyindításának jelzése
- bool startflag = false; // motor működésének engedélyezése, triac gate jel
- bool runflag = false; // motor normál működése
- double Setpoint, Input, Output; // PID változók
- double sKp = 0.1, sKi = 0.2, sKd = 0; // a motor lágy indításához tartozó PID értékek
- double rKp = 0.25, rKi = 1, rKd = 0; // a motor normál működéséhez tartozó PID értékek
- //double Kp=25, Ki=1, Kd=0;
- unsigned long lastDebounceTime = 0,lastDebounceTime1 = 0;
- unsigned long debounceDelay = 50;
- unsigned long longPressDelay = 1000;
- unsigned long buttonCounter,buttonCounter1;
- unsigned long currentMillis;
- unsigned long previousMillis;
- bool readingButton,readingButton1;
- bool buttonShort=false,buttonShort1=false;
- bool buttonLong=false,buttonLong1=false;
- bool buttonShortPress=false,buttonShortPress1=false;
- bool buttonLongPress=false,buttonLongPress1=false;
- bool reading,reading1;
- bool PIDset;
- byte menu;
- bool buttonOK=true;
- unsigned int buttonCountOK;
- unsigned int buttonCount=20000;
- //LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // az LCD I2C címe és a kijelző bekötése
- LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
- Rotary r = Rotary(12, 11); // az enkóder kivezetései
- PID myPID(&Input, &Output, &Setpoint, sKp, sKi, sKd, DIRECT); // a PID szabályozó létrehozása
- void setup() {
- for(int i = 0, j=400; i < 256; i++, j>>=1){
- }
- Serial.begin(115200); // hibakereséshez a soros monitor
- Serial.println("Start ..."); // a szabályozó elindult
- //lcd.begin(16,2); // a kijelző tipusának beállítása és a meghajtó létrehozása
- pinMode(11, INPUT_PULLUP); // az enkóder kivezetése, felhúzó ellenállással
- pinMode(12, INPUT_PULLUP); // az enkóder kivezetése, felhúzó ellenállással
- pinMode(encButton, INPUT_PULLUP); // a gomb, felhúzó ellenállással
- pinMode(FINE, INPUT_PULLUP); // rpm kapcsoló, felhúzó ellenállással
- pinMode(FINE10, INPUT_PULLUP); // rpm kapcsoló, felhúzó ellenállással
- pinMode(RELAY, OUTPUT); // relé kimenet
- pinMode(GATE, OUTPUT); // triac kimenet
- pinMode(LED, OUTPUT); //
- digitalWrite(RELAY, LOW); // relé alaphelyzet, LOW
- digitalWrite(LED,HIGH);
- counter = minrpm; // fordulatszám beállítás kezdő értéke
- Input = 200; // PID szabályozó kezdő értéke
- Setpoint = 200; // PID szabályozó kezdő értéke
- myPID.SetMode(AUTOMATIC); // PID szabályozó bekapcsolása
- myPID.SetOutputLimits(minoutputlimit, maxoutputlimit);
- myPID.SetSampleTime(sampleRate); // és értékek beállítása
- OCR1A = 100; // timer1 komparátor beállítása
- TIMSK1 = 0x03; // timer1 A komparátor és a túlcsordulás megszakítások beállítása
- TCCR1A = 0x00; // timer1 normál működés beállítása
- TCCR1B = 0x00; // timer1 normál működés beállítása
- attachInterrupt(0, tacho, FALLING); // a tacho jeléhez megszakítás beállítása, 2-es kivezetés
- attachInterrupt(1, ZCD, RISING); //a nullaátmenet detektor jeléhez megszakítás beállítása, 3-as kivezetés
- lcd.init();
- lcd.backlight(); // kijelző háttér világításának bekapcsolása
- disp();
- motorStateStop();
- //save(); // ******************************************* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ***************************************
- EEPROM.get(0, rKp);
- EEPROM.get(8, rKi);
- EEPROM.get(16, rKd);
- menu=0;
- //myPID.SetTunings(rKp, rKi, rKd); // a motor normál működéséhez tartozo PID szablyozó értékeinek a beállítása
- }
- void ZCD() { // megszakítás a nullaátmenet detektorhoz
- TCCR1B = 0x04; // timer1 elősztó 256-ra állítása
- TCNT1 = 0; // timer1 értékének nullázása
- OCR1A = dimming; // timer1 A komparátor értékének beállítása
- }
- ISR(TIMER1_COMPA_vect) { // timer1 A komparátor megszakítás (Interrupt Service Routin)
- if (startflag == true) { // motor működés engedélyezés ellenőrzése
- digitalWrite(GATE, HIGH); // triac bekapcsolása
- TCNT1 = 65536 - PULSE; // triac gyújtóimpulzus hosszának a beállítása
- }
- }
- ISR(TIMER1_OVF_vect) { // timer1 túlcsordulás, letelt a gyújtóimpulzus hossza
- digitalWrite(GATE, LOW); // triac gate kikapcsolása. a triac nem kapcsol ki ettől!
- TCCR1B = 0x00; // timer1 normál működés
- }
- void tacho() { // tach impulzus megszakítás. fordulatszám kiszámítása
- count++;
- unsigned long tachotime = micros() - lasttachotime; // két impulzus közötti idő
- float time_in_sec = ((float)tachotime + rpmcorrection) / 1000000; // átszámítás másodpercre
- float prerpm = 60 / time_in_sec; // átszámítás percre
- RPM = prerpm / TACHOPULSES; // és elosztva a fordulatonkénti tacho impulzusok számával
- lasttachotime = micros(); // időpont tárolása
- }
- void loop() {
- if (runflag==true) {
- //myPID.Compute(); // PID szbályozó számítás
- }
- currentMillis = millis();
- if (currentMillis - previousMillis >= 500) { // Timer every 1 second due to display refresh
- previousMillis = currentMillis;
- disp();
- }
- pressButton();
- //pressButton1();
- digitalWrite(LED,!digitalRead(FINE));
- desiredRPM = counter; // a kívánt fordulatszám beállítása
- if (buttonLong==true){ // Long press on the encoder button, enter the time setting menu
- reading=false;
- buttonLong=false;
- Serial.println("Long Press Normal"); // The button has been pressed long time
- if (PIDset==false) {
- PIDset=true;
- menu=1;
- } else {
- PIDset=false;
- menu=0;
- save();
- }
- disp();
- }
- if (buttonShort==true and readingButton==HIGH){ // Short press of encoder button, current timer START
- reading=false;
- buttonShort=false;
- Serial.println("Short Press Normal"); // The button has been pressed short time
- if (runflag == false){
- myPID.SetMode (AUTOMATIC);
- runflag=true;
- softflag = true; // lágyindítás bekapcsolása
- digitalWrite(RELAY, HIGH); // relé bekapcsolása
- delay (300); // a relé kontaktusok záródására várakozás, relé típustól függ
- startflag = true; // motor működés engedélyezése, triac
- RPM=0; // álló motornál kezdő fordulatszám nulla. Nincs ellenőrizve, hogy tényleg áll-e a motor
- } else {
- //myPID.SetMode (MANUAL);
- Setpoint = 200; // PID érték alaphelyzetbe állítása
- Input = 200; // PID érték alaphelyzetbe állítása
- runflag = false; // motor normál működését jelző kikapcsolása
- startflag = false; // motor működését engedélyező jelző kikapcsolása
- delay (300); // várakozás a motor áram megszűnésére, a relé kontaktusának a kímélése miatt
- digitalWrite(RELAY, LOW); // relé kikapcsolása
- motorStateStop(); //
- }
- }
- if (buttonLong1==true){ // Long press on the encoder button, enter the time setting menu
- reading1=false;
- buttonLong1=false;
- Serial.println("Long1 Press Normal"); // The button has been pressed long time
- }
- if (buttonShort1==true and readingButton1==HIGH){ // Short press of encoder button, current timer START
- reading1=false;
- buttonShort1=false;
- Serial.println("Short1 Press Normal"); // The button has been pressed short time
- }
- unsigned char result = r.process(); // enkóder kezelés
- int tmp; // átmeneti tároló a megváltoztatandó érték változásának nagyságához
- if (PIDset==false){
- if (result == DIR_CW) { // ha jobbra történt a forgatás,
- tmp=20; // a változtatás kezdő értéke
- if (counter >= 500) tmp=50; // ha nagyobb az érték, akkor sávosan nagyobb lesz a változtatás mértéke is
- if (counter >=1500) tmp=100;
- if (digitalRead(FINE)==LOW) tmp=1; // ha lépésenkénti állítás
- if (digitalRead(FINE10)==LOW) tmp=10; // ha lépésenkénti állítás
- counter+=tmp; // az új érték kiszámítása
- if (counter >= maxrpm) { // elérte-e vagy meghaladta a maximális értéket
- counter = maxrpm; // ha igen, akkor az érték a maximum lesz
- }
- disp(); // az új érték kijelzése
- }
- else if (result == DIR_CCW) { // ha balra történt a forgatás,
- tmp=20; // a változtatás kezdő értéke
- if (counter >= 500) tmp=50; // ha nagyobb az érték, akkor sávosan nagyobb lesz a változtatás mértéke is
- if (counter >=1500) tmp=100;
- if (digitalRead(FINE)==LOW) tmp=1;// ha lépésenkénti állítás
- if (digitalRead(FINE10)==LOW) tmp=10; // ha lépésenkénti állítás
- counter-=tmp; // az új érték kiszámítása
- if (counter <= minrpm) { // elérte-e vagy kisebb-e a minimális értéknél
- counter = minrpm; // ha igen, akkor az érték a minimum lesz
- }
- disp(); // az új érték kijelzése
- }
- } else {
- if (result == DIR_CW) { // ha jobbra történt a forgatás,
- setplus();
- myPID.SetTunings(rKp,rKi,rKd);
- disp();
- }
- if (result == DIR_CCW) { // ha jobbra történt a forgatás,
- setminus();
- myPID.SetTunings(rKp,rKi,rKd);
- disp();
- }
- if (digitalRead(FINE10)==LOW and menu>1 and buttonOK==true) {
- buttonCountOK=buttonCount;
- buttonOK=false;
- menu--;
- disp();
- }
- if (digitalRead(FINE)==LOW and menu<3 and buttonOK==true) {
- buttonCountOK=buttonCount;
- buttonOK=false;
- menu++;
- disp();
- }
- }
- if (softflag == true) { // lágyindítás kell-e
- myPID.SetTunings(sKp, sKi, sKd); // PID szabályozó lágyindításhoz szükséges értékeinek a beállítása
- int i = (desiredRPM - tempcounter); // a kívánt fordulatszámmal arányos számú szabályozási hurok meghatározása
- for (int j = 1; j <= i; j++) { // a szabályozási hurok
- Input = RPM; // PID szabályozó bemenete a tényleges fordulatszám
- Setpoint = tempcounter; // PID szabályozó állításához tartozó érték
- myPID.Compute(); // PID szbályozó számítás
- dimming = map(Output, minoutputlimit, maxoutputlimit, maxoutputlimit, minoutputlimit); // a PID szabályoző és a triac gyújtásának az ideje fordított
- dimming = constrain(dimming, mindimminglimit, maxdimminglimit); // ellenőrzés, hogy a megfelelő tartományba esik-e az érték
- tempcounter++; // a PID szabályozó állítási értékének a növelése
- delayMicroseconds (risetime); // feléledési idő a PID szabályozónak
- }
- if (tempcounter >= desiredRPM) { // ha elérte a kívánt értéket az átmeneti beállítási érték
- lastcounttime = millis(); // akkor átváltás normál működésre engedélyezés
- lastpiddelay = millis(); // és a hozzá tartozó értékek és jelzők beállítása
- softflag = false;
- runflag = true;
- tempcounter = 100; // átmeneti indító számláló alaphelyzetbe állítása
- }
- }
- if (runflag == HIGH && softflag == false) { // ha nincs lágyindítás,
- unsigned long piddelay = millis(); // időpont olvasása
- if ((piddelay - lastpiddelay) > 1000) { // a lágyindítás engedélyezése óta eltelt-e már 1000ms
- myPID.SetTunings(rKp, rKi, rKd); // ha igen, akkor a motor normál működéséhez tartozo PID szablyozó értékeinek a beállítása
- lastpiddelay = millis(); // az utolsó időpont olvasása
- }
- Input = RPM; // a PID szabályozó bemeneti értéke a tényleges fordulatszám
- Setpoint = desiredRPM; // a PID szabályozó beállítási értéke a kívánt fordulatszám
- myPID.Compute(); // PID szabályozó kimeneti értékének a számítása
- dimming = map(Output, minoutputlimit, maxoutputlimit, maxoutputlimit, minoutputlimit); // a PID szabályoző és a triac gyújtásának az ideje fordított
- dimming = constrain(dimming, mindimminglimit, maxdimminglimit); // ellenőrzés, hogy a megfelelő tartományba esik-e az érték
- }
- unsigned long counttime = millis(); // időpont tárolása
- if (counttime - lastcounttime >= 5000) { // az utolsó tachotól érkezett jeltől eltelt-e már 2000 ms
- if (count == 0 && runflag == true) { // ha igen, akkor hiba, de csak akkor, ha menet közben történt
- startflag = false; // motor engedélyezés kikapcsolása
- delay (300); // várakozás a motor feszültség mentes állapotára
- digitalWrite(RELAY, LOW); // motor relé kikapcsolása
- runflag = LOW; // relé állapot kikapcsolása
- stuckerror(); // nincs tacho jel hiba jelzése
- }
- lastcount = count; // tacho jel számláló tárolása
- count = 0; // tacho jel számláló nullázása
- lastcounttime = millis(); // időpont tárolása az eltelt idő méréséhez
- }
- if (count == 0 && runflag == LOW) { // ha a motor megállt,
- RPM = 0; // akkor a tényleges fordulatszám nullára állítása
- }
- if (runflag == true && RPM > desiredRPM + protection) { // a motor működése közben meghaladja-e a tényleges fordulatszám a beállított fordulatszámot a biztonsági értékkel
- startflag = false; // ha igen, akkor motor kikapcsolása
- //delay (300); // várakozás a motor feszültségmentes állapotára
- digitalWrite(RELAY, LOW); // relé kikapcsolás
- runflag = false; // relé állapotjelző kikapcsolása
- digitalWrite(RELAY, LOW); // motor relé kikapcsolása
- exceederror(); // túlzott fordulatszám hiba jelzése
- }
- if (buttonCountOK!=0) {
- buttonCountOK--;
- if (buttonCountOK==0) {
- buttonOK=true;
- }
- }
- }
- void motorStateStop() {
- lcd.setCursor(0, 1);
- lcd.print (" Press START ");
- }
- void disp() {
- if (menu==0) {
- lcd.setCursor(0, 0);
- lcd.print("RPM: ");
- if (counter < 1000) lcd.print(" ");
- lcd.print(counter);
- lcd.print(" /");
- lcd.setCursor(12, 0);
- if (RPM < 1000) lcd.print(" ");
- if (RPM < 100) lcd.print(" ");
- if (RPM < 10) lcd.print(" ");
- lcd.print(RPM);
- if (runflag == HIGH) {
- lcd.setCursor(0, 1);
- lcd.print(" ");
- lcd.setCursor(0, 1);
- }
- else {
- lcd.setCursor(0, 1);
- lcd.print (" Press START ");
- }
- }
- if (menu==1) {
- lcd.setCursor(0, 1);
- lcd.print(" ");
- lcd.setCursor(3, 1);
- lcd.print("Kp: ");
- lcd.print(rKp);
- }
- if (menu==2) {
- lcd.setCursor(0, 1);
- lcd.print(" ");
- lcd.setCursor(3, 1);
- lcd.print("Ki: ");
- lcd.print(rKi);
- }
- if (menu==3) {
- lcd.setCursor(0, 1);
- lcd.print(" ");
- lcd.setCursor(3, 1);
- lcd.print("Kd: ");
- lcd.print(rKd);
- }
- }
- void exceederror() {
- lcd.clear();
- while (1) {
- lcd.setCursor(5, 0);
- lcd.print("ERROR!");
- lcd.setCursor(2, 1);
- lcd.print("TRIAC DAMAGE");
- }
- }
- void stuckerror() {
- lcd.clear();
- lcd.setCursor(5, 0);
- lcd.print("ERROR!");
- lcd.setCursor(2, 1);
- lcd.print("MOTOR STUCK!");
- delay(1000);
- while (digitalRead(encButton)) {
- }
- delay(500);
- while (!digitalRead(encButton)) {
- }
- delay(500);
- }
- void pressButton() {
- readingButton = digitalRead(encButton);
- if (readingButton==LOW and reading==true) {
- buttonCounter++;
- if ((millis() - lastDebounceTime) > debounceDelay) { // Is the prell time out?
- buttonShort=true;
- }
- if ((millis() - lastDebounceTime) > longPressDelay) {
- buttonLong=true;
- buttonShort=false;
- }
- }
- if (readingButton==HIGH) {
- lastDebounceTime=millis();
- buttonCounter=0;
- reading=true;
- }
- }
- void pressButton1() {
- readingButton1 = digitalRead(FINE);
- if (readingButton1==LOW and reading1==true) {
- buttonCounter1++;
- if ((millis() - lastDebounceTime1) > debounceDelay) { // Letelt-e a prell idő
- buttonShort1=true;
- }
- if ((millis() - lastDebounceTime1) > longPressDelay) { //
- buttonLong1=true;
- buttonShort1=false;
- }
- }// else {
- if (readingButton1==HIGH) {
- lastDebounceTime1=millis();
- buttonCounter1=0;
- reading1=true;
- }
- }
- void setplus() { // Increase value
- Serial.print(menu);
- Serial.print(" ");
- Serial.println(rKp);
- if (menu==1) {
- rKp=rKp+0.01;
- if (rKp>10) rKp=10;
- }
- if (menu==2) {
- rKi=rKi+0.01;
- if (rKi>10) rKi=10;
- }
- if (menu==3) {
- rKd=rKd+0.01;
- if (rKd>10) rKd=10;
- }
- }
- void setminus() { // Decrease value
- if (menu==1) {
- rKp=rKp-0.01;
- if (rKp<0) rKp=0;
- }
- if (menu==2) {
- rKi=rKi-0.01;
- if (rKi<0) rKi=0;
- }
- if (menu==3) {
- rKd=rKd-0.01;
- if (rKd<0) rKd=0;
- }
- }
- void save() {
- EEPROM.put(0,rKp);
- EEPROM.put(8,rKi);
- EEPROM.put(16,rKd);
- }
- /*
- #include<avr/wdt.h> // Header for watchdog timers in AVR
- void setup() {
- Serial.begin(9600); // Define baud rate for serial communication
- Serial.println("Watchdog Demo Starting");
- pinMode(13, OUTPUT);
- wdt_disable(); // Disable the watchdog and wait for more than 2 seconds
- delay(3000); // Done so that the Arduino doesn't keep resetting infinitely in case of wrong configuration
- wdt_enable(WDTO_2S); /* Enable the watchdog with a timeout of 2 seconds
- }
- void loop() {
- for(int i = 0; i<20; i++) // Blink LED for some time
- {
- digitalWrite(13, HIGH);
- delay(100);
- digitalWrite(13, LOW);
- delay(100);
- wdt_reset(); // Reset the watchdog
- }
- while(1); // Infinite loop. Will cause watchdog timeout and system reset.
- } */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement