Включение светодиода и зуммера
Я пытаюсь создать детектор движения, который активирует как светодиод 12 В, так и пьезоизлучатель, но прочитал, что вы не можете использовать delay() с ними обоими. Как активировать светодиод и излучатель одновременно на заданное время (1 секунда)?
Важная часть моего кода выглядит следующим образом (похоже на демо Teapot):
// blink LED to indicate activity
if (Mag > 60) {
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
//digitalWrite(12, blinkState);
//delay(1000);
}
else if (Mag <= 60) {
digitalWrite(LED_PIN, LOW);
//digitalWrite(12,LOW);
}
Полный код:
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
// раскомментируйте "OUTPUT_READABLE_REALACCEL", если хотите увидеть ускорение
// компоненты с удаленной гравитацией. Эта система отсчета ускорения
// не компенсируется ориентацией, поэтому +X всегда +X согласно
// датчик, только без эффектов гравитации. Если вам нужно ускорение
// с компенсацией ориентации, вместо этого используйте OUTPUT_READABLE_WORLDACCEL.
#define OUTPUT_READABLE_REALACCEL
// раскомментируйте "OUTPUT_TEAPOT", если вы хотите, чтобы вывод соответствовал
// формат, используемый для демонстрации чайника InvenSense
#define OUTPUT_TEAPOT
#define LED_PIN 7 // (Arduino — 13, Teensy — 11, Teensy++ — 6)
bool blinkState = false;
// Переменные управления/состояния MPU
bool dmpReady = false; // установить true, если инициализация DMP прошла успешно
uint8_t mpuIntStatus; // содержит фактический байт статуса прерывания от MPU
uint8_t devStatus; // возвращаем статус после каждой операции устройства (0 = успех, !0 = ошибка)
uint16_t packetSize; // ожидаемый размер пакета DMP (по умолчанию 42 байта)
uint16_t fifoCount; // количество всех байтов в данный момент в FIFO
uint8_t fifoBuffer[64]; // буфер хранения FIFO
// переменные ориентации/движения
Quaternion q; // [w, x, y, z] контейнер кватерниона
VectorInt16 aa; // [x, y, z] измерения датчика ускорения
VectorInt16 aaReal; // [x, y, z] измерения датчика ускорения без учета гравитации
VectorInt16 aaWorld; // [x, y, z] измерения датчика ускорения в мировой системе координат
VectorFloat gravity; // [x, y, z] вектор гравитации
float euler[3]; // [psi, theta, phi] Контейнер угла Эйлера
float ypr[3]; // [рыскание, тангаж, крен] контейнер рыскания/тангажа/крена и вектор силы тяжести
// структура пакета для демонстрации чайника InvenSense
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
// ===========================================================
// === ПРОЦЕДУРА ОБНАРУЖЕНИЯ ПРЕРЫВАНИЯ ===
// ===========================================================
volatile bool mpuInterrupt = false; // указывает, перешел ли вывод прерывания MPU в высокий уровень
void dmpDataReady() {
mpuInterrupt = true;
}
// ============================================================
// === НАЧАЛЬНАЯ НАСТРОЙКА ===
// ===========================================================
void setup() {
// присоединяемся к шине I2C (библиотека I2Cdev не делает этого автоматически)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // Частота I2C 400 кГц (200 кГц, если процессор 8 МГц)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
// инициализация последовательной связи
// (выбрано 115200, так как оно требуется для вывода Teapot Demo, но это
// на самом деле все зависит от вашего проекта)
Serial.begin(115200);
while (!Serial); // ждем перечисления Leonardo, остальные продолжают немедленно
// ПРИМЕЧАНИЕ: процессоры хоста 8 МГц или медленнее, например Teensy @ 3.3v или Ardunio
// Pro Mini, работающий при напряжении 3,3 В, не может надежно обрабатывать эту скорость передачи данных из-за
// синхронизация бодов слишком не совпадает с тактами процессора. Вы должны использовать
// 38400 или медленнее в этих случаях, или используйте какой-либо внешний отдельный
// кристаллическое решение для таймера UART.
// инициализируем устройство
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
// проверка соединения
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
// ждем готовности
Serial.println(F("\nSend any character to begin DMP programming and demo: "));
while (Serial.available() && Serial.read()); // пустой буфер
while (!Serial.available()); // ждем данные
while (Serial.available() && Serial.read()); // снова пустой буфер
// загрузка и настройка DMP
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
// укажите здесь свои собственные смещения гироскопа, масштабированные для минимальной чувствительности
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 — заводское значение по умолчанию для моего тестового чипа
// убеждаемся, что все работает (возвращает 0, если так)
if (devStatus == 0) {
// включаем DMP, теперь он готов
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
// включить обнаружение прерываний Arduino
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// устанавливаем наш флаг готовности DMP, чтобы основная функция loop() знала, что ее можно использовать
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
// получить ожидаемый размер пакета DMP для последующего сравнения
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
// ОШИБКА!
// 1 = начальная загрузка памяти не удалась
// 2 = Не удалось обновить конфигурацию DMP
// (если он сломается, обычно код будет 1)
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
// настроить светодиод для выхода
pinMode(LED_PIN, OUTPUT);
}
// ===========================================================
// === ОСНОВНОЙ ЦИКЛ ПРОГРАММЫ ===
// ============================================================
void loop() {
// если программирование не удалось, не пытайтесь ничего делать
if (!dmpReady) return;
// ждем прерывания MPU или появления дополнительных пакетов
while (!mpuInterrupt && fifoCount < packetSize) {
// здесь есть другие сведения о поведении программы
// .
// .
// .
// если вы действительно параноик, вы можете часто проверять между другими
// что-то для проверки, является ли mpuInterrupt истинным, и если да, то "break;" из
// цикл while() для немедленной обработки данных MPU
// .
// .
// .
}
// сбрасываем флаг прерывания и получаем байт INT_STATUS
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// получить текущий счетчик FIFO
fifoCount = mpu.getFIFOCount();
// проверка на переполнение (это никогда не должно происходить, если только наш код не слишком неэффективен)
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
// сброс, чтобы мы могли продолжить работу без ошибок
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
// в противном случае проверьте прерывание готовности данных DMP (это должно происходить часто)
} else if (mpuIntStatus & 0x02) {
// ждем корректной длины доступных данных, ожидание должно быть ОЧЕНЬ коротким
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// прочитать пакет из FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// отслеживайте количество FIFO здесь на случай, если доступен > 1 пакет
// (это позволяет нам немедленно прочитать больше, не дожидаясь прерывания)
fifoCount -= packetSize;
#ifdef OUTPUT_READABLE_REALACCEL
// отображаем реальное ускорение, скорректированное для устранения гравитации
int Mag;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
Serial.print("areal\t");
Serial.print(aaReal.x);
Serial.print("\t");
Serial.print(aaReal.y);
Serial.print("\n");
Mag = sqrt((aaReal.x*aaReal.x) + (aaReal.y*aaReal.y));
Serial.print("Accel. Mag. is ");
Serial.print(Mag);
#endif
#ifdef OUTPUT_TEAPOT
// отображать значения кватерниона в демонстрационном формате InvenSense Teapot:
teapotPacket[2] = fifoBuffer[0];
teapotPacket[3] = fifoBuffer[1];
teapotPacket[4] = fifoBuffer[4];
teapotPacket[5] = fifoBuffer[5];
teapotPacket[6] = fifoBuffer[8];
teapotPacket[7] = fifoBuffer[9];
teapotPacket[8] = fifoBuffer[12];
teapotPacket[9] = fifoBuffer[13];
Serial.write(teapotPacket, 14);
teapotPacket[11]++; // packetCount, зацикливается на 0xFF намеренно
#endif
// мигание светодиода для индикации активности
if (Mag > 60) {
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
//digitalWrite(12, blinkState);
//задержка(1000);
}
else if (Mag <= 60) {
digitalWrite(LED_PIN, LOW);
//digitalWrite(12,LOW);
}
}
}
Если кто-то хочет ссылку на то, как выглядит система, я прикреплю картинку, без схемы. Если схема будет полезна, я отредактирую и прикреплю.

