Использование энкодера в качестве нелинейного регулятора.

Вопросы программирования в системе Ардуино
sum13
Сообщения: 3
Зарегистрирован: 14 авг 2017, 17:20

Использование энкодера в качестве нелинейного регулятора.

Сообщение sum13 » 14 авг 2017, 18:17

Использование энкодера в качестве нелинейного регулятора.
Добрый день,
Автоматизирую сверлильно присадочный станок.
Сделана электронная линейка 3000мм -рабочи ход. Ход каретки

измеряется оптическим энкодером (передача трос на шкивах на

двигателе возможны пропуски шагов или прокруты) . Каретка

управляется шаговым двигателем, эта часть работает.
Не сделано: ввод заданного значения на дисплей
изначально планировал клавиатуру, но не хватает на все

выводов контролера.
Из Вашего урока №55 про мех. энкодер родилась идея

использовать энкодер для задания величины на дисплее

перемещения каретки от 0 до 3000мм с шагом 1мм. (по аналогии

управления перемещения шпинделя сверлильного станка, быстрее

крутим - быстрее меняется число на дисплее).
Можно ли увидеть программу управления шпинделем сверл.станка

полностью с
"...Анализировал признаки timeRight и timeLeft. При ненулевом

значении признаков шаговый двигатель перемещения шпинделя

делал количество шагов в зависимости от значения активного

признака. Зависимость задал в массиве."


Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Использование энкодера в качестве нелинейного регулятора.

Сообщение Эдуард » 14 авг 2017, 18:51

Здравствуйте!
Заказчик программы для управления сверлильным станком разрешил выложить скетч.

Код: Выделить всё

#include <TimerOne.h>
#include <Encod_er.h>
#include <StepDirDriverL.h>
#include <Button.h>
#include <EEPROM.h>
#include <LiquidCrystalRus.h>
#include <avr/wdt.h>

#define PIN_DRILLER_ON  9 // включение двигателя сверла _-_
#define PIN_LIGHT  11 // подсветка _-_
#define PIN_PWM_DRILL  3 // ШИМ двигателя сверла

#define TIME_POWER_SAVE 40  // время перехода в режим энергосбережения (* 0,25 сек, 63 сек макс.)
#define TIME_POWER_OFF 120 // // время перехода в режим выключения двигателя (* 0,25 сек, 63 сек макс.)

#define SPINDLE_VEL 4 // скорость движения ШПИНДЕЛЯ (Tкомм.фаз = SPINDLE_VEL * 0,25 мс)
#define SCALE_SPINDLE 0.1 // массштаб перевода шагов в перемещение шпинделя (сколько в шаге мм)
#define MAX_SPINDLE 1000  // максимальное расстояние перемещения ШПИНДЕЛЯ в шагах
#define MIN_VEL_DRILL 64  // минимальный ШИМ двигателя сверла (0...255) 

#define TIME_FAST_MENU 31 // время для выбора быстрого меню (* 64 мс)
#define TIME_FLASH_SYNHR 2000 // время мигания сообщения СИНХРОНИЗАЦИЯ (* 0,25 мс)

#define ACKN_SPINDLE_UP 40  // число подтверждений датчика ШПИНДЕЛЬ ВВЕРХУ (* 0,25 мс)
#define ACKN_PEDAL 80  // число подтверждений кнопки ПЕДАЛЬ (* 0,25 мс)
#define ACKN_ENCODER 80  // число подтверждений кнопки ЭНКОДЕР (* 0,25 мс)

// адреса EEPROM
#define EEPROM_POS_SP_BEFORE  5 // положение шпиндлера перед деталью
#define EEPROM_POS_SP_DETAIL  10 // положение шпиндлера на деталь
#define EEPROM_POS_DEPTH_DRILL 15 // глубина сверловки
#define EEPROM_MATERIAL_NUMBER 20 // номер материала
#define EEPROM_BRIGHT 22 // яркость подсветки
#define EEPROM_USER_DRILL_VEL 24  // пользовательская скорость сверла
#define EEPROM_USER_SPINDLE_VEL 26  // пользовательская скорость шпинделя

Encod_er encoder(2, 8, 4);  // энкодер
StepDirDriverL spindleMotor(5, 4, 6);  // двигатель шпинделя

Button sensSpindleUp(12, ACKN_SPINDLE_UP);  // датчик ШПИНДЕЛЬ ВВЕРХУ   
Button buttonPedal(7, ACKN_PEDAL);  // кнопка ПЕДАЛЬ   
Button buttonEncoder(10, ACKN_ENCODER);  // кнопка ЭНКОДЕР   

LiquidCrystalRus disp(13, 15, 16, 17, 18, 19); // дисплей

// МАССИВ МЕНЮ ВЫБОР МАТЕРИАЛА
struct  mMenu {
  char materialName[16];  // название материала
  byte materialVelDrill;  // скорость сверловки (0...255)
  byte materialSpindleVel;  // скорость опускания шпинделя (0...255)   
};

