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

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

float kImp = 120;          //ввести кол-во импульсов на 10 оборотов

int AC_LOAD = 3;    // пин управления симистором
volatile int dimming = 130;  // время задержки от нуля   7 = максимально, 128 = минимально

volatile unsigned long time; // время в микросекундах срабатывания датчика нуля
unsigned long tims;           // переменная показаний времени
       
unsigned long currentTime;     //временные переменные для таймера экрана
unsigned long loopTime;



volatile int holl = 0;    //переменная  срабатываня датчика 

volatile int sp = 0;           //переменная суммы срабатываний датчика 

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


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

  
  pinMode(AC_LOAD, OUTPUT);        // назначаем выходом
  attachInterrupt(0, zero_crosss_int, RISING);  // прерывание по пину 2
   
  lcd.begin(16, 2);          //дисплей 16символов 2строчки
  lcd.setCursor(0,0);

lcd.write("Si:");  //в верхней строке выводим время задержки

lcd.setCursor(0,1);  

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

lcd.setCursor(9,1);  

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)|TCNT1 ; //подсчёт тиков
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()  {

  
 int val = analogRead(A0);

if (val > 0){                  //   если регулятор больше 0 
 dimming =map(val, 0, 1023, 130, 7); 
} 
    else {
       dimming =130;      //Если регулятор на 0 то время задержки 130
       
      }
     
    dimming = constrain(dimming,7,130) ; //  Следим чтоб время задержки было не меньше 7 и не больше 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(3,0);
    lcd.print(dimming);
    lcd.print("  ");     // выводим время задержки на экран.

    lcd.setCursor(3,1);
    lcd.print(val);
    lcd.print("  "); 

     
     lcd.setCursor(11,1);
    
lcd.print (int (sp*(1200/kImp)));     // выводим средние обороты на экран.
lcd.print("       "); 
sp = 0;

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