@elarr, 👍1
Обсуждение1 ответ
if (Mag > 60) {
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
digitalWrite (buzzer_Pin, HIGH); // или LOW
//digitalWrite(12, blinkState);
//задержка(1000);
}
Все должно быть так просто.
но с задержкой (1000) и, возможно, отключением зуммера?, @Juraj
Поэтому раскомментируйте строку delay(1000) и добавьте соответствующие строки выключения после задержки., @CrossRoads
Я тоже это пробовал — если добавить линию задержки, ничего не работает., @elarr
Нужно ли включать/выключать зуммер по частоте по эскизу? Или он включается при подаче питания? Как вы управляете зуммером?, @CrossRoads
- Несколько условий оператора if
- Светодиоды: разница между общим анодом и общим катодом
- Остановить мигание светодиодов
- Интеграция 2 кнопок для включения и выключения светодиода.
- Код Arduino для управления 4 светодиодами с 4 кнопок
- Управление цифровой адресной светодиодной лентой RGB 12 В с помощью Arduino
- Пассивный зуммер работает с AnalogWrite(), но не с DigitalWrite(). Он также имеет постоянный статический шум.
- Мигните светодиодом 5 раз с помощью цикла for
посмотрите на пример мерцания без задержки в arduino IDE, @Chad G
как активируется зуммер? достаточно ли установить вывод HIGH или нужна частота с функцией tone()?, @Juraj
Я пробовал установить пин на HIGH, но это не помогло. Не обязательно использовать tone(), когда я использую его на других системах, @elarr
есть ли у вас ссылка на пример кода для зуммера? вы можете попробовать tone(), @Juraj
Ваш комментарий, кажется, противоречит сам себе:
Я пробовал установить вывод на HIGH, но это не помогло. Нет необходимости использовать tone(), когда я использую его в других системах. Так в чем же дело? Работает ли установка вывода наHIGHв других системах? Если да, то установка вывода на высокий уровень на Arduino тоже должна работать. Что именно вы подразумеваете под "другими системами"? Ваш вопрос несколько неясен. Пожалуйста, отредактируйте и обновите его, чтобы прояснить моменты, поднятые в комментариях., @GreenonlineЯ не думаю, что комментарий противоречит сам себе - использование tone() не обязательно, потому что зуммер может быть активирован установкой вывода в HIGH. Здесь это не работает, когда я использую
digitalWrite(12, HIGH);под другими строками кода. Под 'другими системами' я подразумеваю, что если я использую тот же зуммер в более простой конфигурации (без светодиода, показанного на рисунке), он работает при использовании "HIGH"., @elarrна «других системах» вы устанавливаете ВЫСОКИЙ, НИЗКИЙ, ВЫСОКИЙ, НИЗКИЙ в цикле?, @Juraj