Автомобильный блок питания

Orland303
Offline
Зарегистрирован: 03.12.2013

Начал писать скетч для "умного" блока питания в авто.

Цели следующие: 1. Постояная проверка напряжения АКБ. 2. Проверка наличия ACC.

Во втором пункте возникла проблема. При проподании ACC нужно отсчитать 3 секунды и сделать выключение нескольких пинов. При помощи какой функции отсчитывать эти самые 3 секунды. Хотел использовать millis() но не понимаю, как начать отсчет времени именно после пропадания ACC.

Вот что пока имеем.





int BAT = A0; // напряжение Аккумулятора
 int ACC = 2; // наличие АСС
 int NSD = 4; // включение NSD БП (USB HUB, регистратор)
 int LM = 7; // включение LM2596 (Планшет)
 int ACCState = 0;
     
// Установки при запуске: Назначаем пины.
void setup() 
{
  pinMode (BAT, INPUT);
  pinMode (ACC, INPUT);       
  pinMode (NSD, OUTPUT);       
  pinMode (LM, OUTPUT);       
  
  Serial.begin(9600);  // Инициализация порта:
}

// Повторяющийся цикл:
void loop() 
{ 
  int BatValue = analogRead (BAT); // читаем значение напряжения:
    ACCState = digitalRead (ACC); // считываем положение ACC:
  // Преобразуем сигнал в значение напряжения (из 0 - 1023) в вольты:
  float voltage = BatValue * (12 / 1023);
    if (voltage <= 11,0)
    {
      digitalWrite (NSD, LOW);     // Выключаем БП NSD15
      digitalWrite (LM, LOW);     // Выключаем БП LM2596
      Serial.println (voltage);   // Выводим напряжение бортовой сети 
    }
    else if (ACCState == LOW)
             if ( )    // тут нужно проверить отсутствие ACC, если больше 3-х секунд ACC==LOW то
             {                                      
               digitalWrite (NSD, LOW);
               digitalWrite (LM, LOW);
             }
            else
            {   
              digitalWrite (NSD, HIGH);
              digitalWrite (LM, HIGH);
            }
}

Я новичек в arduino. Ткните носом.

Orland303
Offline
Зарегистрирован: 03.12.2013

С millis() вроде разобрался. Но теперь возникло еще пару вопросов?



 int BAT = A0; // напряжение Аккумулятора
  int ACC = 2; // наличие АСС
  int NSD = 4; // включение NSD БП (USB HUB, регистратор)
  int LM = 7; // включение LM2596 (Планшет)
  
  int ACCState;
  int LastACCState;
  unsigned long currentTime = 0;
    
// Установки при запуске: Назначаем пины.
void setup() 
{
  pinMode (BAT, INPUT);
  pinMode (ACC, INPUT); //ПРОВЕРИТЬ!!!
  pinMode (NSD, OUTPUT); //ПРОВЕРИТЬ!!!
  pinMode (LM, OUTPUT); //ПРОВЕРИТЬ!!!
  currentTime = millis();
  Serial.begin(9600);  // Инициализация порта:
}

// Повторяющийся цикл:
void loop() 
{ 
 int BatValue = analogRead (BAT); // читаем значение напряжения:
    ACCState = digitalRead (ACC); // считываем положение ACC:
      // Преобразуем сигнал в значение напряжения (из 0 - 1023) в вольты:
  float voltage = BatValue * (15 / 1023);
    if (voltage <= 11,0)
    {
      digitalWrite (NSD, LOW);     // Выключаем БП NSD15
      digitalWrite (LM, LOW);     // Выключаем БП LM2596
      Serial.println (voltage);   // Выводим напряжение бортовой сети 
    }
    else if (ACCState == HIGH)
         {
          currentTime = millis();
          digitalWrite (NSD, HIGH);
          delay (1000);
          digitalWrite (LM, HIGH);
          ACCState = LastACCState;
         }
         else if (ACCState =! LastACCState && (millis () - currentTime >3000) && (millis () - currentTime <12000)) 
              {  
               digitalWrite (LM, LOW);
               digitalWrite (NSD, HIGH);
              }
              else if (millis () - currentTime >12000)
                   {
                    digitalWrite (LM, LOW);
                    digitalWrite (NSD, LOW);
                   }
}

1. Как сбросить millis в ноль, вед после ~50 дней millis() сама сбросится в 0, а вот переменная currentTime нет. Цикл не будет работать.

2. При загрузке скетча выбирает вот это условие



else if (ACCState =! LastACCState && (millis () - currentTime >3000) && (millis () - currentTime <12000)) 
              {  
               digitalWrite (LM, LOW);
               digitalWrite (NSD, HIGH);
              }

как это обойти? Почему не помогает ACCState =! LastACCState

leon_mz
Offline
Зарегистрирован: 06.12.2013

1.
>>Как сбросить millis в ноль, вед после ~50 дней millis() сама сбросится в 0, а вот переменная currentTime нет. Цикл не будет работать.

Попробуйте вот это:

typedef struct _time_offset {
	unsigned long base;	
	_time_offset() : base(millis()) { }		
	void reset() { base = millis(); }		
	unsigned long get() const { return millis() - base; } 	
    bool operator > (const unsigned long &rhv) const { return get() > rhv; }	
} time_offset;
...
time_offset to;
...
if (to > 30000) {
 doSomeAction();
 to.reset();
}

 

 

Orland303
Offline
Зарегистрирован: 03.12.2013

