Как мигать светодиодом и одновременно запускать другой код?
Я написал код для расчета оборотов двигателей с помощью ИК-датчика и Arduino nano и отображение его на OLED. При этом я хочу, чтобы светодиод моргайте всегда. Вот код, что я сделал:
Вы можете пропустить объявления и часть setup()
. Просто двигайтесь прямо
в loop()
. У меня проблема в цикле. В loop()
горит только светодиод.
мигание и дальнейший расчет оборотов с кодами OLED-дисплея невозможны.
выполнено.
#include "avr/sleep.h"
#include "avr/power.h"
#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
int led = 12;
int in = 13;
int pushbutton=10;
unsigned long duration = 0;
float rpm = 0;
float rpm_a = 0;
int counter = 0;
int present = 0;
int previous = 0;
unsigned long elapsed = 0;
unsigned long elapsed_prev = 0;
int disabled = 0;
void setup() {
Serial.begin(9600);
pinMode(led, OUTPUT);
pinMode(in,INPUT);
pinMode(pushbutton,INPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(35,1);
display.print("xyz");
display.display();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(25,13);
display.print("abc");
display.display();
delay(5000);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("RPMmeter");
display.display();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,19);
display.println("RPM:");
display.setCursor(80,19);
display.println(rpm);
display.display();
elapsed = micros();
}
void loop()
{
/** led blink part **/
digitalWrite(led, HIGH);
delay(70);
digitalWrite(led, LOW);
delay(70);
digitalWrite(led, HIGH);
delay(70);
digitalWrite(led, LOW);
delay(900);
/** led blink part over and rpm calculation and displaying on
* oled part starts **/
if(digitalRead(pushbutton))
{
// Включено низкое энергопотребление Arduino
if(disabled==0)
{
sleep_disable();
disabled = 1;
}
if (digitalRead(in) == 1 && previous == 0)
{
previous = 1;
duration = elapsed - elapsed_prev;
elapsed_prev = micros();
}
if (digitalRead(in) == 1 && previous == 1)
{
previous = 1;
}
if (digitalRead(in) == 0 && previous == 1)
{
previous = 0;
}
if (digitalRead(in) == 0 && previous == 0)
{
previous = 0;
elapsed = micros();
}
rpm = 60000000/duration;
//Добавляем небольшую ошибку в значение оборотов (в данном случае +-2)
if ((rpm_a-2) < rpm && rpm < (rpm_a+2))
{
rpm_a = rpm;
counter = counter + 1;
if (counter == 50)
{
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("JARVIS RPMmeter");
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,19);
display.println("RPM:");
display.setCursor(80,19);
display.println(rpm);
display.display();
counter = 0;
}
}
if (!( (rpm_a-2) < rpm && rpm < (rpm_a+2)))
{
rpm_a=rpm;
}
}//конец, если кнопка=1
else {
display.display();
display.clearDisplay();
delay(10);
duration = 0;
rpm = 0;
rpm_a = 0;
counter = 0;
present = 0;
previous = 0;
// Включено низкое энергопотребление Arduino
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
disabled = 0;
}
}
Это был код. Проблема в том, что без мигающего кода часть цикла, код работает нормально, но если мы включим этот светодиод мигающая часть, код дальше не движется. Я имею в виду, что горит только светодиод мигает, и дальнейшие коды не выполняются. Почему это так? И как выполните как расчет оборотов в минуту с дисплеем на OLED, так и на LED мигание происходит по одному коду одновременно?
@userLP, 👍1
Обсуждение4 ответа
При выполнении команд «Задержка» ваш Arduino на самом деле ничего не делает. Лучшее, что вы можете сделать, — это взглянуть на BlinkWithoutDelay и соответствующим образом адаптировать свой код.
Для этого есть несколько вариантов использования millis(). Ничего, если я изменю 900 мс на кратное 70 мс? Тогда я смогу считать интервалы по 70 мс.
// мигает светодиод: 70 мс вкл., затем 70 мс выкл., затем 70 мс вкл., затем 910 мс выкл.
unsigned long previousMillis;
int count = 0;
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= 70) {
previousMillis = currentMillis;
switch(count) {
case 0:
digitalWrite(13, HIGH);
break;
case 1:
digitalWrite(13, LOW);
break;
case 2:
digitalWrite(13, HIGH);
break;
case 3:
digitalWrite(13, LOW);
break;
}
count++;
if(count >= 16)
count = 0;
}
}
Когда значения интервалов находятся в массиве, код, вероятно, становится меньше.
// мигание светодиода: 70 мс вкл., 70 мс выкл., 70 мс вкл., 900 мс выкл.
unsigned long previousMillis;
const int intervals[4] = {70, 70, 70, 900};
int index = 0;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, HIGH); // включаем светодиод, через 70мс он выключится
}
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= intervals[index]) {
previousMillis = currentMillis;
int level = (index % 2) == 0 ? LOW : HIGH;
digitalWrite(13, level);
index++;
if(index > 3)
index = 0;
}
}
Второй скетч меньше, но я предпочитаю первый.
Посмотрите мой ответ на аналогичный вопрос. Примените тот же принцип к своей проблеме:
- Переместите каждую задачу (мигает; рассчитывается число оборотов в минуту) в отдельную функцию.
- Заставьте цикл() вызывать эти функции как можно чаще.
- Заставьте каждую функцию решить, пора ли выполнить ее задачу, сделать это или нет, и вернуться.
- Эти функции никогда не должны ждать.
Такой тип организации программы, называемый неблокирующей, можно расширить на любое количество задач, пока у вас не закончится память или у процессора не закончится время, чтобы сделать все так быстро, как вам нужно (что будет намного больше, чем те двое, которые вы описали!).
Единственное, что, как я вижу, делает ваш код ошибочным, это тот факт, что вы используете оператор if, чтобы проверить, нажата ли ваша кнопка, а затем у вас есть много кода, который должен быть выполнен в этом операторе, а не устанавливаете bool вне вашего цикла и установите его с помощью функции if, а затем используйте некоторое время, чтобы выполнить всю остальную работу, которая была в вашем операторе if, таким образом, когда кнопка будет отпущена, код все равно будет выполнен, и когда он будет нажат снова, он будет случится снова
Почти забыл о хорошем, да, блинк без задержки — это способ использовать код блинка
- Может ли Arduino UNO постоянно хранить код?
- Можно ли отправить 2 или более сигнала o/p одновременно?
- Случайный сброс Arduino Nano
- Светодиодный матричный модуль FC-16 на базе MAX7219
- Запуск кода кодировщика одновременно с другим кодом в Arduino
- avrdude ser_open() can't set com-state
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Печать string and integer LCD
Не используйте задержку. Вместо этого неблокирующий код, как в примере BlinkWithoutDelay в Arduino IDE. Как это сделать, описано во многих руководствах, а также в вопросах на этом сайте., @chrisl
@userLP, было бы полезно, если бы вы выбрали ответ, который оказался правильным, и отметили его так, чтобы будущие посетители знали, какой ответ вам помог., @st2000