Помогите найти ошибку

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
Добрый день!
Меня зовут Андрей, прошу помощи в поиске ошибки в программе.
Скетч с набором эффектов создан для гирлянды ws2811 состоит из кучи циклов, написанных мной или позаимствованных из разных источников, управление через Ардуино микро.
Программирование - хобби, поэтому скетч не оптимальный, конечно.
Все работает, за исключением одной проблемы, решение которой я не смог найти своими силами. Дело в следующем:
Циклы в диапазонах строк 133-143 и 164-174 вызывают переход в начало программы после строки 257.
При этом сами они (133-143 и 164-174 ) работают корректно и следующие за ними - тоже.
При удалении их из общей программы (закомментировании) скетч отрабатывает до конца, как и требуется.
C++:
// FastLED
// куча эффектов нон-стоп по кругу
#define NUM_LEDS 100
#include "FastLED.h"
#define PIN 6
CRGB leds[NUM_LEDS];
byte counter;
void setup() {
  //Serial.begin(57600);
  FastLED.addLeds<WS2811, PIN, RGB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness(200);
  pinMode(13, OUTPUT);
}
void fadeall()
{
  for (int i = 0; i < NUM_LEDS; i++)
  {
    leds[i].nscale8(250);
  }
}

void loop()
{
  // эффект Cylon
  static uint8_t hue = 0;
  //Serial.print("x");
  // First slide the led in one direction
  for (int i = 0; i < NUM_LEDS; i++) {
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(50);
  }
  // Serial.print("x");
  // Now go in the other direction.
  for (int i = (NUM_LEDS) - 1; i >= 0; i--) {
    // Set the i'th led to red
    leds[i] = CHSV(hue++, 255, 255);
    // Show the leds
    FastLED.show();
    // now that we've shown the leds, reset the i'th led to black
    // leds[i] = CRGB::Black;
    fadeall();
    // Wait a little bit before we loop around and do it again
    delay(50);
  }
  fill_solid( leds, NUM_LEDS, CRGB::Black);

  // случайное включение и гашение LED
  uint32_t x = millis();
  while (millis () - x < 15000)
  {
    leds [random8 ( NUM_LEDS)] = CRGB(random8( ), random8(), random8()); // полностью случайные цвета
    leds [random8( NUM_LEDS)] = CRGB(0, 0, 0); // случайное гашение
    FastLED.show();
    delay( 50 );
  }

  // переливы цвета
  int dk = 0;
  int dl = 1000;
  for ( int i = 0; i <= 255; i ++ )
  {
    fill_solid( leds, NUM_LEDS, CRGB(255 - i, 0, i)); // красный - синий
    FastLED.show();
    delay (dk);
  }
  delay (dl);
  for ( int i = 0; i <= 255; i ++ )
  {
    fill_solid( leds, NUM_LEDS, CRGB(0, i, 255 - i)); // синий - зеленый
    FastLED.show();
    delay (dk);
  }
  delay (dl);
  for ( int i = 0; i <= 255; i ++ )
  {
    fill_solid( leds, NUM_LEDS, CRGB(0, 255 , i)); // зеленый - голубой
    FastLED.show();
    delay (dk);
  }
  delay (dl);
  for ( int i = 0; i <= 255; i ++ )
  {
    fill_solid( leds, NUM_LEDS, CRGB(i, 255 - i, 255)); // голубой - фиолетовый
    FastLED.show();
    delay (dk);
  }
  delay (dl);
  for ( int i = 0; i <= 255; i ++ )
  {
    fill_solid( leds, NUM_LEDS, CRGB(255, i, 255 - i)); // фиолетовый - желтый
    FastLED.show();
    delay (dk);
  }
  delay (dl);
  for ( int i = 0; i <= 255; i ++ )
  {
    fill_solid( leds, NUM_LEDS, CRGB(255, 255 - i, 0)); // желтый - красный
    FastLED.show();
    delay (dk);
  }
  delay (dl);

  //   случайные оттенки красного альтернативный

  int i = 0;
  while (i < 5000)
  {
    leds [random (0 - NUM_LEDS)] = CRGB( 255, random(0 -  75), random(0 - 75));
    leds [random (0 - NUM_LEDS)] = CRGB(0, 0, 0); // случайное гашение
    FastLED.show();
    delay( 2 );
    i++;
  }



  // сплошное заполнение цветом
  for ( int i = 0; i < NUM_LEDS; i ++ )
  {
    leds[i] =  CRGB( 0, 255, 0);
    FastLED.show();
    delay (50);
  }
 
  // случайные оттенки зеленого
  // если раскомментирован этот цикл, то после прохождения одного цикла вместо пяти в пределах
  // строк скетча №№ 204-257 происходит возврат в начало всего скетча
  //  x = millis();
  //  while (millis () - x  < 10000)
  //  {
  //    leds [random (0 - NUM_LEDS)] = CRGB(random(0-75), 255, random(0 - 75));
  //    leds [random (0 - NUM_LEDS)] = CRGB(0, 0, 0); // случайное гашение
  //    FastLED.show();
  //    delay( 30 );
  //  }

  for (int i = 0; i < NUM_LEDS; i ++ )
  {
    leds[i] =  CRGB( 0, 255, 255);
    FastLED.show();
    delay (50);
  }
  for ( int i = 0; i < NUM_LEDS; i ++ )
  {
    leds[i] =  CRGB( 255, 0, 0);
    FastLED.show();
    delay (50);
  }
  for ( int i = 0; i < NUM_LEDS; i ++ )
  {
    leds[i] =  CRGB( 0, 0, 255);
    FastLED.show();
    delay (50);
  }

  // случайные оттенки синего
  // если раскомментирован этот цикл, то после прохождения одного цикла вместо пяти в пределах
  // строк скетча №№ 204-257 происходит возврат в начало всего скетча
  //  x = millis();
  //  while ( millis () - x < 20000)
  //  {
  //    leds [random (0 - NUM_LEDS)] = CRGB(random(0 - 100), random(0 - 100), 255);
  //    leds [random (0 - NUM_LEDS)] = CRGB(0, 0, 0); // случайное гашение
  //    FastLED.show();
  //    delay( 5 );
  //  }

  //   случайные оттенки синего альтернативный ( зависает после 1 цикла на
  //   строках скетча №№ 204-257
  //  uint32_t now = millis();
  //  while (millis () - now < 15000)
  //  {
  //    // тут в течение 15000 миллисекунд вертится код
  //    leds [random (0 - NUM_LEDS)] = CRGB(random(0 - 100), random(0 - 100), 255);
  //    leds [random (0 - NUM_LEDS)] = CRGB(0, 0, 0); // случайное гашение
  //    FastLED.show();
  //    delay( 5 );
  //
  //  }
  //  now = millis();


  for ( int i = 0; i < NUM_LEDS; i ++ )
  {
    leds[i] =  CRGB( 255, 255, 0);
    FastLED.show();
    delay (50);
  }
  for ( int i = 0; i < NUM_LEDS; i ++ )
  {
    leds[i] =  CRGB( 255, 0, 255);
    FastLED.show();
    delay (50);
  }

  // бегущие тройки разных цветов
  int l = 0;
  int j = 0;
  int k = 0;
  int d = 0;
  int de = 5; // здесь установлена задержка бегущего LED
  do
  {
    for (int i = 0; i <= NUM_LEDS + 2; i ++ )
    {
      j = i - 1;
      k = i - 2;
      l = i - 3;
      if (d < 1)
      {
        leds[i] =  CRGB( 0, 255, 0);
        leds[j] =  CRGB( 0, 255, 0);
        leds[k] =  CRGB( 0, 255, 0);
        leds [l] = CRGB ( 0, 0, 0);
      }
      else if (d < 2)
      {
        leds[i] =  CRGB( 0, 0, 255);
        leds[j] =  CRGB( 0, 0, 255);
        leds[k] =  CRGB( 0, 0, 255);
        leds [l] = CRGB ( 0, 0, 0);
      }
      else if (d < 3)
      {
        leds[i] =  CRGB( 255, 255, 0);
        leds[j] =  CRGB( 255, 255, 0);
        leds[k] =  CRGB( 255, 255, 0);
        leds [l] = CRGB ( 0, 0, 0);
      }
      else if (d < 4)
      {
        leds[i] =  CRGB( 255, 0, 255);
        leds[j] =  CRGB( 255, 0, 255);
        leds[k] =  CRGB( 255, 0, 255);
        leds [l] = CRGB ( 0, 0, 0);
      }
      else
      {
        leds[i] =  CRGB( 255, 0, 0);
        leds[j] =  CRGB( 255, 0, 0);
        leds[k] =  CRGB( 255, 0, 0);
        leds [l] = CRGB ( 0, 0, 0);
      }
      FastLED.show();
      delay( 50 );
    }
    d++;
  }
  while (d <  5);
// здесь происходит непредусмотренный переход в начало всей программы

  int y = 0;
  do
  {
    // две бегущие навстречу тройки
    for (int i = 0; i <= NUM_LEDS; i ++ )
    {
      j = NUM_LEDS - i;
      leds[i + 2] =  CRGB( 255, 255, 255);
      leds[i + 1 ] =  CRGB( 0, 255, 0);
      leds[i] =  CRGB( 255, 0, 0);
      leds[i - 1] =  CRGB( 0, 0, 0);
      leds[j - 3] = CRGB( 255, 0, 255);
      leds[j - 2] = CRGB( 255, 255, 0);
      leds[j - 1] = CRGB( 0, 0, 255);
      leds[j ] = CRGB( 0, 0, 0);

      FastLED.show();
      delay(100 );
    }
    y++;
  }
  while ( y <  5);


  k = 0; // заполнение одним бегущим LED
  do
  {
    for (int i = 0; i < NUM_LEDS - k; i ++ )
    {
      leds[i] =  CRGB( 255, 0, 0); // красный
      leds[i - 1] =  CRGB( 0, 0, 0);
      FastLED.show();
      delay( de );
    }
    k++;
  }
  while (k < NUM_LEDS);
  k = 0;

  // радуга от alexgyver
  do
  {
    for (int i = 0; i < NUM_LEDS; i++ ) {
      leds[i] = CHSV(counter + i * 8, 255, 255);  // HSV. Увеличивать HUE (цвет) (оттенок, насыщенность , уровень)
      // умножение i уменьшает шаг радуги
    }
    counter++;        // counter меняется от 0 до 255 (тип данных byte)
    FastLED.show();
    delay(2 );         // скорость движения радуги
    k++;
  }
  while (k < NUM_LEDS * 50);
  k = 0;

  // заполнение одним бегущим LED
  do
  {
    for (int i = 0; i < NUM_LEDS - k; i ++ )
    {
      leds[i] =  CRGB( 0, 255, 0); // зеленый
      leds[i - 1] =  CRGB( 0, 0, 0);
      FastLED.show();
      delay( de );
    }
    k++;
  }
  while (k < NUM_LEDS);
  k = 0;

  // радуга от alexgyver
  do
  {
    for (int i = 0; i < NUM_LEDS; i++ ) {
      leds[i] = CHSV(counter + i * 8, 255, 255);  // HSV. Увеличивать HUE (цвет) (оттенок, насыщенность , уровень)
      // умножение i уменьшает шаг радуги
    }
    counter++;        // counter меняется от 0 до 255 (тип данных byte)
    FastLED.show();
    delay(2 );         // скорость движения радуги
    k++;
  }
  while (k < NUM_LEDS * 50);
  k = 0;

  // заполнение одним бегущим LED
  do
  {
    for (int i = 0; i < NUM_LEDS - k; i ++ )
    {
      leds[i] =  CRGB( 0, 0, 255); // синий
      leds[i - 1] =  CRGB( 0, 0, 0);
      FastLED.show();
      delay( de );
    }
    k++;
  }
  while (k < NUM_LEDS);
  k = 0;

  // радуга от alexgyver
  do
  {
    for (int i = 0; i < NUM_LEDS; i++ ) {
      leds[i] = CHSV(counter + i * 8, 255, 255);  // HSV. Увеличивать HUE (цвет) (оттенок, насыщенность , уровень)
      // умножение i уменьшает шаг радуги
    }
    counter++;        // counter меняется от 0 до 255 (тип данных byte)
    FastLED.show();
    delay(2 );         // скорость движения радуги
    k++;
  }
  while (k < NUM_LEDS * 50);
  k = 0;

  // заполнение одним бегущим LED
  do
  {
    for (int i = 0; i < NUM_LEDS - k; i ++ )
    {
      leds[i] =  CRGB( 0, 255, 255); // голубой
      leds[i - 1] =  CRGB( 0, 0, 0);
      FastLED.show();
      delay( de );
    }
    k++;
  }
  while (k < NUM_LEDS);
  k = 0;

  // радуга от alexgyver
  do
  {
    for (int i = 0; i < NUM_LEDS; i++ ) {
      leds[i] = CHSV(counter + i * 8, 255, 255);  // HSV. Увеличивать HUE (цвет) (оттенок, насыщенность , уровень)
      // умножение i уменьшает шаг радуги
    }
    counter++;        // counter меняется от 0 до 255 (тип данных byte)
    FastLED.show();
    delay(2 );         // скорость движения радуги
    k++;
  }
  while (k < NUM_LEDS * 50);
  k = 0;

  // заполнение одним бегущим LED
  do
  {
    for (int i = 0; i < NUM_LEDS - k; i ++ )
    {
      leds[i] =  CRGB( 255, 0, 255); // фиолетовый
      leds[i - 1] =  CRGB( 0, 0, 0);
      FastLED.show();
      delay( de );
    }
    k++;
  }
  while (k < NUM_LEDS);
  k = 0;

  // радуга от alexgyver
  do
  {
    for (int i = 0; i < NUM_LEDS; i++ ) {
      leds[i] = CHSV(counter + i * 8, 255, 255);  // HSV. Увеличивать HUE (цвет) (оттенок, насыщенность , уровень)
      // умножение i уменьшает шаг радуги
    }
    counter++;        // counter меняется от 0 до 255 (тип данных byte)
    FastLED.show();
    delay(2 );         // скорость движения радуги
    k++;
  }
  while (k < NUM_LEDS * 50);
  k = 0;

  // заполнение одним бегущим LED
  do
  {
    for (int i = 0; i < NUM_LEDS - k; i ++ )
    {
      leds[i] =  CRGB( 255, 255, 0); //желтый
      leds[i - 1] =  CRGB( 0, 0, 0);
      FastLED.show();
      delay( de );
    }
    k++;
  }
  while (k < NUM_LEDS);
  k = 0;

  // радуга от alexgyver
  do
  {
    for (int i = 0; i < NUM_LEDS; i++ ) {
      leds[i] = CHSV(counter + i * 8, 255, 255);  // HSV. Увеличивать HUE (цвет) (оттенок, насыщенность , уровень)
      // умножение i уменьшает шаг радуги
    }
    counter++;        // counter меняется от 0 до 255 (тип данных byte)
    FastLED.show();
    delay(2 );         // скорость движения радуги
    k++;
  }
  while (k < NUM_LEDS * 50);
  k = 0;
}
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Не загружал, не тестировал, но очевидных проблем так не увидел. Проверять каждую переменную - увольте. Что могу предложить
У тебя в цикле куча переменных и наверняка часть из них пересекается с другими циклами - в этом может быть проблема.
Есть такое понятие область видимости переменных. Переменная видна в своем блоке и во всех блоках ниже, если она в них не переопределена.
C++:
int x=123;
Serial.println(x);
{
    while (x<125)
{
        Serial.println(x);
x++;
}
    x=20;
}
Serial.println(x);
выдаст
123
123
124
20
Но если сделать так:
C++:
int x=123;
Serial.println(x);
{
   int x=123;
    while (x<125)
{
        Serial.println(x);
x++;
}
    x=20;
}
Serial.println(x);
выдаст уже
123
123
124
123

