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

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

Прошу прощения сразу, если что-то где-то коряво. Решил сделать автоматический подсос на машинку, машинка старенькая ауди 80 с карбюратором от ВАЗа. вот настроил карбюратор, чтобы работал отменно, подумал, а почему бы не автоматизировать заслонку, когда-то год назад слышал про автозапуск на ардуино. Думаю, мне не светит, потом решил изучить программирование, хотя бы немножко, чтобы выполнять какие-нибудь цели интересные) ну думаю для этого и программируют так-то))) и что-то начало получаться, сначала подправил код, взятый тут https://sites.google.com/site/hobbyarduino/project-updates/arduhome/car-start на автозапуск, чтобы и глушить можно было, и не было произвольных запусков или остановок программы старта, если немного передержал сигнал с телефона, его приложу во втором сообщении ,пальцами еще не щупал, ардуинка никак с китая не придет, уже второй раз заказываю, на алиэкспрессе, хотя у магазина в основном все положительные отзывы, и заказов много. Ну это ладно, пустили слезу, пока все тестирую в протеусе. сСелал там эмулятор ардуино, так сказать. Благо чуть-чуть в электротехнике разбираюсь, ну, в общем, неделя моих упорных изучений и получилось!!! Сначала была идея с ПИД регулятором и сервоприводом, а потом подумал, почему бы не взять двигатель обычный для управления заслонки. таких много валяется, сварочным аппаратом пользуюсь, сделаю красивый кроншейн все будет не хуже сервы))) и вот в общем что получилось.

П.С. код полностью рабочий, но если покажите где можно упростить, буду рад!



int con1 = 7; // концевик полностью открытой заслонки
int con2 = 4; // концевик полностью закрытой заслонки
int temp = A3; // датчик температуры
int rpm = A4; // датчик оборотов(датчик хола)

int out1 = 5; //выход на любой мотор
int out2 = 6; // выход на любой мотор
int  rpm2 = 0; // переменная для рассчета оборотов
void setup()
{
  Serial.begin(9600);
  // объявляем входом
pinMode(con1, INPUT); // подтяжку к минусу реализуем аппаратно резистором в 10кОм 
pinMode(temp, INPUT);
pinMode(rpm, INPUT);
pinMode(con2, INPUT);  // подтяжку к минусу реализуем аппаратно резистором в 10кОм 
// объявляем выходом
pinMode(out1, OUTPUT);
digitalWrite(out1, LOW); 
pinMode(out2, OUTPUT);
digitalWrite(out2, LOW);

}
 
