Как применить millis() вместо delay() в указанном коде?

‘’'/* ИСХОДНЫЕ ДАННЫЕ:
1). Потенциометр, одним концом подключенный к питанию, другим к земле.
Средний контакт - к аналоговому входу микроконтроллера.
2). Семисигментный светодиодный индикатор с общим катодом 5161А.
Он взят просто для экономии места, чтобы не ставить кучу светодиодов.
ЗАДАЧА:
1). Условно разбить весь диапазон значений 0…1023, которые считывает контроллер
при вращении оси потенциометра, на 3 неравных отрезка.
2). При вращении оси потенциометра от нуля направо, т.е. при увеличении напряжения,
светодиоды должны бегать по кругу по часовой стрелке с ускорением в первом и третьем диапазонах.
3). При вращении оси потенциометра от максимального значения налево до минимального
светодиоды должны бегать против часовой стрелки с замедлением в первом и третьем диапазонах.
4). В среднем отрезке должна просто зажигаться чёрточка (светодиод G). Другие светодиоды
гореть и бегать не должны на этом участке.
*/

// НЕИЗМЕНЯЕМЫЕ ПАРАМЕТРЫ (КОНСТАНТЫ):
// Назначаем аналоговый вход A0 для чтения данных с потенциометра:
const int POT = A0;
// Назначаем выходы контроллера для управления светодиодами семисегментного LED-индикатора:
const int LED_A = 2;
const int LED_B = 3;
const int LED_C = 4;
const int LED_D = 5;
const int LED_E = 6;
const int LED_F = 7;
const int LED_G = 8; // Чёрточка в семисигментном индикаторе
// Светодиоды в индикаторе запишем массивом:
int ledPins = { LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G };

// ИЗМЕНЯЕМЫЕ ПАРАМЕТРЫ:
int index, valPOT, next_valPOT = 0; // i, значение напряжения valPOT, следующее считанное значение напряжения
int up_Board = 600; // Верхняя граница среднего участка
int down_Board = 500; // Нижняя граница среднего участка

void setup() {
// Все пины по очереди устанавливаем на выход. Счёт начинается с нуля, поэтому i <= 6, а не 7
for (index = 0; index <= 6; index++) {
pinMode(ledPins[index], OUTPUT);
Serial.begin(9600); // Инициализируем COM-порт для отладки
}
}

void loop() {
valPOT = analogRead(POT); // Читаем текущее значение потенциометра
delay(50); // Задержка программы, чтобы стабилизировать считывание значения valPOT после поворота оси потенциометра
next_valPOT = analogRead(POT); // Читаем другое значение valPOT, чтобы сравнить растёт или нет?
// Если значение valPOT находится в одном ИЛИ другом диапазоне И увеличивается, то движение светодиодов направо
if (((valPOT > 0 && valPOT < down_Board) || (valPOT > up_Board && valPOT <= 1023)) && (next_valPOT >= valPOT)) {
to_the_right();
}
// А может значение valPOT находится в тех же диапазонах И уменьшается? Тогда движение светодиодов налево
if (((valPOT > 0 && valPOT < down_Board) || (valPOT > up_Board && valPOT <= 1023)) && (next_valPOT < valPOT)) {
to_the_left();
}
// А если находится в среднем диапазоне от down_Board до up_Board, то зажечь горизонтальную чёрточку
if (valPOT >= down_Board && valPOT <= up_Board) {
digitalWrite(LED_G, HIGH);
} else {
digitalWrite(LED_G, LOW); // В противном случае горизонтальная черта гореть не должна
}
Serial.println(valPOT); // Выводим в монитор, чтобы посмотреть, как ведёт себя valPOT
}

void to_the_right() { // Функция вращения направо
int valpot = analogRead(POT);
valpot = map(valpot, 0, 1023, 800, 1000); // Ограничиваем значение valpot, получаемое от потенциометра, чтобы быстрее нарастало значение при вращении
for (index = 0; index <= 5; index++) { // Перебор по одному от светодиода к светодиоду направо
int delayTime = 1023 - valpot; // уменьшаем время простоя программы и ускоряем вращение с ростом напряжения
digitalWrite(ledPins[index], HIGH);
delay(delayTime);
digitalWrite(ledPins[index], LOW);
}
}

