Ви не увійшли.
Сторінки 1
Процесс не стоит на месте. Прототип уже установлен на подопытный автомобиль.
Уже реализован шим на частоте 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
}
Мыло активно, ноги, какие вам удобно.
По кнопкам все верно.
Аварийная работа 95% Скважность
Блок управления силовой, сам плавно все делает, тем более вентиляторы довольно инерционны.
Не пойму зачем регулируемый источник? Для имитации можно взять любой подстроечник, я использую 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 датчика температуры, один на ЭБУ двигателя, второй на ЭБУ клмат контроля и третий на стрелку в панеле приборов. Я тупанул и подключился к датчику климата, не знаю на сколько это кретично, но на многих авто, вентилятором охлаждения ОЖ управляет именно климат.
Можно конечно и собрать новые данные, нужно подумать.
Поделюсь и помогу Пете с удовольствием.
На счет точности установки скважности и частоты не знаю, нужно эксперементировать.
Думаю, что 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 возле спидометра и наблюдал за напряжением на датчике температуры.
... ничего не понял, даташит от чего? Что именно правилось?
Прошу прощения, но я пока очень далек от программирования пока. Если не сложно, можно чуток доходчивые, подробнее.
Загрузил вот такое:
/*
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();
}
На скорую руку собрал схемку - не работает. Осцила дома нет...
Но понять охота - подцепил динамик параллельно выходу с транзистора - на слух частота высоковата, анализаторы в андроид приложениях показывают 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гц
Все верно, я имею ввиду скважность. На счёт обратной связи, это я перепутал, неправильно понял.
Если не сложно, кто сталкивался с серво, дайте пример программки , желательно с управлением скважностью через терминал.
И может расскажите пару слов о программных таймерах.
В библиотеке сервы нужно поменять частоту? Я верно понял?
Просто библиотека серво просит обратной связи. Точно мне оно подойдёт?
"как заставить ардуинку выдать эти заветные 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); //---------------------- } }
yarikne для температуры возьмите медь 100. PT1000 не берите, не его задача )
это удорожание проекта, но выхода у вас особо нет."Я где-то "чувствую", что леонардо не для автомобиля" важное замечание - леонардо она как говорится не заточена, по хорошему берете понравившийся контроллер из серии mcu automotive от "любимого" производителя и на нем собираете
но ардуино вам наверное ближе чем натив ... есть и этому решение
в систему нужно добавить
1) трехсекундный watchdog
2) супервизор по питанию
3) хороший источник питание
4) ESD diodeпроверяете так в домашних условиях так - берете шокер, и в см 5 от корпуса держите разряд
не забудьте корпус сделать металический (профиль с эрицентра? у меня что то было но только для маленькой платы ), эго нужно будет занулить позже в авто.если все сделано - пользуйтесь своей леонардо, есть еще синяя хрень для защиты платы от пыли, влаги, вибраций, что то типа пленки, не помешает покрыть плату, название не помню (
Спасибо, хорошие советы, жаль, что производители китайского шарпотрепа для автомобилей не придержуются этих правил. (я про сигналки, блоки ДХО, навигаторы и т п)
С шокером, может и перегиб, но краш тест - должен быть жестким.
Сейчас нарыл блок управления вентиляторами от младшей модели мерседеса(он же используется в фольцвагенах). Это силовая часть с управлением на 25гц. Так сказать линия свзя работает на 25гц, а скважность регулирует обороты.
Вот такая штука
Думаю его очень целесообразно использовать, так как там есть защиты всевозможные и шумоподавляющие фильтры.
Основной вопрос, как заставить ардуинку выдать эти заветные 25гц и еще и скажностью управлять!?!?
yarikne пише:3 - С температурой сейчас вопрос. Я не знаю и не получается найти инфы, как из таблицы с параметрами зависимости напряжение - температура, получить переменную. Которая уже и будет обрабатываться.
сначала нужно выяснить что за датчик температуры, потом посмотреть его даташит, нафига таблицы строить))))
Датчик температуры вот такой
Известно что при 100 градусах на нем 1,8в при 20 - 4,6в. Все классно, я думаю что градусы с него я и не буду смотреть, будем опираться на напряжение, для получение температуры я рядышком прилеплю Lm35 - с него температуру я буду выводить на экран.
Экспериментальным путем подберу напряжения при которых должен работать вентилятор.
Уже известно, что при 1,9в и ниже вентилятор должен работать на всю.
"Не понятно, что за числа в таблице..."
похоже на linear interpolationесли хочете - научитесь )
но leonardo врядли лучшее решение для авто.
Я где-то "чувствую", что леонардо не для автомобиля, хотя и веских аргументов не вижу.
Может вы что то предложите более подходящие?
вы только начинаете, поэтому вам понятнее и проще делать по этапам
запустите дисплей
запустите вент, научитесь им управлять
потом температурой займитесь
ну а дальше всё в кучу
1 - Дисплей запустил, принципы вывода информации на дисплей понял. На данном этапе вывожу на дисплей Напряжение с А0 в вольтах, скважность шим в %, и неверно подсчитанную температуру.
2 - Запустить вент не пробовал, но светодиодом управляю, думаю это проблем не составит.
3 - С температурой сейчас вопрос. Я не знаю и не получается найти инфы, как из таблицы с параметрами зависимости напряжение - температура, получить переменную. Которая уже и будет обрабатываться.
Дано мерс 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. Нужно инвертировать зависимость температуры от напряжения при повышении напряжения растет и температура, нужно наоборот.
Буду благодарен любым подсказкам, очень хочу научится программировать ардуинки.
Сторінки 1