Управление свечами накала - нужна помощь

shmlka
Offline
Зарегистрирован: 28.12.2016

Доброго времени суток!
Из за капризности родного блока управления свечами накала решил собрать ему замену на ардуино. Но так как начал только разбираться в программировании ардуино появились некоторые затруднения в реализации, нужна ваша помощь. Использоваться будет ардуино нано. Скетч готовый уже был, но не понравился алгоритм работы и захотел его переделать.
Алгоритм работы должен быть такой:
1. При включении зажигания включается реле №1 и подает на свечи 12 вольт в течении от 0 до 6 секунд (в зависимости от выбранного алгоритма по температуре двигателя ). Свечи стоят на 6 вольт, при подаче на них 12 вольт происходит быстрый разогрев.

2. Затем при подаче питания на стартер через 1 сек. включается реле №2 которое подает на свечи 6 вольт в течении от 0 до 25 секунд (в зависимости от выбранного алгоритма по температуре двигателя ). При этом должен происходить контроль напряжения на свечах, при превышении значения 6,90 В отключалось реле №2 на 2 сек (если раньше не отключится по времени).

Не могу сообразить как реализовать в программе контроль запуска по стартеру и контроль по напряжению на свечах. В программе пока до первого варианта алгоритма. Наверняка есть какие то ошибки и как мне кажется "delay()" там лишний, но вот как использовать "millis()" не могу понять сколько не читал, че то с трудом все это дается Не могли бы немного помочь как реализовать контроль

Вот схема подключения:

 

 

 

 

 

 

 

 

 

 

 

вод исходник программы:

int analogPinTEM = A0; // Аналоговый вход для считывания напряжения с делителя напряжения термодатчика
int analogPinST = A1; // Аналоговый вход для считывания напряжения с делителя напряжения стартера
float analogPinIN = A2; // Аналоговый вход для считывания напряжения с делителя напряжения для контроля напряж. на свечах
float Vout = 0; // Переменная для хранения значения напряжения в средней точки делителя напряжения термодатчика(0-5.0v)
int Vst = 0; // Переменная для хранения значения напряжения при запуске стартера
float Vin = 0; // Переменная для хранения значения напряжения на свечах (0-7.0v)
int t12 = 0; // Переменная для хранения времени работы реле 12v
int t6 = 0; // Переменная для хранения времени работы реле 6v
float R2 = 0; // Переменная для хранения значения сопротивления термодатчика R2 (датчик температуры двигателя)
int var = 0; // Переменная для хранения значения выбора варианта программы

void setup()
{
   pinMode(12, OUTPUT); // Выход на реле 12 вольт (реле 1)
   pinMode(6, OUTPUT); // Выход на реле 6 вольт (реле 2)
   pinMode(analogPinTEM, INPUT);
   pinMode(analogPinST, INPUT);
   pinMode(analogPinIN, INPUT);
   digitalWrite(12, LOW);
   digitalWrite(6, LOW);
   Serial.begin(9600);
 }

void loop()
{
   Vout = (5.0 / 1023.0) * analogRead(analogPinTEM); // Вычисляем напряжение в средней точки делителя (0-5.0)
   R2 = 10000 / ((5.0 / Vout) - 1); // Вычисляем сопротивление R2 (10000 это значение R1 10 кОм)
   Vst = (5.0 / 1023.0) * analogRead(analogPinST)*5.0; // Вычисляем напряжение на стартере (5.0 коэффициент делителя)
   Vin = (5.0 / 1023.0) * analogRead(analogPinIN)*5.0; // Вычисляем напряжение на свечах когда питаются от 6v (5.0 коэффициент делителя)
   Serial.print("Voltage: ");
   Serial.println(Vout); // Напряжения в средней точки делителя (0-5.0) для справки
   Serial.print("R: "); //
   Serial.print(R2); // Значение сопротивления R2 для справки
   Serial.println("Om");
   Serial.print("Voltage svechi: ");
   Serial.println(Vin); // Напряжение на свечах при питании на 6V, для справки
   delay(500); // Пауза пол сек, затем выбор алгоритма прогрева в зависимости от показаний температуры двигателя
   if (R2 > 8000) var = 1, t12 = 6000, t6 = 30000; //Если температура двигателя от чуть выше нуля и в минус до упора
   if ((R2 < 8000) && (R2 > 3200)) var = 2, t12 = 5000, t6 = 25000; // Если температура двигателя от 0 до +20 градусов
   if ((R2 < 3200) && (R2 > 1500)) var = 3, t12 = 4000, t6 = 10000; // Если температура двигателя от +20 до +40 градусов
   if ((R2 < 1500) && (R2 > 300)) var = 4, t12 = 3000, t6 = 3000; //Если температура двигателя от +40 до +80 градусов
   if (R2 < 300) var = 5, t12 = 0, t6 = 0; // Если температура двигателя от +80 градусов и выше до упора
   Serial.print("VAR: ");
   Serial.println(var);


         switch (var)
   {
       case 1:
       digitalWrite(12, HIGH); // Включаем реле быстрого нагрева свечей от 12v
       delay(t12); // Время быстрого нагрева от 12v
       digitalWrite(12, LOW);// Отключаем реле 12v
       delay(t6); // Время нагрева от 6v
         while (true) {};
         break;
	
	}
}
andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Я надеюсь, Вы не собираетесь использовать переделанный автомобиль на дорогах общего пользования?

bizzon
Offline
Зарегистрирован: 29.03.2016

Возьмите свечу на 6 вольт и подсоедините её к аккумулятору. Вы удивитесь, как быстро она сгорит. Что за авто у вас с таким капризным блоком?

shmlka
Offline
Зарегистрирован: 28.12.2016

Свечи и так идут с завода на 6 вольт, система называется Super Quick Glow. Родные свечи керамические и при подаче на них 12 вольт разогреваются секунды за три, потом происходит запуск мотора и подается уже 6 вольт через сопротивление. Если ставить свечи аналоги, то они разогреваются уже секунд за 6-7 и родной блок с ними некоректно работает (вернее вообще не работает), так как он замеряет сопротивление свечей для контроля температуры, а у аналогов другое сопротивление и блок думает что свечи горячие. Автомобиль Mitsubishi Pajero 2 дизель.

alex-hart
Offline
Зарегистрирован: 14.03.2015

От delay можно избавиться, но это ничего вам не даст. Сам мучился дилемой, изобретать на дуине блок накала, но купил бу, а свечи при покупке в магазине сразу проверяю тестером на сопротивление т.к. при подборе по каталогу получил свечи с сопротивлением в 3 раза большим чем у родных свечей и естественно они не нагревались. 

alex-hart
Offline
Зарегистрирован: 14.03.2015

Еще немного подумал:

Код можно поправить под собственные нужды, основная его проблема отсутствие контроля запуска двигателя. Будет при холодном двигателе постоянно включать накал свечей. Самое простое добавить глобальную переменную выполнения кода программы и в начале цикла loop проверять ее. То есть, в конце кода переменной присваеваем значение true, а в начале проверяем ее и пропускаем весь цикл вне зависимости запустился двигатель или нет. Повторный запуск программы произойдет только при повторном включении зажигания.

Но код это мелочи, основная проблема в самой схеме. Какая она сейчас, она и одного запуска не отработает.  Управление реле: У вас стоят релюшки с 12в управлением, а дуина выдает всего 5в. Вам для управления релюшками надо добавлять в схему логический полевой транзистор на каждое реле, плюс его обвяз 2 резистора, плюс шунтирование реле диодом и конденсатором чтобы задавить помехи которые сразу вынесут мозг дуне. Было бы неплохо развязать управление полевиком через оптопару.

Контролировать стартер через делитель, помоему вообще глупо, при работе стартера будут большие просадки напряжения и еще черт знает что. В лучшем случае получите непонять что, в худшем спалите вход или весь проц. Думаю лучше через опторазвязку контролировать.