void to_the_left() {
int valpot = analogRead(POT); // Функция вращения влево
valpot = map(valpot, 0, 1023, 800, 1000); // Ограничиваем значение valpot, получаемое от потенциометра, чтобы быстрее нарастало значение при вращении
for (index = 5; index >= 0; index–) { // Перебор от светодиода к светодиоду налево без чёрточки, поэтому index=5, а не 6
int delayTime = 1023 - valpot; // уменьшаем время и ускоряем вращение с ростом напряжения
digitalWrite(ledPins[index], HIGH);
delay(delayTime);
digitalWrite(ledPins[index], LOW);
}
}
‘’’

Прежде чем писать - прочти что написано в окне ввода текста!
Это намек как правильно вставить код…

Программа не имеет практического применения. Задачу поставил себе сам. И сам же пытаюсь ее решить. Программа работает, но:
1). Иногда ловит помеху и светодиоды начинают кратковременно вращаться не туда, куда надо.
2). При применении delay программа жутко тормозит. Это видно в мониторе.
3). Хочется применить millis вместо delay, но не могу сообразить, как заставить ее зависеть от переменной считанного значения напряжения для управления скоростью “вращения” светодиодов.
4). Хотел бы применить switsh…case вместо if, но тоже придумать пока не могу.
Еще раз повторяю, что задача не практическая, поэтому если знающий народ посчитает ее неинтересной, то так тому и быть. А если найдутся те, кто подскажет, как решить хотя бы один из пунктов, то буду признателен.

Никто из ниже и выше перечисленного/написаного тобой читать не будет, пока код не вставишь по правилам форума.

/* ИСХОДНЫЕ ДАННЫЕ:
1). Потенциометр, одним концом подключенный к питанию, другим к земле.
Средний контакт - к аналоговому входу микроконтроллера.
2). Семисигментный светодиодный индикатор с общим катодом 5161А.
Он взят просто для экономии места, чтобы не ставить кучу светодиодов.
ЗАДАЧА:
1). Условно разбить весь диапазон значений 0...1023, которые считывает контроллер
при вращении оси потенциометра, на 3 неравных отрезка.
2). При вращении оси потенциометра от нуля направо, т.е. при увеличении напряжения,
светодиоды должны бегать по кругу по часовой стрелке с ускорением в первом и третьем диапазонах.
3). При вращении оси потенциометра от максимального значения налево до минимального
светодиоды должны бегать против часовой стрелки с замедлением в первом и третьем диапазонах.
4). В среднем отрезке должна просто зажигаться чёрточка (светодиод G). Другие светодиоды
гореть и бегать не должны на этом участке.
*/

// НЕИЗМЕНЯЕМЫЕ ПАРАМЕТРЫ (КОНСТАНТЫ):
// Назначаем аналоговый вход A0 для чтения данных с потенциометра:
const int POT = A0;
// Назначаем выходы контроллера для управления светодиодами семисегментного LED-индикатора:
const int LED_A = 2;
const int LED_B = 3;
const int LED_C = 4;
const int LED_D = 5;
const int LED_E = 6;
const int LED_F = 7;
const int LED_G = 8;  // Чёрточка в семисигментном индикаторе
// Светодиоды в индикаторе запишем массивом:
int ledPins[] = { LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G };

// ИЗМЕНЯЕМЫЕ ПАРАМЕТРЫ:
int index, valPOT, next_valPOT = 0;  // i, значение напряжения valPOT, следующее считанное значение напряжения
int up_Board = 600;                  // Верхняя граница среднего участка
int down_Board = 500;                // Нижняя граница среднего участка

void setup() {
  // Все пины по очереди устанавливаем на выход. Счёт начинается с нуля, поэтому i <= 6, а не 7
  for (index = 0; index <= 6; index++) {
    pinMode(ledPins[index], OUTPUT);
    Serial.begin(9600);  // Инициализируем COM-порт для отладки
  }
}

