Вопрос к знатокам, отлитым в бронзе
- Войдите на сайт для отправки комментариев
Ср, 08/11/2017 - 06:42
Кто мне скажет ПОЧЕМУ лыжы не едуть?
template <typename T> Print &operator << (Print &s, T n) { s.print(n); return s; }
const char dow00[] PROGMEM = "Monday";
const char dow01[] PROGMEM = "Tuesday";
const char dow02[] PROGMEM = "Wednesday";
const char dow03[] PROGMEM = "Thursday";
const char dow04[] PROGMEM = "Friday";
const char dow05[] PROGMEM = "Saturday";
const char dow06[] PROGMEM = "SunDay";
const char *const DoW_Array[] PROGMEM = { dow00,dow01,dow02,dow03,dow04,dow05,dow06 };
volatile byte idx = 0;
using PFlashString = __FlashStringHelper *;
PFlashString str;
void setup()
{
Serial.begin(115200);
Serial << F("Program started.\n");
str = PFlashString(dow02);
Serial << idx << ". " << str << '\n';
idx++;
str = PFlashString(DoW_Array[2]);
Serial << idx << ". " << str << '\n';
idx++;
str = PFlashString(DoW_Array[idx]);
Serial << idx << ". " << str << '\n';
}
void loop()
{
/* add main program code here */
}
Я безусловно идиот, и многого по С++ не знаю, но это выше моего понимания. ПАМАГИТИ!!!