struct  mMenu  materialMenu[20] = {
  { "1 tekstolit", 20, 10 },
  { "2 tekstolit", 30, 11 },
  { "3 tekstolit", 40, 12 },
  { "4 tekstolit", 50, 13 },
  { "5 tekstolit", 60, 14 },
  { "6 tekstolit", 80, 15 },
  { "7 tekstolit", 100, 16 },
  { "8 tekstolit", 150, 17 },
  { "9 tekstolit", 200, 18 },
  { "10 tekstolit", 255, 19 },
  { "11 tekstolit", 255, 20 },
  { "12 tekstolit", 255, 21 },
  { "13 tekstolit", 255, 22 },
  { "14 tekstolit", 255, 30 },
  { "15 tekstolit", 255, 50 },
  { "16 tekstolit", 255, 10 },
  { "17 tekstolit", 255, 10 },
  { "18 tekstolit", 255, 10 },
  { "19 tekstolit", 255, 10 },
  { "pol_zovatel_skiy", 255, 10 }
};

// МАССИВ ПЕРЕМЕЩЕНИЯ ШПИНДЕЛЯ ЭНКОДЕРОМ
struct  mE {
  byte timeEncoder; // порог времени энкодера
  byte dividerMoto; // скорость двигателя (делитель)
  long  stepsMoto;  // число шагов   
};

/*
struct mE movEncoder[14] = {
  {5,   4,  30},
  {10,  4,  25},
  {20,  5,  20},
  {30,  5,  15},
  {40,  5,  12},
  {50,  5,  8},
  {60,  5,  6},
  {70,  6,  5},
  {80,  6,  4},
  {90,  7,  3},
  {105, 8,  2},
  {155, 9,  1},
  {255, 10, 1},
  {255, 10, 1}
};
*/

struct mE movEncoder[14] = {
  {5,   4,  300},
  {10,  4,  250},
  {20,  5,  200},
  {30,  5,  150},
  {40,  5,  120},
  {50,  5,  80},
  {60,  5,  60},
  {70,  6,  50},
  {80,  6,  40},
  {90,  7,  30},
  {105, 8,  20},
  {155, 9,  10},
  {255, 10, 5},
  {255, 10, 5}
};
 

long  posSpindle= 0; // текущее положение ШПИНДЕЛЯ
long  posSpindleBefore; // положение ШПИНДЕЛЯ перед деталью
long  posSpindleDetail; // положение ШПИНДЕЛЯ на деталь
long  depthDrill; // глубина сверловки
byte  materialNumber=0; // номер материала
byte  bright=255; // яркость подсветки

byte  mode=0; // режим
unsigned int timer1=0; // таймер 1 (общего назначения, 0,25 мс)
boolean firstCycle; // признак первый проход
boolean errorEeprom=false;  // признак ошибки EEPROM
byte x;
unsigned int  divTimerPS; // делитель таймера энергосберегающего режима
byte   timerPowerSave=0; // таймер энергосберегающего режима (* 0,25 сек)

void setup() {

  //Serial.begin(9600); // инициализируем порт, скорость 9600
  Timer1.initialize(250);  // инициализация таймера 1, период 250 мкс
  Timer1.attachInterrupt(timerInterrupt, 250);  // обработчик прерываний
  spindleMotor.setMode(0, false);  // шаговый режим, без фиксации при остановке
  spindleMotor.setDivider(5);     // делитель частоты
  disp.begin(16, 2);  // инициализируем дисплей 2 строки по 16 символов   
  disp.print("SYNHRONIZASIY"); // сообщение СИНХРОНИЗАЦИЯ
  pinMode(PIN_DRILLER_ON, OUTPUT);  // двигатель сверла
  digitalWrite(PIN_DRILLER_ON, LOW);
 
  // чтение и проверка данных EEPROM
  errorEeprom=false;
  if(readLongFromEeprom(EEPROM_POS_SP_BEFORE, & posSpindleBefore) == false) {posSpindleBefore=0; errorEeprom=true;}
  if(readLongFromEeprom(EEPROM_POS_SP_DETAIL, & posSpindleDetail) == false) {posSpindleDetail=0; errorEeprom=true;}
  if(readLongFromEeprom(EEPROM_POS_DEPTH_DRILL, & depthDrill) == false) {depthDrill=0; errorEeprom=true;}
  if(readByteFromEeprom(EEPROM_MATERIAL_NUMBER, & materialNumber) == false) {materialNumber= 0; }
  if(readByteFromEeprom(EEPROM_BRIGHT, & bright) == false) {bright= 255; }
  x= materialMenu[19].materialVelDrill;
  if(readByteFromEeprom(EEPROM_USER_DRILL_VEL, & materialMenu[19].materialVelDrill) == false) {materialMenu[19].materialVelDrill= x; }
  x= materialMenu[19].materialSpindleVel;
  if(readByteFromEeprom(EEPROM_USER_SPINDLE_VEL, & materialMenu[19].materialSpindleVel) == false) {materialMenu[19].materialSpindleVel= x; }
 
  analogWrite(PIN_LIGHT, bright); // подсветка 
  analogWrite(PIN_PWM_DRILL, 0);  // ШИМ двигателя сверла
  wdt_enable(WDTO_15MS); // разрешение работы сторожевого таймера с тайм-аутом 15 мс
}