Свечи и датчик температуры. Надо добавлять фильтра от помех и прикрывать входа хотябы стабилитроном.

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

Еще немного подумать и схема раздуется до штатного блока накала. Ну вот, как то так.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

andriano пишет:

Я надеюсь, Вы не собираетесь использовать переделанный автомобиль на дорогах общего пользования?

Не ожидал от Вас! Что за бред?

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

Во вторых, непонятно, почему следует считать любого самодельщика идиотом и что-то ему запрещать. А три идиота из отраслевого КБ, которым "можно", они, что умнее по определению?

Да хоть в тормоза, хоть в рулевое. Это реально будет волновать только страховую компанию, которая денег при аварии не выплатит.

------------------

Гребаный патернализм. Нужно, млин, все запретимть, а то могут пострадать дети... врачи и учиталя, Мать!!!!

Если человек сделает что-то неправильно и пострадает другой - то автор ответит в суде. Все. Точка. Не нужно расширять тему, иначе жопа будет.

shmlka
Offline
Зарегистрирован: 28.12.2016

По поводу реле, я собираюсь использовать специально для ардуины реле 5 вольтовые, через них включать основные реле, питание будет через понижающий DC-DC преоброзователь. Контроль по стартеру надо ведь только в первый момент, чтобы узнать что машину начали заводить. Наверное я немного не правильно написал, там не с самого стартера, а с замка зажигания в положении Start, этот провод уже приходит в  родной блок. А делители все я расчитывал с запасом до 20 вольт, кроме на датчик температуры, но он питается ведь от самой ардуины.

alex-hart
Offline
Зарегистрирован: 14.03.2015

Если желание собрать свой блок не пропало, пишите, две головы луше, а там глядишь и народ подтянется, где надо поправят. Правда у самого времени мало.

Всех с наступающим Новым годом!!!, у нас уже через полтора часа наступит

shmlka
Offline
Зарегистрирован: 28.12.2016

alex-hart пишет:

Если желание собрать свой блок не пропало, пишите, две головы луше, а там глядишь и народ подтянется, где надо поправят. Правда у самого времени мало.

Всех с наступающим Новым годом!!!, у нас уже через полтора часа наступит

