Алгоритм выбора с условием

Я тут уже снотворного выпил и спать собрался и мозг родил аналогию. Может дойдет?

АНАЛОГИЯ:

Ты учишь сына варить яйцо на завтрак.
-Смотри. Закипела вода, шумовкой кладешь яйцо, 2 минуты - полусырое, 4 всмятку, 6 - в мешочек, 9 крутое. Всё. Вот и вся наука.
-Папа, я кладу в холодную воду и жду, как закипит.
-Мля! Сына! Я тебе сказал - в кипяток!
-Папа! Что нельза просто сказать, сколько варить в холодной!
-Тваюмать! Нет, нельзя! Хер его знает, какая кастрюля, сколько воды, на каком газу? Нельзя ничего точно сказать.
Вот! Я же говорил, что ты папа нихрена не умеешь яйца варить!
:wink: :wink: :wink:
очень похоже, как мне кажется…

Как раз я на равных и общаюсь тут если ты не заметил… Кто со мной вежливо с тем и я так же,… А если имеешь ввиду, что ты не ответишь на мой вопрос, ой… да бога ради… ну попердишь немного… Думаешь я без тебя не справлюсь - ошибаешься, но говном в данном случае ты и останешься. Это я не тебе лично, Влад, а то подумаешь сейчас… хотя можешь и на себя примерить :wink:

Вообще ни сколько)))) Я постоянно тут читаю ваши аналогии на этом сайте, кто чего только не придумает в свое возвышение)))) Детский сад “Колокольчик”… Впрочем для детей, студентов может это и прокатывает…))))
По делу… какие нахрен яйца? Тут цифровое все, четкое задание выдать последовательность байт исходя из данных. Но реализовать эту последовательность можно по разному, я только ТРИ варианта привел, а их можно напридумывать 100500… Эх, вы… (

кроме программиста. Все приемы программирование выработаны для того, чтобы программисту было сложнее “выстрелить себе в ногу”.
Именно поэтому код не очень хорош.
Переусложнен код потому, что массив, который вложенным вывозом инициализируется. Зачем? Ну и используй его локально в getNext или, что гораздо лучше, передавай битовую маску, сразу и памяти херову гору сэкономишь…

Ну и “трёх” никаких не было. Были попытки перебрать варианты без цикла. Можно их не считать? :wink: Надеюсь…

Еще, пока не уснул. Забудь про экономию памяти путем переноса переменных на стек (в локальные) для однозадачных МК. Нет никакого смысла в этом. Тогда уж лучше, если МК Гарвардской архитектуры, в память программ перенести массивы.
И при маленьком ОЗУ следует ограничивать вложенные вызовы, избегать рекурсии.
Локальные переменные - на стеке. Который не имеет никаких проверок в рантайм.
То есть куча в стек не залезет, маллок не выдаст памяти, а наоборот - сколько угодно, при росте стека в кучу МК никак ничего не скажет.
Старайся писать, понимая как код будет работать в рантайм.
Помни, что на стеке следует размещать то, что реально, по потоку программы, требуется лишь временно и живет счмтанные миллисекунды.
Это не то, чтобы правило, это полезный навык. То что нужно долго - размещаем на куче.

2 лайка

Блин, спать уже собрался, скоро в рейс…
Но за это сообщение спасибо. Скажу честно, не все сказанное понятно, стек, куча… Я не первый раз эти слова слышу, но для меня они очень сложны в понимании, так как в этом деле самоучка, это просто моё хобби. Низкий уровень не знаю ни черта, а вот высокий - ну я бы не сказал, что я совсем лох. Но в любом случае есть над чем подумать и от души спасибо!
И ещё, Влад, не сочти за наглость но напиши полный код как это сделал бы ты… Но это уже не сейчас… Если в ночь вызовут я уеду на некоторое время, но в телефоне смогу немного участвовать))

Я вижу, тут уже более чем достаточно комментариев и разъяснений. Уже сказали выше, просто уйти от локального массива , объявив его static. Здесь, как у меня в соседней ветке: простой пример работает норм, а задумаешь усложнить код, так где-нибудь вылезут косяки. Поэтому лучше сразу делать правильно ИМХО.
Насчёт экономии памяти создавая каждый проход loop массив, тоже не очень. Другого кода , с кнопкой, я не видел. Возможно, всё-же где-то придётся хранить текущее состояние меню.

Для разрядки обстановки, на основе вашего, набросал скетчик, где для хранения статуса пункта меню достаточно одного байта, даже место остаётся))