void loop()
 // сама программа
{
  rpm2 = (analogRead(rpm)*2); // делаем рассчет температуры, что бы удобнее было потом прописывать в градусах
  if ((analogRead(temp) <= 30) && (rpm2 > 100)) // если температура меньше 30 и двигатель не заглушен то управлять первым режимом управления моторчиком
{
 chek_serva();// первая программа управления моторчиком
}
    else if ((analogRead(temp) <= 60) && (rpm2 > 100))// если температура меньше 60 и двигатель не заглушен то управлять первым режимом управления моторчиком
    {
      chek_serva2();// вторая программа управления моторчиком
    }
    else  //если ни одно не верно то запускаем программу управления по температуре
    
 
 {
  chek_temp(); // программа управления по температуре
 }
 // тут ми считываем показания с датчиков что бы настроить под машину задержки нам не мешают, даже помогают, что бы моторчик бешано не крутился постоянно
 Serial.print("temp");
  Serial.println(analogRead(temp));
   Serial.print("rpm");
  Serial.println(rpm2);
   delay(1000);   
}  
void chek_serva()// первая программа управления моторчиком
{
  if(rpm2 >= 1500) // если обороты больше 1500 то провернуть моторчик с небольшой задержкой в одну сторону( сами выберете в какую)
      {
       digitalWrite(out1, HIGH);
       delay(50);
       digitalWrite(out1, LOW);
      }
   else  if ((rpm2 <= 1200)&&(digitalRead(con2)==0)) // если обороты больше 1200 то провернуть моторчик в обратную сторону
      {
       digitalWrite(out2, HIGH);
       delay(50); 
       digitalWrite(out2, LOW);
      }
}
void chek_serva2() // вторая программа управления моторчиком аналогичная только для диапазона от 1300 до 1100( потому что двигатель более менее уже устоялся.
{
  if(rpm2 >= 1300)  
      {
       digitalWrite(out1, HIGH);
       delay(50);
       digitalWrite(out1, LOW);
      }
   else  if ((rpm2 <= 1100)&&(digitalRead(con2)==0))
      {
       digitalWrite(out2, HIGH);
       delay(50); 
       digitalWrite(out2, LOW);
      }
}
void chek_temp() // сюда попадаем если двигатель заглушен
{
  if ((digitalRead(con1) ==0) && (analogRead(temp) > 60)) // если концевик еще не включен(т.е. если заслонка еще не <ОТКРЫЛАСЬ> полностью) а температура <БОЛЬШЕ> 60градусов то <ОТКРЫВАЕМ> на максимум заслонку
  {
    digitalWrite(out1, HIGH);
    delay(100);
    digitalWrite(out1, LOW);
  }
    else if ((digitalRead(con2) ==0) && (analogRead(temp) <60) ) // если концевик еще не включен(т.е. если заслонка еще не <ЗАКРЫЛАСЬ> полностью) а температура <МЕНЬШЕ> 60градусов то <ЗАКРЫВАЕМ> на максимум заслонку
    {
      digitalWrite(out2, HIGH);
    delay(100);
    digitalWrite(out2, LOW);
    }
    
  
}  
  

 

d13lider
d13lider аватар
Offline
Зарегистрирован: 19.10.2015

измененый автозапуск(моих коментариев нет) прошу прощения, какие были коментарии у автора те и оставил


//v 22
//Настройки 
unsigned long ENGINE_WARM_TIME = 1200000; //В миллисекундах время работы мотора после запуска 1200000 миллисекунд = 20 минут
int ENGINE_START_MAX_TIME = 4; //В секундах масимальное время работы стартера типично 3 -10 сек




// select pins for input
const int hand_brake_in  = 3;  //d3 adruino Контакт стояночного тормоза "-"
const int start_in  = 4;  //d4 adruino Сигнал команды на старт от мобильного телефона вибра звонка
const int sharging_in  = 5;  //d5 adruino
 
const int sharging_on = 0; // 0 когда во время работы генератора или от датчика давления масла на этом входе низкое состояние , 1 когда на лампе генератора при работе генератора высокое состояние
const int hand_brake_on = 0; //  0= поднятый датчик ручника замыкает на массу тормоз активен (жигули), 1= датчик ручника в поднятом состоянии выдает высокий уровень напряжения 
 
// select pins for output
const int starter_out  = 6;  //d6 adruino реле стартера
const int engine_out  = 7;  //d7 adruino зажигание
const int secpower_out  = 8;  //d8 цепи вторичного питания печка, фары итд
const int status_out  = 9;  //d9 светодиод статуса системы  горит = система готова к работе(включена, ручник стоит). одно мигание запущен с первой попытки 2 со второй 3 с третьей 
                            //светодиод подключать с этого пина на массу

 
 
// variable for actual mode
int actual_mode = 0; //  2 engine started  
int left_start_try = 0;  // переменная для хранения остатка числа попыток запуска 
 
unsigned long last_start_time = 0; //время в тысячных секунды когда был запущен движок 
 

unsigned long last_stop_time = 0;
 
 
 