void loop() {


  //- 0 ---------- пауза для установки начального состояния кнопок, датчиков
  if(mode == 0) {
    if(timer1 > 200) mode= 1; // переход
  }
 
  //-- 1 --------- движение шпинделя вниз, до тех пор пока не сойдет с датчика ШПИНДЕЛЬ ВВЕРХУ
  else if(mode == 1) {
    if(sensSpindleUp.flagPress == true) {
      // движение шпинделя вниз
      spindleMotor.setDivider(SPINDLE_VEL);     // скорость ШПИНДЕЛЯ
      spindleMotor.step(-10); // движение вниз
    }
    else { mode= 2; timer1=0; } // переход
  }

  //-- 2 --------- движение шпинделя вверх, до тех пор пока не сработает датчик ШПИНДЕЛЬ ВВЕРХУ
  else if(mode == 2) {

    // мигающее сообщение СИНХРОНИЗАЦИЯ
    if(timer1 == 0) disp.print("SYNHRONIZASIY"); 
    if(timer1 == TIME_FLASH_SYNHR) disp.clear();
    if(timer1 == (TIME_FLASH_SYNHR * 2)) timer1= 0;
   
    if(sensSpindleUp.flagPress != true) {
      // движение шпинделя вверх
      spindleMotor.setDivider(SPINDLE_VEL);     // скорость ШПИНДЕЛЯ
      spindleMotor.step(10); // движение вверх
    }
    else {
      spindleMotor.step(0); // остановка ШПИНДЕЛЯ 
      posSpindle= 0;  // положение ШПИНДЕЛЯ
      buttonEncoder.flagClick= false;

      if(errorEeprom == true) {
        // ошибка EEPROM
        // сообщение ОШИБКА EEPROM
        //           ТОЛЬКО МЕНЮ
        disp.clear();
        disp.print("OSIBKA EEPROM");
        disp.setCursor(0, 1);
        disp.print("TOLKO MENU");           
      }
      else {
      // сообщение СВЕРЛО К ДЕТАЛИ
      //           ВЕРХ-> 135.29 мм               
      disp.clear();
      disp.print("SVERLO K DETALI");
      disp.setCursor(0, 1);
      disp.print("VERH-> ");     
      disp.print(posSpindleBefore * SCALE_SPINDLE);
      disp.print(" mm");               
      }
      encoder.timeRight= 0;   
      encoder.timeLeft= 0;
      mode= 3; // переход 
    }         

    timerPowerSave= 0;     
  }

  //-- 3 --------- окончание синхронизации, ожидание первого нажатия педали
  else if(mode == 3) {

    if(errorEeprom == false) {
      if(buttonPedal.flagPress == true) {
        spindleMotor.setDivider(SPINDLE_VEL);     // скорость ШПИНДЕЛЯ
        spindleMotor.step(posSpindle - posSpindleBefore); 
        encoder.timeRight= 0;   
        encoder.timeLeft= 0;   
        timerPowerSave= 0;
        mode= 4; // переход на первое опускание до детали     
      }       
    }
   
    if(buttonEncoder.flagClick == true) {
      buttonEncoder.flagClick= false;
      firstCycle=true;
      timer1= 0;
      timerPowerSave= 0;
      mode=7; // переход на меню
    } 

    if( (encoder.timeRight != 0) || (encoder.timeLeft != 0) ) {
      // двинули энкодер
      // позиция шпинделя
      encoder.timeRight= 0;   
      encoder.timeLeft= 0;
      buttonPedal.flagClick= false;   
      firstCycle= true;
      timerPowerSave= 0;
      mode= 5; // переход на установку энкодером
    }   

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 4 --------- первое опускание шпинделя до позиции перед деталью
  else if(mode == 4) {

    if( (encoder.timeRight != 0) || (encoder.timeLeft != 0) ) {
      // двинули энкодер
      // позиция шпинделя
      posSpindle= posSpindleBefore + spindleMotor.readSteps();  // изменен знак step
      spindleMotor.step(0); // остановка           
      encoder.timeRight= 0;   
      encoder.timeLeft= 0;
      buttonPedal.flagClick= false;   
      firstCycle= true;
      timerPowerSave= 0;
      mode= 5; // переход на установку энкодером
    }
   
    else if( spindleMotor.readSteps() == 0){
      // остановка по достижению позиции
      posSpindle= posSpindleBefore;
      buttonPedal.flagClick= false;
      buttonEncoder.flagClick= false;
      firstCycle= true;
      timerPowerSave= 0;
      mode= 14; // переход на МОЖНО СВЕРЛИТЬ 
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 5 --------- установка положения шпинделя энкодером
  else if(mode == 5) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение УСТ. ШПИНДЕЛЯ
      //           234.18 мм
      disp.clear();
      disp.print("UST. SPINDELY");
      disp.setCursor(0, 1);
      disp.print(posSpindle * SCALE_SPINDLE);
      disp.print(" mm");         
    }

    if( ustSpindleEnc() == true) {  // двинули энкодер
      posSpindleBefore= posSpindle;
      timerPowerSave= 0;
      mode= 6; // переход   
    }           

    if(buttonPedal.flagClick == true) {
      buttonPedal.flagClick= false;
      buttonEncoder.flagClick= false;
      firstCycle= true;
      timerPowerSave= 0;
      mode= 14; // переход на сверловку         
    }           

    if(buttonEncoder.flagClick == true) {
      buttonEncoder.flagClick= false;
      firstCycle=true;
      timer1= 0;
      timerPowerSave= 0;
      mode=7; // переход на меню
    }     
     
    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

   //-- 6 --------- отработка перемещения шпинделя
  else if(mode == 6) {
        if( spindleMotor.readSteps() == 0){
          firstCycle= true;         
          mode= 5; // переход
        }

    timerPowerSave= 0;
   
    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }



//-------------- БЫСТРОЕ МЕНЮ ------------------
 
  //-- 7 --------- выбор типа меню
  else if(mode == 7) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение ПОКА
      // сообщение БЫСТРОЕ МЕНЮ
      disp.clear();
      disp.print("POKA");
      disp.setCursor(0, 1);     
      disp.print("BYSTROE MENU");         
    }

    if( (timer1 >> 8) == TIME_FAST_MENU ) {           
      // сообщение РАСШИРЕННОЕ
      // сообщение МЕНЮ
      disp.clear();
      disp.print("RASHIRENNOE");
      disp.setCursor(0, 1);     
      disp.print("MENU"); 
    }     

    if( buttonEncoder.flagPress == false ) {
      buttonEncoder.flagClick= false;
      encoder.timeRight= 0;   
      encoder.timeLeft= 0;
      firstCycle=true;
      if( (timer1 >> 8) < TIME_FAST_MENU ) mode=8; // переход на быстрое меню
      else mode=18; // переход на расширенное меню
    } 

    timerPowerSave= 0;

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 8 --------- установка положения шпинделя перед деталью
  else if(mode == 8) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение УСТ. ШПИНДЕЛЯ
      //           -> | 234.8 мм
      disp.clear();
      disp.print("UST. SPINDELY");
      disp.setCursor(0, 1);
      disp.print("-> |  ");
      disp.print(posSpindle * SCALE_SPINDLE);
      disp.print(" mm");         
    }

    if( ustSpindleEnc() == true) {  // двинули энкодер
      posSpindleBefore= posSpindle;
      timerPowerSave= 0;
      mode= 9; // переход   
    }           
           
    // проверка перехода дальше по меню
    if(buttonEncoder.flagClick == true) {

      // запись posSpindleBefore в EEPROM
      long _posSpindleBefore;     
      if((readLongFromEeprom(EEPROM_POS_SP_BEFORE, & _posSpindleBefore) == false) || (posSpindleBefore != _posSpindleBefore)) {
        writeLongToEeprom(EEPROM_POS_SP_BEFORE, & posSpindleBefore);
      }
             
      buttonEncoder.flagClick= false;
      firstCycle=true;
      timerPowerSave= 0;
      mode=10; // переход на установку шпинделя на деталь
    }         

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

   //-- 9 --------- отработка перемещения шпинделя
  else if(mode == 9) {
        if( spindleMotor.readSteps() == 0){
          firstCycle= true;         
          mode= 8; // переход
        }

    timerPowerSave= 0;
   
    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 10 --------- установка положения шпинделя на деталь
  else if(mode == 10) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение УСТ. ШПИНДЕЛЯ
      //           ->| 234.8 мм
      disp.clear();
      disp.print("UST. SPINDELY");
      disp.setCursor(0, 1);
      disp.print("->|  ");
      disp.print(posSpindle * SCALE_SPINDLE);
      disp.print(" mm");         
    }

    if( ustSpindleEnc() == true) {  // двинули энкодер
      posSpindleDetail= posSpindle;
      timerPowerSave= 0;
      mode= 11; // переход   
    }           
           
    // проверка перехода дальше по меню
    if(buttonEncoder.flagClick == true) {

      // запись posSpindleDetail в EEPROM
      long _posSpindleDetail;     
      if((readLongFromEeprom(EEPROM_POS_SP_DETAIL, & _posSpindleDetail) == false) || (posSpindleDetail != _posSpindleDetail)) {
        writeLongToEeprom(EEPROM_POS_SP_DETAIL, & posSpindleDetail);
      }
             
      buttonEncoder.flagClick= false;
      firstCycle=true;
      timerPowerSave= 0;
      mode=12; // переход на выбор глубины
    }     

    analogWrite(PIN_PWM_DRILL, 0);   
    digitalWrite(PIN_DRILLER_ON, LOW);                           
  }

   //-- 11 --------- отработка перемещения шпинделя
  else if(mode == 11) {
        if( spindleMotor.readSteps() == 0){
          firstCycle= true;
          timerPowerSave= 0;
          mode= 10; // переход
        }
       
    analogWrite(PIN_PWM_DRILL, 0);
    digitalWrite(PIN_DRILLER_ON, LOW);       
  }

  //-- 12 -------- выбор глубины сверловки
  else if(mode == 12) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение УСТ. ГЛУБИНЫ
      //           234.8 мм
      disp.clear();
      disp.print("UST. GLUBINY");
      disp.setCursor(0, 1);
      disp.print("-|->  ");         
      disp.print(depthDrill * SCALE_SPINDLE);
      disp.print(" mm");         
    }

    // проверка энкодера
    if(encoder.timeRight != 0) {
      for(int i=0; i<14; i++) {
        if(encoder.timeRight <=  movEncoder[i].timeEncoder) {
          depthDrill += movEncoder[i].stepsMoto;
          encoder.timeRight= 0;
          encoder.timeLeft= 0;
          firstCycle= true;
          timerPowerSave= 0;
          break;
        }       
      }     
    }
    else if(encoder.timeLeft != 0) {
      for(int i=0; i<14; i++) {
        if(encoder.timeLeft <=  movEncoder[i].timeEncoder) {
          depthDrill -= movEncoder[i].stepsMoto;
          if(depthDrill < 0) depthDrill=0;
          encoder.timeRight= 0;
          encoder.timeLeft= 0;
          firstCycle= true;
          timerPowerSave= 0;
          break;
        }       
      }     
    }         

    // проверка перехода дальше по меню
    if(buttonEncoder.flagClick == true) {

      // запись depthDrill в EEPROM
      long _depthDrill;     
      if((readLongFromEeprom(EEPROM_POS_DEPTH_DRILL, & _depthDrill) == false) || (depthDrill != _depthDrill)) {
        writeLongToEeprom(EEPROM_POS_DEPTH_DRILL, & depthDrill);
      }
     
      buttonEncoder.flagClick= false;
      buttonPedal.flagClick= false;
      firstCycle=true;
      timerPowerSave= 0;
      mode=15; // переход на сверловку
    }   

    analogWrite(PIN_PWM_DRILL, 0);     
    digitalWrite(PIN_DRILLER_ON, LOW);                     
  }


  //----------------------- СВЕРЛОВКА --------------------
 
  //-- 14 --------- ожидание нажатия педали (рабочего)
  else if(mode == 14) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;

      if( posSpindleBefore > posSpindleDetail ) {
        // сообщение ПАРАМЕТРЫ ЗАДАНЫ
        // сообщение НЕПРАВИЛЬНО     
        disp.clear();
        disp.print("PARAMETRY ZADANY");
        disp.setCursor(0, 1);
        disp.print("NEPRAVILNO");         
      }
      else {
      // сообщение МОЖНО СВЕРЛИТЬ
      disp.clear();
      disp.print("MOGNO SVERLIT");
      disp.setCursor(0, 1);
      disp.print(posSpindle * SCALE_SPINDLE);
      disp.print("  ");         
      disp.print(depthDrill * SCALE_SPINDLE);
      disp.print(" mm");                 
      }     
    }
       
    if(buttonPedal.flagClick == true) {
      spindleMotor.setDivider(materialMenu[materialNumber].materialSpindleVel);     // скорость ШПИНДЕЛЯ
      spindleMotor.step( posSpindle - (posSpindleDetail + depthDrill));         
      posSpindle= posSpindleDetail + depthDrill; 
      buttonPedal.flagClick= false;
      firstCycle=true;   
      timerPowerSave= 0;       
      mode= 15; // переход         
    }       

    if(buttonEncoder.flagClick == true) {
      buttonEncoder.flagClick= false;
      firstCycle=true;
      timer1= 0;
      timerPowerSave= 0;
      mode=7; // переход на меню
    } 

    // корректировка энкодером
    if( ustSpindleEnc() == true) {  // двинули энкодер
      posSpindleBefore= posSpindle;
      timerPowerSave= 0;
      mode= 17; // переход   
    }     

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_SAVE) { analogWrite(PIN_PWM_DRILL, materialMenu[materialNumber].materialVelDrill); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else if(timerPowerSave < TIME_POWER_OFF)  { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }                         
  }

  //-- 15 --------- сверловка
  else if(mode == 15) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение ИДЕТ СВЕРЛОВКА
      disp.clear();
      disp.print("IDET SVERLOVKA");
    }
   
    if( spindleMotor.readSteps() == 0){
      spindleMotor.setDivider(SPINDLE_VEL);     // скорость ШПИНДЕЛЯ
      spindleMotor.step( posSpindle - posSpindleBefore);         
      buttonEncoder.flagClick= false;
      firstCycle=true;     
      mode= 16; // переход
    }

    if(buttonPedal.flagClick == true) {
      //прекращение операции (аварийный стоп)
      buttonPedal.flagClick= false;
      spindleMotor.setDivider(SPINDLE_VEL);     // скорость ШПИНДЕЛЯ
      spindleMotor.step( posSpindle - posSpindleBefore + spindleMotor.readSteps() +2);               
      buttonEncoder.flagClick= false;
      firstCycle=true;     
      mode= 16; // переход     
    }   

    timerPowerSave= 0;

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_SAVE) { analogWrite(PIN_PWM_DRILL, materialMenu[materialNumber].materialVelDrill); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else if(timerPowerSave < TIME_POWER_OFF)  { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }                         
  }

  //-- 16 --------- подъем шпинделя
  else if(mode == 16) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение ПОДЪЕМ ШПИНДЕЛЯ
      disp.clear();
      disp.print("POD_EM SPINDELY");
    }
   
    if( spindleMotor.readSteps() == 0){     
      posSpindle= posSpindleBefore;
      buttonPedal.flagClick= false;
      buttonEncoder.flagClick= false;
      firstCycle=true;
      mode= 14; // переход на ожидание нажатия педали
    }

    timerPowerSave= 0;
   
    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_SAVE) { analogWrite(PIN_PWM_DRILL, materialMenu[materialNumber].materialVelDrill); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else if(timerPowerSave < TIME_POWER_OFF)  { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }                         
  }

   //-- 17 --------- отработка перемещения шпинделя
  else if(mode == 17) {
    if( spindleMotor.readSteps() == 0){
      firstCycle= true;
      timerPowerSave= 0;
      mode= 14; // переход на сверловку
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_SAVE) { analogWrite(PIN_PWM_DRILL, materialMenu[materialNumber].materialVelDrill); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else if(timerPowerSave < TIME_POWER_OFF)  { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }                         
  }


//---------------------- расширенное меню ----------------------

  //-- 18 --------- ЗАМЕНА СВЕРЛА
  else if(mode == 18) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение ЗАМЕНА СВЕРЛА
      disp.clear();
      disp.print("ZAMENA SVERLA");
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 19; // переход на остановку     
    }   

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      mode= 20; // переход на меню ВЫБОР МАТЕРИАЛА           
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      mode= 22; // переход на меню ВЫХОД
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 19 --------- остановка двигателя
  else if(mode == 19) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение МОЖНО МЕНЯТЬ
      //           СВЕРЛО
      disp.clear();
      disp.print("MOZNO MENYT_");
      disp.setCursor(0, 1);
      disp.print("SVERLO");     
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 18; // переход на меню ЗАМЕНА СВЕРЛА     
    }   

    analogWrite(PIN_PWM_DRILL, 0);   
    digitalWrite(PIN_DRILLER_ON, LOW); 
  }

  //-- 20 --------- ВЫБОР МАТЕРИАЛА
  else if(mode == 20) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение ВЫБОР МАТЕРИАЛА
      disp.clear();
      disp.print("VYBOR MATERIALA");
      disp.setCursor(0, 1);
      //disp.print( materialMenu[materialNumber].materialName );   
      textToDisp();               
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 23; // переход на материалы     
    }   

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      mode= 25; // переход на меню ПОЛЬЗ. УСТАНОВКИ           
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      mode= 18; // переход на меню ЗАМЕНА СВЕРЛА
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 21 --------- ОСВЕЩЕНИЕ
  else if(mode == 21) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение ЯРКОСТЬ ОСВЕЩЕНИЯ
      disp.clear();
      disp.print("YRKOST_");
      disp.setCursor(0, 1);
      disp.print("OSVEZENYA  ");     
      disp.print( (float)bright *100. / 255.,0);
      disp.print(" %");
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 24; // переход на установку яркости     
    }   

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      mode= 22; // переход на меню ВЫХОД           
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      mode= 25; // переход на меню ПОЛЬЗ. УСТАНОВКИ
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 22 --------- ВЫХОД
  else if(mode == 22) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение ВЫХОД
      disp.clear();
      disp.print("VYHOD");
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 14; // переход на сверловку     
    }   

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      mode= 18; // переход на меню ЗАМЕНА СВЕРЛА           
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      mode= 21; // переход на меню ОСВЕЩЕНИЕ
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 23 --------- МАТЕРИАЛЫ
  else if(mode == 23) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение МАТЕРИАЛ
      disp.clear();
      //disp.print( materialMenu[materialNumber].materialName ); 
      textToDisp();               
      disp.setCursor(0, 1);
      disp.print("D= ");
      disp.print( (float)materialMenu[materialNumber].materialVelDrill *100. / 255.,0);
      disp.print(" %  S= ");
      disp.print( materialMenu[materialNumber].materialSpindleVel );                                                                       
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 20; // переход на ВЫБОР МАТЕРИАЛА   

      // запись materialNumber в EEPROM
      byte _materialNumber;     
      if((readByteFromEeprom(EEPROM_MATERIAL_NUMBER, & _materialNumber) == false) || (materialNumber != _materialNumber)) {
        writeByteToEeprom(EEPROM_MATERIAL_NUMBER, & materialNumber);   
      }     
    }   

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      materialNumber++;
      if(materialNumber >= 20) materialNumber= 0;     
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      materialNumber--;
      if(materialNumber == 255) materialNumber= 19;     
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 24 --------- установка яркости
  else if(mode == 24) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение ЯРКОСТЬ
      disp.clear();
      disp.print("YRKOST_");
      disp.setCursor(0, 1);
      disp.print( (float)bright *100. / 255.,1);
      disp.print(" %");
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 21; // переход на ОСВЕЩЕНИЕ   

      // запись materialNumber в EEPROM
      if((readByteFromEeprom(EEPROM_BRIGHT, & x) == false) || (bright != x)) {
        writeByteToEeprom(EEPROM_BRIGHT, & bright);   
      }     
    }   

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      bright++;
      if(bright == 0) bright= 255;
      analogWrite(PIN_LIGHT, bright); // подсветка     
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      bright--;
      if(bright == 255) materialNumber= 0;
      analogWrite(PIN_LIGHT, bright); // подсветка     
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 25 --------- УСТАНОВКА ПОЛЬЗ. МАТЕРИАЛА
  else if(mode == 25) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение УСТАНОВКА ПОЛЬЗ.
      //           МАТЕРИАЛА   
      disp.clear();
      disp.print("USTANOVKA POL_Z.");
      disp.setCursor(0, 1);
      disp.print("MATERIALA");
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 26; // переход на выбор скорости сверла     
    }     

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      mode= 21; // переход на меню ОСВЕЩЕНИЕ           
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      mode= 20; // переход на меню ВЫБОР МАТЕРИАЛА
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 26 --------- выбор скорости сверла
  else if(mode == 26) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение СКОРОСТЬ СВЕРЛА
      disp.clear();
      disp.print("SKOROST_ SVERLA");
      disp.setCursor(0, 1);
      disp.print("D= ");
      disp.print( (float) materialMenu[19].materialVelDrill * 100. / 255.,1);
      disp.print(" %");
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 27; // переход на выбор скорости шпинделя   

      // запись materialNumber в EEPROM
      if((readByteFromEeprom(EEPROM_USER_DRILL_VEL, & x) == false) || (materialMenu[19].materialVelDrill != x)) {
        writeByteToEeprom(EEPROM_USER_DRILL_VEL, & materialMenu[19].materialVelDrill);   
      }     
    }   

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      materialMenu[19].materialVelDrill++;
      if(materialMenu[19].materialVelDrill == 0) materialMenu[19].materialVelDrill= 255;     
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      materialMenu[19].materialVelDrill--;
      if(materialMenu[19].materialVelDrill == 255) materialMenu[19].materialVelDrill= 0;     
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }

  //-- 27 --------- выбор скорости шпинделя
  else if(mode == 27) {

    if(firstCycle == true) {  // первый вход
      firstCycle= false;
      // сообщение СКОРОСТЬ ШПИНД.
      disp.clear();
      disp.print("SKOROST_ SPIND.");
      disp.setCursor(0, 1);
      disp.print("S= ");
      disp.print( materialMenu[19].materialSpindleVel );
    }

    if(buttonEncoder.flagClick == true) {
      resAllFlags();
      mode= 25; // переход на УСТАНОВКА ПОЛЬЗ. МАТЕРИАЛА   

      // запись materialNumber в EEPROM
      if((readByteFromEeprom(EEPROM_USER_SPINDLE_VEL, & x) == false) || (materialMenu[19].materialSpindleVel != x)) {
        writeByteToEeprom(EEPROM_USER_SPINDLE_VEL, & materialMenu[19].materialSpindleVel);   
      }     
    }   

    if( encoder.timeRight != 0 ) {
      resAllFlags();
      materialMenu[19].materialSpindleVel++;
      if(materialMenu[19].materialSpindleVel == 0) materialMenu[19].materialSpindleVel= 255;     
    }
       
    if( encoder.timeLeft != 0 ) {
      resAllFlags();
      materialMenu[19].materialSpindleVel--;
      if(materialMenu[19].materialSpindleVel == 255) materialMenu[19].materialSpindleVel= 0;     
    }

    // управление двигателем сверла
    if(timerPowerSave < TIME_POWER_OFF) { analogWrite(PIN_PWM_DRILL, MIN_VEL_DRILL); digitalWrite(PIN_DRILLER_ON, HIGH); }
    else  { analogWrite(PIN_PWM_DRILL, 0); digitalWrite(PIN_DRILLER_ON, LOW); }
  }


  else { while(true) {} }
}


