tmpr=new float[3000];
volt = new float[3000];
mode = new int[3000];
for (i = 0; i < 3000; i++)
{
tmpr[i] = n.temperature;
volt[i] = n.voltage;
mode[i] = n.ChargeMode;
n.simulate();
n.timer = n.chargeControl(n.timer);
n.timer += (float)1.0;
s = "Main: " + i + " volt=" + n.voltage + " temper=" + n.temperature + " Mode=" + n.ChargeMode;
listBox1.Items.Add(s);
}
Console.ReadLine();
}
Программа вызывает функцию, которая эмулирует процесс собственно зарядки и разрядки батареи, а затем позволяет функции управления зарядкой установить нужный режим для зарядного устройства.
Вывод
В результате работы над проектом была создана модель работы зарядного устройства для батареи. Программа описывает выбор режима зарядки, исходя из параметров напряжения и температуры, а так же выводит графики изменения этих параметров.
ПрограмманаписананаMicrosoft Visual C# 2010 Express Edition. Отладка производилась в операционной системе MS Windows ХР.
На этом примере было рассмотрено применение операторов нечёткой логики. Эти операторы используется в самых разнообразных приложениях. Наиболее очевидная область их применения - системы управления, которым нечеткая логика уже обеспечила коммерческий успех. Нечеткая логика используется в устройстве видеокамер и фотоаппаратов с автофокусом, системах смешивания цемента, автомобильных системах (например, системах АБС) и даже системах, основанных на правилах. Наверное, самые полезные области применения все еще остаются неизвестными. Само название «нечеткая логика» не внушает особого доверия, хотя давно известно, что это надежный метод. Как и многие другие методики ИИ, нечеткая логика в настоящее время все чаще используется в устройствах повседневного применения, где она больше не ассоциируется с искусственным интеллектом.
Приложение 1
зарядное устройство батарея нечёткая логика
Код программы:
classNapryagenie
{
int TRICKLE_CHARGE; //charge=заряд 0
int FAST_CHARGE; // 1
public int ChargeMode;
int MAX_LOADS; // 5
public float voltage, temperature;
public float timer;
float[] load;
int curLoad;
float lo;
//constructor
public Napryagenie() {
TRICKLE_CHARGE = 0;
FAST_CHARGE = 1;
ChargeMode = TRICKLE_CHARGE;
MAX_LOADS=5;
load = new float[MAX_LOADS];
curLoad = 0;
temperature = (float)12.0;
timer = (float)0.0;
voltage = (float)20.0;
load[0]=(float)0.02;
load[1]=(float)0.04;
load[2]=(float)0.06;
load[3]=(float)0.08;
load[4] = (float)0.1;
}
int t;
public float charge( int t )
{
float result;
result = (float)Math.Sin((double)((float)t/(float)100.0));
if (result < 0.0) result = (float)0.0;
return result;
}
public int simulate()
{
//extern int chargeMode;
t=0;
// First, update the loading if necessary
if (getSRand() < 0.02) {
curLoad = getRand( MAX_LOADS );
}
// Affect the current battery voltage given the load
voltage -= load[curLoad];
// Next, update the battery voltage given input charge
if (ChargeMode == FAST_CHARGE) {
voltage += (charge(t) * (float)Math.Sqrt(timer));
} else {
voltage += ((charge(t) * (float)Math.Sqrt(timer)) / (float)10.0 );
}
if (voltage < 0.0) voltage = (float)0.0;
else if (voltage > 35.0) voltage = (float)35.0;
// Update the temperature
if (ChargeMode == FAST_CHARGE) {
if (voltage > 25) {
temperature += ((load[curLoad] * ((float)Math.Sqrt(timer)/(float)25.0)) * (float)10.0);
} else if (voltage > 15) {
temperature += ((load[curLoad] * ((float)Math.Sqrt(timer) / (float)20.0)) * (float)10.0);
} else {
temperature += ((load[curLoad] * ((float)Math.Sqrt(timer) / (float)15.0)) *(float) 10.0);
}
} else {
if (temperature > 20.0) {
temperature -= ((load[curLoad] * ((float)Math.Sqrt(timer) / (float)20.0)) * (float)10.0);
} else {
temperature -= ((load[curLoad] * ((float)Math.Sqrt(timer) /(float) 100.0)) * (float)10.0);
}
}
if (temperature < 0.0) temperature = (float)0.0;
else if (temperature > 40.0) temperature = (float)40.0;
t++;
return 0;
}
public float getSRand() {
float c;
Random r=new Random();
uint RAND_MAX=0x7FFFFU;
c=((float)r.Next()/(float)RAND_MAX);
return c;
}
public int getRand(float x) { return (int)((x) * getSRand()); }
public float MAX(float a,float b) { return (a>b) ? a : b; }
public float MIN(float a, float b) { return (a < b) ? a : b; }
public float fuzzyAnd (float a, float b)
{
if (a < 0.0) return 0;
if (a > 1.0) return 0;
if (b < 0.0) return 0;
if (b > 1.0) return 0;
return MAX(a, b);
}
public float fuzzyOr(float a, float b)
{
if (a < 0.0) return 0;
if (a > 0.0) return 0;
if (a < 0.0) return 0;
if (a > 0.0) return 0;
return MIN(a, b);
}
public float fuzzyNot(float a)
{
if (a < 0.0) return 0;
if (a > 1.0) return 0;
float c = (float)1.0 - a;
return c;
}
//нормализация
public int normalize(float inn)
{
if (inn >= 0.5) return 1;
else return 0;
}
//функцияпринадлежностиввидетреугольника
public float spikeProfile (float value, float lo, float high)
{
float peak;
value += (-lo);
if ((lo < 0) && (high < 0))
{
high = -(high - lo);
}
else if ((lo < 0) && (high > 0))
{
high += -lo;
}
else if ((lo > 0) && (high > 0))
{
high -= lo;
}
peak = (float)(high / 2.0);
lo =(float)0.0;
if (value < peak)
{
return (value / peak);
}
else if (value > peak)
{
return ((high - value) / peak);
}
return (float)1.0;
}
// функцияпринадлежностиввидетрапеции
public float plateauProfile(float value, float lo, float lo_plat,
float hi_plat, float hi)
{
float upslope;
float downslope;
value += (-lo);
if (lo < 0.0)
{
lo_plat += -lo; hi_plat += -lo;
hi += -lo; lo = 0;
}
else
{
lo_plat -= lo; hi_plat -= lo;
hi -= lo; lo = 0;
}
upslope =(float) (1.0 / (lo_plat - lo));
downslope = (float)(1.0 / (hi - hi_plat));
if (value < lo) return (float)0.0;
else if (value > hi) return (float)0.0;
else if ((value >= lo_plat) && (value <= hi_plat)) return (float)1.0;
else if (value < lo_plat) return ((value - lo) * upslope);
else if (value > hi_plat) return ((hi - value) * downslope);
return (float)0.0;
}
// функция принадлежностми для высокой температуры
public float m_temp_hot(float temp)
{
const float lo = (float)35.0;
const float lo_plat = (float)45.0;
const float hi_plat = (float)45.0;
const float hi = (float)45.0;
if (temp < lo) return (float)0.0;
if (temp > hi) return (float)1.0;
return plateauProfile(temp, lo, lo_plat, hi_plat, hi);
}
// функция принадлежностми для средней температуры
public float m_temp_warm(float temp)
{
const float lo = (float)15.0;
const float lo_plat = (float)25.0;
const float hi_plat = (float)35.0;
const float hi = (float)45.0;
if ((temp < lo) || (temp > hi)) return (float)0.0;
return plateauProfile(temp, lo, lo_plat, hi_plat, hi);
}
// функция принадлежностми для низкой температуры
public float m_temp_cold(float temp)
{
const float lo = (float)15.0;
const float lo_plat = (float)15.0;
const float hi_plat = (float)15.0;
const float hi = (float)25.0;
if (temp < lo) return (float)1.0;
if (temp > hi) return (float)0.0;
return plateauProfile(temp, lo, lo_plat, hi_plat, hi);
}
//функцияпринадлежностидлянизкогонааряжения
public float m_voltage_low(float voltage)
{
const float lo = (float)5.0;
const float lo_plat = (float)5.0;
const float hi_plat = (float)5.0;
const float hi = (float)10.0;
if (voltage < lo) return (float)1.0;
if (voltage > hi) return (float)0.0;
return plateauProfile(voltage, lo, lo_plat, hi_plat, hi);
}
//функция принадлежности для среднего напряжения
public float m_voltage_medium(float voltage)
{
const float lo = (float)5.0;
const float lo_plat = (float)10.0;
const float hi_plat = (float)20.0;
const float hi = (float)25.0;
if (voltage < lo) return (float)0.0;
if (voltage > hi) return (float)0.0;
return plateauProfile(voltage, lo, lo_plat, hi_plat, hi);
}
//функцияпринадлежностидлявысокогонааряжения
public float m_voltage_high(float voltage)
{
const float lo = (float)25.0;
const float lo_plat = (float)30.0;
const float hi_plat = (float)30.0;
const float hi = (float)30.0;
if (voltage < lo) return (float)0.0;
if (voltage > hi) return (float)1.0;
return plateauProfile(voltage, lo, lo_plat, hi_plat, hi);
}
public float chargeControl(float timer )
{
int i = 0;
if ( (i++ % 10) == 0 ) {
if ( normalize(m_voltage_high(voltage)) ==1) {
ChargeMode = TRICKLE_CHARGE;
timer = (float)0.0;
} else if (normalize( m_temp_hot(temperature))==1) {
ChargeMode = TRICKLE_CHARGE;
timer = (float)0.0;
} else if (normalize(
fuzzyAnd(fuzzyNot(m_voltage_high(voltage)),
fuzzyNot(m_temp_hot(temperature))))==1) {
ChargeMode = FAST_CHARGE;
timer = (float)0.0;
}
}
return timer;
}
}//class
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
Graphics g;
float [] tmpr;
float [] volt;
int [] mode;
private void button1_Click(object sender, EventArgs e)
{
int i;
Napryagenie n = new Napryagenie();
string s="";
tmpr=new float[3000];
volt = new float[3000];
mode = new int[3000];
for (i = 0; i < 3000; i++)
{
tmpr[i] = n.temperature;
volt[i] = n.voltage;
mode[i] = n.ChargeMode;
n.simulate();
n.timer = n.chargeControl(n.timer);
n.timer += (float)1.0;
s = "Main: " + i + " volt=" + n.voltage + " temper=" + n.temperature + " Mode=" + n.ChargeMode;
listBox1.Items.Add(s);
}
Console.ReadLine();
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
class graphic
{
int xw, yw;
Graphics gr;
int mx, my;
int minx,maxx,miny,maxy;
float shx,shy;
public graphic(Graphics g, int mx1, int my1, int minx1, int maxx1, int miny1, int maxy1)
{
gr = g;
mx = mx1; my = my1;
minx = minx1; maxx = maxx1; miny = miny1; maxy = maxy1;
xw = maxx1 - minx1;
yw = maxy1 - miny1;
}
public void drawaxes()
{
int i;
int lrsk = 5;
float x = 0, y;
shx = (float)mx / (float)xw;
shy = (float)my / (float)yw;
for (i = 0; i < xw; i++)
{
x = (float)i * shx;
if (i % 50 == 0)
gr.DrawLine(new Pen(Color.Black, 1), x, my, x, my - lrsk);
}
for (i = 0; i < yw; i++)
{
y = i * shy;
if (i % 1 == 0)
gr.DrawLine(new Pen(Color.Black, 1), 0, y, lrsk, y);
}
}//drawaxes
public void drawgr(Color clr,float [] tmp)
{
float x,y;
int i;
int k = 0;
for (i = maxx - xw; i < maxx; i++)
{
x = k++ * shx;
y = tmp[i] * shy;
gr.DrawEllipse(new Pen(clr, 1), x, my - y, 1, 1);
}
}//drawgr
}//graphic
private void button2_Click(object sender, EventArgs e)
{
g = panel1.CreateGraphics();
graphic gra=new graphic(g,panel1.Width,panel1.Height,0,3000,0,50);
gra.drawaxes();
gra.drawgr(Color.Green, tmpr);
gra.drawgr(Color.Red, volt);
}
}
Приложение 2