Что можно сделать
1) самое простое взять каждый эффект в скобки { и } , тогда области видимости разделятся и точно будет ясно , что никакие переменные не пересекаются. Потребуется определение новых переменных в некоторых эффектах
2) Каждый эффект вынести в свою функцию. Почти то же , что и 1 , но больше возни. При этом читаемость кода увеличится.
 
  • Лойс +1
Реакции: Roden

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Глаз-алмаз! Кстати, это по поводу того разговора, что в си можно то, что нельзя. Вроде бы чушь, но она выдаст какое то значение !
 
  • Лойс +1
Реакции: Roden

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
random(0-75) -- это чего такое?
leds [random (0 - NUM_LEDS)] -- а вот тут ты что делаешь?
random (0-75) - это чтобы были оттенки определенного цвета были близкими к этому цвету
random (0 - NUM_LEDS) - случайное назначение светодиода из количества светодиодов в гирлянде
 

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
0-75 будет (-75). Это какой оттенок ? если надо от 0 до 75, то пишут (0, 75)
Согласен, исправлю. Но (0-75) и (0-NUM_LEDS) вполне себе корректно работают, в т.ч. и с оттенками. Коды пишу всего неделю, потому random (0-x) вообще по наитию попробовал, заработало, поэтому в библиотеку не полез )))
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Оно может и работает, но лучше так не делать. Вполне возможно, что там знак отбрасывается, но всегда есть шанс, что они забудут отбросить. А то получиться как нибудь запись типа random(5,-3), а она уж точно не сработает.
 
  • Лойс +1