Что-то с памятью её стало, стринги на ардуине не велкам. Есть макрос для измерения доступной памяти, поищите.
А не отлитым можно отвечать?
И кстати, дед, то что память не при делах, а просто ты запутался в квалификаторах - это понятно. Но, не веди себя как новичок - объясни чего ты хотел. Конкретный вопрос - чего ты хотел от массив DoW_Array? Он сам должен сидеть в оперативной памаяти или в програмной?
str = PFlashString(DoW_Array[2]); печатается правильноstr = PFlashString(DoW_Array[idx]); печатается неправильно, хотя idx == 2пошто?
Наерно, это только Дракула сможет рассказать, пока трезв, или ЕвгенийП, если снизойдут.
Мля, я тоже могу, если ты мне ответишь на мой вопрос.
Сами строки у тебя живут в progmem, а массив указателей DoW_Array - где? Вернее, где ты хочешь, чтоб он жил?
Это относится к делу? Тогда хочу, чтоб в PROGMEM. Смысла нет держать массив константных указателей в оперативке
Кароче, у тебя два варианта.
1. или ты убираешь слово PROGMEM из строки 13 (попробуй)
2. или читаешь содержимое этого массива из progmem как положено, т.е. в строке 32 вместо DoW_Array[2] пишешь pgm_read_ptr_near(DoW_Array+2), а в строке 37 вместо DoW_Array[idx] пишешь pgm_read_ptr_near(DoW_Array+idx) (пробуй и это)
В любом из этих двух случаев у тебя всё будет работать правильно.
На вопрос: "относится к делу?" ответ уже понятен? Просто сравни два описанных выше варианта.
а я не спрашивал, что надо делать. Я спрашивал ПОЧЕМУ работает по разному при индексе массива == константа и при взятии его из переменной, хотя на мой взгляд, разницы быть не должно.
Потому, что в стоке 32 - константа и компилятор просто подставил готовое значение не вычисляя элемент массива по индексу - тупо сам вычислил и в исполняемом коде у тебя уже сидит готовая "среда".
А в строке 37 он вставил код для честного вычисления "к адресу начала массива прибавить содержимое idx и из получившегося адреса взять содержимое", а посколько это содержимое на самом деле сидит в прогмеме, вот он у тебя и сломался.
Я же во втором примере явно написал то же самое (к адресу прибавил содержимое idx) только при этом указал, что содержимое надо из прогмема брать, вот он нормально и сработал.
Мда. Говорила мне мама, не лезь в С++ со своим скудоумием.
Паду пить.
Это называется "неявное преобразование типов в С++" ?
DetSimen - когда я делал точно такую коллекцию строк в своем скрипте - я счастливо избежал этой ловушки, поместив массив указателей в оперативку. Указатели занимают мало, поэтому совершенно незачем класть их во флеш, зато работать с ними в оперативке много удобнее.
Всё равно нихрена не понимаю
где я баран?
где я баран?
ну вроде Ворота все понятно обьяснил в сообщении №9. В первых двух случаях адрес элемента известен на момент компиляции, в третьем - вычисляется в процессе выполнения. Вот и разница.
А смотрищь как баран на Ворота :)
ви таки не поверите, но вот так тоже не работает
__FlashStringHelper *Get_String(uint8_t idx); void setup() { Serial.begin(115200); Serial << F("Program started.\n"); Serial << idx++ << ". " << (__FlashStringHelper *)(dow02) << '\n'; // правильно Serial << idx++ << ". " << Get_String(2) << '\n'; // правильно Serial << idx << ". " << Get_String(idx) << '\n'; // НЕправильно } void loop(){} __FlashStringHelper *Get_String(uint8_t idx) { return (__FlashStringHelper *)(DoW_Array[idx]); }Хотя тут то уже ничего не подставляется явно. Функция как inline не описана.
вопщем, я думаю, дожность помошника кочегара деревенской котельни при курятнике - потолок моей карьеры.
Вопрос снят, всем спасибо.
Пойду пить, а потом котельни обзванивать в области.
лучше обьясни мне другое - зачем в этой строке два раза const
const char *const DoW_Array[] PROGMEM = { dow00,dow01,dow02,dow03,dow04,dow05,dow06 };
Вот смотри - char* array[] - это массив указателей на данные типа char
const char* array[] - это массив, где эти указатели являются константами
А второй const - указание на то, что и данные по указателям - константы? - а зачем это обьявлять, ведь указателям все равно, на что указывать - на переменные или константы. А сами строки ты и так обьявил контантами и компилятор это учитывает.
По-моему, второй конст из определения массива можно безболезненно выкинуть. Или ошибаюсь?
второй const для PROGMEM, чтоб массив указателей тоже во флэше лежал.
const char *const - константный указатель на константные данные.
А вот это
const char* array[]
значить только то, что ты array присвоить ничего не можешь в программе потом
ЗЫ. как я люблю фонНеймана и его архитектуру. С децтва прям. А этих гарвардских умнеков - нинавижу.
Пойду пить
Погодите квасить с утра! В этой теме ещё до самого забавного и не добрались :)))
Попробуйте взять свой изначальный код со словом PROGMEM в описании массива и без этого слова. Скомпилируйте оба варианта и сравните количество замнимаемой программной памяти :)))))))
второй const для PROGMEM, чтоб массив указателей тоже во флэше лежал.
Нет, это первый const для PROGMEM. А второй const ты смело можешь убрать и класть массив в PROGMEM - второй конст для этого не нужен, попробуй.
Попробуйте взять свой изначальный код со словом PROGMEM в описании массива и без этого слова. Скомпилируйте оба варианта и сравните количество замнимаемой программной памяти :)))))))
значит я в сообщении #12 был прав - нет смысла класть указатели во флеш. Правда сделал я это не от большого ума, а от лени, но все равно приятно :)
значит я в сообщении #12 был прав - нет смысла класть указатели во флеш.
Почему нет? Сравните там же расход оперативной памяти. Со словом PROGMEM он меньше.
Мой-то иезутсякий вброс был не про оперативную, а именно про программную память.
Мой-то иезутсякий вброс был не про оперативную, а именно про программную память.
А, ну это я тоже как-то тестировал. Помещение чего-либо во флеш - очень неэкономная операция, например короткие строки класть во флеш крайне невыгодно, за выигрыш пары байтов оперативки платишь десятками и даже сотнями байтов флеша...
Сейчас не могу проверить этот пример, нет компилятора под рукой.
c PROGMEM
// const char *const DoW_Array[] PROGMEM= { dow00,dow01,dow02,dow03,dow04,dow05,dow06 };
а так так этот массив относится к инициализированным данным, то он и во флэше хранится тоже и плюс копируется рантаим библиотекой в ОЗУ при старте, поэтому занятая память программ не изменилась
у меня то вопрос, в чем разница для компилятора параметры-непосредственные константы и переменные, почему в первом случае адрес строки вычисляется правильно, а во втором - нет
Serial << idx++ << ". " << Get_String(2) << '\n'; // правильно Serial << idx << ". " << Get_String(idx) << '\n'; // НЕ ПРАВИЛЬНО } void loop(){} __FlashStringHelper *Get_String(uint8_t idx) { return (__FlashStringHelper *)(DoW_Array[idx]); }даже вот так - неправильно
Так Вам же всё объяснили. Если компилятор может вычислить нечто - он вычисляет и подставляет готовую константу. То, что у Вас это вызов функции, и даже не инлайн - ему плевать с высокой колокольни - если может, то вычислет и подставляет готовый результат. Что Вы и наблюдаете.
Я как-то про такие особенности оптимизации долго объяснял одному, прости Господи, википедику ... сам по себе срач - дерьмо голимое, но там был очень красивый пример, как компилятор заменил вызов РЕКУРСИВНОЙ (!!!!) функции на готовый результат! О как! Там правда функция была инлайн. Сейчас я специально проверил без инлайн. Смотрите
// Вычисление факториала static long fact(const long n) { return n < 1 ? 1 : n * fact(n - 1); } void setup() { PORTB = fact(5); } void loop(void){}Скомпилиркуйте это в IDE 1.8.1 с опциями "из коробки" и дизассемблируйте. Получите функцию setup вот такую:
и ВСЁ! Как видите он просто выбросих нахрен функцию fact, а вместо вызова fact(5) вставил готовый результат 120.
Ппоробуйте сами скомпилировать и посмотреть, чтоб уж не сомневаться.
Нравится современная оптимизация?
Насчёт опций - это важно. Разумеется, если убрать оптимизацию, то ничего такого не будет.
Спасибо Вам за науку, а компилятору - за оптимизацию.
Тему можно закрывать.
Не готов я еще для С++.
Красиво. А если убрать из описания параметра const - тоже соптимизирует? Как-бы указалово const обещает что функция будет получать только константы времени компиляции. Вполне разумно скомпилять функцию и попытаться её вызвать дабы получить результат ещё на этом этапе.. а вот ежели нету const?
Сам пока проверить не могу, но интересно..
Убрал const, заодно и костанту заменил на переменную. Ничего не изменилось
// Вычисление факториала static long fact(long n) { return n < 1 ? 1 : n * fact(n - 1); } void setup() { int a = 4; PORTB = fact(a); } void loop(void){}Результат
Как-бы указалово const обещает что функция будет получать только константы времени компиляции.
Что за дичь? Ничего такого const не обещает, он лишь гарантирует, что входящий параметр, помеченный квалификатором const, не будет изменён внутри функции. Константы времени компиляции - тут не при делах, от слова "совсем".
Нашли проблему.. Вытягую из исходников контролера самогонного и либок. Проверено, работает.
const char NameMode0[] PROGMEM ="Старт"; const char NameMode1[] PROGMEM ="Жду Температуру"; const char NameMode2[] PROGMEM ="Есть температура"; const char NameMode3[] PROGMEM ="Проверка нагрева"; const char NameMode4[] PROGMEM =" Нагрев"; const char NameMode5[] PROGMEM =" Закипает"; const char NameMode6[] PROGMEM =" Вскипел"; const char NameMode7[] PROGMEM =" Перегон !"; const char NameMode8[] PROGMEM =" Стоп !"; const char NameMode9[] PROGMEM =" Остываеет"; PGM_P const NameMode[] PROGMEM = { NameMode0, NameMode1, NameMode2, NameMode3, NameMode4, NameMode5, NameMode6, NameMode7, NameMode8, NameMode9}; ............................... myOLED.drawStringPP(0,0,NameMode, KubMode); .................................. byte SSD1306::drawStringP(uint8_t x, uint8_t y, const char *c) { return drawStringBase(x, y, [](char* c)->char{return pgm_read_byte(c);}, (char *)c); } byte SSD1306::drawStringPP(uint8_t x, uint8_t y, const char* const* c, byte i) { PGM_P p; memcpy_P(&p, &c[i], sizeof(PGM_P)); return drawStringP(x, y, p); }Человеческим языком, в drawStringPP передаем указатель на массив в PROGMEM указателей на строки в PROGMEM. И индекс в этом массиве. Копируем указатель с заданым индексом и передаем его в drawStringP, там уже все просто, ну былобы просто если б лямбда не затесалась ;) но из песни слов не выкинеш, так в либе. И такое часто пользую.
В стартовом ситуация очевидна, если компилятор при компиляции может оптимизировать и извлечь указатель на строку - работает, иначе нет и нужно явно выцарапать этот указатель из PROGMEM.
Сорри, неверно выразился, ЕвгенийП меня понял верно, пасибки.
Ну и? Получается что 13-й тип оптимизации (глобальная оптимизация потока управления по анализу потока данных) уже по сути внедрен в компиляторы, остается ждать когда памяти хватит на 14-й - глобальная оптимизация потока данных .. когда кумпилятыр станет способен самостоятельно преобразовывать разную муть из комплекта переменных, массивов и объектов в то, что посчитает лучшим решением .. а там, недолго ждать когда оно само и кодить начнет. :)
Здравствуйте.Проблема с кирилицей.Это работает.
[code] #include <avr/pgmspace.h> const char string_0[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997"; // "String 0" etc are strings to store - change to suit. const char string_1[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997-1"; // " Ошибка: выключатель нагрев вкл. Замкнут (4-PB1)" const char string_2[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997-2";// "Ошибка: выключатель нагрев выкл. разомкнут (4-PB2)"; const char string_3[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997-3"; // "Ошибка: выключатель сброса Замкнут (4-PB3)"; const char string_4[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997-4"; // "Ошибка: CB1 Реле замкнуто (K3)"; /*const char string_5[] PROGMEM = "Ошибка: реле нагрев вкл. замкнуто (K4)"; const char string_6[] PROGMEM = "Ошибка: реле инвертор готов замкнуто (K5)"; const char string_7[] PROGMEM = "Ошибка: реле ограничитель тока замкнуто (1CR18)"; const char string_8[] PROGMEM = ""; const char string_9[] PROGMEM = ""; const char string_10[] PROGMEM = "Ошибка: контактор1-CON1 замкнут"; const char string_11[] PROGMEM = "Ошибка: главный выключатель замкнут CB1"; const char string_12[] PROGMEM = "Ошибка: выключатели вспомогательного контура разомкнуты"; const char string_13[] PROGMEM = "Ошибка: стартер двигателя отсоединен или разомкнут 1-CON1"; const char string_14[] PROGMEM = "Ошибка: гидрореле водоохлаждаемых кабелей ВЧ замкнуто 2-FLS2"; const char string_15[] PROGMEM = "Ошибка: гидрореле ВЧ-стойки замкнуто 2-FLS1"; const char string_16[] PROGMEM = "Ошибка: гидрореле радиатора силовой установки замкнуто 1-FLS2"; const char string_17[] PROGMEM = "Ошибка: гидрореле электрического дросселя/SCR замкнуто 1-FLS1"; const char string_18[] PROGMEM = "Ошибка: теплообменник. Низкий уровень воды. Проверить утечки внутри стоек"; const char string_19[] PROGMEM = "Ошибка: гидрореле трансформатора замкнуто 21 FLS 1"; const char string_20[] PROGMEM = "Тревога: аварийная остановка стана"; const char string_21[] PROGMEM = "Тревога: аварийная остановка терминала"; const char string_22[] PROGMEM = "Тревога: аварийная остановка источника электропитания"; const char string_23[] PROGMEM = "Тревога: аварийная остановка ВЧ-генератора"; const char string_24[] PROGMEM = "Тревога: теплообменник.низкий уровень и расход проверить утечки внутри стоек"; const char string_25[] PROGMEM = "Тревога: теплообменник неудачный пуск"; const char string_26[] PROGMEM = "Тревога: обнаружена перегрузка по постоянному току"; const char string_27[] PROGMEM = "Тревога: аварийная остановка стойки трансформатора"; const char string_28[] PROGMEM = "Тревога: открыта дверца стойки трансформатора"; const char string_29[] PROGMEM = "Тревога: сбой подачи питания на карту DC1"; const char string_30[] PROGMEM = "Тревога: контактор отключен/разомкнут 1-CON1"; const char string_31[] PROGMEM = "Тревога: сбой карты DC1 (relay K3)"; const char string_32[] PROGMEM = "Тревога: главный выключатель отключен/разомкнут CB1"; const char string_33[] PROGMEM = "Тревога: дверца источника питания открыта"; const char string_34[] PROGMEM = "Тревога: дверца вч-генератора открыта"; const char string_35[] PROGMEM = "Реле аварийной остановки 1-ESR2 разомкнуто, нажать сброс"; const char string_36[] PROGMEM = "Реле аварийной остановки 1-ESR1 Разомкнуто, нажать сброс"; const char string_37[] PROGMEM = "Перевести выключатель в режим готовности"; const char string_38[] PROGMEM = "Самодиагностика сварочного аппарата OK Перейти в режим готовности"; const char string_39[] PROGMEM = "Запуск системы охлаждения"; const char string_40[] PROGMEM = "Подождите, главный выключатель сейчас замкнется"; const char string_41[] PROGMEM = ""; const char string_42[] PROGMEM = "Блокировка по времени: сварочный аппарат не работает открыто 1-CB1"; const char string_43[] PROGMEM = "Блокировка по времени: сварочный аппарат не работает Открыто 1-CON1"; const char string_44[] PROGMEM = "Ошибка: высокая температура воды на входе"; const char string_45[] PROGMEM = "Тревога: зажим индуктора низкое давление воздуха 6-PS1"; const char string_46[] PROGMEM = "Тревога: трансформатор стартер двигателя отключен/разомкнут"; const char string_47[] PROGMEM = "Тревога: высокая окружающая температура стойки трансформатора"; const char string_48[] PROGMEM = "Тревога: высокая температура воды в стойке трансформатора 21TS1"; const char string_49[] PROGMEM = "Высокая температура воды на входе"; const char string_50[] PROGMEM = "Тревога: низкий расход воды для водоохлаждаемых кабелей Вч-генератора 2FLS2"; const char string_51[] PROGMEM = "Тревога: низкий расход воды в стойке вч 2FLS1"; const char string_52[] PROGMEM = "Тревога: низкий расход воды В радиаторе силовой установки 1FLS2"; const char string_53[] PROGMEM = "Тревога: низкий расход воды для электрического дросселя1FLS1"; const char string_54[] PROGMEM = "Тревога: высокая температура воды для водоохлаждаемых кабелей вч 2 TS6-12"; const char string_55[] PROGMEM = "Тревога: высокая температура воды для стойки вч 2 TS1"; const char string_56[] PROGMEM = "Тревога: высокая окружающая температура источника питания"; const char string_57[] PROGMEM = "Тревога: вспомогательный выключатель отключен"; const char string_58[] PROGMEM = "Тревога: стартер двигателя отключен или разомкнут"; const char string_59[] PROGMEM = "Тревога: потеря напряжения/фазы на линии переменного тока"; const char string_60[] PROGMEM = "Тревога: сбой питания пиропатрона"; const char string_61[] PROGMEM = "Тревога: неисправность модуля перейти в состояние выключено"; const char string_62[] PROGMEM = "Активное состояние защиты ВЧ регулировка согласования нагрузок"; const char string_63[] PROGMEM = "Тревога: активирована защита ВЧ-генератора"; const char string_64[] PROGMEM = "Тревога: внешний блокиратор стана открыт"; const char string_65[] PROGMEM = "Ошибка: управление DC1 выкл./готов (K5 relay)"; const char string_66[] PROGMEM = "Ошибка: нажата кнопка нагрев выкл."; const char string_67[] PROGMEM = "Нажата кнопка нагрев выкл."; const char string_68[] PROGMEM = "Стан не готов"; const char string_69[] PROGMEM = "Тревога: управление DC1 нагрев вкл./выкл. (K4)"; const char string_70[] PROGMEM = "Ручное управление подачей питания Запустить стан"; const char string_71[] PROGMEM = "Нажать кнопку нагрев вкл. сварочного аппарат"; const char string_72[] PROGMEM = "Кнопка нагрев вкл. нажата Питание на сварку блокировано"; const char string_73[] PROGMEM = "Вернуть нажатую кнопку в исходное положение Проверить лампу и прибор"; const char string_74[] PROGMEM = ""; const char string_75[] PROGMEM = "Ошибки сварочного аппарата OK Нажать нагрев вкл."; const char string_76[] PROGMEM = "Система готова Запустить стан"; const char string_77[] PROGMEM = ""; const char string_78[] PROGMEM = "Отключение низкой частоты Проверить индуктор и нагрузку"; const char string_79[] PROGMEM = "Отключение высокой частоты Проверить индуктор и нагрузку"; const char string_80[] PROGMEM = "Ошибка: ошибка заданных значений с масштабированием"; const char string_81[] PROGMEM = "Киловатты – 1111 Частота - 2222"; const char string_82[] PROGMEM = "Тревога: низкий расход воды в стойке трансформатора 21-FLS1"; const char string_83[] PROGMEM = "Тревога: температура обмотки трансформатора 21-TS3"; const char string_84[] PROGMEM = "Достижение двойного предела по напряжению или току"; const char string_85[] PROGMEM = ""; const char string_86[] PROGMEM = ""; const char string_87[] PROGMEM = ""; const char string_88[] PROGMEM = ""; const char string_89[] PROGMEM = ""; const char string_90[] PROGMEM = ""; const char string_91[] PROGMEM = "Тревога: контакт поток охлаждающего вещества 6-FS1"; const char string_92[] PROGMEM = "Тревога: низкое давление воздуха в системе 6-PS2"; const char string_93[] PROGMEM = "Тревога: обеспечить контакты для сварки"; const char string_94[] PROGMEM = "Тревога: контакты выключены (down) Низкое давление 6-PS4"; const char string_95[] PROGMEM = "Тревога: xy-осевой зажим Низкое давление 6-PS3"; const char string_96[] PROGMEM = ""; const char string_97[] PROGMEM = ""; const char string_98[] PROGMEM = "Контакты включены (up) Низкое давление 6-PS5"; const char string_99[] PROGMEM = ""; const char string_100[] PROGMEM = ""; const char string_101[] PROGMEM = ""; const char string_102[] PROGMEM = ""; const char string_103[] PROGMEM = ""; const char string_104[] PROGMEM = ""; const char string_105[] PROGMEM = ""; const char string_106[] PROGMEM = ""; const char string_107[] PROGMEM = ""; const char string_108[] PROGMEM = ""; const char string_109[] PROGMEM = ""; const char string_110[] PROGMEM = ""; const char string_111[] PROGMEM = ""; const char string_112[] PROGMEM = ""; const char string_113[] PROGMEM = ""; const char string_114[] PROGMEM = ""; const char string_115[] PROGMEM = ""; const char string_116[] PROGMEM = ""; const char string_117[] PROGMEM = ""; const char string_118[] PROGMEM = ""; const char string_119[] PROGMEM = ""; const char string_120[] PROGMEM = "Текущий предел Мощность сварки = 1111 квт"; const char string_121[] PROGMEM = "Уровень теплообменника Мощность сварки = 1111 квт Низкий проверить утечки Внутри стоек"; const char string_122[] PROGMEM = "Высокая окружающая температура 1-TS2 Мощность сварки = 1111 квт"; const char string_123[] PROGMEM = "Высокая температура воды 1-TS1 Мощность сварки = 1111 квт"; const char string_124[] PROGMEM = "Высокая частота = 222 кгц Мощность сварки = 1111 квт"; const char string_125[] PROGMEM = "Низкая частота = 222 кгц Мощность сварки = 1111 квт"; const char string_126[] PROGMEM = ""; const char string_127[] PROGMEM = "Частота = 222 кгц Мощность сварки = 1111 квт";*/ // Then set up a table to refer to your strings. const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4};//, string_5, string_6, string_7, string_8, string_9, string_10, string_11, string_12, string_13, string_14, string_15, string_16, string_17, string_18, string_19, string_20, string_21, string_22, string_23, string_24, string_25, string_26, string_27, string_28, string_29, string_30, string_31, string_32, string_33, string_34, string_35, string_36, string_37, string_38, string_39, string_40, string_41, string_42, string_43, string_44, string_45, string_46, string_47, string_48, string_49, string_50, string_51, string_52, string_53, string_54, string_55, string_56, string_57, string_58, string_59, string_60, string_61, string_62, string_63, string_64, string_65, string_66, string_67, string_68, string_69, string_70, string_71, string_72, string_73, string_74, string_75, string_76, string_77, string_78, string_79, string_80, string_81, string_82, string_83, string_84, string_85, string_86, string_87, string_88, string_89, string_90, string_91, string_92, string_93, string_94, string_95, string_96, string_97, string_98, string_99, string_100, string_101, string_102, string_103, string_104, string_105, string_106, string_107, string_108, string_109, string_110, string_111, string_112, string_113, string_114, string_115, string_116, string_117, string_118, string_119, string_120, string_121, string_122, string_123, string_124, string_125, string_126, string_127}; char buffer[60]; void setup() { Serial.begin(9600); while(!Serial); Serial.println("OK"); } void loop() { for (int i = 0; i < 5; i++) { strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); Serial.println(buffer); delay( 1500 ); } } [/code]Этот не работает.
[code] #include <avr/pgmspace.h> const char string_0[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997"; // "String 0" etc are strings to store - change to suit. const char string_1[] PROGMEM ="Ошибка: выключатель нагрев вкл. Замкнут (4-PB1)"; // " Ошибка: выключатель нагрев вкл. Замкнут (4-PB1)" const char string_2[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997-2";// "Ошибка: выключатель нагрев выкл. разомкнут (4-PB2)"; const char string_3[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997-3"; // "Ошибка: выключатель сброса Замкнут (4-PB3)"; const char string_4[] PROGMEM ="Thermatool Europe Cfi welder Copyright 1997-4"; // "Ошибка: CB1 Реле замкнуто (K3)"; /*const char string_5[] PROGMEM = "Ошибка: реле нагрев вкл. замкнуто (K4)"; const char string_6[] PROGMEM = "Ошибка: реле инвертор готов замкнуто (K5)"; const char string_7[] PROGMEM = "Ошибка: реле ограничитель тока замкнуто (1CR18)"; const char string_8[] PROGMEM = ""; const char string_9[] PROGMEM = ""; const char string_10[] PROGMEM = "Ошибка: контактор1-CON1 замкнут"; const char string_11[] PROGMEM = "Ошибка: главный выключатель замкнут CB1"; const char string_12[] PROGMEM = "Ошибка: выключатели вспомогательного контура разомкнуты"; const char string_13[] PROGMEM = "Ошибка: стартер двигателя отсоединен или разомкнут 1-CON1"; const char string_14[] PROGMEM = "Ошибка: гидрореле водоохлаждаемых кабелей ВЧ замкнуто 2-FLS2"; const char string_15[] PROGMEM = "Ошибка: гидрореле ВЧ-стойки замкнуто 2-FLS1"; const char string_16[] PROGMEM = "Ошибка: гидрореле радиатора силовой установки замкнуто 1-FLS2"; const char string_17[] PROGMEM = "Ошибка: гидрореле электрического дросселя/SCR замкнуто 1-FLS1"; const char string_18[] PROGMEM = "Ошибка: теплообменник. Низкий уровень воды. Проверить утечки внутри стоек"; const char string_19[] PROGMEM = "Ошибка: гидрореле трансформатора замкнуто 21 FLS 1"; const char string_20[] PROGMEM = "Тревога: аварийная остановка стана"; const char string_21[] PROGMEM = "Тревога: аварийная остановка терминала"; const char string_22[] PROGMEM = "Тревога: аварийная остановка источника электропитания"; const char string_23[] PROGMEM = "Тревога: аварийная остановка ВЧ-генератора"; const char string_24[] PROGMEM = "Тревога: теплообменник.низкий уровень и расход проверить утечки внутри стоек"; const char string_25[] PROGMEM = "Тревога: теплообменник неудачный пуск"; const char string_26[] PROGMEM = "Тревога: обнаружена перегрузка по постоянному току"; const char string_27[] PROGMEM = "Тревога: аварийная остановка стойки трансформатора"; const char string_28[] PROGMEM = "Тревога: открыта дверца стойки трансформатора"; const char string_29[] PROGMEM = "Тревога: сбой подачи питания на карту DC1"; const char string_30[] PROGMEM = "Тревога: контактор отключен/разомкнут 1-CON1"; const char string_31[] PROGMEM = "Тревога: сбой карты DC1 (relay K3)"; const char string_32[] PROGMEM = "Тревога: главный выключатель отключен/разомкнут CB1"; const char string_33[] PROGMEM = "Тревога: дверца источника питания открыта"; const char string_34[] PROGMEM = "Тревога: дверца вч-генератора открыта"; const char string_35[] PROGMEM = "Реле аварийной остановки 1-ESR2 разомкнуто, нажать сброс"; const char string_36[] PROGMEM = "Реле аварийной остановки 1-ESR1 Разомкнуто, нажать сброс"; const char string_37[] PROGMEM = "Перевести выключатель в режим готовности"; const char string_38[] PROGMEM = "Самодиагностика сварочного аппарата OK Перейти в режим готовности"; const char string_39[] PROGMEM = "Запуск системы охлаждения"; const char string_40[] PROGMEM = "Подождите, главный выключатель сейчас замкнется"; const char string_41[] PROGMEM = ""; const char string_42[] PROGMEM = "Блокировка по времени: сварочный аппарат не работает открыто 1-CB1"; const char string_43[] PROGMEM = "Блокировка по времени: сварочный аппарат не работает Открыто 1-CON1"; const char string_44[] PROGMEM = "Ошибка: высокая температура воды на входе"; const char string_45[] PROGMEM = "Тревога: зажим индуктора низкое давление воздуха 6-PS1"; const char string_46[] PROGMEM = "Тревога: трансформатор стартер двигателя отключен/разомкнут"; const char string_47[] PROGMEM = "Тревога: высокая окружающая температура стойки трансформатора"; const char string_48[] PROGMEM = "Тревога: высокая температура воды в стойке трансформатора 21TS1"; const char string_49[] PROGMEM = "Высокая температура воды на входе"; const char string_50[] PROGMEM = "Тревога: низкий расход воды для водоохлаждаемых кабелей Вч-генератора 2FLS2"; const char string_51[] PROGMEM = "Тревога: низкий расход воды в стойке вч 2FLS1"; const char string_52[] PROGMEM = "Тревога: низкий расход воды В радиаторе силовой установки 1FLS2"; const char string_53[] PROGMEM = "Тревога: низкий расход воды для электрического дросселя1FLS1"; const char string_54[] PROGMEM = "Тревога: высокая температура воды для водоохлаждаемых кабелей вч 2 TS6-12"; const char string_55[] PROGMEM = "Тревога: высокая температура воды для стойки вч 2 TS1"; const char string_56[] PROGMEM = "Тревога: высокая окружающая температура источника питания"; const char string_57[] PROGMEM = "Тревога: вспомогательный выключатель отключен"; const char string_58[] PROGMEM = "Тревога: стартер двигателя отключен или разомкнут"; const char string_59[] PROGMEM = "Тревога: потеря напряжения/фазы на линии переменного тока"; const char string_60[] PROGMEM = "Тревога: сбой питания пиропатрона"; const char string_61[] PROGMEM = "Тревога: неисправность модуля перейти в состояние выключено"; const char string_62[] PROGMEM = "Активное состояние защиты ВЧ регулировка согласования нагрузок"; const char string_63[] PROGMEM = "Тревога: активирована защита ВЧ-генератора"; const char string_64[] PROGMEM = "Тревога: внешний блокиратор стана открыт"; const char string_65[] PROGMEM = "Ошибка: управление DC1 выкл./готов (K5 relay)"; const char string_66[] PROGMEM = "Ошибка: нажата кнопка нагрев выкл."; const char string_67[] PROGMEM = "Нажата кнопка нагрев выкл."; const char string_68[] PROGMEM = "Стан не готов"; const char string_69[] PROGMEM = "Тревога: управление DC1 нагрев вкл./выкл. (K4)"; const char string_70[] PROGMEM = "Ручное управление подачей питания Запустить стан"; const char string_71[] PROGMEM = "Нажать кнопку нагрев вкл. сварочного аппарат"; const char string_72[] PROGMEM = "Кнопка нагрев вкл. нажата Питание на сварку блокировано"; const char string_73[] PROGMEM = "Вернуть нажатую кнопку в исходное положение Проверить лампу и прибор"; const char string_74[] PROGMEM = ""; const char string_75[] PROGMEM = "Ошибки сварочного аппарата OK Нажать нагрев вкл."; const char string_76[] PROGMEM = "Система готова Запустить стан"; const char string_77[] PROGMEM = ""; const char string_78[] PROGMEM = "Отключение низкой частоты Проверить индуктор и нагрузку"; const char string_79[] PROGMEM = "Отключение высокой частоты Проверить индуктор и нагрузку"; const char string_80[] PROGMEM = "Ошибка: ошибка заданных значений с масштабированием"; const char string_81[] PROGMEM = "Киловатты – 1111 Частота - 2222"; const char string_82[] PROGMEM = "Тревога: низкий расход воды в стойке трансформатора 21-FLS1"; const char string_83[] PROGMEM = "Тревога: температура обмотки трансформатора 21-TS3"; const char string_84[] PROGMEM = "Достижение двойного предела по напряжению или току"; const char string_85[] PROGMEM = ""; const char string_86[] PROGMEM = ""; const char string_87[] PROGMEM = ""; const char string_88[] PROGMEM = ""; const char string_89[] PROGMEM = ""; const char string_90[] PROGMEM = ""; const char string_91[] PROGMEM = "Тревога: контакт поток охлаждающего вещества 6-FS1"; const char string_92[] PROGMEM = "Тревога: низкое давление воздуха в системе 6-PS2"; const char string_93[] PROGMEM = "Тревога: обеспечить контакты для сварки"; const char string_94[] PROGMEM = "Тревога: контакты выключены (down) Низкое давление 6-PS4"; const char string_95[] PROGMEM = "Тревога: xy-осевой зажим Низкое давление 6-PS3"; const char string_96[] PROGMEM = ""; const char string_97[] PROGMEM = ""; const char string_98[] PROGMEM = "Контакты включены (up) Низкое давление 6-PS5"; const char string_99[] PROGMEM = ""; const char string_100[] PROGMEM = ""; const char string_101[] PROGMEM = ""; const char string_102[] PROGMEM = ""; const char string_103[] PROGMEM = ""; const char string_104[] PROGMEM = ""; const char string_105[] PROGMEM = ""; const char string_106[] PROGMEM = ""; const char string_107[] PROGMEM = ""; const char string_108[] PROGMEM = ""; const char string_109[] PROGMEM = ""; const char string_110[] PROGMEM = ""; const char string_111[] PROGMEM = ""; const char string_112[] PROGMEM = ""; const char string_113[] PROGMEM = ""; const char string_114[] PROGMEM = ""; const char string_115[] PROGMEM = ""; const char string_116[] PROGMEM = ""; const char string_117[] PROGMEM = ""; const char string_118[] PROGMEM = ""; const char string_119[] PROGMEM = ""; const char string_120[] PROGMEM = "Текущий предел Мощность сварки = 1111 квт"; const char string_121[] PROGMEM = "Уровень теплообменника Мощность сварки = 1111 квт Низкий проверить утечки Внутри стоек"; const char string_122[] PROGMEM = "Высокая окружающая температура 1-TS2 Мощность сварки = 1111 квт"; const char string_123[] PROGMEM = "Высокая температура воды 1-TS1 Мощность сварки = 1111 квт"; const char string_124[] PROGMEM = "Высокая частота = 222 кгц Мощность сварки = 1111 квт"; const char string_125[] PROGMEM = "Низкая частота = 222 кгц Мощность сварки = 1111 квт"; const char string_126[] PROGMEM = ""; const char string_127[] PROGMEM = "Частота = 222 кгц Мощность сварки = 1111 квт";*/ // Then set up a table to refer to your strings. const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4};//, string_5, string_6, string_7, string_8, string_9, string_10, string_11, string_12, string_13, string_14, string_15, string_16, string_17, string_18, string_19, string_20, string_21, string_22, string_23, string_24, string_25, string_26, string_27, string_28, string_29, string_30, string_31, string_32, string_33, string_34, string_35, string_36, string_37, string_38, string_39, string_40, string_41, string_42, string_43, string_44, string_45, string_46, string_47, string_48, string_49, string_50, string_51, string_52, string_53, string_54, string_55, string_56, string_57, string_58, string_59, string_60, string_61, string_62, string_63, string_64, string_65, string_66, string_67, string_68, string_69, string_70, string_71, string_72, string_73, string_74, string_75, string_76, string_77, string_78, string_79, string_80, string_81, string_82, string_83, string_84, string_85, string_86, string_87, string_88, string_89, string_90, string_91, string_92, string_93, string_94, string_95, string_96, string_97, string_98, string_99, string_100, string_101, string_102, string_103, string_104, string_105, string_106, string_107, string_108, string_109, string_110, string_111, string_112, string_113, string_114, string_115, string_116, string_117, string_118, string_119, string_120, string_121, string_122, string_123, string_124, string_125, string_126, string_127}; char buffer[60]; void setup() { Serial.begin(9600); while(!Serial); Serial.println("OK"); } void loop() { for (int i = 0; i < 5; i++) { strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); Serial.println(buffer); delay( 1500 ); } } [/code]Плата нано китайская
Что это и о чем это... в чем разница... кто это писал... для чего.... ?
Разница в String1.По задумке будет выводить сообщения на OLED0.96.Скетч из стандартных примеров,кроме сообщений естественно.
Обождите тему закрывать, у меня тоже вопрос имеется, как и у Симеона...
Вопрос простой: как приструнить компилятор (может есть какая pragma) чтобы он не развлекался с самостоятельной оптимизацией оператора switch? А то у меня как-то всё непредсказуемо получается в этой Arduino IDE: условно 8 шт. case - 8*N байт в прошивку, добавляешь еще один - получаешь 9*N + K , где K - вообще не меньше N. Ну или иногда 10 шт. нормально, а на 11-й - приплыли. Никакого порядка.
В case всё просто может быть - обычные присвоения, по одному на каждую ветку. И кейсы вроде все последовательно делаю, чтобы они ровненько легли - от '1' до '9', например.
Сначала меня всё это очень удивляло (в ассемблерную декомпиляцию, извините, не впадал), но потом прочитал https://embeddedgurus.com/stack-overflow/2010/04/efficient-c-tip-12-be-wary-of-switch-statements/ и понял, что это вроде как англичанка гадит. Теперь я в замешательстве. if-ы не хочется городить, таблица перекодировки не совсем подходит к задаче, а со switch непредсказуемость полная.
Здравствуйте.
Доброе утро!
Проблема с кирилицей.
Позвольте уточнить, каким боком это относится к теме топика?
Как и у первого автора проблема записать и считать PROGMEM
sadman41, а нельзя пример привести, а то я не до конца понял о каком случае Вы говорите.
Статью Джонса прочитал, позабавило выражение "some sense of machismo" - оно в данном контексте очень точное. Человек, вместо того, чтобы почитать стандарт языка и прокачать свои знания о нём, затевает экспериментальное исследование и через весьма непростые эксперименты с удивлением узнаёт, что оказывается порядок проверки case-меток в языке не определён. Вообще-то, он мог узнать об этом просто читая стандарт. Сам люлю такие вещи, но должен признать, что это и есть то самое: "some sense of machismo" :)))))
Как и у первого автора проблема записать и считать PROGMEM
Во-первых, у него проблема не записать и прочитать, это он может, а "понять почему работает именно так".
Во-вторых, Ваша проблема связана не с чтением progmem, а непониманием как устроена кирилица. Вот здесь человеку вроде всё объяснили (и вообще, воспользуйтесь поиском - проблема кириллицы столько раз пережёвана уже!).
В-третьих, если Вы перейдёте в адекватную тему, с удвольствием с Вами поговрю (и не один я), но пожалуйста, прекратите зафлуживать эту - она не о кириллице.
тоже интересно, есть ли какая #pragma, чтоб вырубить оптимизатор хренов конкретно для данного одного файла. У меня, помню целый while из loop-а выкинул, а я пока допер своими синими мозгами, 3 ящика виски выпил.
тоже интересно, есть ли какая #pragma, чтоб вырубить оптимизатор хренов конкретно для данного одного файла.
#pragma GCC optimize ("string"...)
Вот. Я Вас сердечно и категорически благодарю.
Проверил. Работает.
опция #pragma GCC optimize "O0"
делает из 8106 байт программы аш 9214.
sadman41, а нельзя пример привести, а то я не до конца понял о каком случае Вы говорите.
Вот, к примеру (на моем дефолтово настроенном IDE 1.6.11):
void setup() { Serial.begin(9600); byte cb; char cc = (char) random(32,255); switch (cc) { case '0': cb = B1111110; break; case '1': cb = B0110000; break; case '2': cb = B1101101; break; case '3': cb = B1111001; break; case '4': cb = B0110011; break; case '5': cb = B1011011; break; /* case '6': cb = B1011111; break; */ } // switch Serial.println(cb, HEX); }Без case 5 и 6 - "Sketch uses 1,984 bytes" с case 5 "Sketch uses 1,990 bytes" (6 байт разницы), с сase 6 "Sketch uses 2,012 bytes" - разница уже в 22 байта. Начинаем добавлять case 7, case 8 такого же типа - по 6 байт накидывается. Потом опять скачок может быть.
Я, конечно, понимаю, что сейчас как-будто пытаюсь определить причину сбоя ОС по миганию индикаторов жестких дисков... В принципе мне это жить не мешает, но когда прошивка уже еле лезет в МК и тут тебе switch свинью начинает подкидывать - хотелось бы знать, как ему по сусалам-то дать.
делает из 8106 байт программы аш 9214.
И это не может не радовать! :))))))))
Да. Значит деффективный оптимизатор не отрезал всё, до чего дотянулса.
Не люблю, када у оптимизатора мозгов больше, чем у мня.
Ну, это (скачки) как раз его естественное поведение. Если нужно его избежать, то это надо решать либо таблицей (в данном примере просто сама просится), либо макросами SWITCH и CASE, которые прячут под собой if и else if.
Со свитчем есть гораздо худшая задница - когда в операции сравнения с меткой присутствует побочный эффект, то результат вообще в общем случае неопределён - вот это совсем беда.
Проверил на коротком примере - if-else-if дает более предсказуемый результат, конечно. И progmem чуток поменее занимает. На досуге попробую замастрячить в реальной функции - даст ли это существенный выигрыш... Хотя, конечно, мне очень нравятся вот эти прекрасные case без break, которые нужно как-то превращать в if (condition || condition), если ориентироваться на замену оператора switch() макросом.
Ну, это (скачки) как раз его естественное поведение. Если нужно его избежать, то это надо решать либо таблицей (в данном примере просто сама просится)
Это просто тестовый скетч. В полноценных и вызовы функций есть в case и сочетания значений, которые невыгодно, на мой взгляд, укладывать в таблицу, если только не придумывать какой-нибудь аналог hash array.
Побочный эффект в результате какого использования case? Даже представить боюсь.