//----------------------------------------------------------------------------------------

// обработчик прерывания 250 мкс
void  timerInterrupt() {
  wdt_reset(); 
  encoder.scanState();  // сканирование энкодера 
  spindleMotor.control(); // управвление двигателем
  sensSpindleUp.filterAvarage();  // сканирование датчика СУППОРТ ВВЕРХУ     
  buttonPedal.filterAvarage();  // сканирование кнопки ПЕДАЛЬ     
  buttonEncoder.filterAvarage();  // сканирование кнопки ЭНКОДЕР     

  timer1++;

  // таймер режима энергосбережения
  divTimerPS++;
  if(divTimerPS >= 1000) {  // 0,25 сек
    divTimerPS= 0;
    timerPowerSave++;
    if(timerPowerSave == 0) timerPowerSave= 255; 
  } 
}


//--------------------------------- сброс всех флагов
void resAllFlags() {
  buttonPedal.flagClick= false;
  buttonEncoder.flagClick= false;
  encoder.timeRight= 0;   
  encoder.timeLeft= 0;
  timerPowerSave= 0;
  firstCycle=true;
}

// -------------------------------- запись данного типа long в EEPROM с контрольной суммой
void writeLongToEeprom(int adress, long *value) {
 
  EEPROM.write(adress, *((byte*)value));
  EEPROM.write(adress+1, *(((byte*)value)+1));
  EEPROM.write(adress+2, *(((byte*)value)+2));
  EEPROM.write(adress+3, *(((byte*)value)+3));
  EEPROM.write(adress+4, (*((byte*)value) + *(((byte*)value)+1) + *(((byte*)value)+2) + *(((byte*)value)+3)) ^ 0xe5);     
}

