Вопрос к знатокам, отлитым в бронзе

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Кто мне скажет ПОЧЕМУ лыжы не едуть? 


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 */

}

Я безусловно идиот, и многого по С++ не знаю, но это выше моего понимания.  ПАМАГИТИ!!!

Волшебник
Offline
Зарегистрирован: 22.12.2016

Что-то с памятью её стало, стринги на ардуине не велкам. Есть макрос для измерения доступной памяти, поищите. 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

А не отлитым можно отвечать?

И кстати, дед, то что память не при делах, а просто ты запутался в квалификаторах - это понятно. Но, не веди себя как новичок - объясни чего ты хотел. Конкретный вопрос - чего ты хотел от массив DoW_Array? Он сам должен сидеть в оперативной памаяти или в програмной?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

    str = PFlashString(DoW_Array[2]); печатается правильно

    str = PFlashString(DoW_Array[idx]); печатается неправильно, хотя idx == 2

пошто? 

Наерно, это только Дракула сможет рассказать, пока трезв, или ЕвгенийП, если снизойдут. 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Мля, я тоже могу, если ты мне ответишь на мой вопрос.

Сами строки у тебя живут в progmem, а массив указателей DoW_Array - где? Вернее, где ты хочешь, чтоб он жил?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Это относится к делу?  Тогда хочу, чтоб в PROGMEM. Смысла нет держать массив константных указателей в оперативке

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Кароче, у тебя два варианта.

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) (пробуй и это)

В любом из этих двух случаев у тебя всё будет работать правильно.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

На вопрос: "относится к делу?" ответ уже понятен? Просто сравни два описанных выше варианта.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

а я не спрашивал, что надо делать.  Я спрашивал ПОЧЕМУ работает по разному при индексе массива == константа и при взятии его из переменной, хотя на мой взгляд, разницы быть не должно.  

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Потому, что в стоке 32 - константа и компилятор просто подставил готовое значение не вычисляя элемент массива по индексу - тупо сам вычислил и в исполняемом коде у тебя уже сидит готовая "среда".

А в строке 37 он вставил код для честного вычисления "к адресу начала массива прибавить содержимое idx и из получившегося адреса взять содержимое", а посколько это содержимое на самом деле сидит в прогмеме, вот он у тебя и сломался.

Я же во втором примере явно написал то же самое (к адресу прибавил содержимое idx) только при этом указал, что содержимое надо из прогмема брать, вот он нормально и сработал.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Мда.  Говорила мне мама, не лезь в С++ со своим скудоумием.  

Паду пить. 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Это называется "неявное преобразование типов в С++" ?

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen - когда я делал точно такую коллекцию строк в своем скрипте - я счастливо избежал этой ловушки, поместив массив указателей в оперативку. Указатели занимают мало, поэтому совершенно незачем класть их во флеш, зато работать с ними в оперативке много удобнее.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Всё равно нихрена не понимаю 

	Serial << idx++ << ". " << PFlashString(dow02) << '\n';                 // правильно
	Serial << idx++ << ". " << PFlashString(*(DoW_Array+2)) << '\n';        // правильно
	Serial << idx   << ". " << PFlashString(*(DoW_Array+idx)) << '\n';      // неправильно

где я баран?

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

где я баран?

ну вроде Ворота все понятно обьяснил в сообщении №9. В первых двух случаях адрес элемента известен на момент компиляции, в третьем - вычисляется в процессе выполнения. Вот и разница.

А смотрищь как баран на Ворота :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ви таки не поверите, но вот так тоже не работает

__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 не описана. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

вопщем, я думаю, дожность помошника кочегара деревенской котельни при курятнике - потолок моей карьеры.   

Вопрос снят, всем спасибо. 

Пойду пить, а потом котельни обзванивать в области. 

b707
Offline
Зарегистрирован: 26.05.2017

лучше обьясни мне другое - зачем в этой строке два раза const

const char *const DoW_Array[] PROGMEM = { dow00,dow01,dow02,dow03,dow04,dow05,dow06 };

Вот смотри - char* array[] - это массив указателей на данные типа char

const char* array[] - это массив, где эти указатели являются константами

А второй const - указание на то, что и данные по указателям - константы? - а зачем это обьявлять, ведь указателям все равно, на что указывать -  на переменные или константы. А сами строки ты и так обьявил контантами и компилятор это учитывает.

По-моему, второй конст из определения массива можно безболезненно выкинуть. Или ошибаюсь?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

второй const для PROGMEM, чтоб массив указателей тоже во флэше лежал.

const char *const   - константный указатель на константные данные. 

А вот это 

const char* array[] 

значить только то, что ты array присвоить ничего не можешь в программе потом

 

ЗЫ.  как я люблю фонНеймана и его архитектуру.  С децтва прям.  А этих гарвардских умнеков - нинавижу. 

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

DetSimen пишет:

Пойду пить

Погодите квасить с утра! В этой теме ещё до самого забавного и не добрались :)))

Попробуйте взять свой изначальный код со словом PROGMEM в описании массива и без этого слова. Скомпилируйте оба варианта и сравните количество замнимаемой программной памяти :)))))))

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