Желание собрать блок есть. Все эти дни в свободное время пытался набросать код. Щас застопорился на millis(), почему то время не отсчитывается, всегда показывает 1 сек. Уже и так и эдак переписывал :-(  Может кто укажет на ошибку?

Код проверяю пока в симуляторе. 

#define R12v 12
#define R6v 6
#define PinTEM 0 // Анлоговый вход для считывания напряжения с делителя напряжения термодатчика
#define PinST 1 // Анлоговый вход для считывания напряжения с делителя напряжения стартера
#define PinIN 2 // Анлоговый вход для считывания напряжения с делителя напряжения для контроля напряж. на свечах
float Vout = 0; // Переменная для хранения значения напряжения в средней точки делителя напряжения термодатчика(0-5.0v)
int Vst = 0; // Переменная для хранения значения напряжения при запуске стартера
float Vin = 0; // Переменная для хранения значения напряжения на свечах (0-7.0v)
float VinOFF = 6.85; // Максимальное напряжение на свечах при котором сработает защита.
long t12 = 0; // Переменная для хранения времени работы реле 12v
long t6 = 0; // Переменная для хранения времени работы реле 6v
float R2 = 0; // Переменная для хранения значения сопротивления термодатчика R2 (датчик температуры двигателя)
byte var = 0; // Переменная для хранения значения выбора варианта программы
unsigned long prevMillis = 0;
unsigned long time = 0;
byte Voltage = 0;
byte Start = 0; 

void setup()
{
 pinMode(R12v, OUTPUT); // Выход на реле 12 вольт (реле 1)
 pinMode(R6v, OUTPUT); // Выход на реле 6 вольт (реле 2)
 pinMode(PinTEM, INPUT);
 pinMode(PinST, INPUT);
 pinMode(PinIN, INPUT);
 digitalWrite(R12v, LOW);
 digitalWrite(R6v, LOW);
 Serial.begin(9600);
}


void ST()	// Проверка на появления питания на стартере.
{
    if(Vst = (5.0 / 1023.0) * analogRead(PinST)*5.0 > 1) // Вычисляем напряжение на стартере (5.0 коэффициент делителя)    
    {
     Start = 1;
     Serial.print("Startet: ");
     Serial.println(Vst);
    }     
}


void Vmax() // Контроль напряжения на свечах когда питаются от 6v (5.0 коэффициент делителя) 
{
  if(Vin = ((5.0 / 1023.0) * analogRead(PinIN)*5.0) >= VinOFF)
  {
   Voltage = 1;
   Serial.print("Voltage svechi: ");
   Serial.println(Vin); // Напряжение на свечах при питании на 6V, для справки 
  }
}  


void loop()
{
 time = millis(); 
 Vout = (5.0 / 1023.0) * analogRead(PinTEM); // Вычисляем напряжение в средней точки делителя (0-5.0)
 R2 = 10000 / ((5.0 / Vout) - 1); // Вычисляем сопротивление R2 (10000 это значение R1 10 кОм)
 Serial.print("Voltage: ");
 Serial.println(Vout); // Напряжения в средней точки делителя (0-5.0) для справки
 Serial.print("R: "); //
 Serial.print(R2); // Значение сопротивления R2 для справки
 Serial.println("Om");
  
 

   delay(300); // Пауза затем выбор алгоритма прогрева в зависимости от показаний температуры двигателя
   if(R2 > 8000) var = 1; //Если температура двигателя от чуть выше нуля и в минус до упора
   if((R2 < 8000) && (R2 > 3200)) var = 2; // Если температура двигателя от 0 до +20 градусов
   if((R2 < 3200) && (R2 > 1500)) var = 3; // Если температура двигателя от +20 до +40 градусов
   if((R2 < 1500) && (R2 > 300)) var = 4; //Если температура двигателя от +40 до +80 градусов
   if(R2 < 300) var = 5; // Если температура двигателя от +80 градусов и выше до упора
   Serial.print("VAR: ");
   Serial.println(var);
  

    switch (var)
   {
     case 1:
      t12 = 6000;
      t6 = 30000;
       digitalWrite(R12v, HIGH); // Включаем реле быстрого нагрева свечей от 12v.
        if(time - prevMillis > t12) 
         {
          prevMillis = time;
          digitalWrite(R12v, LOW); // Если прошло время t12, отключаем реле прогрева на 12 вольт.
         } 
                 
    	if(Start == 1 && R12v == LOW)
         {
          delay(700); // Немного ждем пока работает стартер.
          digitalWrite(R6v, HIGH); // Включаем реле нагрева свечей на 6v
          	if(time - prevMillis > t6 || Voltage == 1)
             {
              prevMillis = time;
              digitalWrite(R6v, LOW); // Отключаем реле нагрева свечей от 6v
             } 		 
         }
      		  while (true) {};
              break;
      
      case 2:
      t12 = 4000;
      t6 = 10000;
       digitalWrite(R12v, HIGH); // Включаем реле быстрого нагрева свечей от 12v.
        if(time - prevMillis > t12) 
         {
          prevMillis = time;
          digitalWrite(R12v, LOW); // Если прошло время t12, отключаем реле прогрева на 12 вольт.
         } 
                 
    	if(Start == 1 && R12v == LOW)
         {
          delay(700); // Немного ждем пока работает стартер.
          digitalWrite(R6v, HIGH); // Включаем реле нагрева свечей на 6v
          	if(time - prevMillis > t6 || Voltage == 1)
             {
              prevMillis = time;
              digitalWrite(R6v, LOW); // Отключаем реле нагрева свечей от 6v
             } 		 
         }
      		  while (true) {};
              break;
      
      case 3:
      t12 = 5000;
      t6 = 25000;
       digitalWrite(R12v, HIGH); // Включаем реле быстрого нагрева свечей от 12v.
        if(time - prevMillis > t12) 
         {
          prevMillis = time;
          digitalWrite(R12v, LOW); // Если прошло время t12, отключаем реле прогрева на 12 вольт.
         } 
                 
    	if(Start == 1 && R12v == LOW)
         {
          delay(700); // Немного ждем пока работает стартер.
          digitalWrite(R6v, HIGH); // Включаем реле нагрева свечей на 6v
          	if(time - prevMillis > t6 || Voltage == 1)
             {
              prevMillis = time;
              digitalWrite(R6v, LOW); // Отключаем реле нагрева свечей от 6v
             } 		 
         }
      		  while (true) {};
              break;
      
      case 4:
      t12 = 3000;
      t6 = 6000;
       digitalWrite(R12v, HIGH); // Включаем реле быстрого нагрева свечей от 12v.
        if(time - prevMillis > t12) 
         {
          prevMillis = time;
          digitalWrite(R12v, LOW); // Если прошло время t12, отключаем реле прогрева на 12 вольт.
         } 
                 
    	if(Start == 1 && R12v == LOW)
         {
          delay(700); // Немного ждем пока работает стартер.
          digitalWrite(R6v, HIGH); // Включаем реле нагрева свечей на 6v
          	if(time - prevMillis > t6 || Voltage == 1)
             {
              prevMillis = time;
              digitalWrite(R6v, LOW); // Отключаем реле нагрева свечей от 6v
             } 		 
         }
      		  while (true) {};
              break;
      
      case 5:
      //t12 = 0;
      //t6 = 0;
       digitalWrite(R12v, LOW);
       digitalWrite(R6v, LOW);
      	  while (true) {};
          break;
   }
}
alex-hart
Offline
Зарегистрирован: 14.03.2015

Чето я тут ничерта не пойму.

1 Не вижу вызова функции "void ST() // Проверка на появления питания на стартере." Должна постоянно вызываться в цикле loop для определения запуска стартера. Иначе переменная Start всегда будет равна 0.

2  Функция "void Vmax() // Контроль напряжения" нигде не вызывается. 

2 Меня смущает 2 delay  в коде loop, в сумме как раз 1 сек.

В каком симуляторе проверяете? Натыкайте везде "Serial.print" и отслеживайте содержимое переменных.

Отладьте сначала на небольшом куске кода, возьмите из switch (var) только case 1 и проверяйте.

AlexeySh
Offline
Зарегистрирован: 16.01.2017

Ну для начала выражения time - prevMillis в сравнениях в скобки возьмите. Конкретно реализацию C в Ардуино не смотрел, но что-то мне подсказывает что операция сравнения может иметь более высокий приоритет чем вычитание. 

То же самое где Start == 1 и т. д. В документации по Ардуино вы мало полезного на эту тему найдете. Ставьте MS Visual Studio 2015, подключайтесь к MSDN, и читайте описание языка C. Там все по полочкам разложено, вплоть до того < или > имеет более высокий приоритет. Ну или ищите альтернативные источники, где все это есть. Мне таких не попалось к сожалению.

А вообще возьмите за правило: если не знаете, какая из операций имеет более высокий приоритет, то всегда ставьте скобки. Лишними не будут и ещё не раз помогут.

Про такие мелочи, как считали время, подождали 0,3 сек, затем запустили реле наверное говорить не стоит? Так и задумано, что реле 12v  на 0,3 сек меньше должно работать чем указано в t12. а реле 6v на 1 сек меньше чем в t6?

shmlka
Offline
Зарегистрирован: 28.12.2016

Доброго времени суток, спасибо за отклик! Симулятор использую этот https://circuits.io/

По поводу функций void ST() и void Vmax(), я их вызов просто на время пока убрал, думал может из за них проблемы и в switch (var) был только case 1 остольное дописал недавно . Скобки ставил, толку не было.  Вывод в serial.print тоже делал, в time постоянно стоит 1 и не обновляется, включал дебагер и ставил брейкпойнт на time - prevMillis > t12  и на prevMillis = time, срабатывает только на time - prevMillis > t12 и как будто зацикливается на этой строчке. От delay я буду избавляться, просто еще не дошел до него, завис с этим millis().

Для себя проверял и смотрел как работает millis() в таком коде (в том же симуляторе):

const int analogInPin = A0;
float sensorValue = 0;
float war = 13.00;
unsigned long prevMillis = 0;
unsigned long Start;
long t12 = 8000;
float war1 =15.00;
 
void setup() {
  Serial.begin(9600);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
}
 
void loop() {
  unsigned long currentMillis = millis();
    sensorValue =  (5.0 / 1023.0) * analogRead(analogInPin)*5;
   if (sensorValue > war){
    digitalWrite(A1, HIGH);
    //Serial.print("Tek_Time = " );
    //Serial.println(currentMillis);
    }
  if(currentMillis - prevMillis > t12) {
    prevMillis = currentMillis;
    digitalWrite(A1, LOW);
    Serial.print("Time = " );
    Serial.println(prevMillis);
    }
  if (sensorValue > war1){
    digitalWrite(A2, HIGH);
}
}

отробатывает нормально, время обновляется постоянно.

 

evgta
Offline
Зарегистрирован: 02.09.2016

Узнать что авто запустился можно тремя способами 1) по повышению напряжения до 13,5-14,2в 2) по контрольному выходу заряда с генератора(при неработающем - , при зппущенном +) 3) по датчику положения коленвала

shmlka
Offline
Зарегистрирован: 28.12.2016

Нашел причину зацикливания, это while (true) {} в конце каждого case. Я так понял стоит специально, чтобы дальше код не выполнялся как отработает один из case. Без while (true) {} таймер начал работать корректно, но теперь другая проблема, работа идет по кругу.

alex-hart
Offline
Зарегистрирован: 14.03.2015

Об этом я писал еще в первый раз, накал будет работать до тех пор пора двигатель не прогреется. Надо добавить глобальную переменную boolean "Run=false;" а в конце каждого case добавить "Run=true;" и в каждый if(R2 > 8000 && Run==false) var = 1. Пропускаем условие если один раз уже выполняли, следующее выполнение будет после выключения зажигания и обесточивания дуни. Мне кажется, что алгоритм программы надо полностью переделать, практически с ноля. Контроль стартера вам вообще не нужен, вы сами управляете стартером. Не вижу смысла в контроле напряжения на свечах, все по времени. Добавить выход на информационную лампочку накала свечей, горит пока идет накал 12в и тухнет при переходе на 6в. По большому счету можно полностью отказаться от millis()(за такие слова меня закидают тапками) т.к. у вас приложение некритичное к времени исполнения, а поставить delay(), отладить будет на порядок проще.

shmlka
Offline
Зарегистрирован: 28.12.2016

Контроль стартера сделал из за родного алгоритма работы, но вообще было в планах поменять на контроль по генератору. Если без него делать, то просто может быть так что напрасно свечи включаться будут по напряжению 6 вольт, бывает же зажигание включишь потом отвлечешься, а свечи получиться греть просто так будут. Насчет контроля напряжения, чтобы економить ресурс свечей, ведь при нагреве свечей будет увеличиваться сопротивление их и соответсвенно напряжение. Вместо лампочки планировал использовать зуммер, так как родное гнездо лампочки с завода пустое было и я переделал его под другие нужды :-)

Добавил переменную boolean "Run=false;"