Спойлер

#define ITEM_COUNT 5

void setup() {
  Serial.begin(115200);
}

byte getMenu(byte CurrInd) {
  static byte ItemStat = B00010101;//байт для хранения статуса
  byte mask = 1;                   //пунктов меню: 0-й бит - 1пункт
  if (CurrInd >= ITEM_COUNT) return 0; // 1-й - 2пункт и.т.д.
  for (byte i = CurrInd; i < ITEM_COUNT; i++)
    if (ItemStat & (mask << i)) return i + 1;
  return 0;
}

void loop() {
  static byte Ind = 0;
  Ind = getMenu(Ind);
  Serial.println(Ind);
  delay(500);
}

1 лайк

Я таким способом со сдвиговым регистром работаю, зажигая светодиоды состояний в другом проекте…

Ни одного по факту. За исключением последнего от Дракулы. И то, там написано для меня, самоучки, немного сложновато, но это мои проблемы…
Но что-то я все равно понял, а что-то даже знаю, например про рекурсии и как вызываются функции, как в данном случае работает стек и хранятся параметры-переменные… но я это понимаю по своему, объяснить может и не смогу…(

Дело не в массиве и не в его области видимости… Мне важно было понять правильно ли я сделал работу с указателем на него, да я специально это усложнил, сделал для себя первый раз, чтобы параметром в функцию передать другую функцию, которая вернет локальный массив… Трудно для понимания? Согласен.
Но если посмотреть в исходник GRBL то там вообще черт ногу сломает… А блинки писать уже не интересно…

Если все делать правильно, то как не усложняй код, то он все равно будет работать без глюков и косяков…
Как я уже понял из этой ветки и “другого” интернета - с указателями я все таки верно сделал… Буду разбираться, тем более если ошибся, то ничего страшного. Луна не упадет))))

Да чего его видеть-то… Представить сложно?) Да, у меня тоже сложно с воображением такого плана)))… Ладно, просто понять, что код лупа, это отдельная функция, которая вызывается раз в месяц (например по таймеру)

Я же объяснял, что этого делать НЕ НУЖНО, Какой смысл хранить целый месяц прошлое состояния элементов, которые могут поменяться, даже когда тянешь палец к кнопке?

Спасибо)))
Я почему то становлюсь уверен, что вы не верно понимаете работу моей функции, и это понятно… ее можно понять, только когда увидишь это дело в работе на реальном железе, а не так огрызком кода…

Так тоже не пойдет, так как если бы внимательно читали мои сообщения, а я всегда стараюсь подробно все объяснять… но видимо от этого только хуже становится в моих постах… Новичек, чё… че тут нам парит моск))))
Так вот по поводу Индекса, почему его нельзя локально, хоть и статик, потому что этот индекс можно и нужно сбрасывать в “особых случаях” из других мест программы… Сложно все это… но я хотел как проще, сделал даже пример как тут полагается именно “проблемного” участка… Но в итоге получается, что я со всеми спорю, потому как вы видите только узкий момент, но не все в целом… понятно дело, что в этом узком моменте можно все переиграть на свой вкус, но зачем, у меня были конкретные вопросы, зачем все переворачивать?

ЗЫЖ @Дим-мычъ , это не только Вам… это всем))

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

Это невнимательность, хоть и говорил, что целый час изучал ветку, не верю…
Или в голове не укладывается, что вопрошающий может и что-то объяснять? Если я что-то не верно говорил Димычу, так поправьте… это всем будет полезно, не только мне, а так, как сейчас, если я верно говорю, но все на меня накинулись, то все что мной сказано будет восприниматься как ошибка. Оно это надо?)
Что млякоть то сразу))))
ЗЫЖ Что-то поездов нет… везти нечего… на работу не вызывают… Поэтому вырвался крик из души))))) Так что если кому долго идет посылка с алика… сорян… я в этом не виноват))))

Понял, буду исправляться

1 лайк

Тут не только вам, тут всему форуму исправляться нужно. Всем в угол на колени, можно еще гречки для лучшего осознания.

Снести весь форум в ЧЧ. Только эту тему оставить в “проектах”

1 лайк

:astonished:

Спойлер
void F() {
  byte arr[10000];
  .....
}

void G() {
  byte arr[10000];
  .....
}


void setup() {
  
}

void loop() {
  if (прошел час) F();
  if (прошло еще много времени) G();
}

Это, что получается… оба локальных массива будут всегда в памяти (ОЗУ)?

