#1 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-21 21:48:32

Процесс не стоит на месте. Прототип уже установлен на подопытный автомобиль.
Уже реализован шим на частоте 25гц. который необходим для управления заводским блоком управления вентиляторами(Штатный на современных мерседесах и фольцвагенах).
Пока открыт вопрос с входами для запуска вентиляторов от блока кондиционера.
Довесил датчик температуры LM75 и ЛСД 16*2 для отладки.

Спасибо NoName, библиотеку и код писал/правил он.

/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 00):
 * <devgate.info эт gmail.com> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.   
 * ----------------------------------------------------------------------------
 *  Date create: 2017.05.08  
 *  Date change: 2017.05.09 
 *  Date change: 2017.05.22 
 *  Date change: 2017.05.30 add   key function   control 
 * ----------------------------------------------------------------------------
 */
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);


                #include <Wire.h>
                #include <LM75.h>

                LM75 sensor(0x48);  // initialize an LM75 object
       
//#define USE100Hz

char debug_str[100];

#define START_SIGNAL     50
#define KEY1_SIGNAL      50
#define KEY2_SIGNAL      10

#ifdef USE100Hz

 #define MAX_SIGNAL    9000
 #define MIN_SIGNAL    100
#include <dgm_pwm25.h>

#else
#include <dgm_pwm25.h>
 #define MAX_SIGNAL    39000
 #define MIN_SIGNAL    1000
#endif


#define USE_FILTER16
#define DEBUG
//#undef  DEBUG_PWM
//#define DEBUG_TEST_SYSTEM

#define DEBOUNCE_TIME 100

#define TASK_PROCESS_TIME 1000


int KEY1 =  7;
int KEY2 =  8;
 

int test_power;
int lcdPower;



typedef enum {
TIMER_EXE       = 0,
TIMER_DISABLED  = 1,
TIMER_RUN       = 2,
} TE_TIMER;



typedef struct 
{
int pin_number; 
int             time_debounce; 
unsigned long   time_press  ;
unsigned long   time_release;
unsigned long   time_last_press;
unsigned long   time_last_release;

int            press_level_detect;  

 bool            status_press;
 bool            status_release;

bool            interrupt_press;
bool            interrupt_release;
bool            need_release;
bool            execute;

}  tdpkey;

tdpkey key_1;
tdpkey key_2;


// Change these two numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance:  neither pin has interrupt capability
// Encoder myEnc(2, 3);
// avoid using pins with LEDs attached

Servo esc;


void setup() {
  lcd.begin();
  lcd.backlight();

                       Wire.begin();
                          
  esc.attach(9, MIN_SIGNAL, MAX_SIGNAL);
  esc.write ( START_SIGNAL );
  
 key_1.time_debounce  = 50;
 key_1.pin_number  = 7;
 key_1.press_level_detect = HIGH;
 
 key_2.time_debounce  = 50;
 key_2.pin_number  = 8;
 key_2.press_level_detect = HIGH;

 pinMode(key_1.pin_number, INPUT);
 pinMode(key_2.pin_number, INPUT);
 

  pinMode(KEY1, INPUT); 
  pinMode(KEY2, INPUT); 
  Serial.begin(9600);
  Serial.println("Start DGM_PWM_25Hz");

}

// long oldPosition  = 0xFFFF;
// long newPosition;
long _PWM  = 0;


// http://forum.arduino.ua/viewtopic.php?pid=3088#p3088
// GREEN
// CHANGE 
bool KEY1CONTROL()
{
  static bool key_pressed;
  static uint8_t debounce_timer;
  
  if (key_pressed  ==  digitalRead(KEY1)) {
    key_pressed = !key_pressed;
    debounce_timer = DEBOUNCE_TIME;
  }
  else if (debounce_timer && !--debounce_timer && key_pressed)
    return true;
  return false;
}


