Skip to content

Commit 80fef81

Browse files
M4_Eyes: fizzgig servo movement
1 parent bfaafdd commit 80fef81

1 file changed

Lines changed: 32 additions & 17 deletions

File tree

M4_Eyes/user_fizzgig.cpp

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
#if 0 // Change to 1 to enable this code (must enable ONE user*.cpp only!)
22

3-
// WIP DO NOT USE
4-
53
#include "globals.h"
64
#include <Servo.h>
75

86
// Servo stuff
97
Servo myservo;
108
#define SERVO_MOUTH_OPEN 0
119
#define SERVO_MOUTH_CLOSED 180
12-
// TO DO: move servo when sound is playing.
13-
// At end of WAV, move mouth to closed position.
10+
#define SERVO_PIN 3
11+
12+
#define BUTTON_PIN 2
1413

1514
// WAV player stuff
16-
#define WAV_BUFFER_SIZE 256
15+
#define WAV_BUFFER_SIZE 256
1716
static uint8_t wavBuf[2][WAV_BUFFER_SIZE];
1817
static File wavFile;
1918
static bool playing = false;
@@ -22,6 +21,7 @@ static uint8_t activeBuf;
2221
static uint16_t bufIdx, bufEnd, nextBufEnd;
2322
static bool startWav(char *filename);
2423
static void wavOutCallback(void);
24+
static uint32_t wavEventTime; // WAV start or end time, in ms
2525
static const char *wav_path = "fizzgig";
2626
static struct wavlist { // Linked list of WAV filenames
2727
char *filename;
@@ -58,23 +58,35 @@ void user_setup(void) {
5858
wavListPtr->next = wavListStart; // Point last item's next to list head (list is looped)
5959
wavListPtr = wavListStart; // Update list pointer to head
6060
}
61-
myservo.attach(3);
6261
}
6362

6463
void user_loop(void) {
65-
if(!playing && wavListPtr) {
66-
pinMode(2, INPUT_PULLUP);
64+
if(playing) {
65+
// While WAV is playing, wiggle servo between middle and open-mouth positions:
66+
uint32_t elapsed = millis() - wavEventTime; // Time since audio start
67+
uint16_t frac = elapsed % 500; // 0 to 499 = 0.5 sec
68+
float n = 1.0 - ((float)abs(250 - frac) / 500.0); // Ramp 0.5, 1.0, 0.5 in 0.5 sec
69+
myservo.write((int)((float)SERVO_MOUTH_CLOSED + (float)(SERVO_MOUTH_OPEN - SERVO_MOUTH_CLOSED) * n));
70+
// BUTTON_PIN button is ignored while sound is playing.
71+
} else if(wavListPtr) {
72+
// Not currently playing WAV. Check for button press on pin BUTTON_PIN.
73+
pinMode(BUTTON_PIN, INPUT_PULLUP);
6774
delayMicroseconds(20); // Avoid boop code interference
68-
if(!digitalRead(2)) {
75+
if(!digitalRead(BUTTON_PIN)) {
6976
arcada.chdir(wav_path);
7077
startWav(wavListPtr->filename);
7178
wavListPtr = wavListPtr->next; // Will loop around from end to start of list
7279
}
80+
pinMode(BUTTON_PIN, INPUT);
81+
if(myservo.attached()) { // If servo still active (from recent WAV playing)
82+
myservo.write(SERVO_MOUTH_CLOSED); // Make sure it's in closed position
83+
// If it's been more than 1 sec since audio stopped,
84+
// deactivate the servo to reduce power, heat & noise.
85+
if((millis() - wavEventTime) > 1000) {
86+
myservo.detach();
87+
}
88+
}
7389
}
74-
75-
// 'pos' will be determined periodically, maybe not every frame. TBD.
76-
// needs to go to a closed position when WAV is finished.
77-
// myservo.write(pos);
7890
}
7991

8092
static uint16_t readWaveData(uint8_t *dst) {
@@ -146,10 +158,12 @@ static bool startWav(char *filename) {
146158
analogWrite(A0, 128);
147159
analogWrite(A1, 128);
148160
arcada.enableSpeaker(true);
149-
bufIdx = 0;
150-
playing = true;
161+
wavEventTime = millis(); // WAV starting time
162+
bufIdx = 0;
163+
playing = true;
151164
arcada.timerCallback(buf.fmt.sampleRate, wavOutCallback);
152-
nextBufEnd = readWaveData(wavBuf[1]);
165+
nextBufEnd = readWaveData(wavBuf[1]);
166+
myservo.attach(SERVO_PIN);
153167
}
154168
return true;
155169
} else {
@@ -175,7 +189,8 @@ static void wavOutCallback(void) {
175189
if(nextBufEnd <= 0) {
176190
arcada.timerStop();
177191
arcada.enableSpeaker(false);
178-
playing = false;
192+
playing = false;
193+
wavEventTime = millis(); // Same var now holds WAV end time
179194
return;
180195
}
181196
bufIdx = 0;

0 commit comments

Comments
 (0)