//------------------------------- чтение данного типа long из EEPROM с проверкой контрольной суммы
// при успешной операции возвращает true
boolean readLongFromEeprom(int adress, long *value) {

  *((byte*)value) = EEPROM.read(adress);     
  *(((byte*)value)+1) = EEPROM.read(adress+1);     
  *(((byte*)value)+2) = EEPROM.read(adress+2);     
  *(((byte*)value)+3) = EEPROM.read(adress+3);     

  if ( (byte)((*((byte*)value) + *(((byte*)value)+1) + *(((byte*)value)+2) + *(((byte*)value)+3)) ^ 0xe5) == EEPROM.read(adress+4) ) return true;
  return false; 
}

// -------------------------------- запись данного типа byte в EEPROM с контрольной суммой
void writeByteToEeprom(int adress, byte *value) {
 
  EEPROM.write(adress, *value);
  EEPROM.write(adress + 1, (*value) ^ 0xe5 );
}

//------------------------------- чтение данного типа byte из EEPROM с проверкой контрольной суммы
// при успешной операции возвращает true
boolean readByteFromEeprom(int adress, byte *value) {

  *value = EEPROM.read(adress);
  if( ((*value) ^ 0xe5) == EEPROM.read(adress + 1)) return true; 
  return false; 
}


//-------------------------------- установка положения шпиндлера энкодером
boolean ustSpindleEnc() {
  long x;

    // проверка энкодера
    if(encoder.timeRight != 0) {
      for(int i=0; i<14; i++) {
        if(encoder.timeRight <=  movEncoder[i].timeEncoder) {
          spindleMotor.setDivider(movEncoder[i].dividerMoto);     // скорость ШПИНДЕЛЯ

          // ограничение снизу
          x= posSpindle + movEncoder[i].stepsMoto;
          if( x > MAX_SPINDLE ) {
            spindleMotor.step( posSpindle - MAX_SPINDLE );   
            posSpindle= MAX_SPINDLE;
          }
          else {
            spindleMotor.step(- movEncoder[i].stepsMoto); 
            posSpindle= x;
          }                   
          encoder.timeRight= 0;
          encoder.timeLeft= 0;         
          return(true);
        }       
      }     
    }
    else if(encoder.timeLeft != 0) {
      for(int i=0; i<14; i++) {
        if(encoder.timeLeft <=  movEncoder[i].timeEncoder) {
          spindleMotor.setDivider(movEncoder[i].dividerMoto);     // скорость ШПИНДЕЛЯ

          // ограничение сверху
          x= posSpindle - movEncoder[i].stepsMoto;
          if( x < 0 ) {
            spindleMotor.step(posSpindle);
            posSpindle= 0;
          }
          else {
            spindleMotor.step(movEncoder[i].stepsMoto);
            posSpindle= x;
          }                   
          encoder.timeRight= 0;
          encoder.timeLeft= 0;
          return(true);
        }       
      }     
    }         
  return(false); 
}

