//INVERTOR sta in procesor
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <EEPROM.h>
#include <Bounce2.h>
// ================= LCD =================
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
// ================= BUTOANE =================
const int buttonPins[] = {14, 15, 16}; // UP, DOWN, OK
Bounce buttons[3];
// ================= VARIABILE =================
int LUNGIME = 0;
int TIMP1 = 100; // ms
int TIMP2 = 200; // ms
int RINDURI = 1;
const int EEPROM_ADDR_LUNGIME = 0;
const int EEPROM_ADDR_TIMP1 = 10;
const int EEPROM_ADDR_TIMP2 = 20;
const int EEPROM_ADDR_RINDURI = 30;
enum MenuItem {
MENU_LUNGIME,
MENU_TIMP1,
MENU_TIMP2,
MENU_RINDURI,
MENU_TOTAL
};
MenuItem currentMenu = MENU_LUNGIME;
// ===== AUTO-REPEAT BUTOANE =====
unsigned long upPressTime = 0;
unsigned long downPressTime = 0;
unsigned long okPressTime = 0;
bool okLongDone = false;
bool upLongActive = false;
bool downLongActive = false;
const unsigned long LONG_PRESS_TIME = 1000; // 1 secunda
const unsigned long REPEAT_INTERVAL = 200; // viteza incrementare
unsigned long lastRepeatUp = 0;
unsigned long lastRepeatDown = 0;
// ================= Pini =================
const int R1 = 12;
const int R2 = 11;
const int R3 = 10;
const int CILINDRU1 = 5;
const int CILINDRU2 = 9;
const int START = 4;
const int HOME = 6;
const int GO_HOME = 7;
const int PERMISIUNE = 8;
const int ENCODER_A = 2;
const int ENCODER_B = 3;
// ================= STAT =================
volatile long encoderCount = 0;
volatile bool pragAtins = false;
bool isRunning = false;
int CountRINDURI = 0;
bool lastA = 0;
bool lastB = 0;
// ================= DISPLAY =================
int lastEncoderDisplay = -1;
int lastCycleDisplay = -1;
// ================= SETUP =================
void setup() {
Wire.begin();
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print(" ARMESH ");
lcd.setCursor(0,1);
lcd.print(" VER-4-INVERTOR ");
delay(1000);
// Init butoane
for(int i=0;i<3;i++){
pinMode(buttonPins[i], INPUT_PULLUP);
buttons[i].attach(buttonPins[i]);
buttons[i].interval(25);
}
// Citire EEPROM
EEPROM.get(EEPROM_ADDR_LUNGIME,LUNGIME);
EEPROM.get(EEPROM_ADDR_TIMP1,TIMP1);
EEPROM.get(EEPROM_ADDR_TIMP2,TIMP2);
EEPROM.get(EEPROM_ADDR_RINDURI,RINDURI);
if(LUNGIME<0||LUNGIME>9999) LUNGIME=400;
if(TIMP1<0||TIMP1>10000) TIMP1=1010;
if(TIMP2<0||TIMP2>10000) TIMP2=2020;
if(RINDURI<0||RINDURI>1000) RINDURI=1;
afisareMeniu();
pinMode(R1,OUTPUT);
pinMode(R2,OUTPUT);
pinMode(R3,OUTPUT);
pinMode(CILINDRU1,OUTPUT);
pinMode(CILINDRU2,OUTPUT);
pinMode(START,INPUT);
pinMode(HOME,INPUT);
pinMode(GO_HOME,INPUT);
pinMode(PERMISIUNE,OUTPUT);
pinMode(ENCODER_A,INPUT);
pinMode(ENCODER_B,INPUT);
digitalWrite(R1,LOW);
digitalWrite(R2,LOW);
digitalWrite(R3,LOW);
digitalWrite(PERMISIUNE,HIGH);
lastA = digitalRead(ENCODER_A);
lastB = digitalRead(ENCODER_B);
attachInterrupt(digitalPinToInterrupt(ENCODER_A), encoderISR, CHANGE);
Serial.begin(9600);
Serial.println("=== Sistem initializat ===");
}
// ================= AFISARE MENIU =================
void afisareMeniu(){
lcd.clear();
switch(currentMenu){
case MENU_LUNGIME:
lcd.setCursor(0,0); lcd.print(">LUNGIME"); lcd.setCursor(0,1); lcd.print(LUNGIME);
break;
case MENU_TIMP1:
lcd.setCursor(0,0); lcd.print(">TIMP 1"); lcd.setCursor(0,1); lcd.print(TIMP1); lcd.print(" ms");
break;
case MENU_TIMP2:
lcd.setCursor(0,0); lcd.print(">TIMP 2"); lcd.setCursor(0,1); lcd.print(TIMP2); lcd.print(" ms");
break;
case MENU_RINDURI:
lcd.setCursor(0,0); lcd.print(">RINDURI"); lcd.setCursor(0,1); lcd.print(RINDURI);
break;
}
}
void modificaValoare(int delta){
switch(currentMenu){
case MENU_LUNGIME: LUNGIME=max(0,LUNGIME+delta); break;
case MENU_TIMP1: TIMP1=max(0,TIMP1+delta); break;
case MENU_TIMP2: TIMP2=max(0,TIMP2+delta); break;
case MENU_RINDURI: RINDURI=max(0,RINDURI+delta); break;
}
afisareMeniu();
}
// ================= LOOP =================
void loop(){
static unsigned long lastPrint=0;
// Update butoane
for(int i=0;i<3;i++) buttons[i].update();
// ================= UP
if(buttons[0].fell()){ upPressTime=millis(); upLongActive=false; }
if(buttons[0].read()==LOW){
if(!upLongActive && millis()-upPressTime>=LONG_PRESS_TIME){ upLongActive=true; lastRepeatUp=millis();}
if(upLongActive && millis()-lastRepeatUp>=REPEAT_INTERVAL){ modificaValoare(10); lastRepeatUp=millis();}
}
if(buttons[0].rose()){ if(!upLongActive) modificaValoare(1); upLongActive=false; }
// ================= DOWN
if(buttons[1].fell()){ downPressTime=millis(); downLongActive=false; }
if(buttons[1].read()==LOW){
if(!downLongActive && millis()-downPressTime>=LONG_PRESS_TIME){ downLongActive=true; lastRepeatDown=millis();}
if(downLongActive && millis()-lastRepeatDown>=REPEAT_INTERVAL){ modificaValoare(-10); lastRepeatDown=millis();}
}
if(buttons[1].rose()){ if(!downLongActive) modificaValoare(-1); downLongActive=false; }
// ================= OK
if(buttons[2].fell()){ okPressTime=millis(); okLongDone=false; }
if(buttons[2].read()==LOW && !okLongDone && millis()-okPressTime>=LONG_PRESS_TIME){
okLongDone=true;
EEPROM.put(EEPROM_ADDR_LUNGIME,LUNGIME);
EEPROM.put(EEPROM_ADDR_TIMP1,TIMP1);
EEPROM.put(EEPROM_ADDR_TIMP2,TIMP2);
EEPROM.put(EEPROM_ADDR_RINDURI,RINDURI);
lcd.setCursor(0,1); lcd.print("SALVAT EEPROM "); delay(800); afisareMeniu();
}
if(buttons[2].rose() && !okLongDone){
currentMenu=(MenuItem)((currentMenu+1)%MENU_TOTAL);
afisareMeniu();
}
// ================= START
if(digitalRead(START)==LOW && !isRunning){
startCycle();
}
// ================= GO HOME
if(digitalRead(GO_HOME)==LOW){
lcd.setCursor(0,0); lcd.print("GO HOME ");
goHomeProcedure();
}
// ================= HOME
if(digitalRead(HOME)==LOW){
lcd.setCursor(0,0); lcd.print("HOME ATINS ");
homeProcedure();
}
// ================= AFISARE IMPULSURI
if(isRunning && millis()-lastPrint>=100){
if(encoderCount!=lastEncoderDisplay){
lcd.setCursor(0,0);
lcd.print("Imp: "); lcd.print(encoderCount); lcd.print(" ");
lastEncoderDisplay=encoderCount;
}
lastPrint=millis();
}
// ================= COMPLETE CYCLE
if(isRunning && pragAtins){
completeCycle();
}
}
// ================= INTERRUPT ENCODER =================
void encoderISR(){
if(!isRunning) return;
bool a=digitalRead(ENCODER_A);
bool b=digitalRead(ENCODER_B);
if(a!=lastA){
if(a==b) encoderCount++;
}
if(!pragAtins && encoderCount>=LUNGIME){
encoderCount=0;
pragAtins=true;
}
lastA=a;
}
// ================= FUNCTII =================
void startCycle(){
isRunning=true;
noInterrupts(); encoderCount=0; pragAtins=false; interrupts();
digitalWrite(PERMISIUNE,LOW);
// 🔹 CAZ CU DELAY
if((CountRINDURI==0 || digitalRead(HOME)==LOW) && CountRINDURI<RINDURI){
digitalWrite(CILINDRU1,HIGH);
delay(TIMP1);
digitalWrite(CILINDRU2,HIGH);
delay(TIMP2);
} else {
digitalWrite(CILINDRU1,HIGH);
digitalWrite(CILINDRU2,HIGH);
}
digitalWrite(R1,HIGH);
digitalWrite(R3,LOW);
// Reset afisare ciclu
lastCycleDisplay=-1;
afisareCiclu();
}
void completeCycle(){
isRunning=false;
pragAtins=false;
lastEncoderDisplay=-1; // reset afisare encoder
encoderCount=0;
CountRINDURI++;
digitalWrite(R3,HIGH);
if(CountRINDURI>=RINDURI){
lcd.setCursor(0,0); lcd.print("PLASA FABRICATA ");
afisareCiclu();
delay(1500);
endOfCycles();
} else {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("ASTEPT SEMNAL");
digitalWrite(PERMISIUNE,HIGH);
afisareCiclu();
}
}
void endOfCycles(){
CountRINDURI=0;
lastCycleDisplay=-1; // reset afisare ciclu
encoderCount=0;
goHomeProcedure();
}
void goHomeProcedure(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("GO HOME PROCES");
digitalWrite(PERMISIUNE,LOW);
digitalWrite(CILINDRU2,LOW);
delay(TIMP1);
digitalWrite(CILINDRU1,LOW);
delay(TIMP2);
digitalWrite(R1,HIGH); digitalWrite(R2,HIGH); digitalWrite(R3,LOW);
unsigned long t0=millis();
while(digitalRead(HOME)==HIGH){
if(millis()-t0>5000) break; // timeout 5s
}
homeProcedure();
}
void homeProcedure(){
digitalWrite(R1,LOW); digitalWrite(R2,LOW); digitalWrite(R3,LOW);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("HOME atins");
digitalWrite(PERMISIUNE,HIGH);
if(CountRINDURI>=RINDURI){
CountRINDURI=0;
lastCycleDisplay=-1; // forțează reafișarea
}
}
// ================= AFISARE CICLU =================
void afisareCiclu(){
int ciclulCurent=CountRINDURI;
if(ciclulCurent==0) ciclulCurent=1;
if(ciclulCurent!=lastCycleDisplay){
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("RINDURI: "); lcd.print(ciclulCurent); lcd.print("/"); lcd.print(RINDURI);
lastCycleDisplay=ciclulCurent;
}
}