второй const для PROGMEM, чтоб массив указателей тоже во флэше лежал.

Нет, это первый const для PROGMEM. А второй const ты смело можешь убрать и класть массив в PROGMEM - второй конст для этого не нужен, попробуй.

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

Попробуйте взять свой изначальный код со словом PROGMEM в описании массива и без этого слова. Скомпилируйте оба варианта и сравните количество замнимаемой программной памяти :)))))))

значит я в сообщении #12 был прав - нет смысла класть указатели во флеш. Правда сделал я это не от большого ума, а от лени, но все равно приятно :)

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

b707 пишет:

значит я в сообщении #12 был прав - нет смысла класть указатели во флеш. 

Почему нет? Сравните там же расход оперативной памяти. Со словом PROGMEM он меньше.

Мой-то иезутсякий вброс был не про оперативную, а именно про программную память.

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

Мой-то иезутсякий вброс был не про оперативную, а именно про программную память.

А, ну это я тоже как-то тестировал. Помещение чего-либо во флеш - очень неэкономная операция, например короткие строки класть во флеш крайне невыгодно, за выигрыш пары байтов оперативки платишь десятками и даже сотнями байтов флеша...

Сейчас не могу проверить этот пример, нет компилятора под рукой.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

c PROGMEM 

// const char *const DoW_Array[] PROGMEM= { dow00,dow01,dow02,dow03,dow04,dow05,dow06 };

 
Program size: 1 994 bytes (used 6% of a 32 256 byte maximum) (3,65 secs)
Minimum Memory Usage: 189 bytes (9% of a 2048 byte maximum)
 
без него 
 
// const char *const DoW_Array[] = { dow00,dow01,dow02,dow03,dow04,dow05,dow06 };
 
 
Program size: 1 994 bytes (used 6% of a 32 256 byte maximum) (3,69 secs)
Minimum Memory Usage: 203 bytes (10% of a 2048 byte maximum)
 
 
тут я почему-то никаких странностей не вижу, оперативки на 7 указателей, 14 байт больше жрёть. 

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

а так так этот массив относится к инициализированным данным, то он и во флэше хранится тоже и плюс копируется рантаим библиотекой в ОЗУ при старте, поэтому занятая память программ не изменилась

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

у меня то вопрос,  в чем разница для компилятора параметры-непосредственные константы и переменные, почему в первом случае адрес строки вычисляется правильно, а во втором - нет

	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]);
}

даже вот так - неправильно 

	return (__FlashStringHelper *)(*(DoW_Array+idx));
 

 

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

Так Вам же всё объяснили. Если компилятор может вычислить нечто - он вычисляет и подставляет готовую константу. То, что у Вас это вызов функции, и даже не инлайн - ему плевать с высокой колокольни - если может, то вычислет и подставляет готовый результат. Что Вы и наблюдаете.

Я как-то про такие особенности оптимизации долго объяснял одному, прости Господи, википедику ... сам по себе срач - дерьмо голимое, но там был очень красивый пример, как компилятор заменил вызов РЕКУРСИВНОЙ (!!!!) функции на готовый результат! О как! Там правда функция была инлайн. Сейчас я специально проверил без инлайн. Смотрите

// Вычисление факториала
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 вот такую:

  24 0000 88E7      		ldi r24,lo8(120)
  25 0002 85B9      		out 0x5,r24
  26 0004 0895      		ret

и ВСЁ! Как видите он просто выбросих нахрен функцию fact, а вместо вызова fact(5) вставил готовый результат 120.

Ппоробуйте сами скомпилировать и посмотреть, чтоб уж не сомневаться.

Нравится современная оптимизация?

Насчёт опций - это важно. Разумеется, если убрать оптимизацию, то ничего такого не будет.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Спасибо Вам за науку, а компилятору - за оптимизацию.  

Тему можно закрывать. 

Не готов я еще для С++. 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Красиво. А если убрать из описания параметра const - тоже соптимизирует? Как-бы указалово const обещает что функция будет получать только константы времени компиляции. Вполне разумно скомпилять функцию и попытаться её вызвать дабы получить результат ещё на этом этапе.. а вот ежели нету const?

Сам пока проверить не могу, но интересно..

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

Убрал 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){}

 Результат

  25 0000 88E1      		ldi r24,lo8(24)
  26 0002 85B9      		out 0x5,r24
  27 0004 0895      		ret

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Arhat109-2 пишет:

Как-бы указалово const обещает что функция будет получать только константы времени компиляции. 

Что за дичь? Ничего такого const не обещает, он лишь гарантирует, что входящий параметр, помеченный квалификатором const, не будет изменён внутри функции. Константы времени компиляции - тут не при делах, от слова "совсем".

Logik
Offline
Зарегистрирован: 05.08.2014

Нашли проблему.. Вытягую из исходников контролера самогонного и либок. Проверено, работает.


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.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Сорри, неверно выразился, ЕвгенийП меня понял верно, пасибки.