bool KEY2CONTROL()
{
  static bool key_pressed;
  static uint8_t debounce_timer;
  
  if (key_pressed != !digitalRead(KEY2)) {
    key_pressed = !key_pressed;
    debounce_timer = DEBOUNCE_TIME;
  }
  else if (debounce_timer && !--debounce_timer && key_pressed)
    return true;
  return false;
}


TE_TIMER system_delay_uint32 ( unsigned long *timer , unsigned long shift )
{
    if ( *timer > 0 )
    {
      if (*timer > shift )
      {
        *timer -= shift;
        return TIMER_RUN;
      }
       else
      { // save delta time
         *timer =  ( shift - *timer );
         return TIMER_EXE;
      }
    }
  return TIMER_DISABLED;
}





typedef struct 
{
    int  voltage;
    int    power;
}   td_table_unit;

td_table_unit   power_table[] = 
{
  { 5000, 90 },   
  { 2200, 90 },   
  { 2100, 85 },   
  { 2000, 75 },   
  { 1950, 60 },
  { 1900, 40 }, 
  { 1850, 30 }, 
  { 1800, 10 }, 
  { 0,  10 } 
};

int   voltage_array_pos;
int voltage_array_data[16];
bool  enabled_voltage_array = false;



int need_system_power;
int linear_table_interpolation ( int X, int pos )
{
long XXX;
int ret;
long X1, fX1;
long X2, fX2;
 
if ( pos == 0 ) return ( power_table[0].power ) ;

X1     = power_table[pos-1].voltage;
fX1    = power_table[pos-1].power;

X2     = power_table[pos].voltage;
fX2 = power_table[pos].power;

XXX = fX1 + (fX2 - fX1)*(X - X1)/(X2 - X1); 

  //  Serial.print (" X1: ");   Serial.print (X1); Serial.print (" fX1: ");   Serial.println (fX1);
  //  Serial.print (" X2: ");   Serial.print (X2); Serial.print (" fX2: ");   Serial.println (fX2);

ret =  (int) XXX;



if ( ret < 0   )  ret =   0;
if ( ret > 100 )  ret = 100;
return ret;
}



void clear_fkey_interrupt ( tdpkey *pkey )
{
pkey->interrupt_release  = false;
pkey->interrupt_press  = false;
pkey->need_release     = true;
}
//------------------------------------
   
void fKey (tdpkey *pkey, int time_elapsed )
{
  

  
  if ( digitalRead( pkey->pin_number) == pkey->press_level_detect )
  { 
   pkey->time_press         += time_elapsed; 
  }
  else 
  {  
   pkey->time_release += time_elapsed;
  }
  
  // кнопка была отжата
  if  ( pkey->time_release > pkey->time_debounce )
  {
  if ( pkey->status_release == false ) 
    {
    pkey->time_press =  0;
    pkey->status_release  = true;
    pkey->status_press    = false;
    pkey->interrupt_press   = false;

    if  ( pkey->need_release  == false )
        {
      pkey->interrupt_release = true;
    }
    
    pkey->need_release  = false;
    pkey->time_last_release = pkey->time_release;
     pkey->time_release    = 0;
#ifdef DEBUG   
    sprintf  ( debug_str,"key_release");  Serial.println  ( debug_str );  
#endif
    }
  }

if ( pkey->time_press > pkey->time_debounce )
{    
  if ( pkey->status_press == false ) 
    {
    pkey->status_press    = true;

    pkey->need_release    = false;
    pkey->time_release    = 0;
    pkey->status_release  = false;
    pkey->interrupt_press   = true;
        pkey->interrupt_release = false;
    pkey->time_last_release = pkey->time_release;
        pkey->time_release    = 0;
#ifdef DEBUG  
    sprintf  ( debug_str,"key_press");  Serial.println  ( debug_str );  
Serial.println  ( pkey->time_release ); 
     
#endif
    }
}
 return;
}