void setup() {
  
  //---- настройка входов и выходов контроллера --------------  
// init selected pins
  pinMode(hand_brake_in, INPUT); // enable input 
  //digitalWrite(hand_brake_in, HIGH); //если подтяжка реализована аппаратно то тут ненадо
 pinMode(start_in, INPUT); // enable input 
 //digitalWrite(start_in, LOW); //pullup resustor enable
 
  pinMode(sharging_in, INPUT); // enable input 
  //digitalWrite(sharging_in, HIGH); //generator LOW normaly
 
// init outputs
  pinMode(starter_out, OUTPUT); // enable output
  digitalWrite(starter_out, LOW); //set digital 0
 
  pinMode(engine_out, OUTPUT); // enable output
  digitalWrite(engine_out, LOW); //set digital 0
 
  pinMode(secpower_out, OUTPUT); // enable output
  digitalWrite(secpower_out, LOW); //set digital 0 

  pinMode(status_out, OUTPUT); // enable output
  digitalWrite(status_out, LOW); //set digital 0 
  //---- конец настройки входов и выходов контроллера --------------    


}
 
 
void loop()
{
  //---- собственно это и есть весь код программы --------------
if (actual_mode < 2 )    //если двигатель не запущен
        check_start();  //Управляем режимом запуска
//код условия обязательно включать в фигурные скобки если должно быть выполнено несколько инструкций, в данном случае одна, поэтому скобки опущены        
      
else   // иначе
        {
        check_for_shutdown(); //Управляем режимом ожидания окончания прогрева
        } //но хорошая привычка фигурные скобки ставить всегда
 
      
 set_status_led(); //независимо от режима Управляем светодиодом статуса

  //------------------конец основного кода -----------------
 }
 
 
 
 
 
  //---- а дальше идут используемые функции и подфункции -------------- 
 
