Как остановить цикл при использовании attachInterrupt для отслеживания изменения кнопки
Вот что делает программа:
Имеется 1 кнопка для запуска/остановки двигателя, когда он работает. загорится зеленый светодиод, при остановке загорится красный светодиод. Второй Кнопка используется для изменения направления вращения двигателя постоянного тока. Когда температура выше 20°, двигатель остановится, а серводвигатель будет Перейдите в положение красного светодиода. В противном случае серводвигатель находится в состоянии Нейтральное положение. При работающем двигателе играет музыка, которая должна звучать как автомобиль.
Итак, в чём моя проблема: если я нажимаю кнопку остановки двигателя постоянного тока, но музыка продолжает играть, она не останавливается. Я читал о break. Можно ли объединить это с attachInterrupt()? Я также нашёл такие функции, как interrupts() и noInterrupts(). Что нужно сделать, чтобы при нажатии кнопки двигатель постоянного тока сразу останавливался, а светодиод загорался красным?
Инициализация
#include <Servo.h>
#include "notebook.h";
#include "themes.h";
const int input1OfTheDCMotor = 9;
const int input2OfTheDCMotor = 10;
const int pwmInputOfTheDCMotor = 6;
const int buttonToStartStopTheDcMotor = 2;
const int buttonToShowToChangeTheDirectionOfTheDCMotor = 3;
const int greenLed = 12;
const int redLed = 8;
const int tempSensor = A0;
const int servoPin = 11;
Servo servo;
volatile byte stateOfTheButtonToStartStopTheDCMotor = LOW;
bool isRunning = LOW;
bool changeDirection = LOW;
bool isEngineSoundsPlaying = HIGH;
setup()
void setup() {
//Настройка светодиодов
pinMode(greenLed, OUTPUT);
pinMode(redLed, OUTPUT);
digitalWrite(redLed, HIGH);
//кнопки
pinMode(buttonToStartStopTheDcMotor, INPUT);
pinMode(buttonToShowToChangeTheDirectionOfTheDCMotor, INPUT);
//двигатель постоянного тока
pinMode(input1OfTheDCMotor, OUTPUT);
pinMode(input2OfTheDCMotor, OUTPUT);
digitalWrite(input1OfTheDCMotor, LOW);
digitalWrite(input2OfTheDCMotor, HIGH);
//ШИМ-сигнал
pinMode(pwmInputOfTheDCMotor, OUTPUT);
//Сервопривод
servo.attach(servoPin);
//прерывания
attachInterrupt(digitalPinToInterrupt(buttonToStartStopTheDcMotor), readTheChangeToStartStop, RISING );
attachInterrupt(digitalPinToInterrupt(buttonToShowToChangeTheDirectionOfTheDCMotor), readTheChangeToChangeDirection, RISING );
}
Цикл ()
void loop() {
int valueOfTheSensor = analogRead(tempSensor);
float voltage = (valueOfTheSensor / 1024.0) * 5.0;
float temp = (voltage -0.5) * 100;
if (temp >= 20.00)
isRunning = LOW;
}
changeTheStateOfTheLights(isRunning);
startTheDCMotorAndStopIt(isRunning);
changeTheDirectionOfTheDCMotor(changeDirection);
}
Функция readTheChangeToStartStop():
void readTheChangeToStartStop () {
isRunning = !isRunning;
changeTheStatusOfTheEnginePlaying();
}
Функция readTheChangeToChangeDirection():
void readTheChangeToChangeDirection () {
changeDirection = !changeDirection;
}
Функция changeTheStatusOfTheEnginePlaying():
void changeTheStatusOfTheEnginePlaying (){
if (isRunning == HIGH){
isEngineSoundsPlaying = HIGH;
} else {
isEngineSoundsPlaying = LOW;
}
}
Функция changeTheStateOfTheLights():
void changeTheStateOfTheLights(bool stateOfLight) {
digitalWrite(greenLed, stateOfLight);
digitalWrite(redLed, !stateOfLight);
}
Функция startTheDCMotorAndStopIt():
void startTheDCMotorAndStopIt(bool isRunning){
if (isRunning == HIGH) {
digitalWrite(pwmInputOfTheDCMotor, HIGH);
playCarMusicStart();
changeToNeutral();
} else {
digitalWrite(pwmInputOfTheDCMotor, LOW);
changeToRedLight();
}
}
Функция changeTheDirectionOfTheDCMotor():
void changeTheDirectionOfTheDCMotor(bool changeDirection) {
digitalWrite(input1OfTheDCMotor, changeDirection);
digitalWrite(input2OfTheDCMotor, !changeDirection);
}
Функция changeToRedLight():
void changeToRedLight() {
servo.write(0);
delay(15);
}
Функция changeToNeutral():
void changeToNeutral() {
servo.write(40);
delay(15);
}
Функция playCarMusicStart():
void playCarMusicStart(){
if (isEngineSoundsPlaying == HIGH) {
for (int thisNote = 0; thisNote < (sizeof(carSounds_note)/sizeof(int)); thisNote++) {
int noteDuration = 1000 / carsounds_duration[thisNote];
tone(4, carSounds_note[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 2.70;
delay(pauseBetweenNotes);
noTone(4);
isEngineSoundsPlaying = LOW;
}
}
}
Решение
Огромное спасибо @ratchet freak
Мне нужно изменить мой loop() на это:
void loop() {
int valueOfTheSensor = analogRead(tempSensor);
float voltage = (valueOfTheSensor / 1024.0) * 5.0;
float temp = (voltage -0.5) * 100;
if (temp >= 20.00) {
isRunning = LOW;
}
changeTheStateOfTheLights(isRunning);
startTheDCMotorAndStopIt(isRunning);
changeTheDirectionOfTheDCMotor(changeDirection);
playCarMusicStart();
}
Мне также нужно было изменить PlayCarMusicStart():
void playCarMusicStart(){
if (isEngineSoundsPlaying == HIGH && currentNote < (sizeof(carSounds_note)/sizeof(int))) {
int noteDuration = 1000 / carsounds_duration[currentNote];
tone(4, carSounds_note[currentNote], noteDuration);
int pauseBetweenNotes = noteDuration * 2.70;
delay(pauseBetweenNotes);
noTone(4);
currentNote++;
} else {
currentNote = 0;
}
}
И самое меньшее — это установить isEngineSoundsPlaying равным HIGH, я изменил функцию startTheDCMotorAndStopIt() на:
void startTheDCMotorAndStopIt(bool isRunning){
if (isRunning == HIGH) {
isEngineSoundsPlaying = HIGH;
digitalWrite(pwmInputOfTheDCMotor, HIGH);
changeToNeutral();
} else {
isEngineSoundsPlaying = LOW;
digitalWrite(pwmInputOfTheDCMotor, LOW);
changeToRedLight();
}
}
@Steven, 👍1
1 ответ
Лучший ответ:
Ключевым моментом будет разделение playCarMusicStart и создание вместо него playCarMusicStep, который выполнит только одну итерацию цикла и вернётся. Вызывайте его каждый раз в loop(), аналогично blinkWithoutDelay.
В playCarMusicStart вы затем настраиваете состояние воспроизведения, чтобы оно началось правильно.
А когда вам нужно остановить музыку, вы останавливаете ее, устанавливая правильную переменную.
- Проблемы с ШИМ и подключением прерываний
- Остановка программы через 1 секунду
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как устранить шум от вентилятора 12 В с ШИМ-управлением на низкой скорости
- Как работают прерывания на Arduino Uno и аналогичных платах?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Arduino uno + cnc Shield v3 + драйвер шагового двигателя A4988 + AccelStepper?
- Как заставить сервопривод вращаться на угол больше 180°