void loop() {


 static unsigned long  task_time; 
 static unsigned long  key_time_start_press; 
 static unsigned long  key_time_start_unpress; 
 
 TE_TIMER  status; 


 static unsigned long  hw_old_system_timer = 0; 
        unsigned long  hw_current_system_timer = 0; 

 unsigned long  delta_task_timer; 
   int position = 0;

 unsigned long  test;
 int            sensorValue = 0;
 static int     raw_sensorValue  = 0;
 static int     delta = 0;
 long           voltage;

int             power = 95;
int             now_status = 0;
long            new_duty_cycle = 0;
        // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):

int             preset_power = 0;

  hw_current_system_timer  = millis();
  delta_task_timer         = hw_current_system_timer - hw_old_system_timer;
  hw_old_system_timer      = hw_current_system_timer;

  status = system_delay_uint32 ( &task_time, delta_task_timer );

  fKey (&key_1 , delta_task_timer );
   fKey (&key_2 , delta_task_timer );

 
#ifndef DEBUG_TEST_SYSTEM
        raw_sensorValue = analogRead(A0);
#else
//         raw_sensorValue &= 0x3FF;
if ( raw_sensorValue > 1024 )  raw_sensorValue = 0;
#endif

#ifdef USE_FILTER16
  long sum = 0;
  
  voltage_array_data[voltage_array_pos] = raw_sensorValue;
  voltage_array_pos++;
  if ( voltage_array_pos >= 16 )
  {
    enabled_voltage_array = true;
    voltage_array_pos = 0;
  }
  
  if( enabled_voltage_array ) 
  {
    for ( int foo = 0; foo < 16; foo++ )
    sum += voltage_array_data[voltage_array_pos];
    sum >>= 4;   // деление на 16 
    sensorValue = sum; 
  }
 else  
 {
   sensorValue = raw_sensorValue;
 }
#else  
  sensorValue = raw_sensorValue;
#endif
 
   voltage = sensorValue * (5000.0/1023.0);
   // voltage = map(sensorValue, 0, 1023, 0, 5000);

    lcdPower = map(need_system_power, 0, 100, 100, 0);

  // print out the value you read:
 if ( key_1.status_press  ) now_status |= 0x0001;
 if ( key_2.status_press  ) now_status |= 0x0002;


 
 if ( now_status&0x0001 )  preset_power  =  KEY1_SIGNAL;
  else if ( now_status&0x0002 )  preset_power  =  KEY2_SIGNAL ;
 
 #ifdef DEBUG_PWM 
       if ( test_power > 100 ) test_power = 0; 
       esc.write  ( test_power );
       power = test_power;
 #else    
   if ( voltage < 0 ) voltage = 0; 
   for ( position = 0 ; ; position++ )
   {
   if ( voltage >= power_table[position].voltage )
   break;
   }

   need_system_power = linear_table_interpolation (voltage,position);
#endif       
        
  if ( preset_power  > need_system_power )   esc.write  ( preset_power );
  else                                       esc.write  ( need_system_power ); 

#ifdef DEBUG 

  switch ( status )
  {
    case TIMER_EXE:
    case TIMER_DISABLED:
        task_time += TASK_PROCESS_TIME; 

#ifdef DEBUG_TEST_SYSTEM
        raw_sensorValue += 1; 
#endif


     test_power++;

          Serial.print (digitalRead(KEY1));  
          Serial.print (digitalRead(KEY2));  


    if ( now_status  & 0x0001 )
          Serial.print (" D7: ON  ");  
    else  Serial.print (" D7: OFF ");

    if ( now_status  & 0x0002 )
          Serial.print ("D8: ON  ");
    else  Serial.print ("D8: OFF ");

    Serial.print ("ADC: ");
    Serial.print (sensorValue);
    Serial.print (" ");
    Serial.print ("V: ");
    Serial.print (voltage);
    Serial.print (" ");

    Serial.print  ("p: ");
    Serial.println  (lcdPower);

                               // get temperature from sensor
                    //           Serial.print("Current temp: ");
                   //            Serial.print(sensor.temp());
                    //           Serial.println(" C");
                               
  lcd.clear();
  lcd.print("Sens:");
  lcd.print(voltage); 
  lcd.print("V ");

                             if ( now_status  & 0x0001 )
                             lcd.print("1:ON");  
                             
                             if ( now_status  & 0x0002 )
                             lcd.print("2:ON");
                           
   
  lcd.setCursor(0,1);
   lcd.print("FAN:");
   lcd.print(lcdPower); 
   lcd.print("% ");
                               lcd.print("T:");
                               lcd.print(sensor.temp()); 
                               lcd.print("C");
    //delay(150);
    
/*
    Serial.print  (" ");
    test = esc.readMicroseconds(); 
    Serial.print ("t: ");
    Serial.print  (test);

    Serial.print(" ");

    test = esc.read (); 
    Serial.print ("ms: ");

    Serial.println (test);
*/
   
   break;
    
    case TIMER_RUN:
     break;   
 }

#endif



}

