Перебор массива в обратном порядке

Тема в разделе "Arduino & Shields", создана пользователем VitaliyGrim, 3 сен 2020.

  1. VitaliyGrim

    VitaliyGrim Нуб

    Я только начал учиться, подсказать некому, поэтому не бейте сильно.... слегка пинка под зад можно..++
    решил сделать зажигание светодиодов лесенкой от 2 до 9 пина с использованием многомерного массива.
    И вот когда я по своему разумению инвертировал часть кода с перебором массива для выключения светодиодов сзади-наперед, возникла проблема. Спонтанно тухнет случайный светодиод(или несколько) и зависание(пауза) на полпути назад. Подскажите где, я неправильно что то сделал?
    Arduino nano(китай CH340)
    листинг выкладываю:

    Код (C++):
    int leds[][4] = {{2,3,4,5},{6,7,8,9}};
    int ledsFirstLevel = sizeof(leds) / sizeof(leds[0]);
    int ledsSecondLevel = sizeof(leds[0]) / sizeof(int *);
    int pause = 100;

    // the setup function runs once when you press reset or power the board
    void setup() {
    for(int i=0; i < ledsFirstLevel; i++){
    for(int j=0; j < ledsSecondLevel; j++){
    pinMode(leds[i][j], OUTPUT);
      }
    }
    }

    void loop(){
    //  Цикл for - для, включаем диоды по очереди
      for(int i=0; i < ledsFirstLevel; i++){
    for(int j=0; j < ledsSecondLevel; j++){
      ledOn(leds[i][j], 100);
       }
      }
    // Выключаем диоды по очереди
    for(int i=ledsFirstLevel; i > -1; i--){
    for(int j=ledsSecondLevel; j > -1; j--){
      ledOff(leds[i][j], 100);
      }
    }
    }
    void ledOn (int numberPin, int paramPause){
      digitalWrite(numberPin, HIGH);
      delay(paramPause);
    }
    void ledOff (int numberPin, int paramPause){
      digitalWrite(numberPin, LOW);
      delay(paramPause);
      }

     
     
  2. b707

    b707 Гуру

    подсказка - в массиве array размера N нет элемента array[N]
     
  3. VitaliyGrim

    VitaliyGrim Нуб

    Спасибо за совет! Нашел в чем ошибка.
    Исправил и заработало=) я не учел что контроллер начинает считать с 0. и соответственно он пытался перебрать несуществующие в массиве элементы.
    Код (C++):
    for(int i=ledsFirstLevel-1; i >= 0; i--){
    for(int j=ledsSecondLevel-1; j >= 0; j--){
      ledOff(leds[i][j], 100);
     
    P.S. заодно научился работать с монитором.
     
  4. VitaliyGrim

    VitaliyGrim Нуб

    И еще один вопрос. Добавил выполнение, однократно данного перебора, по нажатию на кнопку... все заработало, но светодиоды почему-то стали еле заметно светить. Вопрос почему? Использовал защиту от дребезга с millis и состоянием кнопки с использованием флага.
    Код (Text):

    int leds[][4] = {{2,3,4,5},{6,7,8,9}};
    int ledsFirstLevel = sizeof(leds) / sizeof(leds[0]);
    int ledsSecondLevel = sizeof(leds[0]) / sizeof(int *);
    int pause = 100;

    void setup() {
    //  Serial.begin(9600);
      pinMode(3, INPUT_PULLUP);
     
    }
    bool flag = false;
    uint32_t btnTimer = 0;
    void loop() {
      // читаем инвертированное значение
      bool btnState = !digitalRead(3);
      if (btnState && !flag && millis() - btnTimer > 100) {
      btnTimer = millis();
      // Serial.println("press");
      //включаем диоды по очереди
      for(int i=0; i < ledsFirstLevel; i++){
     for(int j=0; j < ledsSecondLevel; j++){
      ledOn(leds[i][j]+2, 20);

      }
     
      }
      delay(100);
    // Выключаем диоды по очереди
     for(int i=ledsFirstLevel-1; i >= 0; i--){
     for(int j=ledsSecondLevel-1; j >= 0; j--){
      ledOff(leds[i][j]+2, 60);
      }
     }
      delay(500);
      flag = true;
      }
      if (!btnState && flag) {
      flag = false;
      btnTimer = millis();
      //Serial.println("release");
      }
    }
    void ledOn (int numberPin, int paramPause){
      digitalWrite(numberPin, HIGH);
      delay(paramPause);
    }
    void ledOff (int numberPin, int paramPause){
      digitalWrite(numberPin, LOW);
      delay(paramPause);
      }
     
     
    Последнее редактирование: 5 сен 2020
  5. b707

    b707 Гуру

    раньше вы в сетапе настраивали все выходы командой pinMode. а теперь этого там нет
     
  6. VitaliyGrim

    VitaliyGrim Нуб

    блин... упустил. надо быть внимательней. Благодарю!
     
  7. VitaliyGrim

    VitaliyGrim Нуб

    Добрый день! Подскажите как избавиться от delay() в коде. Пытался по примеру
    Код (Text):

    void ledOn (int numberPin, int paramPause){
      if (millis() - timing > paramPause){
      timing=millis();
      digitalWrite(numberPin, HIGH);
      }
    }
     
    но увы загорается и тухнет только первый светодиод. или если в функции ledOff то загораются все и только последний тухнет.
    то есть функция выполняется только раз и все, а дальше не выполняется почему то, при этом срабатывание кнопки есть, блоки запускаются.
     
  8. b707

    b707 Гуру

    переменная timing должна быть для каждого светодиода своя, как и переменные int numberPin, int paramPause
     
  9. VitaliyGrim

    VitaliyGrim Нуб

    Переписал вот так:
    Код (Text):

    int leds[][4] = {{2,3,4,5},{6,7,8,9}};
    uint32_t ledsTiming[][4] = {{0,0,0,0},{0,0,0,0}};
    int ledsTimingFL = sizeof(ledsTiming) / sizeof(ledsTiming[0]);
    int ledsTimingSL = sizeof(ledsTiming[0]) / sizeof(uint32_t*);
    int ledsFirstLevel = sizeof(leds) / sizeof(leds[0]);
    int ledsSecondLevel = sizeof(leds[0]) / sizeof(int *);
    uint32_t pause = 50;
    bool flag = false;
    uint32_t btnTimer = 0;



    void setup() {
      Serial.begin(9600);
      pinMode(3, INPUT_PULLUP);
      for (int i=0; i < ledsFirstLevel; i++){
      for (int j=0; j < ledsSecondLevel; j++){
      pinMode(leds[i][j]+2, OUTPUT);
      }
      }
      }

    void loop() {
    // читаем инвертированное значение
      bool btnState = !digitalRead(3);
      if (btnState && !flag && millis() - btnTimer > 100) {
      btnTimer = millis();
      Serial.println("press");
    //включаем диоды по очереди
    for (int i=0; i < ledsFirstLevel; i++){
    for (int j=0; j < ledsSecondLevel; j++){
    for (int k=0; k < ledsTimingFL; k++){
    for (int l=0; l < ledsTimingSL; l++){
      ledsTiming[k][l] = (millis());
      ledOn(leds[i][j]+2, pause, ledsTiming[k][l]);
      }
      }
      }
      }

    // Выключаем диоды по очереди
    for (int i=ledsFirstLevel-1; i >= 0; i--){
    for (int j=ledsSecondLevel-1; j >= 0; j--){
    for (int k=ledsTimingFL-1; k >= 0; k--){
    for (int l=ledsTimingSL-1; l >= 0; l--){
      ledsTiming[k][l] = (millis());
      ledOff(leds[i][j]+2, pause, ledsTiming[k][l]);
      }
      }
      }
      }

      flag = true;
      }
      if (!btnState && flag) {
      flag = false;
      btnTimer = millis();
      Serial.println("release");
      }
      }
    // функция включения диодов
    void ledOn (int numberPin, uint32_t paramPause, uint32_t timing){
      if (millis()-timing > paramPause){
      timing=millis();
      digitalWrite(numberPin, HIGH);
      Serial.println("Diod_on");
      }
      }
    //функция выключения диодов
    void ledOff (int numberPin, uint32_t paramPause, uint32_t timing){
      if (millis()-timing > paramPause){
      timing=millis();
      digitalWrite(numberPin, LOW);
      Serial.println("Diod_off");
      }
      }
     
    функции работают, но нету задержки. Подскажите как это сделать? не могу сообразить - хоть убейся...
     
    Последнее редактирование: 8 сен 2020
  10. VitaliyGrim

    VitaliyGrim Нуб

    Монитор выдает следующее по нажатию кнопки
    Код (Text):
    press
    157611
    157612
    157612
    157612
    157613
    157613
    157613
    157613
    157618
    157626
    157634
    157642
    157650
    157659
    157667
    157675
    157684
    157692
    157701
    157709
    157717
    157725
    157733
    157742
    157751
    157759
    157767
    157775
    157784
    157792
    157800
    157808
    157817
    157826
    157834
    157842
    157850
    157858
    157867
    157875
    157884
    157892
    157900
    157908
    157917
    157925
    157933
    157941
    157950
    157959
    157967
    157975
    157983
    157991
    158000
    158008
    158017
    158025
    158033
    158042
    158050
    158058
    158066
    158074
    158084
    158092
    158100
    158108
    158116
    158125
    158133
    158141
    158150
    158158
    158167
    158175
    158183
    158191
    158199
    158208
    158217
    158225
    158233
    158241
    158249
    158258
    158266
    158274
    158283
    158291
    158300
    158308
    158316
    158324
    158332
    158341
    158350
    158358
    158366
    158374
    158383
    158391
    158399
    158407
    158416
    158425
    158433
    158441
    158449
    158457
    158466
    158474
    158483
    158491
    158499
    158508
    158516
    158524
    158532
    158540
    158550
    158558
    158566
    158574
    158582
    158590
    158599
    158607
    release
     
     
  11. b707

    b707 Гуру

    Вы запутались с массивами
    Вот, например, тут
    Код (C++):
    for (int i=0; i < ledsFirstLevel; i++){
      for (int j=0; j < ledsSecondLevel; j++){
      pinMode(leds[i][j]+2, OUTPUT);
      }
      }
    что это за "+2" к номеру пина, какой в этой двойке смысл?

    Ну а тут вообще ерунда
    Код (C++):
    for (int i=0; i < ledsFirstLevel; i++){
    for (int j=0; j < ledsSecondLevel; j++){
    for (int k=0; k < ledsTimingFL; k++){
    for (int l=0; l < ledsTimingSL; l++){
      ledsTiming[k][l] = (millis());
      ledOn(leds[i][j]+2, pause, ledsTiming[k][l]);
      }
      }
      }
      }
    зачем вы тайминги перебираете отдельно от светодиодов? К каждому светодиоду - свой тайминг, значит отдельные циклы для таймингов не нужны.

    И вообще. я бы советовал для начала убрать из кода ваш "двойной" массив. Отработайте код на одинарном массиве, потом перепишете для двойного
     
  12. VitaliyGrim

    VitaliyGrim Нуб

    Спасибо. Попробую. двойку добавил, потому, что пины сдвинулись на две ноги, а массив переписать было лень.
     
  13. VitaliyGrim

    VitaliyGrim Нуб

    Изменил вот так:
    Код (Text):

    int leds[] = {4,5,6,7,8,9,10,11};
    uint32_t ledsTiming[] = {0,0,0,0,0,0,0,0};
    int ledscount = sizeof(leds) / sizeof(int *);
    uint32_t pause = 100;
    bool flag = false;
    uint32_t btnTimer = 0;

    void setup() {
      Serial.begin(9600);
      pinMode(3, INPUT_PULLUP);
      for (int i=0; i < ledscount; i++){

      pinMode(leds[i], OUTPUT);

      }
      }

    void loop() {
    // читаем инвертированное значение
      bool btnState = !digitalRead(3);
      if (btnState && !flag && millis() - btnTimer > 100) {
      btnTimer = millis();
      Serial.println("press");
    //включаем диоды по очереди
    for (int i=0; i < ledscount; i++){

      ledsTiming[i] = (millis());
      ledOn(leds[i], pause, ledsTiming[i]);
      }
    // Выключаем диоды по очереди
    for (int i=ledscount-1; i >= 0; i--){

      ledsTiming[i] = (millis());
      ledOff(leds[i], pause, ledsTiming[i]);

      }

      flag = true;
      }
      if (!btnState && flag) {
      flag = false;
      btnTimer = millis();
      Serial.println("release");
      }
      }
    // функция включения диодов
    void ledOn (int numberPin, uint32_t paramPause, uint32_t timing){

      if (millis()-timing > paramPause){
      timing=millis();
      Serial.println(timing) ;
      digitalWrite(numberPin, HIGH);
      Serial.println(numberPin, "Diod_on");
      }
      }
    //функция выключения диодов
    void ledOff (int numberPin, uint32_t paramPause, uint32_t timing){
      if (millis()-timing > paramPause){
      timing=millis();
      digitalWrite(numberPin, LOW);
      }
      }
     
    Но функция включения и выключения не работают с таким образом написанной задержкой. я видимо неправильно понимаю как обрабатывает код МК, просто не выполняется условие оператора if. вот тут я и не могу понять почему не работает.
     
    Последнее редактирование: 8 сен 2020
  14. b707

    b707 Гуру

    Вы тайминги каждого диода приравниваете millis дважды - сначала во внешнем цикле For. потом во внутренних процедурах ledOn() ledOff()
    Одно из этих присваиваний - лишнее. какое - попробуйте разобраться сами. иначе не интересно :)
     
  15. VitaliyGrim

    VitaliyGrim Нуб

    на одиночном диоде без кнопки работает, мигает
     
  16. VitaliyGrim

    VitaliyGrim Нуб

    Спасибо, разберемся. Всегда самому интереснее дойти, чем взять готовое. Да и когда берешь готовый код, почти ничему не учишся кроме копипаста.;)
     
  17. VitaliyGrim

    VitaliyGrim Нуб

    убрал присваивание millis в цикле for. все заработало, но без задержки включения/выключения. По моей логике получается так:
    1. в цикле for перебираем массивы и считываем значения для каждого диода.
    2. передаем значения в процедуры ledOn() ledOff()
    3. в процедурах при первом проходе у нас срабатывает условие: истина- текущие millis больше задержки, так как от них отнимается 0
    4. при следующем цикле это условие уже не работает, так как timing=millis() -> millis()-timing уже больше задержки и цикл останавливается.

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

    P.S. учусь сам, подсказать некому. Читаю разные самоучителе и прочее, но там .... ну как бы мягко говоря помигали диодам, сделали пару кнопок и пошла жара... черт пойми что. в итоге просто читаю справочники по коду Arduino и примеры с разных источников и сопоставляю.
     
  18. issaom

    issaom Гуру

    Если действительно хотите чему-то научиться купите пару нормальных толстых книг (лучше бумажных), читайте и делайте из них примеры кода. Чему то учиться в Интернете это самая глупая мысль которая только может прийти в голову. Все эти статьи в Интернет пишут такие же "учителя" которые где то что-то нашли и скопипастили к себе в блог или на сайт сделав при этом кучу ошибок.
     
    parovoZZ нравится это.
  19. b707

    b707 Гуру

    уточню - книги не "про программирование ардуино", а про программирование на Си
     
  20. issaom

    issaom Гуру

    Сейчас есть авторы которые Ардуино сразу как МК рассматривают, а не конструктор для домохозяек. Начинается там все с мигания светодиодом, а заканчивается работой с прерываними и таймерами без ардуиновских библиотек. Там и теория глубокая с нуля и как алгоритмы строить для программ и практических примеров много дается. Так что грызть только сухую теорию сейчас уже совсем не обязательно.