Микроэлектроника для чайников. Урок 4. Еще пара функций C для Arduino
Автор megabax   
30.09.2017 г.
New Page 1

Микроэлектроника для чайников. Урок 4. Еще пара функций C для Arduino

На прошлом уроке мы с вами улучшили программы для схемы "бегущего огонька". Теперь у нас стала "музыка огонька", то есть, мы можем задавать длительность мерцания отдельный светодиодов и какой именно будет загораться и гаснуть. Прямо как по нотам. Согласитесь, это уже кое-что. Но Arduino не ограничивается миганием одними только светодиодами.  Этот микроконтроллер может управлять шаговым двигателем, позволяет подключать к себе датчик, индикаторы и еще много интересного. Но, прежде чем идти дальше и все это изучать, освоим получше программирование.

Начнем с того, что в нашей программе "Музыка огонька" исправим один недочет. Точнее, это даже не недочет, а нарушение культы программирования. На результат это никак не повлияло, но так делать, как мы с вами сделали, не стоит. Мы сделали это только как учебный пример. А именно, не стоит увлекаться delay. Лучше сделать по другому, использовать встроенный таймер:

#define count 16 //количество элементов массива, правильней его задать так

 

struct node {

    bool light; //горит ли лампочка

    int led; //номер порта

    int delay_mils; //задержка, миллисекунд

} a[count] = {{true, 10, 300}, {true, 11, 300}, {true, 12, 300}, {true,13, 300}, {false,13,1000}, {false,12,1000}, {false,11,1000}, {false, 10,1000}, {true, 10,500},

          {false, 10,200}, {true,11,500},

          {false,11,200}, {true,12,500}, {false,12,200}, {true,13,500}, {false,13,1500}}; 

 

unsigned long previousMillis = 0;  //предыдущее значение времени

int i=0; //указатель на текущий элемент массива

 

void setup() {

  // put your setup code here, to run once:

  pinMode(10, OUTPUT);

  pinMode(11, OUTPUT);

  pinMode(12, OUTPUT);

  pinMode(13, OUTPUT);

}

 

void loop() {

  unsigned long currentMillis = millis(); //получим текущее время в миллисекундах

  if(currentMillis-previousMillis<a[i].delay_mils) return; // если не настало время следующего шага - выходим

  if(a[i].light)

  {

     digitalWrite(a[i].led, HIGH); //эта команда используется для включения или выключения напряжения на цифровом порте; led - номер порта, второй аргумент - включение (HIGH) или выключение (LOW)

  }

  else

  {

       digitalWrite(a[i].led, LOW); //эта команда используется для включения или выключения напряжения на цифровом порте; led - номер порта, второй аргумент - включение (HIGH) или выключение (LOW)

  }

  i++;

  if(i>=count) i=0;

  previousMillis=currentMillis;

}

 

Почему этот вариант программы лучше? Дело в том, что теперь мы не заставляем процессор зависать в ожидании, а просто ничего не делаем, если время очередного шага еще не наступило. Казалось бы, какая разница: ничего не делать или заставлять процессор ждать? А разница в том, что если вместо "ничего не делать", при желании мы можем поручить процессору какие-либо другие действия, например, читать состояние датчиков, или нагрузить каким-то вычислениями. В этом случае будет разница, так как если мы заставим процессор ждать командой delay, то он не сможет сделать ничего другого. но в нашем случае, так как процессору ничего другого делать не надо, то разницы нет.

Познакомимся с еще одной функцией языка C для Arduino. Эта функция  - random() - генератор случайных числе. вот пример ее использования:

#define delay_max 500 //максимальная длина задержки

 

unsigned long previousMillis = 0;  //предыдущее значение времени

int delay_mils=random(0,delay_max); //инициализируем задержку случайным числом

 

void setup() {

  // put your setup code here, to run once:

  pinMode(10, OUTPUT);

  pinMode(11, OUTPUT);

  pinMode(12, OUTPUT);

  pinMode(13, OUTPUT);

}

 

void loop() { 

  unsigned long currentMillis = millis(); //получим текущее время в миллисекундах

  if(currentMillis-previousMillis<delay_mils) return; // если не настала время следующего шага - выходим

  if(random(10)>5)

  {

        digitalWrite(random(10,14), HIGH); //эта команда используется для включения или выключения напряжения на цифровом порте; led - номер порта, второй аргумент - включение (HIGH) или выключение (LOW)

  }

  else

  {

       digitalWrite(random(10,14), LOW); //эта команда используется для включения или выключения напряжения на цифровом порте; led - номер порта, второй аргумент - включение (HIGH) или выключение (LOW)

  }

  delay_mils=random(0,delay_max); //следующее значение задержки

  previousMillis=currentMillis;

}

 

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