libraries.rar

#2 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-08 22:42:49

Мыло активно, ноги, какие вам удобно.
По кнопкам все верно.
Аварийная работа 95% Скважность
Блок управления силовой, сам плавно все делает, тем более вентиляторы довольно инерционны.

#3 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-08 19:08:01

Не пойму зачем регулируемый источник? Для имитации можно взять любой подстроечник, я использую 10к. Средняя нога выход крайние питание.
Датчик - термистор, подключенный как плечо делителя напряжения, вторая половина плеча в ЭБУ. Физически расположен на корпусе термостата, на выходе из него. На датчик приходит масса ЭБУ и "подтяжка 5 вольт". Напряжения снимальсь ардуинкой:
  int sensorValue = analogRead(A0);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = sensorValue * (5.0 / 1023.0);
  // print out the value you read:
  Serial.println(voltage);
типа так.
Всего на двигателе 3 датчика температуры, один на ЭБУ двигателя, второй на ЭБУ клмат контроля и третий на стрелку в панеле приборов. Я тупанул и подключился к датчику климата, не знаю на сколько это кретично, но на многих авто, вентилятором охлаждения ОЖ управляет именно климат.
Можно конечно и собрать новые данные, нужно подумать.

#4 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-08 14:53:02

Поделюсь и помогу Пете с удовольствием.

На счет точности установки скважности и частоты не знаю, нужно эксперементировать.

Думаю, что 5 ступенек скважности будет достаточно, 30% 50% 60% 80 и 90 (100 - не ставим, это аварийный режим, типа короткое замыкание управляющей линии на +  или -).
Было-бы неплохо не энкодер, он не к чему, а напряжение на А0 соответствующие диапазонам.
от 5в до-2,1в - 10% (вентилятор выключен, если их нет, то он аварийно включается)
2в -30%;
от 2в до 1,95в-50%;
1,96в-1,90в - 60%;
1,89в-1,84в -80%;
и ниже 1,84в пусть гудит на всю, 90%.
Ну и еще нужно 2 цифровых входа, при подаче на один + вентилятор должен включаться на 50% при любых условиях, а второй на 90% - Это для работы кондиционера.

Это все цифры с головы, я какое-то время ездил с 16*2 возле спидометра и наблюдал за напряжением на датчике температуры.

#5 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-08 10:43:42

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

#6 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-07 21:42:04

Загрузил вот такое:

/*
 Controlling a servo position using a potentiometer (variable resistor)
 by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>

 modified on 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);

Servo myservo;  // create servo object to control a servo

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  lcd.begin();
}

void loop() {
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there

    lcd.print("TEMP: ");
    lcd.print(val); // отображение температуры
    lcd.print("C ");
    lcd.print(val); // отображение температуры
    lcd.print("V ");
    lcd.setCursor(0,1); // перевод курсора на следующую сторку
    lcd.print("FANS: ");
    lcd.print(val); // отображение скорости вращения вентилятора
    lcd.print("%");
    delay(200);
    lcd.clear();
    }

На скорую руку собрал схемку - не работает. Осцила дома нет... sad
Но понять охота - подцепил динамик параллельно выходу с транзистора - на слух частота высоковата, анализаторы в андроид приложениях показывают 800 гц, могут врать конечно...

мой Servo.h

/*
  Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
  Copyright (c) 2009 Michael Margolis.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/* 
  A servo is activated by creating an instance of the Servo class passing 
  the desired pin to the attach() method.
  The servos are pulsed in the background using the value most recently 
  written using the write() method.

  Note that analogWrite of PWM on pins associated with the timer are 
  disabled when the first servo is attached.
  Timers are seized as needed in groups of 12 servos - 24 servos use two 
  timers, 48 servos will use four.
  The sequence used to sieze timers is defined in timers.h

  The methods are:

    Servo - Class for manipulating servo motors connected to Arduino pins.

    attach(pin )  - Attaches a servo motor to an i/o pin.
    attach(pin, min, max  ) - Attaches to a pin setting min and max values in microseconds
    default min is 544, max is 2400  
 
    write()     - Sets the servo angle in degrees.  (invalid angle that is valid as pulse in microseconds is treated as microseconds)
    writeMicroseconds() - Sets the servo pulse width in microseconds 
    read()      - Gets the last written servo pulse width as an angle between 0 and 180. 
    readMicroseconds()   - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
    attached()  - Returns true if there is a servo attached. 
    detach()    - Stops an attached servos from pulsing its i/o pin. 
 */

#ifndef Servo_h
#define Servo_h

#include <inttypes.h>

/* 
 * Defines for 16 bit timers used with  Servo library 
 *
 * If _useTimerX is defined then TimerX is a 16 bit timer on the current board
 * timer16_Sequence_t enumerates the sequence that the timers should be allocated
 * _Nbr_16timers indicates how many 16 bit timers are available.
 */

// Architecture specific include
#if defined(ARDUINO_ARCH_AVR)
#include "avr/ServoTimers.h"
#elif defined(ARDUINO_ARCH_SAM)
#include "sam/ServoTimers.h"
#elif defined(ARDUINO_ARCH_SAMD)
#include "samd/ServoTimers.h"
#else
#error "This library only supports boards with an AVR, SAM or SAMD processor."
#endif

#define Servo_VERSION           2     // software version of this library

#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo  
#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo 
#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached
#define REFRESH_INTERVAL    40000     // minumim time to refresh servos in microseconds 

#define SERVOS_PER_TIMER       12     // the maximum number of servos controlled by one timer 
#define MAX_SERVOS   (_Nbr_16timers  * SERVOS_PER_TIMER)

#define INVALID_SERVO         255     // flag indicating an invalid servo index

typedef struct  {
  uint8_t nbr        :6 ;             // a pin number from 0 to 63
  uint8_t isActive   :1 ;             // true if this channel is enabled, pin not pulsed if false 
} ServoPin_t   ;  

typedef struct {
  ServoPin_t Pin;
  volatile unsigned int ticks;
} servo_t;

class Servo
{
public:
  Servo();
  uint8_t attach(int pin);           // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
  uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes. 
  void detach();
  void write(int value);             // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds 
  void writeMicroseconds(int value); // Write pulse width in microseconds 
  int read();                        // returns current pulse width as an angle between 0 and 180 degrees
  int readMicroseconds();            // returns current pulse width in microseconds for this servo (was read_us() in first release)
  bool attached();                   // return true if this servo is attached, otherwise false 
private:
   uint8_t servoIndex;               // index into the channel data for this servo
   int8_t min;                       // minimum is this value times 4 added to MIN_PULSE_WIDTH    
   int8_t max;                       // maximum is this value times 4 added to MAX_PULSE_WIDTH   
};

