Как динамически устанавливать pinMode и динамически записывать значение в контакты в Arduino с использованием массивов?

Я пытаюсь создать библиотеку под названием "LED" для светодиодного секвенсора в Arduino IDE, где пользователь должен настроить выводы светодиодов с помощью массива и передать его в конструктор светодиодов в программе, а затем сможет использовать функции BlinkAll (), LeftToRight () и RightToLeft(), которые освещают СВЕТОДИОД отображается слева направо или справа налево в зависимости от последовательности, указанной в массиве. Проблема в том, что когда я инициирую массив и передаю его конструктору, контакты 4,5,7 вообще не работают, пожалуйста, помогите мне найти, в чем возможная проблема кода LED.cpp файл показан ниже

#include <Arduino.h>
#include "LED.h"

LED::LED(int channel, int* a){
  _channel = channel;
  for(int i = 0 ; i < channel; i ++)
  {
    _pins[i] = a[i] ;
    pinMode(_pins[i],OUTPUT);
  }
}
void LED :: BlinkAll(int delay_ms)
{
   for (int i = 0 ; i<_channel;i++)
   {
    digitalWrite(_pins[i],HIGH);
   }
   delay(delay_ms);
   for (int i = 0 ; i<_channel;i++)
   {
    digitalWrite(_pins[i],LOW);
   }
   delay(delay_ms);
}
void LED :: LeftToRight(int numberofLEDs, int delay_ms)
{
  for(int i =0 ;i<_channel; i++)
  {
    digitalWrite(_pins[i], LOW);
  }
  for(int i =0 ;i<_channel; i++)
  {
//    if (i > 0)
//    {
//     digitalWrite(_pins[i-1], LOW);
//    }
  for(int i =0 ;i<_channel; i++)
  {
    digitalWrite(_pins[i], LOW);
  }
    digitalWrite(_pins[i], HIGH);
    delay(delay_ms);
  }
}
void LED :: RightToLeft(int numberofLEDs,int delay_ms)
{
    for(int i =_channel ;i>0; i--)
  {
    digitalWrite(_pins[i], LOW);
  }
  for(int i = _channel ;i>0; i--)
  {
    if (i < _channel)
    {
     digitalWrite(_pins[i+1], LOW);
    }
    digitalWrite(_pins[i], HIGH);
    delay(delay_ms);
  }
}

ЖК.ч

#ifndef LED_h
#define LED_h

#include <Arduino.h>

class LED 
{
public:
  LED(int channel, int* pins);
  void BlinkAll(int delay_ms);
  void LeftToRight(int numberofLEDs, int delay_ms);
  void RightToLeft(int numberofLEDs, int delay_ms);
  void BlinkAlternate(int delay_ms);
private:
  int _channel;
  int _pins[16];
};

#endif

Пример кода

#include "LED.h"

int const LED_pins[8]={5,6,7,8,9,10,11,12};
int const No_of_LED = 8;

LED led(8,LED_pins);

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  led.LeftToRight(1,500);
  led.RightToLeft(1,500);
}

, 👍1

Обсуждение

Пожалуйста, покажите нам полный код. Имеется в виду также файл LED.h и небольшой тестовый скетч, который использует вашу библиотеку и показывает проблему., @chrisl

Непосредственно я думаю, что у вас есть несбалансированные фигурные скобки в функции LeftToRight (), и вы используете индекс массива вне границ в функции RightToLeft () (эффективно выполняя _pins [_channel], хотя наибольший индекс должен быть _channel-1), @chrisl

если вы исправите уровни отступов в своем коде, то, возможно, сможете сами увидеть проблемную область, @jsotola

pinMode не должен быть в конструкторе. Для этого вам нужен метод begin, который можно вызвать из программы установки. Конструктор может быть запущен до установки и до того, как оборудование будет готово к pinMode., @Delta_G


1 ответ


1

Похоже, что в методе LeftToRight вы недостаточно прокомментировали (или слишком много), потому что вы используете цикл for внутри другого цикла for, который, вероятно, непреднамерен.

В методе RightToLeft я попытаюсь устранить проблему, поэтому вы можете аналогичным образом изменить методLeftToRight.

void LED :: RightToLeft(int numberofLEDs,int delay_ms)
{
  for(int i =_channel ;i>0; i--)
  {
    digitalWrite(_pins[i], LOW);
  }
  for(int i = _channel ;i>0; i--)
  {
    if (i < _channel)
    {
     digitalWrite(_pins[i+1], LOW);
    }
    digitalWrite(_pins[i], HIGH);
    delay(delay_ms);
  }
}

Первый цикл for заключается в выключении светодиодов, я бы сделал это отдельным методом, чтобы его можно было повторно использовать как в методе LeftToRight, так и в методе RightToLeft, так что вы получите:

void LED::RightToLeft(int numberofLEDs, int delay_ms)
{
  switchAllLedsOff();

  for(int i = _channel; i > 0; i--)
  {
    if (i < _channel)
    {
     digitalWrite(_pins[i + 1], LOW);
    }
    digitalWrite(_pins[i], HIGH);
    delay(delay_ms);
  }
}

void LED::SwitchAllLedsOff()
{
  for(int i = _channel; i > 0; i--)
  {
    digitalWrite(_pins[i], LOW);
  }
}

Проблема также в том, что вы всегда записываете значение HIGH в вывод, поскольку оно перезаписывает возможное назначение LOW в операторе if. Чтобы исправить это, вы получаете:

void LED::RightToLeft(int numberofLEDs, int delay_ms)
{
  switchAllLedsOff();

  for(int i = _channel; i > 0; i--)
  {
    digitalWrite(_pins[i + 1], i >= _channel ? HIGH : LOW);
    delay(delay_ms);
  }
}

Вы также можете использовать оператор if , но в этом случае оператор ternary (? :) более понятен, поскольку назначение предназначено для одного назначения (_pins[i + 1]). Таким образом, в случае, если i >= channel, для него устанавливается значение HIGH, в противном случае устанавливается значение FALSE. Я также перевернул оператор, но вы можете оставить его тоже перевернутым.

В-третьих, _channel, по-видимому, представляет собой количество элементов в массиве, если вы используете его в индексе, он должен начинаться с _channel - 1, так что вы получите:

void LED::RightToLeft(int numberofLEDs, int delay_ms)
{
  switchAllLedsOff();

  for(int i = _channel - 1; i >= 0; i--)
  {
    digitalWrite(_pins[i + 1], i >= _channel - 1 ? HIGH : LOW);
    delay(delay_ms);
  }
}

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

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

(обратите внимание, что я не тестировал программу).

,

Спасибо мистеру Мишелю Кейерсу. Буду работать над этим и дам вам знать, @Mr.B

Мистер Мишель, я попробовал ваш код RightToLeft(), но ничего не горит, поэтому я изменил i>=_channel на i <= _Channel затем он загорается, но светодиод продолжает светиться, не выключаясь, как гистограмма вместо светодиодной прокрутки., @Mr.B

Я думал, вам нужен график, а не один светодиод, в этом случае вы можете удалить цикл for и использовать set one pin только для high ., @Michel Keijzers

Это полезно, спасибо мистеру Мишелю Кейзерсу. Но я также выяснил некоторые незакрепленные аппаратные соединения , из - за которых светодиод на 5 - м выводе не светился . Тем не менее, я не могу понять, почему 6-й контакт не светится. в остальном Это работает ., @Mr.B

Проверьте, исправен ли провод, измерив его с помощью мультиметра, или замените светодиод и провод (всего 4 комбинации), пока не убедитесь, что хотя бы компонент и провод в порядке., @Michel Keijzers