Тесты на ледах

Roman_Olegovich
Offline
Зарегистрирован: 19.12.2012

Доброго дня, уважаемые.

Есть ардуино нано и n-светодиодов подключеных к ногам. Нечего особенного.
Управляет всем этим вот такой код:
 

// Переменные.
int incomingByte;
// Пины светодиодов
byte LedPin[]={2,3,4,5,6,7,8,9,10,11,12,13,A0,A1,A2}; 
// Вычисляем сколько ледов.
#define LedCount sizeof(LedPin)/sizeof(byte) 
// Длина паузы между сменой состояний диода
#define PAUSE 100

void setup ()
{
  // Запускаем сериал
  Serial.begin(9600);
  // Включаем светики на выход
  for(byte i=0; i<LedCount; i++){
    pinMode(LedPin[i],OUTPUT); 
  }
}

void loop ()
{
  // Если входящий байт 1
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if(incomingByte=='1'){
      ledUp();
      ledDown();
    }
  }
}

// Включаем по порядку вверх.
void ledUp(){
  for(byte i=0; i<LedCount; i++){
    digitalWrite(LedPin[i], !digitalRead(LedPin[i]));
    // Проверяем порядки
    Serial.print("i_up ");
    Serial.println(i);
    delay(PAUSE);
  }
}

// Включаем по порядку вниз.
void ledDown(){
  for(byte i=LedCount; i>0; i--){
    digitalWrite(LedPin[i], !digitalRead(LedPin[i]));
    // Проверяем порядки
    Serial.print("i_down ");
    Serial.println(i);
    delay(PAUSE);
    // Так как осчет заканчивается на 1, выключаем лед 0.
    if (i==1){
      digitalWrite(LedPin[0], !digitalRead(LedPin[0]));
    }
  }
}

 
При вводе в сериал леды по очереди загораются и тухнут в обратном порядке. Вооооот =)
С этим вроде всё понятно. Но хочется, не нагромождая кода, заставлять леды загоратся в в другой последовательности. 
Для определения последовательностей была идея завернуть послеовательности в:

byte FirstLedTurn[]={2,4,6,8,10,12,A0,A2,3,5,7,9,11,13,A1}; 
byte SecondLedTurn[]={3,5,2,4,7,9,6,8,10,12,11,13,A1,A2,A0}; 

Ну допустим так. Но непонятно тогда как их вызывать в ledUp и ledDown.

Сильно кирпичами не кидайтесь, я учусь =)
Конструктивную критику по существующему коду приму только с обьяснениями своих косяков ;)

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Roman_Olegovich пишет:

byte FirstLedTurn[]={2,4,6,8,10,12,A0,A2,3,5,7,9,11,13,A1}; byte SecondLedTurn[]={3,5,2,4,7,9,6,8,10,12,11,13,A1,A2,A0};

Ну допустим так. Но непонятно тогда как их вызывать в ledUp и ledDown.

Надо функции переделать.

Запускаем цикл перебора членов массива. Внутри этого цикла дергаем функцииLedUP и LedDOWN с соответствующим параметром того пина, на котором надо включить, или выключить светодиод.

Roman_Olegovich
Offline
Зарегистрирован: 19.12.2012

Andrey_Y_Ostanovsky пишет:

Надо функции переделать.

Запускаем цикл перебора членов массива. Внутри этого цикла дергаем функцииLedUP и LedDOWN с соответствующим параметром того пина, на котором надо включить, или выключить светодиод.

Хм.... кажется я вас не понял...
Ведь мне получается надо перебирать массивы, а не члены одного массива?

Или поясните вашу мысль...

maksim
Offline
Зарегистрирован: 12.02.2012

Вым нужно передать в функцию указатель массива:

// Включаем по порядку вверх.
void ledUp(byte *LedTurn){
  for(byte i=0; i<LedCount; i++){
    digitalWrite(LedTurn[i], !digitalRead(LedTurn[i]));
    // Проверяем порядки
    Serial.print("i_up ");
    Serial.println(i);
    delay(PAUSE);
  }
}

и при вызове функции в качестве аргумента передаете нужный указатель:

ledUp(FirstLedTurn);
ledUp(SecondLedTurn);

 

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Roman_Olegovich пишет:

Хм.... кажется я вас не понял...
Ведь мне получается надо перебирать массивы, а не члены одного массива?

Или поясните вашу мысль...

А что Вас смущает? Можете перебирать два массива одновременно. :) Запустили счетчик по i и вынимаем одновременно i-е элементы из нескольких массивов, если так хочется... Можно попробовать сделать двухмерный массив, но я не уверен, что система с ним сможет работать... Тут ведь главное - что Вы хотите передать этими массивами контроллеру. Если "один зажигается - один гаснет" - то я бы сделал просто со сдвигом номера ножки и одним массивом, или поискать random(), получить из него int и сминусовать.

Т.е., получаем из массива "5", из функции типа int(random()) - 2, значит второй кандидат живет на ножке "5-2" или "5+2", как-то так можно.

Roman_Olegovich
Offline
Зарегистрирован: 19.12.2012

А! Большое спасибо за объяснения!
Сейчас попробую, вывалю то что получится :)

Roman_Olegovich
Offline
Зарегистрирован: 19.12.2012

Так, получилось вот что:

// Переменные.
int incomingByte;
// Пины светодиодов
byte LedPin[]={
  2,3,4,5,6,7,8,9,10,11,12,13,A0,A1,A2}; 
// Вычисляем сколько ледов.
#define LedCount sizeof(LedPin)/sizeof(byte) 
// Длина паузы между сменой состояний диода
#define PAUSE 100
// Очередность ледов
byte FirstLedTurn[]={
  2,4,6,8,10,12,A0,A2,3,5,7,9,11,13,A1};
byte SecondLedTurn[]={
  3,5,2,4,7,9,6,8,10,12,11,13,A1,A2,A0};


void setup ()
{
  // Запускаем сериал
  Serial.begin(9600);
  // Включаем светики на выход
  for(byte i=0; i<LedCount; i++){
    pinMode(LedPin[i],OUTPUT); 
  }
}

void loop ()
{
  // Если входящий байт 1
  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    if(incomingByte=='1'){
      ledUp(LedPin);
      ledDown(LedPin);
    }
    if(incomingByte=='2'){
      ledUp(FirstLedTurn);
      ledDown(FirstLedTurn);
    }
    if(incomingByte=='3'){
      ledUp(SecondLedTurn);
      ledDown(SecondLedTurn);
    }
  }
}

// Включаем по порядку вверх.
void ledUp(byte *LedTurn){
  for(byte i=0; i<LedCount; i++){
    digitalWrite(LedTurn[i], !digitalRead(LedTurn[i]));
    // Проверяем порядки
    Serial.print("i_up ");
    Serial.println(i);
    delay(PAUSE);
  }
}

// Включаем по порядку вниз.
void ledDown(byte *LedTurn){
  for(byte i=LedCount - 1; i>0; i--){
    digitalWrite(LedTurn[i], !digitalRead(LedTurn[i]));
    // Проверяем порядки
    Serial.print("i_down ");
    Serial.println(i);
    delay(PAUSE);
    // Так как осчет заканчивается на 1, выключаем лед 0.
    if (i==1){
      digitalWrite(LedTurn[0], !digitalRead(LedTurn[0]));
    }
  }
}

Пришлось изменить строчку
 

for(byte i=LedCount; i>0; i--){

на 
 

for(byte i=LedCount - 1; i>0; i--){

Чтобы при выключении не "цепляло" последний символ массива.
Всем большое спасибо за обьяснение =)

maksim
Offline
Зарегистрирован: 12.02.2012

Это естественно, нумерация элементов начинается с 0, и будьте внимательнее с вот этим for(byte i=LedCount - 1; i>0; i--) потому как если вы замените i>0; на i=>0; то цикл станет бесконечным и МК зависнет. Это происходит из-за того что byte не может принимать отрицательные значения, в таких случаях, если максимальное значение i позволяет, нужно объявлять i как char, то есть знаковым типом.

for(char i=LedCount - 1; i=>0; i--)

Roman_Olegovich
Offline
Зарегистрирован: 19.12.2012

Да, столкнулся с этим, но про char, если честно не подумал. По неопытности путаюсь в типах...

Я где-то тут на форуме читал, как leshak подробно обьяснял как использовать mills() вместо delay(), но не могу найти... киньте пожалуйста ссылкой, если знаете название темы....

Я только начинаю изучать ардуино, и начал с малого, сначала моргал одним диодом, потом несколькими и тп. Вот добрался до массивов =) Постепенно усложняю себе задачку. Вот теперь хотелось бы разобраться с делэями, так как народ доступно обьяснил, во многих темах тут, что это не гуд :)

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Roman_Olegovich пишет:

Я где-то тут на форуме читал, как leshak подробно обьяснял как использовать mills() вместо delay(), но не могу найти... киньте пожалуйста ссылкой, если знаете название темы....

millis() - это, грубо говоря, аптайм микроконтроллера в миллисекундах тип unsigned long.

Соответственно, алгоритм использования примерно такой:

- задаем константу "наша пауза", и переменную "начало цикла ожидания" = 0,

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

 

Главное - тип переменной, в которую будем записывать значение millis() - должен быть той же размерности: unsigned long.

leshak
Offline
Зарегистрирован: 29.09.2011

Roman_Olegovich пишет:

Я где-то тут на форуме читал, как leshak подробно обьяснял как использовать mills() вместо delay(), но не могу найти... киньте пожалуйста ссылкой, если знаете название темы....

Да я постоянно это делаю :(. Сегодня в очередной :)

http://arduino.ru/forum/obshchii/led-matrix-8x8-zazhech-opredelennye-sve...

P.S. Два месяца не заходил на форум, зашел - и как будто не отходил. Те же вопросы (число в Serial, как мигать без delay и все это в 10-ти ветках с информативным названием вида "помогите новичку") :)

maksim
Offline
Зарегистрирован: 12.02.2012

Мне кажется быстрее найдешь нужный ответ на любой вопрос, если в поиске набрать не вопрос, а
"помогите новичку" ))) Поэтому "новички" и не находят ответов в поиске ))) и заводят новую
тему "помогите новичку" )))))))

Roman_Olegovich
Offline
Зарегистрирован: 19.12.2012

Вооооооот!! Вот где косяк! Надо это дело в ФаК поиска по форуму записать :)