//----------------------------------------- вывод данных для дурацких индикаторов
void textToDisp() {

  switch(materialNumber) {

    case 0:
      disp.print("1 tekstolit"); break;
    case 1:
      disp.print("2 tekstolit"); break;
    case 2:
      disp.print("3 tekstolit"); break;
    case 3:
      disp.print("4 tekstolit"); break;
    case 4:
      disp.print("5 tekstolit"); break;
    case 5:
      disp.print("6 tekstolit"); break;
    case 6:
      disp.print("7 tekstolit"); break;
    case 7:
      disp.print("8 tekstolit"); break;
    case 8:
      disp.print("9 tekstolit"); break;
    case 9:
      disp.print("10 tekstolit"); break;
    case 10:
      disp.print("11 tekstolit"); break;
    case 11:
      disp.print("12 tekstolit"); break;
    case 12:
      disp.print("13 tekstolit"); break;
    case 13:
      disp.print("14 tekstolit"); break;
    case 14:
      disp.print("15 tekstolit"); break;
    case 15:
      disp.print("16 tekstolit"); break;
    case 16:
      disp.print("17 tekstolit"); break;
    case 17:
      disp.print("18 tekstolit"); break;
    case 18:
      disp.print("19 tekstolit"); break;
    case 19:
      disp.print("pol_zovatel_skiy"); break;     
  } 
}