#define R12v 12 // Выход на реле на 12v (реле 1) питание свечей.
#define R6v 6 // Выход на реле 6v (реле 2) питание для свечей.
#define PinTEM 0 // Анлоговый вход для считывания напряжения с делителя напряжения термодатчика
#define PinST 1 // Анлоговый вход для считывания напряжения с делителя напряжения стартера
#define PinIN 2 // Анлоговый вход для считывания напряжения с делителя напряжения для контроля напряж. на свечах
float Vout = 0; // Переменная для хранения значения напряжения в средней точки делителя напряжения термодатчика(0-5.0v)
int Vst = 0; // Переменная для хранения значения напряжения при запуске стартера
float Vin = 0; // Переменная для хранения значения напряжения на свечах (0-7.0v)
float VinOFF = 6.85; // Максимальное напряжение на свечах при котором сработает защита.
long t12 = 0; // Переменная для хранения времени работы реле 12v
long t6 = 0; // Переменная для хранения времени работы реле 6v
float R2 = 0; // Переменная для хранения значения сопротивления термодатчика R2 (датчик температуры двигателя)
byte var = 0; // Переменная для хранения значения выбора варианта программы
unsigned long prevMillis = 0;
unsigned long time = 0;
byte Voltage = 0;
byte Start = 0; 
boolean Run = false;


void setup()
{
 pinMode(R12v, OUTPUT);
 pinMode(R6v, OUTPUT);
 pinMode(PinTEM, INPUT);
 pinMode(PinST, INPUT);
 pinMode(PinIN, INPUT);
 digitalWrite(R12v, LOW);
 digitalWrite(R6v, LOW);
 Serial.begin(9600);
}


void ST()	// Проверка на появления питания на стартере.
{
    if(Vst = (5.0 / 1023.0) * analogRead(PinST)*5.0 > 1) // Вычисляем напряжение на стартере (5.0 коэффициент делителя)    
    {
     Start = 1;
     Serial.print("Startet: ");
     Serial.println(Vst);
    }     
}


void Vmax() // Контроль напряжения на свечах когда питаются от 6v (5.0 коэффициент делителя) 
{
  if(Vin = ((5.0 / 1023.0) * analogRead(PinIN)*5.0) >= VinOFF)
  {
   Voltage = 1;
   Serial.print("Voltage svechi: ");
   Serial.println(Vin); // Напряжение на свечах при питании на 6V, для справки 
  }
}  


void loop()
{
 time = millis();
 Vout = (5.0 / 1023.0) * analogRead(PinTEM); // Вычисляем напряжение в средней точки делителя (0-5.0)
 R2 = 10000 / ((5.0 / Vout) - 1); // Вычисляем сопротивление R2 (10000 это значение R1 10 кОм)
 Serial.print("Voltage: ");
 Serial.println(Vout); // Напряжения в средней точки делителя (0-5.0) для справки
 Serial.print("R: "); //
 Serial.print(R2); // Значение сопротивления R2 для справки
 Serial.println("Om");
 

   delay(300); // Пауза затем выбор алгоритма прогрева в зависимости от показаний температуры двигателя
   if((R2 > 8000) && (Run == false)) var = 1; //Если температура двигателя от чуть выше нуля и в минус до упора
   if((R2 < 8000) && (R2 > 3200) && (Run == false)) var = 2; // Если температура двигателя от 0 до +20 градусов
   if((R2 < 3200) && (R2 > 1500) && (Run == false)) var = 3; // Если температура двигателя от +20 до +40 градусов
   if((R2 < 1500) && (R2 > 300) && (Run == false)) var = 4; //Если температура двигателя от +40 до +80 градусов
   if((R2 < 300) && (Run == false)) var = 5; // Если температура двигателя от +80 градусов и выше до упора
   Serial.print("VAR: ");
   Serial.println(var);
  

    switch (var)
   {
     case 1:
      t12 = 6000;
      t6 = 30000;
       digitalWrite(R12v, HIGH); // Включаем реле быстрого нагрева свечей от 12v.
        if((time - prevMillis) > t12) 
         {
          prevMillis = time;
          digitalWrite(R12v, LOW); // Если прошло время t12, отключаем реле прогрева на 12 вольт.
         } 
                 
    	if((Start == 1) && (R12v == LOW)) // Если появилось питание на стартере и реле2 отключено, то...
         {
            digitalWrite(R6v, HIGH); // Включаем реле нагрева свечей на 6v
          	if((time - prevMillis) > t6 || (Voltage == 1)) // Если прошло время t6 или напряжение на свечах превысило допустимое, отключаем реле.
             {
              prevMillis = time;
              digitalWrite(R6v, LOW); // Отключаем реле нагрева свечей от 6v
             } 		 
         }
              Run = true;
              break;

Все равно так же гоняет по кругу. И странно он пропускает часть кода (смотрел через дебагер по шагам) Начинет с 057 строки, доходит до 087 строки потом прыгает на 099 и далее на 100 строки, и дальше опять на 057 по кругу.

 

AlexeySh
Offline
Зарегистрирован: 16.01.2017

evgta пишет:

Узнать что авто запустился можно тремя способами 1) по повышению напряжения до 13,5-14,2в 2) по контрольному выходу заряда с генератора(при неработающем - , при зппущенном +) 3) по датчику положения коленвала

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

Второй и третий работают нормально. Ставил себе на машину водородный генератор, подключил вторым способом. Работает нормально. Сначала был подключен первым, были проблемы. Весной и в начале зимы приходилось подстраивать напряжение срабатывания.

Контрольный выход может быть по разному реализован. На дизеле Pajero 4 автоэлектрик долго разбирался с подключением, подключил транзисторный ключ где то в разрез провода, который идет к панели приборов. На блок управления дизеля этот сигнал не подается. На бензиновом он подается. Смотрите документацию по конкретной машине. При заведенном двигателе на этом выводе напряжение питания, при незаведенном 0 вольт.

alex-hart
Offline
Зарегистрирован: 14.03.2015

Ну вы даете, так и должно быть, функция loop выполняется в постоянном цикле, процесор работает, loop крутится. Run =true,false вводилось для одноразового выполнения кода, теперь при первом запуске в выборе программы происходит проверка, выполнялся уже код или нет. Если false , то с момента подачи питания код не выполнялся и он будет полностью выполнен. 

Черт, сам сбился и вас с толку сбил. if((R2 > 8000) && (Run == false)) var = 1; - здесь run==false бесполезен т.к. основное выполнение в switch(var) находится, еще раз извиняюсь. Чтобы не оборачивать switch в if и проверять run на значение можно попробывать в начале цикла использовать оператор goto, хотя это почемуто не приветствуется.

#define R12v 12 // Выход на реле на 12v (реле 1) питание свечей.
#define R6v 6 // Выход на реле 6v (реле 2) питание для свечей.
#define PinTEM 0 // Анлоговый вход для считывания напряжения с делителя напряжения термодатчика
#define PinST 1 // Анлоговый вход для считывания напряжения с делителя напряжения стартера
#define PinIN 2 // Анлоговый вход для считывания напряжения с делителя напряжения для контроля напряж. на свечах
float Vout = 0; // Переменная для хранения значения напряжения в средней точки делителя напряжения термодатчика(0-5.0v)
int Vst = 0; // Переменная для хранения значения напряжения при запуске стартера
float Vin = 0; // Переменная для хранения значения напряжения на свечах (0-7.0v)
float VinOFF = 6.85; // Максимальное напряжение на свечах при котором сработает защита.
long t12 = 0; // Переменная для хранения времени работы реле 12v
long t6 = 0; // Переменная для хранения времени работы реле 6v
float R2 = 0; // Переменная для хранения значения сопротивления термодатчика R2 (датчик температуры двигателя)
byte var = 0; // Переменная для хранения значения выбора варианта программы
unsigned long prevMillis = 0;
unsigned long time = 0;
byte Voltage = 0;
byte Start = 0; 
boolean Run = false;


