I am new to Arduino and am trying to create a sketch using a servo and a sound file on the SD card of my MKR Zero.
I want the sound to be played back while the servo moves. I am using ServoEasing but I'm having a hard time understanding how to implement the triggering of the sound file.
The servo moves at variable speeds from 0 to 180 degrees. The sound file is short, but should start when the servo starts moving and stop when the servo stops.
If anyone can help me in the right direction I would be very grateful!
sketch below >
#include <Arduino.h>
#define ENABLE_EASE_QUADRATIC // Must specify this before the include of "ServoEasing.hpp"
#include "ServoEasing.hpp"
#include "PinDefinitionsAndMore.h"
ServoEasing Servo1;
#define START_DEGREE_VALUE 90
unsigned long currentMillis = 0;
#include <SD.h>
#include <SPI.h>
#include <AudioZero.h>
const int chipSelect = SDCARD_SS_PIN; //MKR Zero
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
// Just to know which program is running on my Arduino
#if !defined(PRINT_FOR_SERIAL_PLOTTER)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_SERVO_EASING));
#endif
#if defined(ESP32)
analogReadResolution(10);
#endif
Servo1.attach(9);
// Wait for servos to reach start position.
delay(500);
Servo1.startEaseToD(0, 1000, START_UPDATE_BY_INTERRUPT);
delay(1000);
Serial.println(F("Set easing type to QUADRATIC_IN_OUT for Servo1"));
Servo1.setEasingType(EASE_QUADRATIC_IN_OUT);
delay(1000);
Serial.print("\nInitializing SD card...");
// we'll use the initialization code from the utility libraries
if (!SD.begin(chipSelect)) {
Serial.println(" failed!");
while(true);
}
Serial.println(" done.");
}
void loop() {
File myFile = SD.open("test.wav");
// 44100kHz stereo => 88200 sample rate
AudioZero.begin(2*44100);
uint16_t tSpeed = analogRead(SPEED_IN_PIN);
tSpeed = map(tSpeed, 0, 1023, 5, random(100, 150 + 1)); //random value changes speed for each loop
setSpeedForAllServos(tSpeed);
/*
* Move servo without interrupt handler
*/
#if !defined(PRINT_FOR_SERIAL_PLOTTER)
Serial.print(F("Move to 0 degree with "));
Serial.print(Servo1.getSpeed());
Serial.println(F(" degree per second with updates by own do-while loop"));
#endif
/*
* Here we use the allServos functions
*/
setDegreeForAllServos(3, 0, 0, 0);
setEaseToForAllServos();
synchronizeAllServosAndStartInterrupt(false); // false, since we call updateAllServos() manually below
do {
// here you can call your own program
delay(REFRESH_INTERVAL_MILLIS); // optional 20ms delay
} while (!updateAllServos());
/*
* Move servo with interrupt handler
*/
#if !defined(PRINT_FOR_SERIAL_PLOTTER)
Serial.print(F("Move to 180 degree with "));
Serial.print(Servo1.getSpeed());
Serial.println(F(" degree per second using interrupts"));
#endif
Servo1.setEaseTo(180);
Servo1.startEaseTo(180);
AudioZero.play(myFile);
AudioZero.end();
delay(random(2000, 4000 + 1)); //adding a random pause between each loop
/*
* No need to call synchronizeAllServosAndStartInterrupt(), since I know that all durations are the same
* Since all servos stops at the same time I have to check only one
* Call yield for the ESP boards must be handled in areInterruptsActive()
*/
while (ServoEasing::areInterruptsActive()) {
; // no delays here to avoid break between forth and back movement
}
}