Ну и? Получается что 13-й тип оптимизации (глобальная оптимизация потока управления по анализу потока данных) уже по сути внедрен в компиляторы, остается ждать когда памяти хватит на 14-й - глобальная оптимизация потока данных .. когда кумпилятыр станет способен самостоятельно преобразовывать разную муть из комплекта переменных, массивов и объектов в то, что посчитает лучшим решением .. а там, недолго ждать когда оно само и кодить начнет. :)

PLYT
Offline
Зарегистрирован: 06.11.2017

Здравствуйте.Проблема с кирилицей.Это работает.

[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]

Плата нано китайская

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Что это и о чем это... в чем разница... кто это писал... для чего.... ?

PLYT
Offline
Зарегистрирован: 06.11.2017

Разница в String1.По задумке будет выводить сообщения на OLED0.96.Скетч из стандартных примеров,кроме сообщений естественно.

sadman41
Offline
Зарегистрирован: 19.10.2016

Обождите тему закрывать, у меня тоже вопрос имеется, как и у Симеона...

Вопрос простой: как приструнить компилятор (может есть какая 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 непредсказуемость полная.

 

 

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

PLYT пишет:

Здравствуйте.

Доброе утро!

PLYT пишет:

Проблема с кирилицей.

Позвольте уточнить, каким боком это относится к теме топика?

 

PLYT
Offline
Зарегистрирован: 06.11.2017

Как и у первого автора проблема записать и считать PROGMEM

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

sadman41, а нельзя пример привести, а то я не до конца понял о каком случае Вы говорите.

Статью Джонса прочитал, позабавило выражение "some sense of machismo" - оно в данном контексте очень точное. Человек, вместо того, чтобы почитать стандарт языка и прокачать свои знания о нём, затевает экспериментальное исследование и через весьма непростые эксперименты с удивлением узнаёт, что оказывается порядок проверки case-меток в языке не определён. Вообще-то, он мог узнать об этом просто читая стандарт. Сам люлю такие вещи, но должен признать, что это и есть то самое: "some sense of machismo" :)))))

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

PLYT пишет:

Как и у первого автора проблема записать и считать PROGMEM

Во-первых, у него проблема не записать и прочитать, это он может, а "понять почему работает именно так".

Во-вторых, Ваша проблема связана не с чтением progmem, а непониманием как устроена кирилица. Вот здесь человеку вроде всё объяснили (и вообще, воспользуйтесь поиском - проблема кириллицы столько раз пережёвана уже!).

В-третьих, если Вы перейдёте в адекватную тему, с удвольствием с Вами поговрю (и не один я), но пожалуйста, прекратите зафлуживать эту - она не о кириллице.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

тоже интересно, есть ли какая #pragma, чтоб вырубить оптимизатор хренов конкретно для данного одного файла.  У меня, помню целый while из loop-а выкинул, а я пока допер своими синими мозгами, 3 ящика виски выпил. 

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

DetSimen пишет:

тоже интересно, есть ли какая #pragma, чтоб вырубить оптимизатор хренов конкретно для данного одного файла. 

#pragma GCC optimize ("string"...)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Вот.  Я Вас сердечно и категорически благодарю.

Проверил.   Работает.

  опция #pragma GCC optimize "O0"

делает из 8106 байт программы аш 9214. 

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

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 свинью начинает подкидывать - хотелось бы знать, как ему по сусалам-то дать.

 

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

DetSimen пишет:

делает из 8106 байт программы аш 9214. 

И это не может не радовать! :))))))))

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Да.  Значит деффективный оптимизатор не отрезал всё, до чего дотянулса. 

Не люблю, када у оптимизатора мозгов больше, чем у мня. 

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

Ну, это (скачки) как раз его естественное поведение. Если нужно его избежать, то это надо решать либо таблицей (в данном примере просто сама просится), либо макросами SWITCH и CASE, которые прячут под собой if и else if.

Со свитчем есть гораздо худшая задница - когда в операции сравнения с меткой присутствует побочный эффект, то результат вообще в общем случае неопределён - вот это совсем беда.

sadman41
Offline
Зарегистрирован: 19.10.2016

Проверил на коротком примере - if-else-if дает более предсказуемый результат, конечно. И progmem чуток поменее занимает. На досуге попробую замастрячить в реальной функции - даст ли это существенный выигрыш... Хотя, конечно, мне очень нравятся вот эти прекрасные case без break, которые нужно как-то превращать в if (condition || condition), если ориентироваться на замену оператора switch() макросом.

ЕвгенийП пишет:

Ну, это (скачки) как раз его естественное поведение. Если нужно его избежать, то это надо решать либо таблицей (в данном примере просто сама просится)

Это просто тестовый скетч. В полноценных и вызовы функций есть в case и сочетания значений, которые невыгодно, на мой взгляд, укладывать в таблицу, если только не придумывать какой-нибудь аналог hash array.

ЕвгенийП пишет:

Со свитчем есть гораздо худшая задница - когда в операции сравнения с меткой присутствует побочный эффект, то результат вообще в общем случае неопределён - вот это совсем беда.

Побочный эффект в результате какого использования case? Даже представить боюсь.