void setup()
{
 pinMode(R12v, OUTPUT);
 pinMode(R6v, OUTPUT);
 pinMode(PinTEM, INPUT);
 pinMode(PinST, INPUT);
 pinMode(PinIN, INPUT);
 digitalWrite(R12v, LOW);
 digitalWrite(R6v, LOW);
 Serial.begin(9600);
}


void ST()  // Проверка на появления питания на стартере.
{
    if(Vst = (5.0 / 1023.0) * analogRead(PinST)*5.0 > 1) // Вычисляем напряжение на стартере (5.0 коэффициент делителя)    
    {
     Start = 1;
     Serial.print("Startet: ");
     Serial.println(Vst);
    }     
}


void Vmax() // Контроль напряжения на свечах когда питаются от 6v (5.0 коэффициент делителя) 
{
  if(Vin = ((5.0 / 1023.0) * analogRead(PinIN)*5.0) >= VinOFF)
  {
   Voltage = 1;
   Serial.print("Voltage svechi: ");
   Serial.println(Vin); // Напряжение на свечах при питании на 6V, для справки 
  }
}  


void loop()
{
if(Run==true){goto Ends;}
 time = millis();
 Vout = (5.0 / 1023.0) * analogRead(PinTEM); // Вычисляем напряжение в средней точки делителя (0-5.0)
 R2 = 10000 / ((5.0 / Vout) - 1); // Вычисляем сопротивление R2 (10000 это значение R1 10 кОм)
 Serial.print("Voltage: ");
 Serial.println(Vout); // Напряжения в средней точки делителя (0-5.0) для справки
 Serial.print("R: "); //
 Serial.print(R2); // Значение сопротивления R2 для справки
 Serial.println("Om");
 

   delay(300); // Пауза затем выбор алгоритма прогрева в зависимости от показаний температуры двигателя
   if(R2 > 8000)  var = 1; //Если температура двигателя от чуть выше нуля и в минус до упора
   if(R2 < 8000 && R2 > 3200)var = 2; // Если температура двигателя от 0 до +20 градусов
   if(R2 < 3200 && R2 > 1500)var = 3; // Если температура двигателя от +20 до +40 градусов
   if(R2 < 1500 && R2 > 300)var = 4; //Если температура двигателя от +40 до +80 градусов
   if(R2 < 300)  var = 5; // Если температура двигателя от +80 градусов и выше до упора
   Serial.print("VAR: ");
   Serial.println(var);
  
 
    switch (var)
   {
     case 1:
      t12 = 6000;
      t6 = 30000;
       digitalWrite(R12v, HIGH); // Включаем реле быстрого нагрева свечей от 12v.
        if((time - prevMillis) > t12) 
         {
          prevMillis = time;
          digitalWrite(R12v, LOW); // Если прошло время t12, отключаем реле прогрева на 12 вольт.
         } 
                 
      if((Start == 1) && (R12v == LOW)) // Если появилось питание на стартере и реле2 отключено, то...
         {
            digitalWrite(R6v, HIGH); // Включаем реле нагрева свечей на 6v
            if((time - prevMillis) > t6 || (Voltage == 1)) // Если прошло время t6 или напряжение на свечах превысило допустимое, отключаем реле.
             {
              prevMillis = time;
              digitalWrite(R6v, LOW); // Отключаем реле нагрева свечей от 6v
             }     
         }
              Run = true;
              break;
   }  
  Ends:  
  Serial.print("Run: ");
   Serial.println(Run);        
 
}

 

evgta
Offline
Зарегистрирован: 02.09.2016

Ну почему, ходовые огни у меня при 13,2в включаются, проблем не зпмечено.

alex-hart
Offline
Зарегистрирован: 14.03.2015

У вас к вашей машине дожна быть подобная диаграмма работы системы накала

Это для nissan, но они очень похожи, вот от нее и надо плясать

AlexeySh
Offline
Зарегистрирован: 16.01.2017

evgta пишет:
Ну почему, ходовые огни у меня при 13,2в включаются, проблем не зпмечено.

У вас это в каком регионе? У вас есть зимой -40, а летом +40? а если машина постояла на солнце, то под капотом намного больше. У нас вот есть. И проблемы были с порогом включения. Думаете мне очень хотелось пол машины разбирать чтобы подключить блок к генератору?

Плюс ещё от машины зависит. От алгоритма регулировки напряжения заряда аккумулятора.

evgta
Offline
Зарегистрирован: 02.09.2016

Регион ЛО, на аккумуляторе полностью заряженном 12,8 вольт, мах 13В, а напряжение заряда даже при полностю разряженном акб и включенных фарах и подогревателях ниже 13,5 не опускалось, зарядные напряжения для акб-летом 13,8В. Зимой до 14,5В. Причем ходовики не я делал, магнетти марелли.

shmlka
Offline
Зарегистрирован: 28.12.2016

Да есть,

 

 

 

 

 

 

 

 

 

 

 

 

По диаграмме реле два уже включено при работе стартера, я хотел чтобы реле попозже включалось, чтобы стартеру легче было крутить. Но наверное буду исправлять на родной алгоритм работы. Тем более с генератора тоже провод приходит  в родной блок. Там по книжке при включении зажигания появляется 1-4в, при работе двигателя на холостом ходу выше 11в.

Попробую наверное переписать код, вроде появилось немного понимания как сделать сегодня :-)  Спасибо всем за помощь.

То что там код должен крутиться по кругу я понял, но не разобрался почему пропускает этот участо в кейсе, как я писал выше?

if((Start == 1) && (R12v == LOW)) // Если появилось питание на стартере и реле2 отключено, то...

091          {
092             digitalWrite(R6v, HIGH); // Включаем реле нагрева свечей на 6v
093             if((time - prevMillis) > t6 || (Voltage == 1)) // Если прошло время t6 или напряжение на свечах превысило допустимое, отключаем реле.
094              {
095               prevMillis = time;
096               digitalWrite(R6v, LOW); // Отключаем реле нагрева свечей от 6v
097              }      

 

evgta
Offline
Зарегистрирован: 02.09.2016

А как обратная связь осуществляется что бы узнать что температура выше 1050градусов? В голову только контроль по току приходит, по падению тока в свечах накала от повышения сопротивления свечей с увеличением температуры.

alex-hart
Offline
Зарегистрирован: 14.03.2015

Т.к. функция void ST() у вас не вызывается, переменная Start у вас всегда равна 0. If проверяет состояние start и R12v на значение true и пропускает цикл т.к. Start=0.

alex-hart
Offline
Зарегистрирован: 14.03.2015

evgta пишет:
А как обратная связь осуществляется что бы узнать что температура выше 1050градусов? В голову только контроль по току приходит, по падению тока в свечах накала от повышения сопротивления свечей с увеличением температуры.

По времени и падению напряжения

shmlka
Offline
Зарегистрирован: 28.12.2016

Где то находил информацию, что контроль идет по сопротивлению свечей. Поэтому он и не работает с другими свечами.

shmlka
Offline
Зарегистрирован: 28.12.2016

Всем привет! Вот навоял новую версию программы, выкладываю на вашу критику :-) В симуляторе вроде нормально работает. В место питания на стартере теперь будет питание с генератора. Пока до одного "case".