void loop() {
  valPOT = analogRead(POT);       // Читаем текущее значение потенциометра
  delay(50);                      // Задержка программы, чтобы стабилизировать считывание значения valPOT после поворота оси потенциометра
  next_valPOT = analogRead(POT);  // Читаем другое значение valPOT, чтобы сравнить растёт или нет?
  // Если значение valPOT находится в одном ИЛИ другом диапазоне И увеличивается, то движение светодиодов направо
  if (((valPOT > 0 && valPOT < down_Board) || (valPOT > up_Board && valPOT <= 1023)) && (next_valPOT >= valPOT)) {
    to_the_right();
  }
  // А может значение valPOT находится в тех же диапазонах И уменьшается? Тогда движение светодиодов налево
  if (((valPOT > 0 && valPOT < down_Board) || (valPOT > up_Board && valPOT <= 1023)) && (next_valPOT < valPOT)) {
    to_the_left();
  }
  // А если находится в среднем диапазоне от down_Board до up_Board, то зажечь горизонтальную чёрточку
  if (valPOT >= down_Board && valPOT <= up_Board) {
    digitalWrite(LED_G, HIGH);
  } else {
    digitalWrite(LED_G, LOW);  // В противном случае горизонтальная черта гореть не должна
  }
  Serial.println(valPOT);  // Выводим в монитор, чтобы посмотреть, как ведёт себя valPOT
}

void to_the_right() {  // Функция вращения направо
  int valpot = analogRead(POT);
  valpot = map(valpot, 0, 1023, 800, 1000);  // Ограничиваем значение valpot, получаемое от потенциометра, чтобы быстрее нарастало значение при вращении
  for (index = 0; index <= 5; index++) {     // Перебор по одному от светодиода к светодиоду направо
    int delayTime = 1023 - valpot;           // уменьшаем время простоя программы и ускоряем вращение с ростом напряжения
    digitalWrite(ledPins[index], HIGH);
    delay(delayTime);
    digitalWrite(ledPins[index], LOW);
  }
}

void to_the_left() {
  int valpot = analogRead(POT);              // Функция вращения влево
  valpot = map(valpot, 0, 1023, 800, 1000);  // Ограничиваем значение valpot, получаемое от потенциометра, чтобы быстрее нарастало значение при вращении
  for (index = 5; index >= 0; index--) {     // Перебор от светодиода к светодиоду налево без чёрточки, поэтому index=5, а не 6
    int delayTime = 1023 - valpot;           // уменьшаем время и ускоряем вращение с ростом напряжения
    digitalWrite(ledPins[index], HIGH);
    delay(delayTime);
    digitalWrite(ledPins[index], LOW);
  }
}

Строка 40. Зачем инициализировать УАРТ 7 раз подряд?
Делей разве принимает переменную? Насколько знаю, крайне не рекомендуют так делать. Только константа.
Как вариант завернуть delay в цикл.

От неопытности пока.

Согласен. Serial.print не туда вставил. За подсказку ошибки спасибо. Но это не решает основных проблем.

fot(i=0;i<valport;i++)
{
delay(10);
}

Как-то так примерно.

А какая ему, дилею, разница?

2 лайка

Попробую подсказку. Пощупаю, что получится.

@Dmitrii_Sever , “съездить в гости” и “поговорить по телефону” - это несколько разные вещи, и телефон в автомобиль не переделаешь.
millis() и delay() предполагают совершенно различную структуру программы. Фактически программу надо перепроектировать с нуля. Т.е. переделать работу, которая выполняется еще до написания первой строчки кода. Возможно, какие-то фрагменты существующего кода возможно будет применить в новом. Но в любом случае эти фрагменты надо будет собрать на совершенно другой основе.

Тоже спасибо за подсказку. Я уже приходил к такому же выводу, но все же решил спросить у взрослых дядей.

Так в инструкции написано))) Сам не пользовался.
А стандартные функции _delay_ms() и _delay_us() вообще только константы.

Где?
специально посмотрел:

и
https://www.arduino.cc/reference/en/language/functions/time/delay/

Тлетворное влияние ассемблера в @te238s чую я

1 лайк

Может он с де Диваном в личке тайно общается? ;).
“Только двое их - Учитель и Ученик” :rofl:

ну как бы valPOT у вас результат чтения analogRead(). так что он в любом случае изменяется от нуля до 1023, поэтому два из четырех сравнений в условии лишние.

Когда пробегаете по всем значениям массива из, скажем, семи элементов - принято писать

for (index = 0; index < 7; index++) {

а не “меньше-равно 6” как у вас:

В первой записи сразу видно, сколько элементов в массиве, а во втором нужно еще задуматся и прибавить единицу. Это лишний повод ошибиться.

Поэтому вот тут я не знаю, хотели ли вы пробежать по шести светодиодам или просто ошиблись:

светодиодов-то у вас семь…

Дух Дедивана неистребим)

Да как бы куда дотянулся…к Гиверу. Его строка в поиске гугла была первой)

Нет) Хотя я иногда люблю хардкор, прерывания и чёткую работу МК)
Но за идею спасибо🤣