sum13
Сообщения: 3
Зарегистрирован: 14 авг 2017, 17:20

Re: Использование энкодера в качестве нелинейного регулятора.

Сообщение sum13 » 23 авг 2017, 18:09

Спасибо огромное!
Разбираюсь, много интересного и нового...

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Использование энкодера в качестве нелинейного регулятора.

Сообщение Эдуард » 23 авг 2017, 20:58

Здравствуйте!
Если человек, который заказал мне программу доделает сверлильный станок и вышлет мне фотографии, то я отдельной темой опишу устройство, схему, алгоритм работы. Сейчас он ждет двигатель с Алиэкспресс. Заказал двигатель, ему через 2 месяца вернули деньги. Опять ждет новый двигатель.

sum13
Сообщения: 3
Зарегистрирован: 14 авг 2017, 17:20

Re: Использование энкодера в качестве нелинейного регулятора.

Сообщение sum13 » 24 авг 2017, 15:07

Добрый день!
Очень интересно было бы посмотреть!
Если у нас все получиться, выложу наше "ноу хау" ;)

solomsv
Сообщения: 3
Зарегистрирован: 05 дек 2017, 12:55

Re: Использование энкодера в качестве нелинейного регулятора.

Сообщение solomsv » 05 дек 2017, 21:13

Доброго времени суток.

Получилось реализовать станок ? Было бы очень интересно разобрать как это получилось, прям добавить серию уроков.

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Использование энкодера в качестве нелинейного регулятора.

Сообщение Эдуард » 05 дек 2017, 22:44

Здравствуйте!
Вроде двигатель с АлиЭкспресс ему пришел, но пока молчит.
Программу в принципе он полностью проверил. У него не было только двигателя сверловки.


Вернуться в «Программирование Ардуино»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя