

int obMin = 50;          //ввести минимальные обороты
int obMax = 9100;         //ввести максимальные обороты
int kImp = 120;          //ввести кол-во импульсов на 10 оборотов
int minzn = 107;           //  минимальное значение симмистора на котором начинается вращение.
int ogrmin =  70 ;         // ограничение симистора на минимальных оборотах.
int mindimming = 100;        //значение симистора при закллинившем станке (первоначальный импульс)



#include <LiquidCrystal.h>      // библиотека экрана

LiquidCrystal lcd(  4, 5, 6, 7,9, 10); // пины экрана

int AC_LOAD = 3;    // пин управления симистором
volatile int dimming = 130;  // время задержки от нуля   7 = максимально, 130 = минимально
volatile unsigned long time; // время в микросекундах срабатывания датчика нуля
int  rew ;
unsigned long tims;           // переменная показаний времени

unsigned long currentTime;     //временные переменные для таймера экрана
unsigned long loopTime;

int dopusk  ;         //допуск оборотов в минус и плюс
int holl = 0;    //переменная  срабатываня датчика
int pR;                  // показания регулятора
int ogr ;                 //переменная ограничений симистора натекущих оборотах
volatile int sp = 0;           //переменная суммы срабатываний датчика
volatile int prOb ;   //предвар реальн обороты
volatile int rOb ;    // реальные обороты

volatile unsigned int int_tic;    //переменные для подсчёта времени между импульсами.
volatile unsigned long tic;
volatile int t = 0;               //минимальное время импульсов +1
int val ;

int r1 = 15;//  Реле  на А1
int r2 = 16;//   реле  на А2 



void setup()
{
 pinMode(r1, OUTPUT);// Назначаем выходом
  pinMode(r2, OUTPUT);//назначаем выходом
  digitalWrite(r1, LOW);// Оставляем невключеным
  digitalWrite(r2, HIGH);//оставляем невключенным

  t = (15000 / ( obMin * (kImp / 10))) * 2; //высчитываем минимальное время импульсов +1
  pinMode(AC_LOAD, OUTPUT);        // назначаем выходом
  attachInterrupt(0, zero_crosss_int, RISING);  // прерывание по пину 2

  lcd.begin(16, 2);          //дисплей 16символов 2строчки


  lcd.setCursor(0, 1);

  lcd.write("D:");  // В нижней выводим показания датчика

  lcd.setCursor(8, 0);

  lcd.write("S:");  //в верхней строке будем выводить требуемые обороты




  pinMode (8, INPUT); // вход сигнала ICP( №8 only для atmega328)
  //настройка 16 бит таймера-счётчика 1
  TCCR1B = 0; TCCR1A = 0; TCNT1 = 0;
  TIMSK1 = (1 << ICIE1) | (1 << TOIE1); //создавать прерывание от сигнала на пине ICP1
  TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CS10); //div 1

}

ISR (TIMER1_CAPT_vect) { //прерывание захвата сигнала на входе ICP1
  tic = ((uint32_t)int_tic << 16) | ICR1 ; //подсчёт тиков
  ICR1 = 0; int_tic = 0; TCNT1 = 0;
  sp = sp + 1 ; // для подсчёта оборотов в минуту.
  holl = holl + 1;
}   // после каждого срабатывания датчика холл+1


ISR (TIMER1_OVF_vect) { //прерывание для счёта по переполнению uint
  int_tic++; //считать переполнения через 65536 тактов
  if (int_tic > t) {
    tic = 0;  //если на входе пусто более минимального времени то обнулить счётчики
    int_tic = 0;
  }
  if (int_tic > 500) {
    dimming = 130; // если стоим 2 секунды, то сбрасываем напряжение.
  }
}

// the interrupt function must take no parameters and return nothing
void zero_crosss_int()  // function to be fired at the zero crossing to dim the light
{
  time = micros();

}

void loop()  {


  val = analogRead(A0);
  pR = map(val, 0, 1023, obMin, obMax); //Приводим показания регулятора к минимальным и максимальным оборотам
  dopusk = (analogRead(A3)+1);
  rew = pR - dopusk;
  if (rew < 0)rew = 0;

  if (val > 0) {                                       //   если регулятор больше 0
    if ( holl >= 1) {                                  // если сработал датчик
      prOb = 60000000 / ((tic * 0.0625 ) * kImp / 10); //Высчитываем обороты по показаниям датчика
      if ( prOb >= 0) {                                //проверяем на соответствие.
        rOb = prOb ;                                   //если нормально, записываем в реальные обороты
      }

      ogr = map(val, 0, 1023, ogrmin, 7);              //исходя из показаний регулятора узнаём на сколько может быть открыт симистор.

      dimming = map(rOb, rew , (pR + dopusk), ogr, minzn); //рассчитываем управление симистором.
      holl = 0;                                                       // обнуляем срабатывание датчика
    }

    if (tic == 0) {                                    // если двигатель не вращается
      dimming = mindimming ;                          //  время задержки равно первоначальному импульсу
    }
    dimming = constrain(dimming, ogr, minzn) ;       //  Следим чтоб время задержки было не меньше ограничения и не больше минимального значения
  }
  else {
    dimming = 130;                                   //Если регулятор на 0 то время задержки 130

  }


  int dimtime = (75 * dimming);               // For 60Hz =>65
  tims = micros();                            // считываем время, прошедшее с момента запуска программы
  if (tims >= (time + dimtime)) {             //если время больше или равно времени срабатывания нуля + время задержки

    digitalWrite(AC_LOAD, HIGH);              // открываем симистор
    delayMicroseconds(10);                   // задержка 10 микросекунд (для 60Hz = 8.33)
    digitalWrite(AC_LOAD, LOW);              // выключаем сигнал на симистор.
  }
  else {}




  // Для вывода значений на дисплей 2 раз в секунду

  currentTime = millis();                           // считываем время, прошедшее с момента запуска программы
  if (currentTime >= (loopTime + 500)) {            // сравниваем текущий таймер с переменной loopTime + 0,5 секунд

    // выводим показания датчика



    lcd.setCursor(2, 1);
    lcd.print(dopusk );
    lcd.print("  ");     // выводим допуск на экран.

    lcd.setCursor(10, 0);
    lcd.print(pR);
    lcd.print("       ");     // выводим нужные обороты на экран.


    sp = 0;
    loopTime = currentTime;                         // в loopTime записываем новое значение
  }
}