leon_mz, А если не сложно можешь хоть примерно расписать какая функция что делает? Хочется не просто воткнуть код а понять что же он делает?

Orland303
Offline
Зарегистрирован: 03.12.2013

leon_mz, А если не сложно можешь хоть примерно расписать какая функция что делает? Хочется не просто воткнуть код а понять что же он делает?

Orland303
Offline
Зарегистрирован: 03.12.2013

А если не сложно можешь хоть примерно расписать какая функция что делает? Хочется не просто воткнуть код а понять что же он делает? 

Orland303
Offline
Зарегистрирован: 03.12.2013

А если не сложно можешь хоть примерно расписать какая функция что делает? Хочется не просто воткнуть код а понять что же он делает? 

Orland303
Offline
Зарегистрирован: 03.12.2013

Второй вопрос победил в 40 строке вместо ACCState = LastACCState; заменил на LastACCState = ACCState;

С первым вопросом разбираюсь. Изучаю весь доступный материал по Arduino. Вот неплохая книга http://dvrobot.ru/literatura/yiazik_programm_iya.rar Может еще есть что-то наподобии, а то везде только базовый курс а дальше ...... на С++ сразу переходить?

 

Orland303
Offline
Зарегистрирован: 03.12.2013

С режимами включения и выключения разобрался.

Алгоритм работы:

1. При появлении ACC , включается сначала USB HUB с (переферийными устройствами для планшета) и регистратор. Спустя 2 секунды просыпается сам планшет.

2. При кручении стартера ACC пропадает. Чтобы не выключились блоки питания ждем 4 секунды. Если ACC нет и дальше, считаем что ключ вытащен и усыпляем планшет. Если ACC появилось до истечения 4 секунд - оба блока питания продолжают работать, если после 4 секунд - возвращаемся в пункт 1  

3. Если ACC нет больше 20 минут - выключаем и второй блок питания (USB HUB и регистратор)

Вот что получилось



#define BAT A0 // напряжение Аккумулятора
#define ACC 2 // наличие АСС
#define NSD 4 // включение NSD БП (USB HUB, регистратор)
#define LM 7 // включение LM2596 (Планшет)

int ACCState;
int LastACCState;
int InterspaceACCState;    // промежуточное состояние ACC:
unsigned long currentTime;

// Установки при запуске: Назначаем пины.
void setup() 
{
  pinMode (BAT, INPUT);
  pinMode (ACC, INPUT); 
  pinMode (NSD, OUTPUT); 
  pinMode (LM, OUTPUT);
  currentTime = millis(); 
  Serial.begin(9600);  // Инициализация порта:
}

// Повторяющийся цикл:
void loop() 
{ 
  if (millis() < currentTime)   // Проверка переполнения. Проверяем millis, если меньше:
  {
    currentTime = millis();  // присваиваем currentTime новое значение millis:
  }
  ACCState = digitalRead (ACC); // считываем положение ACC:
  int BatValue = analogRead (BAT); // читаем значение напряжения:
  // Преобразуем сигнал в значение напряжения (из 0 - 1023) в вольты:
  float voltage = BatValue * (15 / 1023);
  if (voltage <= 11,0)
  {
    digitalWrite (NSD, LOW);     // Выключаем БП NSD15
    digitalWrite (LM, LOW);     // Выключаем БП LM2596
    Serial.println (voltage);   // Выводим напряжение бортовой сети 
  }
  if (ACCState == HIGH)
  {
    currentTime = millis();
  }
  if (ACCState == HIGH && InterspaceACCState == LOW)
  {
    digitalWrite (NSD, HIGH);
    delay (2000);
    digitalWrite (LM, HIGH);
    LastACCState = ACCState;
    InterspaceACCState = ACCState;
    currentTime = millis();
  }
  else if (ACCState != LastACCState && millis () - currentTime >4000 && millis () - currentTime <=1200000) 
  {  
    digitalWrite (LM, LOW);
    digitalWrite (NSD, HIGH);
    InterspaceACCState = ACCState;  
  }
  else if (ACCState != LastACCState && millis () - currentTime >1200000)
  {
    digitalWrite (LM, LOW);
    digitalWrite (NSD, LOW); 
    LastACCState = ACCState;
  }
}

4. Проверку напряжения АКБ пока не диагностировал. Взял из примера. Чуть позже проверю.

 

groove-max
Offline
Зарегистрирован: 30.11.2015

Доброе время суток!

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

Orland303
Offline
Зарегистрирован: 03.12.2013

Схему использовал вот эту, только NSD заменил на KIS

Прошивал при помощи arduino 

Схема, печатная плата и прошивка

Niferman
Offline
Зарегистрирован: 27.02.2015

У меня вопрос немного не в тему может, но все таки: Почему заменили NSD на KIS ? NSD вроде как по круче будет. Хотя бы потому что там можно избежать так называемой земляной петли. Т.е. не надо делать общую землю, объединять всю низковольтную землю до dc-dc преобразователей с землей после них же. Или с NSD есть какие  то  проблемы? Просто сам планирую использовать именно их в своем БП.

Orland303
Offline
Зарегистрирован: 03.12.2013

KIS были в наличии, и цена на порядок дешевле. Спаял уже два таких. Стоят на разных машинах. Питают:

Управляет обогревом руля, питанием регистратора, и USB портами для зарядки. При просаживании питания АКБ - все отключается. Но программу придется проверять(исправлять значение напряжения срабатывания) для каждой пары делителя (62кОм и 20кОм).

Проблем с помехами и шумами в магнитолах нет (усилки и буфера не использую)