Помогите решить задачу

lex_007
Offline
Зарегистрирован: 23.05.2015

Всем привет. В общем такая задача, нужно в программе Arduino IDE реализовать вот такое математиечское выражение: m[KT] = m[(K-1)T] + e[(K-1)T] - e[(K-2)T] + e[(K-3)T],

где m - выходной сигнал регулятора; e - входной сигнал регулятора; К - число тактов; Т - время между тактами.

В свою очередь e[K] = S - y[K],

где S - сигнал задания (мы задем его сами); y[K] - сигнал с датчика в тактовый момент.

Сложность состоит в том, что в любой тактовый момент от 0 и до бесконечности (тактовый момент это и есть K, принимает целочисленные значения), мы определяем выходной сигнал. То есть, при К допустим = 5, мы сначала должны определить выходной сигнал при К = 0, потом при К = 1 и так далее до К = 5. Данные должны хранится в памяти и решать эту задачу нужно через массивы.

Вот кое что набросал, помогите пожалуйста.

#include <EEPROM.h>
int K = 5;
int z; 
int m;

int y;
int e;

int SPin = 2;
int yPin = 3;
int mPin = 4;

void setup() 
{
  pinMode(SPin,INPUT);
  pinMode(yPin,INPUT);
  pinMode(mPin,OUTPUT);  
}

void loop() 
{
  y = digitalRead(yPin);  
  EEPROM.write(y, y);
  e = S - y;
  EEPROM.write(S, S);
  for (z = 0; z <= (K-1)*T; z = z + 1) {
  int mas[z];
}
   
}

   

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

прощай EEPROM... ( скупая мужская слеза)

lex_007
Offline
Зарегистрирован: 23.05.2015

А как нужно не подскажите?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А сигналы поступают последовательно? Т.е. сначала К=0, затем 1 и т.д.?

И ещё вопрос: начальное условие, т.е. чему равно m[KT] (и y[KT]) при К равном 0, 1 и 2? По этой формуле это не вычислишь, должны быть начальные условия.

 

lex_007
Offline
Зарегистрирован: 23.05.2015

Да, сигналы поступают последовательно, то есть если мы задаем к примеру К = 3, тогда сначала подается сигнал К = 0, потом К = 1, после К = 2 и наконец после этого К = 3.

y[K] - сигнал с датчика, а Т мы задаем сами допустим 1 секунда (Т = 1).

То есть как я это понимаю, мы задали S = 1 (к примеру) и К = 3, и дальше пошел цикл начиная с К = 0. Далее считывается значение с датчика это y[K] вычисляется e[K] = S - y[K]. После этого вычисляется m[KT]. Потом тоже самое при К = 1, при К = 2 и при К = 3.

Еще добавлю, что если в квадратных скобках стоит 0 (e[0*T]) или отрицательное значение (e[-T]), то значение e[0*T] и e[-T] будет равно 0. Тоже самое и для m[0*T] и m[-T].

Я напишу как я вижу это математически, допустим при К = 3:

К = 0: m[0*T] = m[-1*T] + e[-1*T] - e[-2*T] + e[-3*T] = 0 + 0 + 0 + 0 = 0;

К = 1: m[1*T] = m[0*T] + e[0*T] - e[-1*T] + e[-2*T] = 0 + 0 + 0 + 0 = 0;

К = 2: m[2*T] = m[1*T] + e[1*T] - e[0*T] + e[-1*T] = 0 + (S - y[1*T]) + 0 + 0 = S-y[1*T];

К = 3: m[3*T] = m[2*T] + e[2*T] - e[1*T] + e[0*T] = (S-y[1*T]) + (S-y[2*T]) + (S-y[2*T]) + 0.

 

Можно задать такие начальные параметры: S = 1; T = 1; K = 7. То есть чтобы мы могли менять начальные параметры и проблем с математикой не возникало.

 

Maverik
Offline
Зарегистрирован: 12.09.2012

lex_007 пишет:

А как нужно не подскажите?

он хотел сказать что память eeprom не предназначена для работы с ней как с ОЗУ.

ее нужно использовать как энергонезависимую память, которую можно часто читать но редко туда писАть.

количество циклов перезаписи у нее на порядки ниже чем у ОЗУ.   Вы же туда что-то пишете в цикле даже без пауз. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Тогда я напишу Вам как нужно считать m всякий раз, для следующего К (приведу функцию расчёта m[k]).

Для начала, заметим, что для рассчёта m Вам нужно знать ОДНО предыдущее значение m и три предыдущих значений e. 

В моей функции они хранятся как статические переменная и массив из трёх элементов.

Вы хотели хранить их в епроме, но это имеет смысл только если Вам нужно сохранять их при выключении питания, т.е. после включения питания продолжать счёт со старых значений, а не начинать заново. Это нужно? Если нужно, то надо действительно перейти на епром. Так, как сейчас сделано у меня - при включении пиатния всё начинается сначала.

Ну, вот собственно функция. Для k равых 0, 1 и 2 она выдаёт нули, а уже для k==3 и больше выдаёт расчитанные значения.

Кстати, для этой функции совершенно не нужно T - какая ей разница? Оно тут и не используется.

//
//	Вычисляем новое m по предыдущему и трём предыдущим e.
//	Вычисленные m и e запоминаем для следующего вычисления m
//
//		m[KT] = m[(K-1)T] + e[(K-1)T] - e[(K-2)T] + e[(K-3)T]
//		e[K] = S - y[K]
//
//		при этом: m[0] == m[1] == m[2] == 0
//
//	Параметры:
//	k - нужен лишь для того, чтобы понять, что он меньше трёх и мы возвращаем 0 или он >=3, тогда считаем.
//	y и s - нужны для вычисления e
//
int m (int k, int y, int s) {
	static int ThreeOldEs[] = { 0,0,0 };	// место для хранения трёх старых значений e

	// Если k < 3, то считаем e (на будущее) и возвращаем 0
	if (k < 3) {
		ThreeOldEs[k] = s - y;
		return 0;
	}

	// Значение m[k-1] - сначала 0, а потом будет храниться с прошлого вычисления
	static int MKminusOne = 0;

	// Вычисление по основной формуле.
	// Здесь
	//	ThreeOldEs[2] соответствует e[k-1]
	//	ThreeOldEs[1] соответствует e[k-2]
	//	ThreeOldEs[0] соответствует e[k-3]
	// Заодно запоминаем вычисленное m для использования в следующий раз в качестве m[k-1]
	MKminusOne = MKminusOne + ThreeOldEs[2] - ThreeOldEs[1] + ThreeOldEs[0];

	// Сдвигаем массив хранения e и "забываем" e[k-3] (оно больше не понадобится)
	ThreeOldEs[0] = ThreeOldEs[1];
	ThreeOldEs[1] = ThreeOldEs[2];

	// Записываем новое e для дальнейшего использования
	ThreeOldEs[2] = s - y;

	// собственно всё, возвращаем вычисленное значение
	return MKminusOne;
}