#endif

во вложении фотка осциллограммы, это то, что хотелось бы получить.
И фотки процесса )))

намерил подручными средствами 138гц

вернул в зад #define REFRESH_INTERVAL    20000 - получил 50гц

#7 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-07 11:04:22

Все верно, я имею ввиду скважность. На счёт обратной связи, это я перепутал, неправильно понял.
Если не сложно, кто сталкивался с серво, дайте пример программки , желательно с управлением скважностью через терминал.
И может расскажите пару слов о программных таймерах.

#8 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-07 00:55:12

В библиотеке сервы нужно поменять частоту? Я верно понял?
Просто библиотека серво просит обратной связи. Точно мне оно подойдёт?

NoName пише:

"как заставить ардуинку выдать эти заветные 25гц и еще и скажностью управлять!?!?"
это классический пример работы серво
у меня на новый год  газовый котол сдох , пришлось делать подмену датчика

в примере подключал мотор от коптера
но принцип такой же
и в серве должна быть замена   частоты, это сами разберетесь как

 
/* Encoder Library - Basic Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

//#define MAX_SIGNAL  2300
// #define NETRUAL     1400
// #define MIN_SIGNAL  400


#define MAX_SIGNAL  2000
#define NETRUAL     1500
#define MIN_SIGNAL  1000

#include <Encoder.h>
#include <Servo.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(2, 3);
//   avoid using pins with LEDs attached

Servo esc;
// int throttlePin = 0;


void setup() {
  esc.attach(9);
  esc.writeMicroseconds ( NETRUAL );
  myEnc.write           ( 50 );

  Serial.begin(9600);
  Serial.println("Start DIIV:");

}

long oldPosition  = 0xFFFF;
long newPosition;
long _PWM  = 0;

#define DEBUG


void loop() {

   long throttle = myEnc.read();
   if ( throttle   < 0      ) { throttle = 0;      myEnc.write ( throttle ); }  
   if ( throttle  > 100   )   { throttle = 100;    myEnc.write ( throttle ); }
   newPosition =  throttle;

   if ( newPosition != oldPosition) {
    oldPosition = newPosition;
    throttle = map(newPosition, 0,100, MIN_SIGNAL, MAX_SIGNAL );

    #ifdef DEBUG 
    //----------------------
    Serial.print("encoder: ");
    Serial.print(newPosition);
    //----------------------
    Serial.print(" throttle: ");
    Serial.println(throttle);
    //----------------------
    #endif
    esc.writeMicroseconds(throttle);
   //----------------------
  }
}

#9 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-06 13:56:17

NoName пише:

yarikne для температуры возьмите медь 100. PT1000 не берите, не его задача )
это удорожание проекта,  но выхода у вас особо нет.

"Я где-то "чувствую", что леонардо не для автомобиля" важное замечание - леонардо она как говорится не заточена, по хорошему берете понравившийся  контроллер из серии mcu automotive от "любимого" производителя и на нем собираете

но ардуино вам наверное ближе чем натив ... есть  и этому решение
в систему нужно добавить
1) трехсекундный watchdog 
2) супервизор по питанию
3) хороший источник питание
4) ESD diode

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

если все сделано -  пользуйтесь своей леонардо,   есть еще синяя хрень для защиты платы от пыли, влаги, вибраций, что то типа пленки, не помешает покрыть плату,  название не помню (

Спасибо, хорошие советы, жаль, что производители китайского шарпотрепа для автомобилей не придержуются этих правил. (я про сигналки, блоки ДХО, навигаторы и т п)
С шокером, может и перегиб, но краш тест - должен быть жестким.
Сейчас нарыл блок управления вентиляторами от младшей модели мерседеса(он же используется в фольцвагенах). Это силовая часть с управлением на 25гц. Так сказать линия свзя работает на 25гц, а скважность регулирует обороты. 
Вот такая штука
Думаю его очень целесообразно использовать, так как там есть защиты всевозможные и шумоподавляющие фильтры.
Основной вопрос, как заставить ардуинку выдать эти заветные 25гц и еще и скажностью управлять!?!?

#10 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-06 13:47:22

vvr пише:
yarikne пише:

3 - С температурой сейчас вопрос. Я не знаю и не получается найти инфы, как из таблицы с параметрами зависимости напряжение - температура, получить переменную. Которая уже и будет обрабатываться.

сначала нужно выяснить что за датчик температуры, потом посмотреть его даташит, нафига таблицы строить))))

Датчик температуры вот такой

Известно что при 100 градусах на нем 1,8в при 20 - 4,6в. Все классно, я думаю что градусы с него я и не буду смотреть, будем опираться на напряжение, для получение температуры я рядышком прилеплю Lm35 - с него температуру я буду выводить на экран.
Экспериментальным путем подберу напряжения при которых должен работать вентилятор.
Уже известно, что при 1,9в и ниже вентилятор должен работать на всю.

#11 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-05 19:16:13

NoName пише:

"Не понятно, что за числа в таблице..."
похоже на  linear interpolation

если хочете - научитесь )
но leonardo врядли лучшее решение для авто.

Я где-то "чувствую", что леонардо не для автомобиля, хотя и веских аргументов не вижу.
Может вы что то предложите более подходящие?

#12 Re: Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-05 19:14:27

vvr пише:

вы только начинаете, поэтому вам понятнее и проще делать по этапам
запустите дисплей
запустите вент, научитесь им управлять
потом температурой займитесь
ну а дальше всё в кучу

1 - Дисплей запустил, принципы вывода информации на дисплей понял. На данном этапе вывожу на дисплей Напряжение с А0 в вольтах, скважность шим в %, и неверно подсчитанную температуру.
2 - Запустить вент не пробовал, но светодиодом управляю, думаю это проблем не составит.
3 - С температурой сейчас вопрос. Я не знаю и не получается найти инфы, как из таблицы с параметрами зависимости напряжение - температура, получить переменную. Которая уже и будет обрабатываться.

#13 Проекти » Управление вентилятором радиатора автомобиля, разработка. » 2017-05-04 23:33:10

yarikne
відповідей: 26

Дано мерс w124;
У него два эл. вентилятора с потреблением 30А;
Ардуино Леонардо;
16х2 + I2C;
Датчик температуры штатный в автомобиле, резистивный.
При температуре 20 градусов напряжение 4,5в, при 90 2в. (Более детальная таблица в разработке);

Необходимо:
- Считывание температуры с датчика согласно таблице, вывод на ЛСД
- ШИМ управление вентилятором согласно заданным параметром (Например: Запуск на 30% при т 80градусов и плавный набор оборотов до 100% при 110 градусов и выше)
- Включение для работы с кондиционером при внешнем управлении, 2 входа 50 и 100%
- Аварийный запуск при обрыве цепи датчика температуры

Силовая часть будет выглядеть, как мощный полевик либо будет использован блок управления вентилятором от серийных авто, например такой, ему нужен шим частотой от 100 до 200гц и скважностью от 10 до 90% (как я понял частоту от 100 до 200 сложно реализовать на ардуино).


Пока удалось лишь слепить набросок из чужих кодов

#include <LiquidCrystal_I2C.h>
    //источник: http://www.electroschematics.com/9540/arduino-fan-speed-controlled-temperature/
    LiquidCrystal_I2C lcd(0x3F, 16, 2);
    int tempPin = A0; // Вход сигнала температуры
    int fan = 11; // вывод на вентилятор
    int led = 8; // вывод на светодиод
    int temp;    // Температура в градусах
    int tempMin = 30; // температура начала вращения вентилятора
    int tempMax = 70; // максимальная температура, когда вентилятор вращается на 100%
    int fanSpeed;     // скорость вентилятора в ??
    int fanLCD;       //Переменная для вывода процентов скорости вентилятора на экран
    
    void setup() {
    pinMode(fan, OUTPUT);
    pinMode(led, OUTPUT);
    pinMode(tempPin, INPUT);
    lcd.begin();
    }
     
    void loop() {
  int sensorValue = analogRead(A0);    // Переменная для приобразования в вольты
      // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = sensorValue * (5.0 / 1023.0);
 
  
    temp = readTemp(); // получаем температуру
    if(temp < tempMin) { // если temp меньше минимума
    fanSpeed = 0; // кулер не вращается
    digitalWrite(fan, LOW);
    }
    if((temp >= tempMin) && (temp <= tempMax)) { // если temp больше минимума
    fanSpeed = map(temp, tempMin, tempMax, 32, 255); // текущая скорость вентилятора
    fanLCD = map(temp, tempMin, tempMax, 0, 100); // скорость вращения для отображения на LCD
    analogWrite(fan, fanSpeed); // вращаем кулер со скоростью fanSpeed
    }
    if(temp > tempMax) { // если temp больше максимума
    digitalWrite(led, HIGH); // включаем светодиод
    } else { // иначе выключаем светодиод
    digitalWrite(led, LOW);
    }
    lcd.print("TEMP: ");
    lcd.print(temp); // отображение температуры
    lcd.print("C ");
    lcd.print(voltage); // отображение температуры
    lcd.print("V ");
    lcd.setCursor(0,1); // перевод курсора на следующую сторку
    lcd.print("FANS: ");
    lcd.print(fanLCD); // отображение скорости вращения вентилятора
    lcd.print("%");
    delay(200);
    lcd.clear();
    }
     
    int readTemp() { // получить температуру и переконвертировать ее в цельсии
    temp = analogRead(tempPin);
    return temp * 0.2;
    }

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

float addr[151][2] = {
{0,28.0170},
{1,26.8255},
{2,25.6972},
{3,24.6290},
{4,23.6176},
{5,22.6597},
{6,21.7522},
{7,20.8916},
{8,20.0749},
{9,19.2988},
{10,18.5600},
{11,18.4818},
{12,18.1489},
{13,17.6316},
{14,16.9917},
{15,16.2797},
{16,15.5350},
{17,14.7867},
{18,14.0551},
{19,13.3536},
{20,12.6900},
{21,12.0684},
{22,11.4900},
{23,10.9539},
{24,10.4582},
{25,10.0000},
{26,9.5762},
{27,9.1835},
{28,8.8186},
{29,8.4784},
{30,8.1600},
{31,7.8608},
{32,7.5785},
{33,7.3109},
{34,7.0564},
{35,6.8133},
{36,6.5806},
{37,6.3570},
{38,6.1418},
{39,5.9343},
};
 
void setup() {
Serial.begin(9600);
pinMode(A0,INPUT) ;
}
 
void loop() {
Serial.println(analogRead(A0));
Serial.println(getTemp(analogRead(A0)));
delay(2000);
}
 
float getR(float V)
{
float result;
result=-10*V/(V-1024);
return result;
}
 
float getTemp(float V)
{
float R;
R=getR(V);
int i=0;
while (addr[i][1] >R)
{
i++;
}
float result;
result=(R-addr[i][1])*(addr[i-1][0]-addr[i][0])/(addr[i-1][1]-addr[i][1])+addr[i][0];
return result;
}

Не понятно, что за числа в таблице...


На данном этапе код не работает, так как:
1. Не интегрирована таблица
2. Если запустить схему с температурой 100 градусов вентилятор не запускается (Нужно попасть в диапазон от 30 до70)
3. Нужно инвертировать зависимость температуры от напряжения при повышении напряжения растет и температура, нужно наоборот.

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

Підвал форуму