#define R12v 12               // Выход на реле на 12v (реле 1) питание свечей.
#define R6v 6                 // Выход на реле 6v (реле 2) питание свечей.
#define PinTEM 0              // Анлоговый вход для считывания напряжения с делителя напряжения термодатчика.
#define PinGen 1              // Анлоговый вход для считывания напряжения с делителя напряжения генератора.
#define PinINsv 2                    // Анлоговый вход для считывания напряжения с делителя напряжения для контроля напряж. на свечах.
float Vtem = 0;                        // Переменная для хранения значения напряжения в средней точке делителя напряжения термодатчика(0-5.0v)
int Vgen = 0;                           // Переменная для хранения значения напряжения с генератора.
float Vsv = 0;                          // Переменная для хранения значения напряжения на свечах (0-7.0v)
float VsvOFF = 6.85;             // Максимальное напряжение на свечах при котором сработает защита.
long time12 = 0;                     // Переменная для хранения времени работы реле 12v
long time6 = 0;                       // Переменная для хранения времени работы реле 6v
float Rtem = 0;                       // Переменная для хранения значения сопротивления термодатчика R2 (датчик температуры двигателя)
byte var = 0;                           // Переменная для хранения значения выбора варианта программы
unsigned long prevMillis = 0; // Переменная хранит время отключения реле.
boolean Run = false;             // Переменная для хранения состояния выполнения цикла Case.
boolean Gen = false;            // Для вызова функци Vcc().
boolean Svechi = false;        // Для вызова функци Vmax().
boolean flagR12 = false;
boolean flagR6 = false;


void setup() {
 pinMode(R12v, OUTPUT);
 pinMode(R6v, OUTPUT);
 pinMode(PinTEM, INPUT);
 pinMode(PinGen, INPUT);
 pinMode(PinINsv, INPUT);
 digitalWrite(R12v, LOW);
 digitalWrite(R6v, LOW);
 Serial.begin(9600);
}
  
  // Функция выбора алгоритма прогрева по температуре двигателя.
  byte Variant(){
    if (Run == false){
  	delay(300);
      if(Temp() > 8000){										//Если температура двигателя от чуть выше нуля и в минус до упора.
        var = 1; 
        time12 = 6000; 
        time6 = 28000;
      }
      else if((Temp() < 8000) && (Temp() > 3000)){					// Если температура двигателя от 0 до +20 градусов.
    	var = 2; 
        time12 = 4000; 
        time6 = 10000;
      }
      else if((Temp() < 3000) && (Temp() > 1500)){					// Если температура двигателя от +20 до +40 градусов.
    	 var = 3; 
         time12 = 2000;
         time6 = 5000;
      }
      else if((Temp() < 1500) && (Temp() > 800)){				     //Если температура двигателя от +40 градусов и выше.
    	 var = 4; 
         time12 = 1000; 
         time6 = 0;
      }
      else if(((Temp() < 800) && (Temp() > 300)) || (Temp() <= 300)){     // Если температура двигателя от ? до +80 градусов.
    	 var = 5;
      	 time12 = 0;
         time6 = 0;
      }
      Serial.print("Variant algoritma: ");                                    		     // Вывод выбранного 
  	 Serial.println(var);									     // алгоритма для справки.
    } return var; 																			
  }

 // Функция определения показаний термодатчика.
 float Temp(){
   Vtem = (5.0 / 1023.0) * analogRead(PinTEM);     // Вычисляем напряжение в средней точки делителя (0-5.0)
   Rtem = 10000 / ((5.0 / Vtem) - 1);                        // Вычисляем сопротивление термодатчика (10000 это значение сопротивления в делителе 10 кОм)
   Serial.print("R: ");                                                 // Значение
   Serial.print(Rtem);                                               // сопротивления термодатчика
   Serial.println("Om");                                            // для справки  
   return Rtem;
 }
 // Конец функции.


// Функция проверки появления питания с генератора.
boolean Vcc(){                                             
 boolean flag1 = false;
    if((Vgen = (5.0 / 1023.0) * analogRead(PinGen)*5.0) > 6){  // Вычисляем напряжение (5.0 коэффициент делителя)    
     flag1 = true;                                                                        // Если напряжение на входе превышает 6в/
    } Serial.print("Generator: ");
      Serial.print(Vgen);
  	  Serial.println("Volt");
      Serial.println(flag1);
  return flag1;                                            
}
// конец функции


// Функция контроля напряжения на свечах при питании от 6в.
boolean Vmax() {                                              
 boolean flag2 = false;                                            
    if(Vsv = ((5.0 / 1023.0) * analogRead(PinINsv)*5.0) >= VsvOFF){    // Вычисляем напряжение (5.0 коэффициент делителя)
     flag2 = true;
    } else {
       flag2 = false;
    } 
  Serial.print("Vcc svechi: ");     // Напряжение на свечах
  Serial.print(Vsv);                    // при питании от 6в
  Serial.println("Volt");		// для справки  
  Serial.println(flag2);               
  return flag2; 
}  
// конец функции


void loop() {
       
  switch (Variant()){
    case 1:
  	  Run = true;
  if ((flagR12 == false) && (Vcc() == false)){		                   
      digitalWrite(R12v, HIGH);                                                     // Включаем реле быстрого нагрева свечей от 12v.     
  }
  else{
    digitalWrite(R12v, LOW);
  }     
       if(((millis() - prevMillis) > time12) && (flagR12 == false)){     // Если прошло время t12,
          prevMillis = millis();                                                            // отключаем реле
          digitalWrite(R12v, LOW);				                   // прогрева на 12 вольт.
          flagR12 = true;
          Serial.print("Rele1: ");
          Serial.println("OFF");                
         } 
                 
    	    if((Vcc() == true) && (flagR6 == false)){                      						// Если появилось питание с генератора,
            digitalWrite(R6v, HIGH);											// включаем реле нагрева свечей на 6в.
            }																
          	 if((((millis() - prevMillis) > time6) && (flagR6 == false)) || (Vmax() == true)){    // Если прошло время t6 или
                prevMillis = millis();                                                			                        // напряжение на свечах
                digitalWrite(R6v, LOW);                            							// превысило допустимое,
               	flagR6 = true;						 							// отключаем реле нагрева свечей от 6в.
             } break; 
         
	} 
}

 

AlexeySh
Offline
Зарегистрирован: 16.01.2017

1) Если Temp() будет равно 8000, 3000, 1500 или 800, то ваш алгоритм работать не будет.

2) Если результат Temp() будет разный при двух вызовах функции (а он будет разный), то поведение такого алгоритма непредсказуемо. Правильное решение - вызвать эту функцию один раз, сохранить результат в переменную. И все логические проверки выполнять уже с переменной.

Простейший пример для понимания: при первом вызове Temp() = 7999, при втором Temp() = 8001. Куда уйдет ваш алгоритм?

Дальше не проверял, возможно есть и ещё ошибки.

shmlka
Offline
Зарегистрирован: 28.12.2016

Там ведь в "Variant(){" есть строка "if (Run == false){"  где Run присваивается "True" в "case 1:" и весь код в "Variant(){" пропускается при следующем чтении, а больше "Temp()" нигде не вызывается.

"1) Если Temp() будет равно 8000, 3000, 1500 или 800, то ваш алгоритм работать не будет."  - Да, упустил этот вариант, надо добавить "=" я так понимаю?

И как мне кажется можно откозаться от использования оператора Switch? Только чето не пойму как получить из функции "Variant(){" значения переменных time12 и time6.

 

 

 

AlexeySh
Offline
Зарегистрирован: 16.01.2017

shmlka пишет:

Там ведь в "Variant(){" есть строка "if (Run == false){"  где Run присваивается "True" в "case 1:" и весь код в "Variant(){" пропускается при следующем чтении, а больше "Temp()" нигде не вызывается.

Я вам пример с цифрами для чего написал? Пройдите по алгоритму и поймете свою ошибку.

Первый раз проверили на 7999 больше 8000. Не соответствует.

Перешли ко второй проверке. 8001 меньше 8000. Не соответствует. И пролетели до конца функции Variant().

Ни один из вариантов не подошел.

alex-hart
Offline
Зарегистрирован: 14.03.2015

Ну вообщето switch для этого и предназначен, выбор чего либо из многого. Вот = добавить точно надо. Заморочился установкой Atmel Studio и Visual Micro, разберусь, протресу ваш код. Программная часть это хорошо конечно потом война начнется с аппаратной частью, это будет куда веселее. 

