В этом случае часть данных ... сбрасывавется в файл на SD, а на освободтвшемся месте размещается требуемый массив. Когда надобность в новом массиве отпадет, данные читаются с SD на прежнее место.
Общо понятно, а не поделитесь каким-нибудь примерчиком? Не встречал ещё ничего подобного.
Mega - стоит 400 руб. С бесплатной доставкой. Если сейчас закажите, то через месяц решите свою проблему. Или рассказывайте задачу, и народ посоветует как экономить память. Других вариантов нет.
Сложный случай, запущенный. Да еще и без открытого кода. Пробуйте так.
1. Убедитесь что памяти действительно нехватает, что именно стеком затирает, а не стрельба по памяти. Полезно уяснить в какой цепочке вызовов происходит лажа.
2. Если активно используете прерывания - попробуйте позапрещать их при входе в длинную цепь. Может нашару и решите.
3.Алгоритмическая оптимизация - все ли буферы промежуточных реально нужны, может некоторые проще не хранить, а заново расчитывать? Подумать про обработку данных по цепочке, без буферов. Плавающую точку поубирать по макмимуму. Проконтролировать где излишки точности и исправить.
4. Приведеный фрагмент кода, там где case 221:.. сильно намекает что все в коде очень плохо. Не все что матрица в математике стоит в массив пихать.
ПС. Более конкретные советы могут быть только после просмотра кода.
Если есть интерес, я создам отдельную тему на этот счёт. У меня на ПК "развёрнута" такая машина и я пользуюсь её функционалом, в т.ч. для ответов здесь (если полностью приведён код программы).
Вот рабочая прога, которую я затем использовал как модуль в своём скетче. Что скажет Ваша машина?
#define ROW 6
#define COL 3
const double eps = 1/pow(2,32);
double BBB[] = {16.74,-24.24,9.17,14.03,-22.19,8.68,15.24,-23.04,-0.06,18.03,-27.06,7.10,19.09,-21.24,6.27,19.29,-24.24,1.71};
double X[6];
double M_OS[3];
double M_SC[3];
double M_m[3];
#include <math.h>
#include <SoftwareSerial.h>
#define ENDLESS 0xffffffff //Бесконечный таймаут для форматированного ввода
void *Malloc (size_t size);
double **MakeMatr ( size_t n, size_t m );
void DelMatr ( double *Matr[] );
void ZnachMatr (double *Matr[], double *AA, const int n, const int m);
void OutMatr( char *name, double *Matr[], const int n, const int m );
void TRANS (double *MatrT[], double *MatrC[], const int n, const int m);
void MULTI (double *MatrM[], double *MatrT[], double *MatrC[], const int n, const int m, const int l);
void INVERS (double *MatrI[], double *MULTI[], const int m);
void PLUS_C (double *MatrC[], double *Matr[], const int n, const int m);
//**************************************
void setup()
{
Serial.begin(9600);
while (!Serial) {
}
Serial.setTimeout(ENDLESS);
}
//**************************************
void loop()
{
int n = ROW, m = COL, mm = COL+3;
double **B;
/* Выделение памяти под матрицу*/
B = MakeMatr(n, m);
/* Заполнение матрицы значениями */
ZnachMatr(B, BBB, n, m);
/* Печать матрицы B для контроля */
OutMatr("B = ", B, n, m);
/* Добавление столбцов справа */
double **HH;
HH = MakeMatr(n, mm);
PLUS_C (HH, B, n, m);
double **W;
W = MakeMatr(n, 1);
for(int i = 0; i < n; i++)
W[i][0] = sq(B[i][0]);
double **HT;
HT = MakeMatr(mm, n);
TRANS (HT, HH, n, mm);
/*Произведение матрицы */
double **M;
M = MakeMatr(mm, mm);
MULTI (M, HT, HH, mm, mm, ROW);
double **MI;
MI = MakeMatr(mm, mm);
INVERS (MI, M, mm);
OutMatr("(HTxH)(-1) = ", MI, mm, mm);
double **MM;
MM = MakeMatr(mm, mm);
MULTI (MM, MI, HT, mm, mm, ROW);
// OutMatr("(HTxH)(-1)xHT = ", MM, mm, mm);
double **X;
X = MakeMatr(mm, 1);
MULTI (X, MM, W, mm, 1, ROW);
OutMatr("X = (HTxH)(-1)xHT x W = ", X, mm, 1);
M_OS[0] = X[0][0] / 2;
M_OS[1] = X[1][0] / (2 * X[3][0]);
M_OS[2] = X[2][0] / (2 * X[4][0]);
Serial.println("M_OS = ");
for (int i = 0; i < 3; i ++)
{
Serial.print(M_OS [i]);
Serial.println(" ");
}
Serial.println();
double AA = X[5][0] + sq (M_OS[0]) + X[3][0] * sq (M_OS[1]) + X[4][0] * sq (M_OS[2]);
double BB = AA / X[3][0];
double CC = AA / X[4][0];
Serial.print("AA = ");
Serial.print(AA);
Serial.println(" ");
Serial.print("BB = ");
Serial.print(BB);
Serial.println(" ");
Serial.print("CC = ");
Serial.print(CC);
Serial.println(" ");
double MAG1[n][m];
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
MAG1[i][j] = B[i][j] - M_OS [j]; //коррекция оси X
Serial.print (MAG1[i][j]);
Serial.print ("\t");
}
Serial.println();
}
M_SC[0] = sqrt (AA);
M_SC[1] = sqrt (BB);
M_SC[2] = sqrt (CC);
for (int i = 0; i < 3; i ++)
{
Serial.print("M_SC = ");
Serial.print(M_SC[i]);
Serial.println(" ");
}
Serial.println();
double MAG2[n][m];;
Serial.print("Mag2[X]");
Serial.print("\t");
Serial.print("Mag2[Y]");
Serial.print("\t");
Serial.print("Mag2[Z]");
Serial.println();
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
MAG2[i][j] = MAG1[i][j] / M_SC[j];
Serial.print (MAG2[i][j]);
Serial.print ("\t");
}
Serial.println();
}
/* Освобождаем динамическую память под матрицами */
DelMatr(B);
DelMatr(HH);
DelMatr(W);
DelMatr(HT);
DelMatr(M);
DelMatr(MI);
DelMatr(MM);
DelMatr(X);
}
//**********************************************
/* Подпрограммы */
/* Вывод матрицы на монитор */
void OutMatr( const char *name, double *Matr[], const int n, const int m )
{
Serial.println(name);
// Цикл по строкам
for (int row = 0; row < n; row++)
{
// цикл по столбцам внутри строки
for (int col = 0; col < m; col ++)
{
Serial.print(Matr [row] [col]);
Serial.print(" ");
}
Serial.println();
}
}
void ZnachMatr (double *Matr[], double *AA, const int n, const int m)
// void ZnachMatr (double *Matr[], const int n, const int m)
{
int i, j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
Matr[i][j] = AA [i * COL + j];
}
/* Добавление трёх столбцов справа */
void PLUS_C (double *MatrC[], double *Matr[], const int n, const int m)
{
int i, j;
for(i = 0; i < n; i++)
{
for(j = 0; j < m; j++)
{
MatrC[i][j] = Matr [i][j];
MatrC[i][j+1] = -sq(Matr [i][j-1]);
MatrC[i][j+2] = -sq(Matr [i][j]);
MatrC[i][j+3] = 1;
}
}
}
/* Транспонирование матрицы A */
void TRANS (double *MatrT[], double *MatrC[], const int n, const int m)
{
int i, j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
MatrT[j][i] = MatrC[i][j];
}
/*Произведение матриц */
void MULTI (double *MatrM[], double *MatrT[], double *MatrC[], const int n, const int m, const int l)
{
for (int row = 0; row < n; row++) {
for (int column = 0; column < m; column ++) {
MatrM[row][column] = 0;
for (int r = 0; r < l; r++) {
MatrM[row][column] += MatrT[row][r] * MatrC[r][column];
}
}
}
}
/*Обращение матрицы */
void INVERS (double *MatrI[], double *MULTI[], const int m)
{
double **KM;
KM = MakeMatr(m, m);
for(int i = 0; i < m; i++)
{
for(int j = 0; j < m; j++)
{
KM[i][j] = MULTI[i][j];
}
}
for(int i = 0; i < m; i++)
{
for(int j = 0; j < m; j++)
{
if(i == j)
MatrI[i][j] = 1;
else
MatrI[i][j] = 0;
}
}
int i, j, k, leader_pos;
double leader, temp;
for(i = 0; i < m; i++)
{
leader = KM[i][i];
leader_pos = i;
for(j = i; j < m; j++)
if ( fabs(KM[j][i]) > fabs(leader) )
{
leader = KM[j][i];
leader_pos = j;
}
if (fabs(leader) > eps)
{
for(j=0; j < m; j++)
{
temp = KM[i][j];
KM[i][j] = KM[leader_pos][j];
KM[leader_pos][j] = temp;
temp = MatrI[i][j];
MatrI[i][j] = MatrI[leader_pos][j];
MatrI[leader_pos][j] = temp;
}
for(j = 0; j < m; j++)
{
if (i != j)
{
temp = (KM[j][i] / KM[i][i]);
for(k = 0; k < m; k++)
{
KM[j][k] -= KM[i][k] * temp;
MatrI[j][k] -= MatrI[i][k] * temp;
}
}
}
}
}
double t4;
for(i = 0; i < m; i++)
{
t4 = KM[i][i];
KM[i][i] /= t4;
for(int k = 0; k < m; k++)
MatrI[i][k] /= t4;
}
/* Очистка динамической памяти */
DelMatr(KM);
}
/* Выделение динамической памяти */
void *Malloc( size_t size )
{
void *p = malloc(size);
if( !p )
{
Serial.println("Недостаточно памяти!");
exit(1);
}
return p;
}
/* Конструктор матрицы */
double **MakeMatr( size_t n, size_t m )
{
double **Matr; size_t i;
Matr = (double**) Malloc( (n + 1) * sizeof(double *) );
// Matr = (double**) Malloc( n * sizeof(double *) );
for(i = 0; i < n; i++)
Matr[i] = (double *) Malloc( m * sizeof(double) );
Matr[n] = NULL;
return Matr;
}
/* Деструктор матрицы */
void DelMatr( double *Matr[] )
{
size_t i;
for(i = 0; Matr[i]; i++)
{
free(Matr[i]);
Matr[i] = NULL;
}
free(Matr);
Matr = NULL;
}
Вечером только смогу посмотреть, т.к. "отладчик" дома развёрнут. Если до этого вам тут не найдут ошибки, я промоделирую ваш код и скажу в чём дело.
Повторюсь, этот скетч - лишь работающий модуль моего скетча, в нём НИКАКИХ проблем не обнаружил. Привёл для того, чтобы познакомиться с работой Вашей машины.
Конечно, более грамотные спецы что-нибудь наковырют для оптимизации этого кода, за что им буду благодарен, ессно.
Тогда я могу сделать по-другому. Если хотите, могу дать эту виртуальную машину (для определённости, назовём её Arduino Virtual Debug Machine - Виртуальная Машина Отладки Arduino) и показать как на ней отлаживать ваш демо-пример, а дальше вы уже сами разберётесь.
Ну йолы палы! Вот в 59 строке у Вас посчиталась М, затем она использовалась в стр 64 и все, больще нигде не задействована. Зачем под ней память держать до конца? Конечно памяти ненапасетесь! Есть 2 варианта - освобождать как перестала быть нужной (но про фрагментацию кучи думать, в каком порядке распределять и освобождать!!) и повторно использовать в следующих вычеслениях.
Ну йолы палы! Вот в 59 строке у Вас посчиталась М, затем она использовалась в стр 64 и все, больще нигде не задействована. Зачем под ней память держать до конца?
Простите, а в строке 150 она не очищается?
Корректирую. Понял Вашу мысль. Когда петух клюнул, куда надо, я подправил места очищения переменных. Извините, что ввёл Вас в заблуждение этим скетчем. В данном случае М очистил сразу после её использования.
Корректирую. Понял Вашу мысль. Когда петух клюнул, куда надо, я подправил места очищения переменных. Извините, что ввёл Вас в заблуждение этим скетчем. В данном случае М очистил сразу после её использования.
Ну, там ещё много всего. Например,
HH размещается в памяти в строке 45. Последнее использование - строка 60. Что она делает в памяти аж до строки 147?
А между прочим, между строкой 60 и строкой 147 Вы размещаете на стеке ещё две матрицы (строка 103 и строка 128) и запрашиваете динамически ещё несколько (стр. 73, например). Так что там в это время делает HH? Только место занимает?
Просмотрите весь код внимательно.
Кроме того, те матрицы, что Вы размещаете на стеке, необходимо освобождать сразу как только они перестают быть нужны. Для этого достаточно поставить фигурные скобки: откырвющую перед объявлением матрицы и закрывающую как только она перестала быть нужной (только следите, чтобы внутри скобок не было объявлено ещё что-то, что нельзя пока освобождать).
Кроме того, те матрицы, что Вы размещаете на стеке, необходимо освобождать сразу как только они перестают быть нужны. Для этого достаточно поставить фигурные скобки: откырвющую перед объявлением матрицы и закрывающую как только она перестала быть нужной (только следите, чтобы внутри скобок не было объявлено ещё что-то, что нельзя пока освобождать).
В этом случае очищать специальной командой типа DelMatr(M) уже не нужно, если заключить в фигурные скобки, или я не правильно понял? Можно небольшой пример записи?
В этом случае очищать специальной командой типа DelMatr(M) уже не нужно
Нет, конечно, Вы же её не запрашивали! Я имею в виду строки 103 и 128 (может ещё где есть, но эти - точно). Вы же здесь не запрашивали память, так как же Вы её будете освобождать.
Вот Вы написали.
double MAG1[n][m];
Теперь эта матрица будет занимать место на стеке вплоть до ближайшей открытой } Т.е. в Вашем случае до строки 154.
Стеком можно управлять. Например:
{ // начало блока
double MAG1[n][m]; // размещаем массив на стеке
.....
// здесь пользуемся MAG1
.....
} // Конец блока. Всё, что было объявлено в блоке выбрасывается, и стек освобождается
Этот приём Вам ничего не стоит. Всё, что было объявлено вне блока (выше) доступно и в нём. Нужно только следить, чтобы в блоке не оказались объявленными какие-то переменные. которые нужны и после. Если таковые найдутся. их объявление нужно вынести выше блока.
Тут есть в разделе "Общий" пример успешного решения для расширения SRAM на +32 килобайт и мой проект расширителя на +512 килобайт. Но такие расширители или платы в с памятью Вам придется изготавливать практически самостоятельно.
Я не смог найти этот пример. Подскажите, пжлст, как его найти.
Теперь эта матрица будет занимать место на стеке вплоть до ближайшей открытой }
А откуда следует, что вместе с окончанием области видимости одновременно и освобождается стек? По крайней мере, такое решение проигрывает как по производительности, так и по объему кода.
PS. Посмотрел в коде: стек оно, коначно, распределяет и освобождает только в начале и конце тела функции, в середине никакого перераспределения нет. Но объем в стеке выделяет, учитывая, пересекаются ли области видимости. Вопрос: регламентируется ли такое поведение или оно зависит от реализации компилятора (или его настроек).
swap файл в avr - круто :) Хотя скорее это сарказм. Нет, нет, наверное еще не маразм, раз кто-то это использует.
А Вам достоверно известно, что это кто-то использует?
Просто ТС, похоже, не верит на слово, что в его случае самое оптимальное решение - сменить камень на что-то помощнее. Вот мне и захотелось, чтобы он пришел к этой мысли самостоятельно, взвесив все альтернативы.
Просто ТС, похоже, не верит на слово, что в его случае самое оптимальное решение - сменить камень на что-то помощнее. Вот мне и захотелось, чтобы он пришел к этой мысли самостоятельно, взвесив все альтернативы.
Иногда можно изменить алгоритм и больший камень не потребуется.
А откуда следует, что вместе с окончанием области видимости одновременно и освобождается стек? По крайней мере, такое решение проигрывает как по производительности, так и по объему кода.
PS. Посмотрел в коде: стек оно, коначно, распределяет и освобождает только в начале и конце тела функции, в середине никакого перераспределения нет. Но объем в стеке выделяет, учитывая, пересекаются ли области видимости. Вопрос: регламентируется ли такое поведение или оно зависит от реализации компилятора (или его настроек).
Это сложный вопрос. Вернее, откуда следует – это то как раз просто – из п. 6.7.2 стандарта языка. А сложность вот в чём. Стандарт не определяет работу со стеком (более того, он даже не требует, чтобы локальные переменные хранились на стеке) он лишь требует, чтобы переменные «уничтожались» при выходе из блока.
Поэтому компиляторы ведут себя так:
1. Для экземпляров классов, у которых имеется деструктор с побочным эффектом – деструктор вызывается немедленно по достижении }, что кстати прямо следует из того самого п. 6.7.2 (пруфскетч №1 ниже). Это правило железное для всех компиляторов, и ни от каких опций не зависит. У него есть тонкости связанные с обработкой прерываний, мы не будем туда лезть.
пруфскетч №1 – освобождение объекта с деструктором
Заметьте, деструктор вызван между точками №2 и №3, т.е. точно на }
2. Во всех остальных случаях действует такое правило: по достижению конца блока переменная должна быть освобождена, но делать это или нет и как именно делать – отдаётся на откуп компилятору (вернее, оптимизатору). Главное, чтобы это не влияло на поведение программы и она вела бы себя так, как будто всё освобождается.
Конкретно в нашем GCC пошли ещё дальше. Вместо «освобождения стека» они ввели понятие «повторное использование стека» (stack reusing), которое позволяет «освободить» стек даже до того, как закончился блок, если компилятор посчитает, это эта переменная больше не нужна. Управляется всё это опциями оптимизатора (см.). Но на деле он не освобождает стек, а хапает его сразу на всю функцию (что Вы и наблюдали), но при этом повторно использует его куски по мере того, как переменные становятся не нужны (например, блок закончился или оптимизатор решил, что они больше не нужны).
С точки зрения поведения программы это тоже самое, как если бы он его освобождал. Поэтому я и говорю об освобождении - просто проще говорить в такой парадигме, а с точки зрения логики программы это верно.
Например, то, что я написал ТС абсолютно верно. См. пруфскетч №2 – «освобождение» стека по }
Тема http://arduino.ru/forum/obshchii/atmega-128a-au-vneshnyaya-sram-62256-74... находится поиском по запросу "расширенная память". Это вариант добавления SRAM ко всем вариантам микроконтроллеров, оснащенных x-bus интерфейсом. При добавлении до 64к - никаких специальных мер особо применять не придется. Надо будет только в настройках компиляции платы указать предельный размер памяти и можно уточнить положение стека и кучи, для повышения скорости работы с ним. Как - тут уже есть намеки. Но, это путь "изготовления своей платы".
В вашем примере, уже много сказано как его улучшить. Кардинальное улучшение возможно, если тщательно пересмотреть код и отказаться от типовых "матричных вычислений", заменив их прямыми циклами, без накопления промежуточных матриц и вовсе. Но, это достаточно объемная и кропотливая работа.
Peotr, выведите в терминал адреса, получаемые при динамическом выделении памяти (до момента появления ошибок).
Извините, упустил немаловажный момент. В итоговом скетче, (см. приведенный фрагмент в начале темы) проблема начинается при формировании матрицы HH[12][6], так вот, если уменьшить эту матрицу до HH[12][4] и менее, ВСЯ ПРОГРАММА РАБОТАЕТ! Но начиная с HH[12][5] начинается описанный сбой.
Это всегда так. Человек пересел с мощных компьютеров на маломощные, а "осетра не урезал". Вот и верь сказкам про попаданцев-компьтерщеков, попавших в прошлое СССР, и двигающих науку. Да они как дети, ничего не могут с той техникой.
Здесь выделяется память под матрицу только для того, чтобы в Serial.print не писать
MAG1[i][j] / M_SC[j]
и таких мест полно в коде.
Вообще-то у меня MAG2 используется не только для принтирования.
В общем, понятно, я рассчитывал на общие рекомендации, а у меня ищут локальные ошибки. В этом случае действительно нужно приводить код целиком, а мне не хотелось мучить публику навороченным почти до 3000 строк скетчем, да и, честно признаться, не люблю, когда за меня что-то делают по принципу: отойди, потом срисуешь. Я привык сначала разбираться в проблеме целиком, а потом самому засучивать рукава.
В общем, понятно, я рассчитывал на общие рекомендации, а у меня ищут локальные ошибки.
Ну, вроде ж тут многие, я я в их числе, дали Вам общую рекомендацию: внимательно пересмотреть код. Вон я привёл пример, когда два массива по 800 байтов одну и ту же память заняли - не впечатлило? :)))
Ну, вроде ж тут многие, я я в их числе, дали Вам общую рекомендацию...
Виноват, неверно высказался. В последнем посту я обращался не ко всем, а к участникам, с которыми у меня просто не получилось диалога. Я просто оправдывался в ответ на выявленные частные ошибки и неточности кода, хотя вопрос ставил не в виде просьбы помочь заставить программу работать, а помочь разобраться в источнике проблемы и поиске возможных путей её решения.
Огромную помощь мне оказали, извините, перечислю по алфавиту: Andriano, Arhat109-2, ЕвгенийП, Uni.
Не за что, собственно ничего такого и не было посоветовано. Разве что полностью переработать код. Судя по отдельным наименованиям - это какая-то тригонометрия для гироскопа или магнитометра .. там можно делать все а) в целых числах и б) выкинуть матричное исчисление.
Судя по отдельным наименованиям - это какая-то тригонометрия для гироскопа или магнитометра .. там можно делать все а) в целых числах и б) выкинуть матричное исчисление.
Ответ верен! Но! Вычисления в целых числах привели к переполнению при расчёте обратных матриц, возможно, нужно было бы ввести предварительную "децимацию" - деление, даже на несколько порядков, с последующим восстановлением, но поскольку в начале работы проблем с оперативкой не было, пошёл по более лёгкому пути - float. Второе, что касается матричного исчисления. Где-то наковырял, как без матриц вычислить транспонированную псевдоматрицу от исходной псевдоматрицы, а вот как найти обратную, да ещё [6][6], просто не вижу как!
Сейчас как раз прорабатываю возможность уйти от float, пока так.
P.S. Может, есть методики расчёта вообще без матриц, но таковыми не обладаю.
Есть хорошие и не очень новости. Начнём с плохих. Мне не удалось завести ваш пример в Proteus, т.к. в нём нет контроллеров avr с поддержкой usb. Это означает что нельзя промоделировать в точности плату Arduino Leonardo, т.к. она основана на мк ATMega32u4. Также нельзя выйти из положения, если заменить мк на ATmega32, т.к. у последнего как минимум меньше размер ОЗУ, но это полбеды.
В общем, Arduino Leonardo в Proteus 7 нельзя промоделировать.
Но... и тут мы подходим к хорошей новости. Если нас не интересует специфический функционал плат Arduino, а мы пользуемся общими для них функциями, то для целей выяснения работы программы мы можем подобрать мк с похожими ограничениями или вообще выбрать любой мк, если отлаживаем какой-то конкретный функционал, являющийся частью большой программы.
Пока я запустил ваш код на виртуальном клоне Arduino Mega 2560. И, да, он работает и делает вывод каких-то расчётов. См. картинку ниже.
Если нам интересно как происходит работа с памятью, то такой модели, я думаю, может быть достаточно, чтобы выявить ошибки.
Что касается Виртуальной Машины, то она в процессе изготовления. С её помощью можно будет моделировать код так, как это показано на картинке. К сожалению, я пока не придумал простой инструкции по её использованию. Если кто-то захочет отладить свой код подобным образом, то ему придётся немного потрудиться, чтобы понять как всё взаимосвязано.
Если нам интересно как происходит работа с памятью, то такой модели, я думаю, может быть достаточно, чтобы выявить ошибки.
Что касается Виртуальной Машины, то она в процессе изготовления. С её помощью можно будет моделировать код так, как это показано на картинке.
Да, жаль, что Леонардо пришёлся не ко двору, я в своей работе часто использую да просто для проверки идей на Ардуине, а обкатку делаю на железе с ATmega32U4 соответственно для полного соответствия. Пороюсь в новых версиях Proteus, вдруг там его "пригрели".
Но для решения моей проблемы я готов пересесть хоть на чёрта лысого ( :)) ), лишь бы получить хотя бы приблизительный результат.
А что даст Виртуальная Машина дополнительно к тому, что Вы получили на Proteus? Если там так же, "как это показано на картинке".
Вы бы задачу изложили, хотя бы словами какой датчик, что измеряет, что хотите получить матричным исчислением. Помнится расчет углов опережения по авиационной цели считался на компах куда как слабее дунек, в гражданке звавшихся Д3-28...
Сама виртуальная машина нужна только для того, чтобы всё ПО для отладки было собрано в одном месте.
Сам я, кстати, делаю наоборот - код проверяю, если возможно, в Proteus, а уже потом на реальном железе, т.к. порой и железа ещё нет и платы не куплены, а посмотреть как работает хочется.
Ещё можно узнать почему не работает сторонний код, взятый из сети, опять же, если в Proteus можно создать прототип устройства. Конкретно в вашем случае можно наглядно посмотреть растёт ли куча и движется ли она в сторону стека. Я специально привёл окно, которое показывает содержимое SRAM. Там видны данные, а где их нет (в старших адресах) - там нули. Можно запустить программу на выполнение и через некоторое время остановить, потом посмотреть содержимое SRAM. Так можно косвенно определить явные проблемы с памятью.
В общем, когда потеряна уже всякая надежда отладить код при помощи терминала, можно это сделать при помощи виртуального отладчика.
Что касается Proteus. Можно отлаживать довольно сложные схемы, включающие работу с индикаторами, SD-картой, внешними ИМС типа RTC и пр. Более того, виртуальный контроллер через реальный COM-порт можно связать с реальным устройством, либо программой. Я так изучал работу библиотеки freemodbus. Она сложная и без отладчика понять её работу очень не просто, поэтому я залил её в виртуальный контроллер и по шагам смотрел что делает код. С Ардуино такое сделать практически невозможно (только если есть оригинальный отладчик, но и с ним не всё так просто).
Вот, кстати, в соседней теме у человека проблема, не знает в чём дело и код даже полностью привёл. В Proteus его схему можно промоделировать целиком, включая реакцию на геркон и вывод на дисплей. Но у меня пока нет наработок на все случаи жизни и сразу завести его схему я не могу. А была бы виртуальная машина с набором типовых схем, то можно было в раз набросать и посмотреть что там не так.
Что касается Proteus. Можно отлаживать довольно сложные схемы, включающие работу с индикаторами, SD-картой, внешними ИМС типа RTC и пр.
Вы инициировали во мне желание заняться Proteus вплотную. Я забросил его однажды, когда занимался цифровой фильтрацией. Тогда он меня разочаровал, возможно, из-за недостатка времени на его изучение.
А что Вы скажете об AStudio? Он у меня в плане пока первым по списку.
Да не люблю лишний раз напрягать людей своими заморочками. Только в случае длительных затыков.
А так - ничего особенного: магнитометр с акселерометром, но в отличие от моих прежних наработок этот случай особый из-за высоких требований к точности, что привело к созданию сложных алгоритмов калибровки. Отсюда рост объёма и сложности программы. А ведь я ещё не впихнул туда фильтр Калмана, но это уже в следующем образце с другим камнем.
В таком разе может есть смысл перебраться на Мега2560? Там все-таки 8 килов оперативы. Или может сразу искать проц с вещественной арифметикой, не? Какой смысл в запиливании задачи в таком виде на камне, в целом не предназначенном для её решения?
Если под AStudio понимается Atmel Studio, то я этой средой не пользуюсь в виду того, что это не имеет смысла без отладчика. Тот же самый код я могу писать и в Visual Studio. До сих пор пользуюсь AVR Studio, так как к ней можно подключить самодельный отладчик HappyJtag 2.
Что касается цифровых алгоритмов, то их тоже можно и нужно сначала моделировать. К примеру, я проверял работу программы прямого цифрового синтеза на AVR (AVR DDS2), очень удобно эмулировать, так как это проще постоянной перепрошивки мк.
В таком разе может есть смысл перебраться на Мега2560? Там все-таки 8 килов оперативы. Или может сразу искать проц с вещественной арифметикой, не? Какой смысл в запиливании задачи в таком виде на камне, в целом не предназначенном для её решения?
Я собирался перебираться на AT91SAM3X8E, и прикупить к нему Arduino Due для отладки. А вот проц с вещественной арифметикой не рассматривал, как-то не стыковался доселе. У вас есть что-нибудь для "подтолкнуть", или сразу к старику Гуглу?
Если под AStudio понимается Atmel Studio, то я этой средой не пользуюсь в виду того, что это не имеет смысла без отладчика. Тот же самый код я могу писать и в Visual Studio. До сих пор пользуюсь AVR Studio, так как к ней можно подключить самодельный отладчик HappyJtag 2.
Что касается цифровых алгоритмов, то их тоже можно и нужно сначала моделировать. К примеру, я проверял работу программы прямого цифрового синтеза на AVR (AVR DDS2), очень удобно эмулировать, так как это проще постоянной перепрошивки мк.
AStudio и Atmel Studio почти синонимы, кажется, разница лишь в версиях. Я не прав?
Atmel Studio в своей основе имеет Visual Studio, а по крайней мере 6-я версия (какая у меня) имеет опцию для Arduino, я пока не разбирался, только код для симулятора, или уже использовать как отладчик.
С AVR DDS2 и вовсе не знаком. Что за зверь? Если ещё не утомил.
А так - ничего особенного: магнитометр с акселерометром, но в отличие от моих прежних наработок этот случай особый из-за высоких требований к точности, что привело к созданию сложных алгоритмов калибровки. Отсюда рост объёма и сложности программы. А ведь я ещё не впихнул туда фильтр Калмана, но это уже в следующем образце с другим камнем.
Калибровать нужно при каждом включении? Может быть обработу на большой компьютер отдать, а сюда только калибровочные коэффициенты для работы вносить один раз?
Калибровать нужно при каждом включении? Может быть обработу на большой компьютер отдать, а сюда только калибровочные коэффициенты для работы вносить один раз?
Нет, конечно, калибровка производится один раз, в дальнейшем при необходимости и согласно регламенту при поверках.
Идея взвалить большую математику на ПК уже витает в воздухе, но это пока третий план.
Porter, массивы всегда должны быть в активном состоянии? Если нет, то может попробовать воспользоваться malloc() и free(), так можно в одном и том же пространстве ОЗУ работать с разными массивами.
Porter, массивы всегда должны быть в активном состоянии? Если нет, то может попробовать воспользоваться malloc() и free(), так можно в одном и том же пространстве ОЗУ работать с разными массивами.
Да я и использую динамические массивы, чем и поднимаю "кучу". Использованные массивы сразу очищаю (что не очевидно из приведенного модуля, за что уже получил подзатыльник :) )
А чем, ради увеличения памяти, не устраивает стандартный и2с еепром от Атмела? Он 256 Кбит = 32КБайта, скорость по и2с до 1000КГц.
Например на 800КГц вы 2 кбайта памяти поменяете за 40 мс. Стоит эта фигня на Али 60р.
Вот я очень ждал подобного предложения. МОЖНО ЛИ К ATmega32U4 как-то присобачить какую-нибудь приблуду для увеличения оперативки? В случае с XRAM всё ясно, но это для камней типа ATmega128. А в моём случае кроме ампутации головы есть что-нибудь?
Ваше предложение годится для моего случая, или тоже через "ампутацию"?
В этом случае часть данных ... сбрасывавется в файл на SD, а на освободтвшемся месте размещается требуемый массив. Когда надобность в новом массиве отпадет, данные читаются с SD на прежнее место.
Общо понятно, а не поделитесь каким-нибудь примерчиком? Не встречал ещё ничего подобного.
swap файл в avr - круто :) Хотя скорее это сарказм. Нет, нет, наверное еще не маразм, раз кто-то это использует.
Mega - стоит 400 руб. С бесплатной доставкой. Если сейчас закажите, то через месяц решите свою проблему. Или рассказывайте задачу, и народ посоветует как экономить память. Других вариантов нет.
Сложный случай, запущенный. Да еще и без открытого кода. Пробуйте так.
1. Убедитесь что памяти действительно нехватает, что именно стеком затирает, а не стрельба по памяти. Полезно уяснить в какой цепочке вызовов происходит лажа.
2. Если активно используете прерывания - попробуйте позапрещать их при входе в длинную цепь. Может нашару и решите.
3.Алгоритмическая оптимизация - все ли буферы промежуточных реально нужны, может некоторые проще не хранить, а заново расчитывать? Подумать про обработку данных по цепочке, без буферов. Плавающую точку поубирать по макмимуму. Проконтролировать где излишки точности и исправить.
4. Приведеный фрагмент кода, там где case 221:.. сильно намекает что все в коде очень плохо. Не все что матрица в математике стоит в массив пихать.
ПС. Более конкретные советы могут быть только после просмотра кода.
Если есть интерес, я создам отдельную тему на этот счёт. У меня на ПК "развёрнута" такая машина и я пользуюсь её функционалом, в т.ч. для ответов здесь (если полностью приведён код программы).
Вот рабочая прога, которую я затем использовал как модуль в своём скетче. Что скажет Ваша машина?
Вечером только смогу посмотреть, т.к. "отладчик" дома развёрнут. Если до этого вам тут не найдут ошибки, я промоделирую ваш код и скажу в чём дело.
Вечером только смогу посмотреть, т.к. "отладчик" дома развёрнут. Если до этого вам тут не найдут ошибки, я промоделирую ваш код и скажу в чём дело.
Повторюсь, этот скетч - лишь работающий модуль моего скетча, в нём НИКАКИХ проблем не обнаружил. Привёл для того, чтобы познакомиться с работой Вашей машины.
Конечно, более грамотные спецы что-нибудь наковырют для оптимизации этого кода, за что им буду благодарен, ессно.
Тогда я могу сделать по-другому. Если хотите, могу дать эту виртуальную машину (для определённости, назовём её Arduino Virtual Debug Machine - Виртуальная Машина Отладки Arduino) и показать как на ней отлаживать ваш демо-пример, а дальше вы уже сами разберётесь.
... показать как на ней отлаживать ваш демо-пример, а дальше вы уже сами разберётесь.
А я, вроде, как раз об этом.
Ну йолы палы! Вот в 59 строке у Вас посчиталась М, затем она использовалась в стр 64 и все, больще нигде не задействована. Зачем под ней память держать до конца? Конечно памяти ненапасетесь! Есть 2 варианта - освобождать как перестала быть нужной (но про фрагментацию кучи думать, в каком порядке распределять и освобождать!!) и повторно использовать в следующих вычеслениях.
Ну йолы палы! Вот в 59 строке у Вас посчиталась М, затем она использовалась в стр 64 и все, больще нигде не задействована. Зачем под ней память держать до конца?
Простите, а в строке 150 она не очищается?
Корректирую. Понял Вашу мысль. Когда петух клюнул, куда надо, я подправил места очищения переменных. Извините, что ввёл Вас в заблуждение этим скетчем. В данном случае М очистил сразу после её использования.
Простите, а в строке 150 она не очищается?
Корректирую. Понял Вашу мысль. Когда петух клюнул, куда надо, я подправил места очищения переменных. Извините, что ввёл Вас в заблуждение этим скетчем. В данном случае М очистил сразу после её использования.
Ну, там ещё много всего. Например,
В этом случае очищать специальной командой типа DelMatr(M) уже не нужно, если заключить в фигурные скобки, или я не правильно понял? Можно небольшой пример записи?
В этом случае очищать специальной командой типа DelMatr(M) уже не нужно
Нет, конечно, Вы же её не запрашивали! Я имею в виду строки 103 и 128 (может ещё где есть, но эти - точно). Вы же здесь не запрашивали память, так как же Вы её будете освобождать.
Вот Вы написали.
Теперь эта матрица будет занимать место на стеке вплоть до ближайшей открытой } Т.е. в Вашем случае до строки 154.
Стеком можно управлять. Например:
Этот приём Вам ничего не стоит. Всё, что было объявлено вне блока (выше) доступно и в нём. Нужно только следить, чтобы в блоке не оказались объявленными какие-то переменные. которые нужны и после. Если таковые найдутся. их объявление нужно вынести выше блока.
Нет, конечно, Вы же её не запрашивали! Я имею в виду строки 103 и 128 ...
Вот это для меня находка!
Большое спасибо, хоть это и не решит мою конкретную проблему, но намного улучшит мои скетчи!
Тут есть в разделе "Общий" пример успешного решения для расширения SRAM на +32 килобайт и мой проект расширителя на +512 килобайт. Но такие расширители или платы в с памятью Вам придется изготавливать практически самостоятельно.
Я не смог найти этот пример. Подскажите, пжлст, как его найти.
Спасибо.
Вот Вы написали.
Теперь эта матрица будет занимать место на стеке вплоть до ближайшей открытой }
А откуда следует, что вместе с окончанием области видимости одновременно и освобождается стек? По крайней мере, такое решение проигрывает как по производительности, так и по объему кода.
PS. Посмотрел в коде: стек оно, коначно, распределяет и освобождает только в начале и конце тела функции, в середине никакого перераспределения нет. Но объем в стеке выделяет, учитывая, пересекаются ли области видимости. Вопрос: регламентируется ли такое поведение или оно зависит от реализации компилятора (или его настроек).
swap файл в avr - круто :) Хотя скорее это сарказм. Нет, нет, наверное еще не маразм, раз кто-то это использует.
А Вам достоверно известно, что это кто-то использует?
Просто ТС, похоже, не верит на слово, что в его случае самое оптимальное решение - сменить камень на что-то помощнее. Вот мне и захотелось, чтобы он пришел к этой мысли самостоятельно, взвесив все альтернативы.
Просто ТС, похоже, не верит на слово, что в его случае самое оптимальное решение - сменить камень на что-то помощнее. Вот мне и захотелось, чтобы он пришел к этой мысли самостоятельно, взвесив все альтернативы.
Иногда можно изменить алгоритм и больший камень не потребуется.
PS. Посмотрел в коде: стек оно, коначно, распределяет и освобождает только в начале и конце тела функции, в середине никакого перераспределения нет. Но объем в стеке выделяет, учитывая, пересекаются ли области видимости. Вопрос: регламентируется ли такое поведение или оно зависит от реализации компилятора (или его настроек).
Это сложный вопрос. Вернее, откуда следует – это то как раз просто – из п. 6.7.2 стандарта языка. А сложность вот в чём. Стандарт не определяет работу со стеком (более того, он даже не требует, чтобы локальные переменные хранились на стеке) он лишь требует, чтобы переменные «уничтожались» при выходе из блока.
Поэтому компиляторы ведут себя так:
1. Для экземпляров классов, у которых имеется деструктор с побочным эффектом – деструктор вызывается немедленно по достижении }, что кстати прямо следует из того самого п. 6.7.2 (пруфскетч №1 ниже). Это правило железное для всех компиляторов, и ни от каких опций не зависит. У него есть тонкости связанные с обработкой прерываний, мы не будем туда лезть.
пруфскетч №1 – освобождение объекта с деструктором
Заметьте, деструктор вызван между точками №2 и №3, т.е. точно на }
2. Во всех остальных случаях действует такое правило: по достижению конца блока переменная должна быть освобождена, но делать это или нет и как именно делать – отдаётся на откуп компилятору (вернее, оптимизатору). Главное, чтобы это не влияло на поведение программы и она вела бы себя так, как будто всё освобождается.
Конкретно в нашем GCC пошли ещё дальше. Вместо «освобождения стека» они ввели понятие «повторное использование стека» (stack reusing), которое позволяет «освободить» стек даже до того, как закончился блок, если компилятор посчитает, это эта переменная больше не нужна. Управляется всё это опциями оптимизатора (см.). Но на деле он не освобождает стек, а хапает его сразу на всю функцию (что Вы и наблюдали), но при этом повторно использует его куски по мере того, как переменные становятся не нужны (например, блок закончился или оптимизатор решил, что они больше не нужны).
С точки зрения поведения программы это тоже самое, как если бы он его освобождал. Поэтому я и говорю об освобождении - просто проще говорить в такой парадигме, а с точки зрения логики программы это верно.
Например, то, что я написал ТС абсолютно верно. См. пруфскетч №2 – «освобождение» стека по }
Заметьте, у этих двух массивов просто один и тот же адрес, т.е. второй просто лёг поверх первого. Чем это не «освобождение»?
Важное замечание после перечитывания поста .... утром перепроверил и удалил замечание, всё там нормально.
Тема http://arduino.ru/forum/obshchii/atmega-128a-au-vneshnyaya-sram-62256-74... находится поиском по запросу "расширенная память". Это вариант добавления SRAM ко всем вариантам микроконтроллеров, оснащенных x-bus интерфейсом. При добавлении до 64к - никаких специальных мер особо применять не придется. Надо будет только в настройках компиляции платы указать предельный размер памяти и можно уточнить положение стека и кучи, для повышения скорости работы с ним. Как - тут уже есть намеки. Но, это путь "изготовления своей платы".
В вашем примере, уже много сказано как его улучшить. Кардинальное улучшение возможно, если тщательно пересмотреть код и отказаться от типовых "матричных вычислений", заменив их прямыми циклами, без накопления промежуточных матриц и вовсе. Но, это достаточно объемная и кропотливая работа.
Peotr, выведите в терминал адреса, получаемые при динамическом выделении памяти (до момента появления ошибок).
Извините, упустил немаловажный момент. В итоговом скетче, (см. приведенный фрагмент в начале темы) проблема начинается при формировании матрицы HH[12][6], так вот, если уменьшить эту матрицу до HH[12][4] и менее, ВСЯ ПРОГРАММА РАБОТАЕТ! Но начиная с HH[12][5] начинается описанный сбой.
Вот я и подозреваю слияние стека с кучей.
Здесь выделяется память под матрицу только для того, чтобы в Serial.print не писать
и таких мест полно в коде.
и таких мест полно в коде.
Это всегда так. Человек пересел с мощных компьютеров на маломощные, а "осетра не урезал". Вот и верь сказкам про попаданцев-компьтерщеков, попавших в прошлое СССР, и двигающих науку. Да они как дети, ничего не могут с той техникой.
Здесь выделяется память под матрицу только для того, чтобы в Serial.print не писать
и таких мест полно в коде.
Вообще-то у меня MAG2 используется не только для принтирования.
В общем, понятно, я рассчитывал на общие рекомендации, а у меня ищут локальные ошибки. В этом случае действительно нужно приводить код целиком, а мне не хотелось мучить публику навороченным почти до 3000 строк скетчем, да и, честно признаться, не люблю, когда за меня что-то делают по принципу: отойди, потом срисуешь. Я привык сначала разбираться в проблеме целиком, а потом самому засучивать рукава.
Всем спасибо.
В общем, понятно, я рассчитывал на общие рекомендации, а у меня ищут локальные ошибки.
Ну, вроде ж тут многие, я я в их числе, дали Вам общую рекомендацию: внимательно пересмотреть код. Вон я привёл пример, когда два массива по 800 байтов одну и ту же память заняли - не впечатлило? :)))
Ну, вроде ж тут многие, я я в их числе, дали Вам общую рекомендацию...
Виноват, неверно высказался. В последнем посту я обращался не ко всем, а к участникам, с которыми у меня просто не получилось диалога. Я просто оправдывался в ответ на выявленные частные ошибки и неточности кода, хотя вопрос ставил не в виде просьбы помочь заставить программу работать, а помочь разобраться в источнике проблемы и поиске возможных путей её решения.
Огромную помощь мне оказали, извините, перечислю по алфавиту: Andriano, Arhat109-2, ЕвгенийП, Uni.
Большое спасибо ВСЕМ за помощь и внимание.
Не за что, собственно ничего такого и не было посоветовано. Разве что полностью переработать код. Судя по отдельным наименованиям - это какая-то тригонометрия для гироскопа или магнитометра .. там можно делать все а) в целых числах и б) выкинуть матричное исчисление.
Судя по отдельным наименованиям - это какая-то тригонометрия для гироскопа или магнитометра .. там можно делать все а) в целых числах и б) выкинуть матричное исчисление.
Ответ верен! Но! Вычисления в целых числах привели к переполнению при расчёте обратных матриц, возможно, нужно было бы ввести предварительную "децимацию" - деление, даже на несколько порядков, с последующим восстановлением, но поскольку в начале работы проблем с оперативкой не было, пошёл по более лёгкому пути - float. Второе, что касается матричного исчисления. Где-то наковырял, как без матриц вычислить транспонированную псевдоматрицу от исходной псевдоматрицы, а вот как найти обратную, да ещё [6][6], просто не вижу как!
Сейчас как раз прорабатываю возможность уйти от float, пока так.
P.S. Может, есть методики расчёта вообще без матриц, но таковыми не обладаю.
Спасибо.
Есть хорошие и не очень новости. Начнём с плохих. Мне не удалось завести ваш пример в Proteus, т.к. в нём нет контроллеров avr с поддержкой usb. Это означает что нельзя промоделировать в точности плату Arduino Leonardo, т.к. она основана на мк ATMega32u4. Также нельзя выйти из положения, если заменить мк на ATmega32, т.к. у последнего как минимум меньше размер ОЗУ, но это полбеды.
В общем, Arduino Leonardo в Proteus 7 нельзя промоделировать.
Но... и тут мы подходим к хорошей новости. Если нас не интересует специфический функционал плат Arduino, а мы пользуемся общими для них функциями, то для целей выяснения работы программы мы можем подобрать мк с похожими ограничениями или вообще выбрать любой мк, если отлаживаем какой-то конкретный функционал, являющийся частью большой программы.
Пока я запустил ваш код на виртуальном клоне Arduino Mega 2560. И, да, он работает и делает вывод каких-то расчётов. См. картинку ниже.
Если нам интересно как происходит работа с памятью, то такой модели, я думаю, может быть достаточно, чтобы выявить ошибки.
Что касается Виртуальной Машины, то она в процессе изготовления. С её помощью можно будет моделировать код так, как это показано на картинке. К сожалению, я пока не придумал простой инструкции по её использованию. Если кто-то захочет отладить свой код подобным образом, то ему придётся немного потрудиться, чтобы понять как всё взаимосвязано.
П.С. Картинка большого размера (ссылка).
Если нам интересно как происходит работа с памятью, то такой модели, я думаю, может быть достаточно, чтобы выявить ошибки.
Что касается Виртуальной Машины, то она в процессе изготовления. С её помощью можно будет моделировать код так, как это показано на картинке.
Да, жаль, что Леонардо пришёлся не ко двору, я в своей работе часто использую да просто для проверки идей на Ардуине, а обкатку делаю на железе с ATmega32U4 соответственно для полного соответствия. Пороюсь в новых версиях Proteus, вдруг там его "пригрели".
Но для решения моей проблемы я готов пересесть хоть на чёрта лысого ( :)) ), лишь бы получить хотя бы приблизительный результат.
А что даст Виртуальная Машина дополнительно к тому, что Вы получили на Proteus? Если там так же, "как это показано на картинке".
Вы бы задачу изложили, хотя бы словами какой датчик, что измеряет, что хотите получить матричным исчислением. Помнится расчет углов опережения по авиационной цели считался на компах куда как слабее дунек, в гражданке звавшихся Д3-28...
Сама виртуальная машина нужна только для того, чтобы всё ПО для отладки было собрано в одном месте.
Сам я, кстати, делаю наоборот - код проверяю, если возможно, в Proteus, а уже потом на реальном железе, т.к. порой и железа ещё нет и платы не куплены, а посмотреть как работает хочется.
Ещё можно узнать почему не работает сторонний код, взятый из сети, опять же, если в Proteus можно создать прототип устройства. Конкретно в вашем случае можно наглядно посмотреть растёт ли куча и движется ли она в сторону стека. Я специально привёл окно, которое показывает содержимое SRAM. Там видны данные, а где их нет (в старших адресах) - там нули. Можно запустить программу на выполнение и через некоторое время остановить, потом посмотреть содержимое SRAM. Так можно косвенно определить явные проблемы с памятью.
В общем, когда потеряна уже всякая надежда отладить код при помощи терминала, можно это сделать при помощи виртуального отладчика.
Что касается Proteus. Можно отлаживать довольно сложные схемы, включающие работу с индикаторами, SD-картой, внешними ИМС типа RTC и пр. Более того, виртуальный контроллер через реальный COM-порт можно связать с реальным устройством, либо программой. Я так изучал работу библиотеки freemodbus. Она сложная и без отладчика понять её работу очень не просто, поэтому я залил её в виртуальный контроллер и по шагам смотрел что делает код. С Ардуино такое сделать практически невозможно (только если есть оригинальный отладчик, но и с ним не всё так просто).
Вот, кстати, в соседней теме у человека проблема, не знает в чём дело и код даже полностью привёл. В Proteus его схему можно промоделировать целиком, включая реакцию на геркон и вывод на дисплей. Но у меня пока нет наработок на все случаи жизни и сразу завести его схему я не могу. А была бы виртуальная машина с набором типовых схем, то можно было в раз набросать и посмотреть что там не так.
Что касается Proteus. Можно отлаживать довольно сложные схемы, включающие работу с индикаторами, SD-картой, внешними ИМС типа RTC и пр.
Вы инициировали во мне желание заняться Proteus вплотную. Я забросил его однажды, когда занимался цифровой фильтрацией. Тогда он меня разочаровал, возможно, из-за недостатка времени на его изучение.
А что Вы скажете об AStudio? Он у меня в плане пока первым по списку.
Вы бы задачу изложили...
Да не люблю лишний раз напрягать людей своими заморочками. Только в случае длительных затыков.
А так - ничего особенного: магнитометр с акселерометром, но в отличие от моих прежних наработок этот случай особый из-за высоких требований к точности, что привело к созданию сложных алгоритмов калибровки. Отсюда рост объёма и сложности программы. А ведь я ещё не впихнул туда фильтр Калмана, но это уже в следующем образце с другим камнем.
В таком разе может есть смысл перебраться на Мега2560? Там все-таки 8 килов оперативы. Или может сразу искать проц с вещественной арифметикой, не? Какой смысл в запиливании задачи в таком виде на камне, в целом не предназначенном для её решения?
Если под AStudio понимается Atmel Studio, то я этой средой не пользуюсь в виду того, что это не имеет смысла без отладчика. Тот же самый код я могу писать и в Visual Studio. До сих пор пользуюсь AVR Studio, так как к ней можно подключить самодельный отладчик HappyJtag 2.
Что касается цифровых алгоритмов, то их тоже можно и нужно сначала моделировать. К примеру, я проверял работу программы прямого цифрового синтеза на AVR (AVR DDS2), очень удобно эмулировать, так как это проще постоянной перепрошивки мк.
В таком разе может есть смысл перебраться на Мега2560? Там все-таки 8 килов оперативы. Или может сразу искать проц с вещественной арифметикой, не? Какой смысл в запиливании задачи в таком виде на камне, в целом не предназначенном для её решения?
Я собирался перебираться на AT91SAM3X8E, и прикупить к нему Arduino Due для отладки. А вот проц с вещественной арифметикой не рассматривал, как-то не стыковался доселе. У вас есть что-нибудь для "подтолкнуть", или сразу к старику Гуглу?
Если под AStudio понимается Atmel Studio, то я этой средой не пользуюсь в виду того, что это не имеет смысла без отладчика. Тот же самый код я могу писать и в Visual Studio. До сих пор пользуюсь AVR Studio, так как к ней можно подключить самодельный отладчик HappyJtag 2.
Что касается цифровых алгоритмов, то их тоже можно и нужно сначала моделировать. К примеру, я проверял работу программы прямого цифрового синтеза на AVR (AVR DDS2), очень удобно эмулировать, так как это проще постоянной перепрошивки мк.
AStudio и Atmel Studio почти синонимы, кажется, разница лишь в версиях. Я не прав?
Atmel Studio в своей основе имеет Visual Studio, а по крайней мере 6-я версия (какая у меня) имеет опцию для Arduino, я пока не разбирался, только код для симулятора, или уже использовать как отладчик.
С AVR DDS2 и вовсе не знаком. Что за зверь? Если ещё не утомил.
А так - ничего особенного: магнитометр с акселерометром, но в отличие от моих прежних наработок этот случай особый из-за высоких требований к точности, что привело к созданию сложных алгоритмов калибровки. Отсюда рост объёма и сложности программы. А ведь я ещё не впихнул туда фильтр Калмана, но это уже в следующем образце с другим камнем.
Калибровать нужно при каждом включении? Может быть обработу на большой компьютер отдать, а сюда только калибровочные коэффициенты для работы вносить один раз?
Калибровать нужно при каждом включении? Может быть обработу на большой компьютер отдать, а сюда только калибровочные коэффициенты для работы вносить один раз?
Нет, конечно, калибровка производится один раз, в дальнейшем при необходимости и согласно регламенту при поверках.
Идея взвалить большую математику на ПК уже витает в воздухе, но это пока третий план.
Porter, массивы всегда должны быть в активном состоянии? Если нет, то может попробовать воспользоваться malloc() и free(), так можно в одном и том же пространстве ОЗУ работать с разными массивами.
Создал отдельную тему про виртуальную отладочную машину. Все вопросы по отладке конкретных скетчей можно перенести туда.
Да, к сожалению, могу только отправить в Гугль. .. погуглил сам и как-то его выдача несколько "странновата".
Porter, массивы всегда должны быть в активном состоянии? Если нет, то может попробовать воспользоваться malloc() и free(), так можно в одном и том же пространстве ОЗУ работать с разными массивами.
Да я и использую динамические массивы, чем и поднимаю "кучу". Использованные массивы сразу очищаю (что не очевидно из приведенного модуля, за что уже получил подзатыльник :) )
Спасибо.
Вы работаете с MPU-6050 и отдельным магнетометром?
А чем, ради увеличения памяти, не устраивает стандартный и2с еепром от Атмела? Он 256 Кбит = 32КБайта, скорость по и2с до 1000КГц.
Например на 800КГц вы 2 кбайта памяти поменяете за 40 мс. Стоит эта фигня на Али 60р.
А чем, ради увеличения памяти, не устраивает стандартный и2с еепром от Атмела? Он 256 Кбит = 32КБайта, скорость по и2с до 1000КГц.
Например на 800КГц вы 2 кбайта памяти поменяете за 40 мс. Стоит эта фигня на Али 60р.
Вот я очень ждал подобного предложения. МОЖНО ЛИ К ATmega32U4 как-то присобачить какую-нибудь приблуду для увеличения оперативки? В случае с XRAM всё ясно, но это для камней типа ATmega128. А в моём случае кроме ампутации головы есть что-нибудь?
Ваше предложение годится для моего случая, или тоже через "ампутацию"?
Спасибо.
Вы работаете с MPU-6050 и отдельным магнетометром?
ADIS16210 и FLC3-70