Реакции: Roden

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
Понимаю, что мало кому интересно, но все же отпишусь:
Во всех random () исправил минус на запятую
Взял цикл, после которого скетч возвращался в начало (и следующий, на всякий случай, тоже) в скобки { }
Поменял все переменные в счетчиках millis() и проблемном цикле на уникальные
Проблема не ушла (
Может ли быть причина в таймерах на millis()? Ведь именно при их исключении из работы программы она начинает отрабатывать до конца и не возвращается в начало непонятно почему.
 

Roden

✩✩✩✩✩✩✩
19 Апр 2019
31
5
Согласен, исправлю. Но (0-75) и (0-NUM_LEDS) вполне себе корректно работают, в т.ч. и с оттенками. Коды пишу всего неделю, потому random (0-x) вообще по наитию попробовал, заработало, поэтому в библиотеку не полез )))
Массивы это участки памяти с определенным размером, считай таблица у которой есть адрес и значение.
Каждая строка в таблице имеет свой адрес (адрес предыдущей строки + количество байтов предыдущей строки), к примеру вот массив типа int
АдресЗначение (int занимает 4 байта, значеения от -2147483648 до 2147483647)
0 (адрес массива в памяти, все адреса в памяти начинаются с 0)Какое то значение от -2147483648 до 2147483647 (диапазон значений int)
4Какое то значение от -2147483648 до 2147483647 (диапазон значений int)
8Какое то значение от -2147483648 до 2147483647 (диапазон значений int)
12Какое то значение от -2147483648 до 2147483647 (диапазон значений int)
leds у тебя массив какого-то типа (предпалагю что int) размером 100, то есть в памяти у тебя 400 байтов под все эти значения.
Цифра в квадратных скобках leds[NNN] (в твоём случае ты получаешь эту цифру через random).
Когда ты передаёшь в random в max значение ниже минимального (а по умолчанию оно 0) ты рискуешь получать значения которые ты не хотел получать (а 0-NUM_LEDS таковым и является). Возможно, где то ты получаешь значения выходящие за рамки твоего массива (0-99), и тогда есть два варианта событий:
Вылет программы (возможно перезагрузка МК)​
Получение значений из вне массива, и тут начинается трэш, давай рассмотрим именно этот вариант поворота событий:​
Как я говорил ранеее, каждая переменная, массив получают какой то адрес в памяти (и самый первый адрес = 0).​
Возьмём вот эти переменные и разберём как они хранятся в памяти:​
C++:
int number;
boolean flag;
byte smallNumber;
int array[3];
Давай разберём сколько байтов занимает каждый тип данных для начала, а потом построим таблицу с адресами памяти​
int - 4 байта​
boolean - 1 байт​
byte - 1 байт​
массив int размером 3 ячейки - 4 байта для каждой ячейки, итого 12 байт​
Теперь давай сделаем таблицу адресов памяти и подпишем какой адрес относится к какой переменной​
ПеременнаяАдресРазмер значения в байтах
number0 (адрес начинается с 0)4 байта
flag0 (адрес number) + 4 (размер number) = 41
smallNumber4 (адрес flag) + 1 (размер flag) = 51
array[0]5 (адрес smallNumber) + 1 (размер smallNumber) = 64
array[1]6 (адрес array[0]) + 4 (размер) = 104
array[2]10 (адрес array[0]) + 4 (размер) = 144
Выглядит очень просто, а теперь давай рассмотрим вариант что random вернёт значение 0, а массив leds в нашем случае это array​
Значит мы говорим МК обратиться к адресу первого значения array (адрес 6) со сдвигом 0 значений int (умножая на размер intt, тобишь 4 байта = 0 * 4 байта = 0 байт), итого получаем адреес 6 + 0 = 6. Окей, всё отлично.​
Возьмём теперь пример что random вернуло 1, делаем то же самое, начало массива по адресу 6 + 4 байта так как сдвигаем 1 int = 10, тоже работает и получаем то что надо.​
А теперь рассмотрим вариант когда random вернёт -1, делаем то же самое, начало массива по адресу 6, умножаем размер int на смещение (-1 * 4 и получаем -4), прибавляем значение к адресу массива и получаем 6 - 4 = 2, итого ты попадаешь в пространство между number и началом массива. Ты получишь значение двух последних байтов number + значение flag + значение smallNumber, итого 4 байта, меняя уже это значение ты влияеншь на другие переменные, может одна из них потом передаёт значение к другой функции и вжух, МК не может обработать значение (потому что ты ожидал что в функцию ты передашь значение A, а из-за того что у тебя данные записались в другой адрес памяти ты передаёшь значение B).​
Конечно этот сценарий мало-вероятен так как сегодня МК умеют перезагружаться когда ты пытаешься получить значение из массива но передаёшь значение вне его диапозоне, но такой сценарий также надо иметь ввиду.​
p.s возможно где то ошибься
p.s.s если есть ошибки в тексте тапками не бросайтесь, ну не русский я
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Надо все эффекты брать в скобки. а лучше в отдельные функции. Кто его знает из какого эффекта это идет ?
И еще, а что если плата перегружается ?
 
  • Лойс +1