AlexeySh
Offline
Зарегистрирован: 16.01.2017

alex-hart пишет:

Ну вообщето switch для этого и предназначен, выбор чего либо из многого. Вот = добавить точно надо. Заморочился установкой Atmel Studio и Visual Micro, разберусь, протресу ваш код. Программная часть это хорошо конечно потом война начнется с аппаратной частью, это будет куда веселее. 

switch для работы с диапазонами не удобен, в switch идет точное соответствие значению, а здесь соотвествие диапазону значений. Идея правильная, а вот реализация пока что хромает. Там ещё второе условие в else if лишнее используется.

shmlka
Offline
Зарегистрирован: 28.12.2016

AlexeySh пишет:

shmlka пишет:

Там ведь в "Variant(){" есть строка "if (Run == false){"  где Run присваивается "True" в "case 1:" и весь код в "Variant(){" пропускается при следующем чтении, а больше "Temp()" нигде не вызывается.

Я вам пример с цифрами для чего написал? Пройдите по алгоритму и поймете свою ошибку.

Первый раз проверили на 7999 больше 8000. Не соответствует.

Перешли ко второй проверке. 8001 меньше 8000. Не соответствует. И пролетели до конца функции Variant().

Ни один из вариантов не подошел.

Наверное или я Вас не понял, или Вы меня :-)

Я писал по поводу: (2) Если результат Temp() будет разный при двух вызовах функции (а он будет разный), то поведение такого алгоритма непредсказуемо. Правильное решение - вызвать эту функцию один раз, сохранить результат в переменную. И все логические проверки выполнять уже с переменной.)

щас исправил "Variant()"

// Функция выбора алгоритма прогрева по температуре двигателя.
  byte Variant(){
    if (Run == false){
  		delay(300);
      if(Temp() >= 8000){									//Если температура двигателя от чуть выше нуля и в минус до упора.
        time12 = 6000; 
        time6 = 28000;
      }
      else if((Temp() <= 8000) && (Temp() >= 3000)){			// Если температура двигателя от 0 до +20 градусов.
    	time12 = 4000; 
        time6 = 10000;
      }
      else if((Temp() <= 3000) && (Temp() >= 1500)){			// Если температура двигателя от +20 до +40 градусов.
    	 time12 = 2000;
         time6 = 5000;
      }
      else if((Temp() <= 1500) && (Temp() >= 800)){				//Если температура двигателя от +40 градусов и выше.
    	 time12 = 1000; 
         time6 = 0;
      }
      else if(((Temp() <= 800) && (Temp() >= 300)) || (Temp() < 300)){  //Если температура двигателя от ? до +80 градусов.
    	 time12 = 0;
         time6 = 0;
      }
      Serial.print("Variant algoritma: ");                                    		// Вывод выбранного 
  	 Serial.println(time12);
       Serial.println(time6);// алгоритма для справки.
    }  																			
  }

и убрал Switch

void loop(){
  Variant();
   if ((flagR12 == false) && (Vcc() == false)){	// Включаем реле быстрого нагрева свечей от 12v.
      digitalWrite(R12v, HIGH);
      Run = true;
  }
  else{
    digitalWrite(R12v, LOW);
  }     
       if(((millis() - prevMillis) > time12) && (flagR12 == false)){   // Если прошло время t12,
          prevMillis = millis();                  // отключаем реле
          digitalWrite(R12v, LOW);				  // прогрева на 12 вольт.
          flagR12 = true;
          Serial.print("Rele1: ");
          Serial.println("OFF");                
         } 
                 
    	    if((Vcc() == true) && (flagR6 == false)){        // Если появилось питание с генератора,
            digitalWrite(R6v, HIGH);				// включаем реле нагрева свечей на 6в.
            }																
          	 if((((millis() - prevMillis) > time6) && (flagR6 == false)) || (Vmax() == true)){  // Если прошло время t6 или
                prevMillis = millis();                                                			// напряжение на свечах
                digitalWrite(R6v, LOW);                            				// превысило допустимое,
               	flagR6 = true;						 				// отключаем реле нагрева свечей от 6в.
              }
         
	} 

 

AlexeySh
Offline
Зарегистрирован: 16.01.2017

Вы не поняли. Только к сожалению не меня, а как работает код на реализации C для Ардуино.

Теперь по шагам. Вы вызвали функцию Variant() первый раз и ожидаете, что она измерит температуру и в зависимости от температуры установит нужный режим работы вашего устройства.

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

При первой проверке if (Temp() > 8000) вы вызываете функцию Temp(). Она измеряет температуру возвращает вам например 7999.

Условие не выполнено, переходим ко второй проверке if (Temp() <= 8000). Функция Temp() вызывается второй раз и возвращает например 8001.

Все, считайте вы уже пролетели. Если вы больше Variant() не вызовете, то вы режим уже никогда не установите.

AlexeySh
Offline
Зарегистрирован: 16.01.2017

Кстати, чтобы не городить огород с переменными для отслеживания, первый ли раз выполняется код, достаточно было этот код поместить в setup(). setup() выполняется один раз после запуска микроконтроллера.

shmlka
Offline
Зарегистрирован: 28.12.2016

В setup() пробовал перед этим, но чето тогда компилятор ругался и я решил не замарачиваться. Но раз все таки можно, то опять заморочусь тогда.

shmlka
Offline
Зарегистрирован: 28.12.2016

Доброго времени суток! Вот новый вариант программы, в симуляторе работает вроде без глюков, гонял по разным режимам и вариантам работы. Решил все таки в setup() не писать, а остаться с переменными для отслеживания работы :-)

// Программа для замены родного блока Super Quick Glow Mitsubishi.


#define Ton 5		      // Выход на зумер
#define R12v 12               // Выход на реле на 12v (реле 1) питание свечей.
#define R6v 6                 // Выход на реле 6v (реле 2) питание свечей.
#define PinTEM 0              // Анлоговый вход для считывания напряжения с делителя напряжения термодатчика.
#define PinGen 1              // Анлоговый вход для считывания напряжения с делителя напряжения генератора.
#define PinINsv 2             // Анлоговый вход для считывания напряжения с делителя напряжения для контроля напряж. на свечах.
float Vtem = 0;               // Переменная для хранения значения напряжения в средней точке делителя напряжения термодатчика(0-5.0v)
int Vgen = 0;                 // Переменная для хранения значения напряжения с генератора.
float Vsv = 0;                // Переменная для хранения значения напряжения на свечах (0-7.0v)
float VsvOFF = 6.85;          // Максимальное напряжение на свечах при котором сработает защита.
long time12 = 0;              // Переменная для хранения времени работы реле 12v
long time6 = 0;               // Переменная для хранения времени работы реле 6v
float Rtem = 0;               // Переменная для хранения значения сопротивления термодатчика R2 (датчик температуры двигателя)
byte var = 0;                 // Переменная для хранения значения выбора варианта программы
unsigned long prevMillis = 0; // Переменная хранит время отключения реле.
boolean flagR12 = false;      // Переменная хранит состояние отработало реле1 (на 12в) или нет, чтобы код не выполнялся повторно.
boolean flagR6 = false;       // Переменная хранит состояние отработало реле2 (на 6в) или нет, чтобы код не выполнялся повторно.


void setup() {
 pinMode(R12v, OUTPUT);     // Определяем
 pinMode(R6v, OUTPUT);      // входа
 pinMode(PinTEM, INPUT);    // выхода
 pinMode(PinGen, INPUT);    // на
 pinMode(PinINsv, INPUT);   // пинах.
 digitalWrite(R12v, LOW);   // Реле1 отключено при старте.
 digitalWrite(R6v, LOW);    // Реле2 отключено при старте.
 Variant();                 // Запускаем один раз при старте функцию выбора алгоритма прогрева.
 Serial.begin(9600);
}
  

