//------------------------------------------------------------------------
// Steuerung für eine Wickelmaschine mit Schrittmotor
// Das Poti dient zur Drehzahlsteuerung 
// PULSE_PRO_UMDREHUNG ist abhängig von der Einstellung am Treiberbaustein
// Getestet mit Arduino NANO Board
//
// Autor: Anton Burger  This Software is Public Domain Software 2024
//
//-----------------------------------------------------------------------
#include <LiquidCrystal_I2C.h>
#include <TimerOne.h>
#define PULSE_PRO_UMDREHUNG     2000     // Impulse pro Umdrehung. Einstellung am Kontroller
#define START                   HIGH
#define STOP                    LOW
#define LINKS                   LOW
#define RECHTS                  HIGH
#define DREHRICHTUNG            2       // Eingabe Pin Drehrichtung
#define PULS                    4
#define ENABLE                  5
#define DIR                     6
#define POTI                   A0       // Pin 14
#define MAX_RPM               120       // Maximal Umdrehungszahl
unsigned int rpm;
bool drehrichtung = RECHTS;
unsigned int poti_old;
LiquidCrystal_I2C lcd(0x27,16,2);
void setup() {
  Serial.begin(115200);
  Serial.println("\n\nSteuerung für Wickelmaschine v1.0");
  Serial.println("Einstellungen für Arduino Nano");
  Serial.print("Pulse pro Umdrehung.....: "); Serial.println(PULSE_PRO_UMDREHUNG);
  Serial.print("PULS Pin................: "); Serial.println(PULS);
  Serial.print("ENABLE Pin..............: "); Serial.println(ENABLE);
  Serial.print("DIR Pin.................: "); Serial.println(DIR);
  Serial.print("POTI Pin................: "); Serial.println(POTI);
  
  pinMode(PULS, OUTPUT);
  pinMode(ENABLE, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(DREHRICHTUNG, INPUT_PULLUP);
  Timer1.initialize(100000);              // Timer initalisieren
  Timer1.attachInterrupt(timer_isr);      // Routine zuordnen
  setNewPeriod(0);
  lcd.init();
  lcd.backlight();
  lcd.clear();
  //lcd.cursor();
  lcd.setCursor(0, 0); lcd.print("WICKELMASCHINE");
  lcd.setCursor(0, 1); lcd.print("Version 1.0");
  delay(1200);
  lcd.clear();
  lcd.print("UMDREHUNGEN/MIN");
  lcd.noCursor();
  showRPM(rpm);
}
void loop() {
  
  int poti = analogRead(POTI);
  if (poti != poti_old) {
    poti_old = poti;
    rpm = map(poti, 0, 1023, 0, MAX_RPM); 
    setNewPeriod(rpm);
    showRPM(rpm);
    delay(100);
  }
  if( digitalRead(DREHRICHTUNG) != digitalRead(DIR)){
    digitalWrite( DIR, digitalRead(DREHRICHTUNG));
    showRPM(rpm);
  }
   
}
void setNewPeriod(unsigned int rpm) {
  float r;
  if(rpm == 0) {
    // Stoppen
    Serial.println("-> Timer stopped");
    Timer1.stop();
    digitalWrite(ENABLE,STOP);
  }
  else
  {
    // Laufen
    r =  1000000 / (rpm * PULSE_PRO_UMDREHUNG);
    Serial.print("-> New Poti value: ");Serial.print(rpm);
    Serial.print(" New Timer value: "); Serial.print(r,1); 
    Serial.print(" gerundet "); Serial.println(round(r) );
    Timer1.resume();
    Timer1.setPeriod(round(r)); 
    digitalWrite(ENABLE,START);
  } 
}
void showRPM_f() {
  char buf1[20];
  char buf2[20];
  lcd.setCursor(5, 1);
  dtostrf(rpm, 4, 1, buf2);
  sprintf(buf1,"%s rpm", buf2);
  lcd.print(buf1);
}
void showRPM(unsigned int rpm) {
  char buf1[20];
  char drl[] = "Links ";
  char dr[]  = "Rechts";
  if(digitalRead(DREHRICHTUNG) == RECHTS)  strcpy(dr, drl);
  lcd.setCursor(3, 1);
  sprintf(buf1,"%3i  %s", rpm, dr);
  lcd.print(buf1);
}
void timer_isr(void) {
  digitalWrite(PULS,!digitalRead(PULS)); 
}