Реакции: Roden

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
Массивы это участки памяти с определенным размером, считай таблица у которой есть адрес и значение.
Каждая строка в таблице имеет свой адрес (адрес предыдущей строки + количество байтов предыдущей строки), к примеру вот массив типа int
АдресЗначение (int занимает 4 байта, значеения от -2147483648 до 2147483647)
0 (адрес массива в памяти, все адреса в памяти начинаются с 0)Какое то значение от -2147483648 до 2147483647 (диапазон значений int)
4Какое то значение от -2147483648 до 2147483647 (диапазон значений int)
8Какое то значение от -2147483648 до 2147483647 (диапазон значений int)
12Какое то значение от -2147483648 до 2147483647 (диапазон значений int)
leds у тебя массив какого-то типа (предпалагю что int) размером 100, то есть в памяти у тебя 400 байтов под все эти значения.
Цифра в квадратных скобках leds[NNN] (в твоём случае ты получаешь эту цифру через random).
Когда ты передаёшь в random в max значение ниже минимального (а по умолчанию оно 0) ты рискуешь получать значения которые ты не хотел получать (а 0-NUM_LEDS таковым и является). Возможно, где то ты получаешь значения выходящие за рамки твоего массива (0-99), и тогда есть два варианта событий:
Вылет программы (возможно перезагрузка МК)​
Получение значений из вне массива, и тут начинается трэш, давай рассмотрим именно этот вариант поворота событий:​
Как я говорил ранеее, каждая переменная, массив получают какой то адрес в памяти (и самый первый адрес = 0).​
Возьмём вот эти переменные и разберём как они хранятся в памяти:​
C++:
int number;
boolean flag;
byte smallNumber;
int array[3];
Давай разберём сколько байтов занимает каждый тип данных для начала, а потом построим таблицу с адресами памяти​
int - 4 байта​
boolean - 1 байт​
byte - 1 байт​
массив int размером 3 ячейки - 4 байта для каждой ячейки, итого 12 байт​
Теперь давай сделаем таблицу адресов памяти и подпишем какой адрес относится к какой переменной​
ПеременнаяАдресРазмер значения в байтах
number0 (адрес начинается с 0)4 байта
flag0 (адрес number) + 4 (размер number) = 41
smallNumber4 (адрес flag) + 1 (размер flag) = 51
array[0]5 (адрес smallNumber) + 1 (размер smallNumber) = 64
array[1]6 (адрес array[0]) + 4 (размер) = 104
array[2]10 (адрес array[0]) + 4 (размер) = 144
Выглядит очень просто, а теперь давай рассмотрим вариант что random вернёт значение 0, а массив leds в нашем случае это array​
Значит мы говорим МК обратиться к адресу первого значения array (адрес 6) со сдвигом 0 значений int (умножая на размер intt, тобишь 4 байта = 0 * 4 байта = 0 байт), итого получаем адреес 6 + 0 = 6. Окей, всё отлично.​
Возьмём теперь пример что random вернуло 1, делаем то же самое, начало массива по адресу 6 + 4 байта так как сдвигаем 1 int = 10, тоже работает и получаем то что надо.​
А теперь рассмотрим вариант когда random вернёт -1, делаем то же самое, начало массива по адресу 6, умножаем размер int на смещение (-1 * 4 и получаем -4), прибавляем значение к адресу массива и получаем 6 - 4 = 2, итого ты попадаешь в пространство между number и началом массива. Ты получишь значение двух последних байтов number + значение flag + значение smallNumber, итого 4 байта, меняя уже это значение ты влияеншь на другие переменные, может одна из них потом передаёт значение к другой функции и вжух, МК не может обработать значение (потому что ты ожидал что в функцию ты передашь значение A, а из-за того что у тебя данные записались в другой адрес памяти ты передаёшь значение B).​
Конечно этот сценарий мало-вероятен так как сегодня МК умеют перезагружаться когда ты пытаешься получить значение из массива но передаёшь значение вне его диапозоне, но такой сценарий также надо иметь ввиду.​
p.s возможно где то ошибься
p.s.s если есть ошибки в тексте тапками не бросайтесь, ну не русский я
Все, уже исправил синтаксис в random() все равно не работает(

Надо все эффекты брать в скобки. а лучше в отдельные функции. Кто его знает из какого эффекта это идет ?
И еще, а что если плата перегружается ?
Буду пробовать все забрать в скобки.
Плату перезагружал, найн эффектен
 

Roden

✩✩✩✩✩✩✩
19 Апр 2019
31
5
Старик Похабыч прав, у тебя возможно стэк перегружается от такого количества переменных.
Все эффекты надо в отдельные функции, таким образом тебе будет проще найти в каком эффекте ошибка и ты будешь очищать стэк от ненужных переменных.
 

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
Старик Похабыч прав, у тебя возможно стэк перегружается от такого количества переменных.
Все эффекты надо в отдельные функции, таким образом тебе будет проще найти в каком эффекте ошибка и ты будешь очищать стэк от ненужных переменных.
Я убрал одну переменную (вместе с циклом с millis()), но добавил 5 новых, уникальных. Количество переменных стало больше, но скетч при этом работает. Да и не так уж их (переменных) много в программе (ИМХО). Или я неправильно рассуждаю?

14-15 переменных это много или нормально?
 

Roden

✩✩✩✩✩✩✩
19 Апр 2019
31
5
Иногда и 1 переменной бывает много, всё зависит от их типа.
На сколько я знаю, в ардуино нано/уно у тебя есть 2кб памяти, тобишь 2048 байта.
Смотрим на таблицу которую я скинул выше, если все переменные типа int то ты можешь максимум 512 переменных создать (и это если вся память уходит только на переменные), есть типы данных и по сложнее, и они могут занимать уже намного больше чем 4 байта.
Когда у тебя заканчивается блок {}, все созданные в нём переменные удаляются и всё, память освобождается.
Всегда надо стараться использовать минимум памяти, тогда получишь максимум профита.
 

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
"Глобальные переменные используют 391 байт (15%) динамической памяти, оставляя 2169 байт для локальных переменных. Максимум 2560 байт", - мы об этом говорим?
 

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
Спасибо, отрисую скобки везде, погляжу что получится
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,267
1,303
Москва
Буду пробовать все забрать в скобки.
Плату перезагружал, найн эффектен
Я не совсем то имел ввиду. Скетч доходит до определенного места, а потом идет просадка по напряжению и плата сама перегружается и дальше не идет. Если подключить монитор порта и в setup сделать вывод фразы "стартую.." например, то будет видно была перезагрузка или нет.
 

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
Я не совсем то имел ввиду. Скетч доходит до определенного места, а потом идет просадка по напряжению и плата сама перегружается и дальше не идет. Если подключить монитор порта и в setup сделать вывод фразы "стартую.." например, то будет видно была перезагрузка или нет.
Просадка по напряжению может как-то быть связана с программой? Вряд ли. Ошибка вылезает когда я включаю в работу цикл, содержащий цикл с таймером. Да и не может быть никакой просадки по напряжению, плата запитана от USB ноутбука. Ноутбук работает в режиме "от сети".
 

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
Ну как сказать. Вот запустить всю ленту белым светом на всё катушку и сделайте замер.
Гирлянда отдельно запитана, по правилам, от БП (до 30А) В этом случае ардуине все равно как там все горит с какой яркостью. Колебания I <= 1A. Напряжение не просаживается ни на грамм (индикацию вижу).
 

Andrei528

✩✩✩✩✩✩✩
12 Сен 2020
19
0
Короче, все циклики забрал в скобки {}.
Не помогло. Пойду застрелюсь.
Все дело в
C++:
 {
    // случайные оттенки синего
    //   если раскомментирован этот цикл, то после прохождения одного цикла вместо пяти в пределах
    //   строк скетча №№ 187 - 240 происходит возврат в начало всего скетча
            uint32_t kk = millis();
            while ( millis () - kk < 20000)
            {
              leds [random (0 , NUM_LEDS)] = CRGB(random(0 ,100), random(0 , 100), 255);
              leds [random (0 , NUM_LEDS)] = CRGB(0, 0, 0); // случайное гашение
              FastLED.show();
              delay( 5 );
            }
  }