// Функция выбора алгоритма прогрева по температуре двигателя. ***************************************************
byte Variant(){
  delay(300);                                     // Ждем 300 мс для стабилизации показаний термодатчика.
   if(Temp() >= 8000){			          // Если температура двигателя от чуть выше нуля и в минус до упора.
     time12 = 6000;                               // Время работы реле1 в мс (6 сек)
     time6 = 28000;                               // Время работы реле2 в мс (28 сек)
     }
   else if((Temp() <= 8000) && (Temp() >= 3000)){ // Если температура двигателя от 0 до +20 градусов.
     time12 = 4000;                               // Время работы реле1 в мс (4 сек)
     time6 = 10000;                               // Время работы реле2 в мс (10 сек)
     }
   else if((Temp() <= 3000) && (Temp() >= 1500)){ // Если температура двигателя от +20 до +40 градусов.
     time12 = 2000;                               // Время работы реле1 в мс (2 сек)
     time6 = 5000;                                // Время работы реле2 в мс (5 сек)
     }
   else if((Temp() <= 1500) && (Temp() >= 800)){  // Если температура двигателя от +40 градусов и выше.
     time12 = 1000;                               // Время работы реле1 в мс (1 сек)
     time6 = 0;                                   // Время работы реле2 в мс (0 сек)
     }
   else if((Temp() <= 800) && (Temp() >= 300)){   // Если температура двигателя от +40 до +80 и больше градусов.
     time12 = 0;                                  // Время работы реле1 в мс (0 сек)
     time6 = 0;                                   // Время работы реле2 в мс (0 сек)
     }
   Serial.print("R: ");                           // Вывод информации
   Serial.print(Rtem);                            // о выбранном алгоритме
   Serial.println(" Om");			  // прогрева,
   Serial.print("Rele1 vremya: ");		  // сопротивление
   Serial.print(time12/1000);			  // термодатчика 
   Serial.println(" s");			  // время в сек. реле1 и реле2
   Serial.print("Rele2 vremya: ");		  // для справки.
   Serial.print(time6/1000);
   Serial.println(" s"); 
}   // Конец функции *********************************************************************************************



// Функция расчета показаний термодатчика (PinTEM). **************************************************************
float Temp(){
  Vtem = (5.0 / 1023.0) * analogRead(PinTEM); // Вычисляем напряжение в средней точки делителя (0-5.0).
  Rtem = 10000 / ((5.0 / Vtem) - 1);          // Вычисляем сопротивление термодатчика (10000 это значение сопротивления в делителе 10 кОм).
  return Rtem;                                // Возвращаем значение сопротивления из функции в вызывающую функцию.
}  // Конец функции. *********************************************************************************************



// Функция расчета напряжения поступаемого на PinGen (с генератора). *********************************************
float Vcc(){                                             
  Vgen = (5.0 / 1023.0) * analogRead(PinGen)*5.0;  // Вычисляем напряжение (5.0 коэффициент делителя)    
  Serial.print("Generator: ");                     // Вывод
  Serial.print(Vgen);                              // информации о напряжении 
  Serial.println(" V");                            // поступаемого с генератора. Для справки.
  return Vgen;                                     // Возвращаем значение напряжения из функции в вызывающую функцию.
}  // Конец функции. *********************************************************************************************



// Функция расчета напряжения поступаемого на свечи (PinINsv). ***************************************************
float Vmax(){                                              
  Vsv = ((5.0 / 1023.0) * analogRead(PinINsv))*5.0; // Вычисляем напряжение (5.0 коэффициент делителя)
  Serial.print("Vcc svechi: ");                     // Вывод
  Serial.print(Vsv);                                // информации о напряжении
  Serial.println(" V");                             // на свечах. Для справки.
  return Vsv;                                       // Возвращаем значение напряжения из функции в вызывающую функцию.
} // Конец функции. **********************************************************************************************



void loop(){
  if((flagR12 == false) && (time12 != 0)){ // Если цикл еще ни разу не отработал (flagR12=false) и время (time12) работы реле не равно 0сек.,
      digitalWrite(R12v, HIGH);            // то включаем реле1 (быстрый прогрев свечей), иначе пропускаем код.
   do{  
    if((millis() - prevMillis) > time12){  // Проверяем не прошел ли нужный интервал работы Реле1 (time12), если прошел то
       prevMillis = millis();              // сохраняем время отключения Реле1 и 						
       digitalWrite(R12v, LOW);		   // отключаем реле1,						
       flagR12 = true;                     // меняем состояние flagR12 на true.
       tone(Ton, 2000, 200);               // Воспроизводим сигнал частотой 2000 Гц и длительностью 200 мс.
      }
    } while(flagR12 != true && Vcc() < 8.00); // Цикл будет выполняться пока flagR12 не будет равно true или не появится напряжение с генератора больше 8в.
       flagR12 = true;                        // Если выход из цикла произошел при появлении напряжения с генератора, то
       digitalWrite(R12v, LOW);               // меняем состояние flagR12 на true и отключаем реле1.
       Serial.print("Rele1: ");               // Вывод информации, что реле1
       Serial.println("OFF");                 // отключилось. Для справки.
  }           
  
  if((flagR6 == false) && (Vcc() > 8.00) && (time6 != 0)){ // Если цикл еще ни разу не отработал (flagR6=false) и время (time6) работы реле не равно 0сек.,
       digitalWrite(R6v, HIGH);                            // то включаем реле2 (рабочий прогрев свечей), иначе пропускаем код.
   do{
    if(((millis() - prevMillis) > time6) || (Vcc() < 10.00)){ // Проверяем не прошел ли нужный интервал работы Реле2 (time6) и напряжение поступаемое с генератора,
       prevMillis = millis();              // если время прошло или пропало напряжение с генератора, то сохраняем время отключения Реле2.             			
       digitalWrite(R6v, LOW);             // и отключаем реле2,							 
       flagR6 = true;                      // меняем состояние flagR6 на true.
      }
     }while((flagR6 != true) && (Vmax() <= VsvOFF)); // Цикл будет выполняться пока flagR6 не будет равно true или напряжение на свечах не превысит заданное в переменной VsvOFF.
       flagR6 = true;             // Если выход из цикла произошел из за превышения напряжения на свечах, меняем состояние flagR6 на true
       digitalWrite(R6v, LOW);    // и отключаем реле2.
       Serial.print("Rele2: ");   // Вывод информации, что реле2
       Serial.println("OFF");     // отключилось. Для справки.
   }  
} 

 

Mahonin83
Offline
Зарегистрирован: 12.11.2019

Здравствуйте ! Это работает ?

bwn
Онлайн
Зарегистрирован: 25.08.2014

Не исключено, беда в том, что автор почти три года назад убыл тестировать в железе, с тех пор его никто не видел.)))))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

bwn пишет:

Не исключено, беда в том, что автор почти три года назад убыл тестировать в железе, с тех пор его никто не видел.)))))

он что, сразу на реальном авто тестировал?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Как понеслось-понеслось.... Три года на орбите с остатками чипсов и водой из бачка омывателя )))

bwn
Онлайн
Зарегистрирован: 25.08.2014

ua6em пишет:

он что, сразу на реальном авто тестировал?

Кто про то знает? Нет Снуппи, ушел на болота и не вернулся.(с) д.Мортимер))))
Из всех креативщиков, одни отчитались, один раз.))))

shmlka
Offline
Зарегистрирован: 28.12.2016

bwn пишет:

Не исключено, беда в том, что автор почти три года назад убыл тестировать в железе, с тех пор его никто не видел.)))))

Нет, просто попался заводской блок управления от корейца, поставил его. А на ардуино не успел до собирать плату.