void check_start() 
{
if (digitalRead(start_in) == 1 && left_start_try == 0 ) // 1 is command for start  - 1  значит импульс старта пришел с дистанционного управления <--- тут определяется полярность импульса запуска
  {
    if  (millis() > last_stop_time+12000)
  {
   left_start_try = 3;   // указываем что нужно попытаться трижды запустить движок
  } 
  }
 
 if ( left_start_try > 0)    
 {
    digitalWrite(engine_out, HIGH);   //включаем зажигание 
    digitalWrite(secpower_out, HIGH); //включаем печку фары итд
    delay(3000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление, все датчики включились
    
    if (digitalRead(hand_brake_in) != hand_brake_on ) //без ручника не делаем запуск
    {
      do_shutdown();
      actual_mode = 2; // заканчиваем попытки запустить движок
      left_start_try = 0; //без ручника другие попытки бесполезны
      return;  
    }
    
  
   if (digitalRead(sharging_in) != sharging_on  )    // проверяем что генератор не работает 
   {
      do_start(); // пытаемся запустить движок
      left_start_try = left_start_try - 1 ; //уменьшаем число попыток

        if (left_start_try == 0 ) 
          actual_mode = 2; // заканчиваем попытки запустить движок
    } // конец проверки что ручник стоит а генератор не работает
}   

      
} // конец процедуры старта
 
 
void do_start()
{
 //тут будет запуск движка    
 //   digitalWrite(engine_out, HIGH);   //включаем зажигание 
 //   digitalWrite(secpower_out, HIGH); //включаем печку фары итд
 //   delay(3000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление
    
    digitalWrite(secpower_out, LOW); //выключаем печку фары итд

//----------------------------------------------------------------------------------- цикл стартера 
    digitalWrite(starter_out, HIGH); //включаем стартер 
    for (int secs=0; secs <= ENGINE_START_MAX_TIME ; secs++) // 
      {
      delay(1000); // и продолжаем его держать включенным 1 секунду
      if (digitalRead(sharging_in) == sharging_on) //если зарядка пошла то 
               break;  // прерываем цикл
      }
//----------------------------------------------------------------------------------- 
    digitalWrite(starter_out, LOW); //отключаем стартер 

    if (digitalRead(sharging_in) == sharging_on) //еще раз смотрим что  зарядка пошла  
    {
      actual_mode = 2; //Запоминаем что движок запущен
      last_start_time = millis(); // запоминаем время запуска движка
    
    }
    
    else
    {
      digitalWrite(engine_out, LOW);   //выключаем зажигание чтбы разблокировать реле стартера
      digitalWrite(secpower_out, LOW); //выключаем печку фары итд
      delay(5000); // останавливаем код на 3 секунды чтобы бензонасос набрал давление
    }
    
    
}
 

 
 
 
 
 
 
 
void check_for_shutdown() 
{
//сюда мы попадаем когда контроллер считает что движок работает
 
    
      
    if (digitalRead(sharging_in) != sharging_on  )  //проверяем что движок случайно не заглох
          do_shutdown();
    else 
          digitalWrite(secpower_out, HIGH); //включаем печку фары итд
                 
    
    if ((digitalRead(hand_brake_in) != hand_brake_on) || (digitalRead(start_in) == 1) && (millis() > last_start_time+12000)) //проверяем что если злодеи сняли с ручника то глушим мотор
      {
         do_shutdown();
         left_start_try =0; // и больше не заводим
         last_start_time = 0;
        last_stop_time = millis();
      }
    
  
//тут будем контролировать чтоб если забыли машинку заведенной она не молотила до скончания бензобака а выключалась через какоето время
 
 
    if (actual_mode != 0  ) //значит не выключили заглохший двигатель только что 
    {
      
      // милисекунды в ардуино обнуляются каждые 49 суток
      // для того чтобы в случае если запуск произошел в течении последних 20 минут до обнуления мотор не молотил еще 49 суток
      //  нужно обнулить и время старта, при этом мотор максимум будет прогреваться вдвое больше обычного 
      if (millis() < last_start_time)
          {
          last_start_time = 0;
          }   
      
      
      if (millis() > last_start_time+ENGINE_WARM_TIME)  // если текущее время больше чем время старта + время прогрева
         {
         do_shutdown();
         left_start_try =0; // и больше не заводим
         }
    }
 }



void do_shutdown()
{
        digitalWrite(secpower_out, LOW); //выключаем печку фары итд         
        digitalWrite(engine_out, LOW); //вырубаем зажигание
        actual_mode = 0;  // движок выключили запомним это
        last_start_time = 0; // ну и забудем о том что он был включен
        delay(1000);
        
}


void set_status_led()
{
if (digitalRead(hand_brake_in) != hand_brake_on  ) //Если ручник не стоит то выкл светодиод нечего ему в пути мигать попусту
  {
  digitalWrite(status_out, LOW);
  return; //прерываем выполнение функции
  }
  
if (actual_mode ==  2) //Движок запущен
     status_led_flash(); // показываем с какой попытки был прошлый запуск
else
     digitalWrite(status_out, HIGH); // постоянное свечение - показываем что готов к следующему запуску

}



void status_led_flash()
{
static unsigned long big_interval = 0;
static unsigned long flash_interval = 0;
unsigned long flash_count = 0;
flash_count = 3 - left_start_try;  //сколько раз мигать


//1 секндный интервал
if (millis() > flash_interval + 1000L)
      flash_interval = millis() ; //задаем счетчие от 0 до 1 секунды

//задаем 6 секунд 
if (millis() > big_interval + 6000L)
     {
      big_interval = millis() ;  //задаем счетчие от 0 до 10секунд
      flash_interval = big_interval;
     }  



if (millis() <  big_interval +  flash_count * 1000L) // делим 6 секндный интервал на два периода, в первый мигаем количество раз соответствующее числу израсходованных попыток
  { //мигает 
    if (millis() > flash_interval + 500L) 
      digitalWrite(status_out, HIGH);
    else
      digitalWrite(status_out, LOW);

  } 
else 
  { // негорит
    digitalWrite(status_out, LOW); //set digital 0 
  }
}

 

ojakov
Offline
Зарегистрирован: 26.11.2015

???