С этим все понятно. Рекурсия “забьет” стек своими параметрами, но в моем случае (вложенные вызовы) передается один раз и только указатель (4 байта)

Это всегда должно быть на первом месте!
Остальное комментировать не буду… сложновато мне)))

Если бы не такие комментарии, то форум не засорялся бы… Но и без них скучно, жаль только становится все бесполезно)))

Вы как дети тут… хоть многим уже больше полувека от роду… Сретесь и сретесь… где сели там и насрали… Ну есть же специальные места (разделы) для этого, там без дела можно попиз@ить… зачем лезть туда, где срать-то нельзя… Ну дети, ё-моё))))

нет. ты не не понял.

Локальные переменные размещаются на стеке. То есть для них должно быть достаточно места на стеке. Если переменная нужна дольше чем “один лишь миг”, то не нужно её размещать на стеке.

В твоем случае ты размещаешь временные данные, но в коде они не собираются “на просторах вселенной”, а задаются, то есть программа в коде содержит эти данные. Ну так и положи их сразу так, как надо! Ты же сперва отвел память на стеке (локальный массив), потом его заполнил данными, которые УЖЕ есть в МК, только в памяти программы.

Еще раз, если не понятно. Это не закон. Это прием того, как НЕ выстрелить себе в ногу. Как мыть руки перед едой. В целом - конечно нет гигиенической необходимости, то тех пор пока не подхватишь дизентерию. 100 человек никогда не подхватят, а один проведет незабываемую неделю на горшке! :wink:

Так, я сейчас не затем компом, где у меня программа, поэтому абстрактным кодом напишу. Мой массив состояний в принципе и нужен лишь на время, пока отработает функция getNextIndex. В остальное время он нафик не нужен.
Перенести его(массив) в getNextIndex можно, но для облегчения читания кода я как раз и вынес это в отдельную функцию, так как один элемент массива - это примерно вот так: arr[n] = Pump[n].Enable && !Pump[n].ErrorData.Code && (Pump[n].Sens.Raw < Pump[n].RawOff || Pump[n].Sens.Raw > CritLowPress)… и может еще что-то, не помню…
Так вот из-за такой конструкции и вынес заполнение массива в отдельную функцию…
Про вычисление логических выражений в курсе, располагать их стараюсь так, что бы легкие вычисления и более вероятные значения ставлю раньше, Что бы при однозначном результате остальные не высчитывались… тут не соблюл этот порядок… написал что вспомнил…

ничего страшного… я же учусь… столько раз уже сидел на горшке… хорошо, хоть каждый раз инфекция новая(другая) Набираюсь опыта, переписываю с уже новыми, полученными знаниями… набираю иммунитет, так что посидеть на горшке тоже полезно :)))

Так то да, и массив в общем то не нужен, можно просто эти выражения(которые при заполнении массива) использовать в getNextIndex,… ну это ужасно будет, если учесть, что один пункт там заполняется отдельно arr[n] = Heat.Enable && …
Может я конечно и не прав, сделав массив и вынес его заполнение в отдельную функцию, но… но код получился гораздо читаемым, чем… со всей этой “кашей”
Дайте посмотреть на ваш код… что там у вас? Вы блинки пишите? )))) …это всем)

… что там у вас? Вы блинки пишите? )))) …это всем)

:slight_smile:
Вот же блинк!
VID_20230207_112140

//имитатор 20 светодиодов на цветном дисплее st7735 128*160
//групповой блинк
#include "svetodiod_.h"
long Y[20];//моменты переключения
int t[20]={127,220,380,500,550,600,660,180,240,400,490,560,620,700,745,800,333,444,777,999};//длительности
bool flag[20];//флаги состояний
uint16_t color[]={green,yellow,orange,blue,
 green,yellow,orange,blue,green,yellow,orange,blue,
 green,yellow,orange,blue,green,yellow,orange,blue};//цвета

void setup() {
 fun_setup();
 }
void loop() {
 for(int i=0;i<20;i++){
 if(millis()-Y[i]>t[i]){
 Y[i]=millis();flag[i]=!flag[i];
 if(flag[i]){led_(i,color[i]);}else{led_(i,off);}
 }
 }
 }

Файл svetodiod_.h думаю не интересен.

1 лайк

Какой же это Blink? Не живой, не тёплый, не ламповый
:frowning:

Я хотел сделать на 20 светодиодах, но понял, что провода и резисторы не осилю в макете.
Получилось как в кино - … бляааа!, он как живой, только не живой.