Хорошо объяснюсь по порядку. Изначально пишу на основе уже существующего кода. Код меня много в чем не устраивает особенно тем что построен на куче case для прокрутке меню и десятке использований millis для кнопок когда можно для этого использовать библиотеку. Один подпункт меню у меня будет аналогично сделанному на casах: каждое нажатие кнопки обновляет информацию на экране так что ДОПУСТИМ обновляется строка "STEPS" и соответственно ей переменная profileSteps, следующее нажатие "RAMP: " и double rampRateStep[9]; и т д
Перечислю их
// заданы в виде массива
double rampRateStep[9];
int temperatureStep[9];
int dwellTimerStep[9];
//
int pwr_TOP, pwr_BOTTOM;
int profileSteps;
int Setpoint2;
double kp1, kd1, ki1; // возможно int
double kp2, kd2, ki2; // возможно int
Переменные имеют разный тип поэтому удобно их обработать через структуру
Тестовый код
// TEST
#include <avr/pgmspace.h>
char buf[8];
struct station {
double rampRateStep[9];
int temperatureStep[9];
int dwellTimerStep[9];
int pwr_TOP, pwr_BOTTOM;
int profileSteps;
int Setpoint2;
double kp1, kd1, ki1; // возможно int
double kp2, kd2, ki2; // возможно int
};
const char string_0[] PROGMEM = "STEPS ";
const char string_1[] PROGMEM = "B.HEAT";
const char string_2[] PROGMEM = "T.HEAT";
const char string_3[] PROGMEM = "B.PWR ";
const char string_4[] PROGMEM = "T.PWR ";
const char string_5[] PROGMEM = "RAMP: ";
const char string_6[] PROGMEM = "TARGET ";
const char string_7[] PROGMEM = "DWELL ";
const char *const text[] PROGMEM = { string_0, string_1, string_2, string_3, string_4, string_5, string_6, string_7 };
void setup () {
Serial.begin(9600);
} // void setup()
void loop() {
while (!Serial.available());
byte s = Serial.read()-'0'; // Жмем кнопки 0 - 5.
function(s);
} // void loop()
void function (const uint8_t n) {
station reflow;
strcpy_P(buf, (char*)pgm_read_word(&(text[n])));
Serial.print(buf);
//Serial.print(reflow.Setpoint2);
}
Моя идея решения простая: создается функция и в нужном месте вызывается и достаточно. Но решена проблема только со строками. Переменные имеют разный тип и некоторые заданы в виде массива, я это показал. А значит и возника идея в нумерации элементов структуры чтобы затем этот номер и передавать функции чтобы затем по номеру вернуть искомую переменную и ее вывести. Плодить if не хочу
ЕвгенийП пишет:
Я правда не понимаю, что Вам нужно. Все нормальные люди в такой ситуации пишут пачку ифов. Если Вы хотите работать как с массивом, Вам нужно менть организацию данных. Если Вы хотите спрятать печать и писать её в одном месте, Вам надо что структура сама себя печатала через интерфейст Printable. Чего Вам надо то?
Плодить if не хочу. Возможно вы хотели сказать что можно в одном месте печатать струтуру, расскажите подробнее. Да вызов функции необязателен мне просто нужно будет по нажатию печатать элемент затем по следующему уже другой элемент то есть печатать элементы структуры в порядке очереди. Очередь задается нажатием
ЕвгенийП, в этой ветке упоминалось что возможно добавить такую функциональность в класс LCD. Подскажите каким образом, на основе вашего же кода? Заранее спасибо
struct SSensorValue : public Printable {
unsigned long timeStamp; // Время съёма показаний (мс от запуска МК)
float temperture; // температура в градусах С
float humidity; // влажность в %
float pressure; // давление в мм.рт.ст.
size_t printTo(Print& p) const { // в качестве p нам передадут, например, Serial
size_t res = p.print("SENSOR VALUE: Time:");
res += p.print(timeStamp);
res += p.print("ms; T:");
res += p.print(temperture);
res += p.print("C; H:");
res += p.print(humidity);
res += p.print("%; P:");
res += p.print(pressure);
return res + p.println("mm");
}
};
void setup() {
Serial.begin(115200);
Serial.println("Fun begins!");
//
// Объявляем структуру и заполняем какими-то значениями
//
SSensorValue sv;
sv.timeStamp = millis();
sv.temperture = 36.6;
sv.humidity = 93.2;
sv.pressure = 755;
//
// Печатаем структуру
//
Serial.print(sv);
}
void loop() {}
Да это возможно. Дальше уже через if буду выводить как мне нужно. Нужно было раньше найти ваши этюды, помогло
Возник неприятная проблема: если метод вызывается в функции setup() все работает. Как только переношу его в loop() отказывается что либо выводить. Направьте
PS Евгений чтобы у вас потом вопросов не возникало добавлю. К вашему коду претензий не имею но вы в примере:
ЕвгенийП пишет:
Давайте это напишем:
struct SSensorValue : public Printable {
unsigned long timeStamp; // Время съёма показаний (мс от запуска МК)
float temperture; // температура в градусах С
float humidity; // влажность в %
float pressure; // давление в мм.рт.ст.
size_t printTo(Print& p) const { // в качестве p нам передадут, например, Serial
size_t res = p.print("SENSOR VALUE: Time:");
res += p.print(timeStamp);
res += p.print("ms; T:");
res += p.print(temperture);
res += p.print("C; H:");
res += p.print(humidity);
res += p.print("%; P:");
res += p.print(pressure);
return res + p.println("mm");
}
};
void setup() {
Serial.begin(115200);
Serial.println("Fun begins!");
//
// Объявляем структуру и заполняем какими-то значениями
//
SSensorValue sv;
sv.timeStamp = millis();
sv.temperture = 36.6;
sv.humidity = 93.2;
sv.pressure = 755;
//
// Печатаем структуру
//
Serial.print(sv);
}
void loop() {}
Вот так! Обратите внимание: в строке 1 мы указали, что наша структура поддерживает интерфейс Printable, а в строках 7-17 мы реализовали необходимый для этого интерфейса метод printTo. Теперь, мы можем просто писать Serial.print(sv) (строка 34) и система поймёт, чтов этот момент надо просто вызвать наш метод, а он всё. что нужно, напечатает. Причём напечатает не тупо в Serial, а именно в тот поток, для которого он был вызван.
Если Вы запустите этот скетч, то он спокойно скомпилируется и в сериале Вы увидите:
Fun begins!
SENSOR VALUE: Time:0ms; T:36.60C; H:93.20%; P:755.00mm
Организовали метод SSensorValue, для вывода показаний с датчика и сделали вывод в setup(). Да но в моем случае меню логичнее сделать это в loop() поскольку показания постоянно обновляются (нужно часто настраивать). Если перенести это в функцию вызваемую из loop() не работает, не пойму почему
В Вышем коде я не вижу вызова этого метода (всё закоментировано, а то, что заскомментировано - то написано неправильно).
Вот у Вас же есть строки 69-76.
Вставьте такие же в loop (для начала в точности такие же) и больше ничего. Убедитесь, что работает. Потом попробуйте что Вам надо. Если не получится, то покажите код. Но именно неработающий код, а не кучу комментариев.
А от так, строки у тебя будут лежать в PROGMEM, а массив нет. Ну, для конкретно этого массива, думаю, 10 байт (число строк * размер указателя) в ОЗУ не жалко, но, если нада больше строк, то его тоже можно во флэш запхать. Только читать потом придёца специальным образом.
А от так, строки у тебя будут лежать в PROGMEM, а массив нет. Ну, для конкретно этого массива, думаю, 10 байт (число строк * размер указателя) в ОЗУ не жалко, но, если нада больше строк, то его тоже можно во флэш запхать. Только читать потом придёца специальным образом.
да, строк будет много, поэтому с прогмем и хочу заморочиться. Тот пример, что ты написал, в принципе у меня уже работает, (только и массив в прогмем). Но суть вопроса с твоим примером также остается - Помимо самих строк, нужно забивать вручную массив .
Уважаемые Гуру, если не затруднит, посмотрите правильно ли я запихал строки в прогмем по примеру № 3 Садмана (а также вывод их на печать). И ещё, строка прагма оптимизатора действительно нужна? что делает этот оптимизатор?
первая часть кода, это правка к опубликованному коду, для старых версий ардуино, который будет выдавать ошибку вторая часть кода, наработка как использовать массив указателей в SRAM, что значительно быстрее и удобнее... третья часть кода, немного измененный вариант
все три варианта проверены ... а с массивами - давно уже рабочие... и данные примеры писались, естественно, быстро, на коленке, по памяти
если есть что сказать - говорите, народ обсудит, сообществу пригодиться, если это будет умная мымсль
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < 5; i++)
{
Print_PROGMEM((char*)pgm_read_word(&(Lang_Str[j][i])), 0, 130);
lcd.Fill_Screen(BLACK);
delay( 500 );
}
}
При установке констант - оптимизатор выкидывает ВСЕ не используемые строки и массив ! Остаётся только одна строка и у неё есть конкретный адрес - вот он и передаётся ...
Хорошо объяснюсь по порядку. Изначально пишу на основе уже существующего кода. Код меня много в чем не устраивает особенно тем что построен на куче case для прокрутке меню и десятке использований millis для кнопок когда можно для этого использовать библиотеку. Один подпункт меню у меня будет аналогично сделанному на casах: каждое нажатие кнопки обновляет информацию на экране так что ДОПУСТИМ обновляется строка "STEPS" и соответственно ей переменная profileSteps, следующее нажатие "RAMP: " и double rampRateStep[9]; и т д
Перечислю их
Переменные имеют разный тип поэтому удобно их обработать через структуру
Тестовый код
Моя идея решения простая: создается функция и в нужном месте вызывается и достаточно. Но решена проблема только со строками. Переменные имеют разный тип и некоторые заданы в виде массива, я это показал. А значит и возника идея в нумерации элементов структуры чтобы затем этот номер и передавать функции чтобы затем по номеру вернуть искомую переменную и ее вывести. Плодить if не хочу
Я правда не понимаю, что Вам нужно. Все нормальные люди в такой ситуации пишут пачку ифов. Если Вы хотите работать как с массивом, Вам нужно менть организацию данных. Если Вы хотите спрятать печать и писать её в одном месте, Вам надо что структура сама себя печатала через интерфейст Printable. Чего Вам надо то?
Плодить if не хочу. Возможно вы хотели сказать что можно в одном месте печатать струтуру, расскажите подробнее. Да вызов функции необязателен мне просто нужно будет по нажатию печатать элемент затем по следующему уже другой элемент то есть печатать элементы структуры в порядке очереди. Очередь задается нажатием
Прежде всего поймите что строки в меню разные по типу https://habr.com/post/257607/
Главным догматом менюОС является «Все есть файл». Да будет так.
У каждого файла есть тип, название, родительская папка, прочие параметры
Евгений нашел ваши Этюды для начинающих: интерфейс Printable
Буду разбираться http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-interfeis-printable
ЕвгенийП, в этой ветке упоминалось что возможно добавить такую функциональность в класс LCD. Подскажите каким образом, на основе вашего же кода? Заранее спасибо
Да это возможно. Дальше уже через if буду выводить как мне нужно. Нужно было раньше найти ваши этюды, помогло
Возник неприятная проблема: если метод вызывается в функции setup() все работает. Как только переношу его в loop() отказывается что либо выводить. Направьте
Ошибок нет, но и монитор пуст
PS Евгений чтобы у вас потом вопросов не возникало добавлю. К вашему коду претензий не имею но вы в примере:
Давайте это напишем:
Вот так! Обратите внимание: в строке 1 мы указали, что наша структура поддерживает интерфейс Printable, а в строках 7-17 мы реализовали необходимый для этого интерфейса метод printTo. Теперь, мы можем просто писать Serial.print(sv) (строка 34) и система поймёт, чтов этот момент надо просто вызвать наш метод, а он всё. что нужно, напечатает. Причём напечатает не тупо в Serial, а именно в тот поток, для которого он был вызван.
Если Вы запустите этот скетч, то он спокойно скомпилируется и в сериале Вы увидите:
Организовали метод SSensorValue, для вывода показаний с датчика и сделали вывод в setup(). Да но в моем случае меню логичнее сделать это в loop() поскольку показания постоянно обновляются (нужно часто настраивать). Если перенести это в функцию вызваемую из loop() не работает, не пойму почему
Какая разница методу откуда его вызывают?
В Вышем коде я не вижу вызова этого метода (всё закоментировано, а то, что заскомментировано - то написано неправильно).
Вот у Вас же есть строки 69-76.
Вставьте такие же в loop (для начала в точности такие же) и больше ничего. Убедитесь, что работает. Потом попробуйте что Вам надо. Если не получится, то покажите код. Но именно неработающий код, а не кучу комментариев.
Рабочий
Нерабочий
Их единственное отличие
В первом случае на экран выводится надпись "Steps:9", во втором экран пустой
Какая разница методу откуда его вызывают?
Согласен с вами, но не могу найти ошибку
В первом случае на экран выводится надпись "Steps:9", во втором экран пустой
вангую - причина в строке 56.
Кстати Всех с наступающим праздником :) Мирного неба над головой
Приехал домой, кое что убрал в нерабочем коде, заработал. Задумаюсь... может и правда - причина в строке 56 (проверка буфера)
Сериал соединение мне только для отладки нужно было, его убрал. Спасибо всем
Ну, и слава Богу.
Кстати, поупражняйтесь. Два часа потратил! Правда, большую часть на писание текста :)
напишу сюда. Взял стандартный пример прогмем. Все работает
но в моем скетче нужно будет часто изменять число строк и сами строки. Можно ли сделать попроще, чтобы каждый раз этот массив
не заполнять вручную?
Может как-то так:
только как бы заставить автоматически заполнять массив string_tableMES в зависимости от количества строк в массиве stringMES ?
у тебя в этом случае
в PROGMEM попадают не сами строки, а указатели на них, а сами строки по-брежнему валяюца в ОЗУ. Думаю, это не то, что ты хотел.
и от это
string_tableMES[
sizeof
(stringMES)/BUF_LENGTH];
мня неуловимо смущает. Мошт, я, правда не протрезвел еще.
Если ты мне, как тупому, обьяснишь, что ты _на самом деле_ хочешь получить - мошт и получица помочь.
А от так, строки у тебя будут лежать в PROGMEM, а массив нет. Ну, для конкретно этого массива, думаю, 10 байт (число строк * размер указателя) в ОЗУ не жалко, но, если нада больше строк, то его тоже можно во флэш запхать. Только читать потом придёца специальным образом.
Если есть желание поиграться с PROGMEM, то вот вам задачка
да, строк будет много, поэтому с прогмем и хочу заморочиться. Тот пример, что ты написал, в принципе у меня уже работает, (только и массив в прогмем). Но суть вопроса с твоим примером также остается - Помимо самих строк, нужно забивать вручную массив .
string_tableMES[
sizeof
(stringMES)/BUF_LENGTH];
мня неуловимо смущает. Мошт, я, правда не протрезвел еще.
Если ты мне, как тупому, обьяснишь, что ты _на самом деле_ хочешь получить - мошт и получица помочь.
все строки будут одинаковой длины, поэтому чтобы, забивая массив, ничего не забыть (в противном случае компилятор должен ругнуться), сделал так
string_tableMES[
sizeof
(stringMES)/BUF_LENGTH]; а не так
string_tableMES[
]
все строки будут одинаковой длины,
http://arduino.ru/forum/programmirovanie/progmem-tricks#comment-439006 -> №3
пасиб, посмотрю
Ответ на задачу #65
не заполнять вручную?
прагму выкинь, она отключает оптимизацию
ок, понятно зачем эта строка.
ну и безопаснее будет вместо
написать
добрый день
по поводу поста #23
на старых версиях мандарины (младше 1.6.х) будет выдаваться ошибка
соотв. строки надо изменить на
И давно у нас char стал размера 16 бит, как нужно функции pgm_read_word?
Sunjob, помоему вы ерунду предложили
> помоему вы ерунду предложили
во первых, Вы пропустили либо пробел, либо тире, во вторых, да, я обычно так и делаю, предлагаю всякую ерунду :о)
можно немного упростить (разыменовывать обычным обращением к элементу массива)
-->
т.о. можно создавать "разношерстные" массивы/списки строк, находящиеся в EEPROM, и перебирать их обычным способом
удачи :о)
p.s. к стати, можно и по "другому упаковать"
ver. Arduino-1.5.8
p.s.
по поводу EEP_xxx: писалось быстро, на коленке, переделкой старого кода, поэтому все так "как есть"... :o)
могу ошибаться, правьте :о)
Можешь, и ашыбаешьса.
отлично, банкуй, ушастый... рассказывай, примеры на коленке накоцаны, возможно, что-то ступил, вот вы сейчас все и поправите :о)
Нет. Не поправлю. Думай.
я сюда зашел не для "запроса вашей помочи"...
первая часть кода, это правка к опубликованному коду, для старых версий ардуино, который будет выдавать ошибку
вторая часть кода, наработка как использовать массив указателей в SRAM, что значительно быстрее и удобнее...
третья часть кода, немного измененный вариант
все три варианта проверены ... а с массивами - давно уже рабочие... и данные примеры писались, естественно, быстро, на коленке, по памяти
если есть что сказать - говорите, народ обсудит, сообществу пригодиться, если это будет умная мымсль
но иногда, лучше, молчать...
Ну да, типично...
"ребята, три дня искал как кнопку прочитать, в гугле ничего похожего нет... выкладываю код, может кому пригодицца..."
Все приветствую, прошу помочь разобраться.. Есть рабочая программа
Дальше создаю функцию Print_PROGMEM
вставляю в loop
после этого программа выводит абракадабру, если задаю переменные константами j = 1 и i = 1 без цикла, все работает. Что не так, плиз ???
Массив же в PROGMEM !!!
При установке констант - оптимизатор выкидывает ВСЕ не используемые строки и массив ! Остаётся только одна строка и у неё есть конкретный адрес - вот он и передаётся ...
Спасибо, разобрался