84 lines
3.0 KiB
C++
84 lines
3.0 KiB
C++
// SERVO BAT: flapping paper-cutout bat (attached to servo on SERVO_PIN)
|
|
// triggered by contact-sensitive conductive thread on CAPTOUCH_PIN.
|
|
// See user.cpp for basics of connecting user code to animated eyes.
|
|
|
|
#if 0 // Change to 1 to enable this code (must enable ONE user*.cpp only!)
|
|
|
|
#include "Adafruit_FreeTouch.h"
|
|
#include <Servo.h>
|
|
|
|
#define CAPTOUCH_PIN A5 // Capacitive touch pin - attach conductive thread here
|
|
#define SERVO_PIN 4 // Servo plugged in here
|
|
|
|
// Set up capacitive touch button using the FreeTouch library
|
|
static Adafruit_FreeTouch touch(CAPTOUCH_PIN, OVERSAMPLE_4, RESISTOR_50K, FREQ_MODE_NONE);
|
|
static long oldState; // Last-read touch value
|
|
static bool isTouched = false; // When true, bat is flapping
|
|
static uint32_t touchTime = 0; // millis() time when flapping started
|
|
static uint32_t touchThreshold;
|
|
|
|
Servo servo;
|
|
|
|
void user_setup(void) {
|
|
if (!touch.begin())
|
|
Serial.println("Cap touch init failed");
|
|
servo.attach(SERVO_PIN);
|
|
servo.write(0); // Move servo to idle position
|
|
servo.detach();
|
|
|
|
// Attempt to auto-calibrate the touch threshold
|
|
// (assumes thread is NOT touched on startup!)
|
|
touchThreshold = 0;
|
|
for(int i=0; i<10; i++) {
|
|
touchThreshold += touch.measure(); // Accumulate 10 readings
|
|
delay(50);
|
|
}
|
|
touchThreshold /= 10; // Average "not touched" value
|
|
touchThreshold = ((touchThreshold * 127) + 1023) / 128; // Threshold = ~1% toward max
|
|
|
|
oldState = touch.measure();
|
|
}
|
|
|
|
#define FLAP_TIME_RISING 900 // 0-to-180 degree servo sweep time, in milliseconds
|
|
#define FLAP_TIME_FALLING 1200 // 180-to-0 servo sweep time
|
|
#define FLAP_REPS 3 // Number of times to flap
|
|
#define FLAP_TIME_PER (FLAP_TIME_RISING + FLAP_TIME_FALLING)
|
|
#define FLAP_TIME_TOTAL (FLAP_TIME_PER * FLAP_REPS)
|
|
|
|
void user_loop(void) {
|
|
long newState = touch.measure();
|
|
Serial.println(newState);
|
|
|
|
if (isTouched) {
|
|
uint32_t elapsed = millis() - touchTime;
|
|
if (elapsed >= FLAP_TIME_TOTAL) { // After all flaps are completed
|
|
isTouched = false; // Bat goes idle again
|
|
servo.write(0);
|
|
servo.detach();
|
|
} else {
|
|
elapsed %= FLAP_TIME_PER; // Time within current flap cycle
|
|
if (elapsed < FLAP_TIME_RISING) { // Over the course of 0 to FLAP_TIME_RISING...
|
|
servo.write(elapsed * 180 / FLAP_TIME_RISING); // Move 0 to 180 degrees
|
|
} else { // Over course of FLAP_TIME_FALLING, return to 0
|
|
servo.write(180 - ((elapsed - FLAP_TIME_RISING) * 180 / FLAP_TIME_FALLING));
|
|
}
|
|
}
|
|
} else {
|
|
// Bat is idle...check for capacitive touch...
|
|
if (newState > touchThreshold && oldState < touchThreshold) {
|
|
delay(100); // Short delay to debounce
|
|
newState = touch.measure(); // Verify whether still touched
|
|
if (newState > touchThreshold) { // It is!
|
|
isTouched = true; // Start a new flap session
|
|
touchTime = millis();
|
|
servo.attach(SERVO_PIN);
|
|
servo.write(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
oldState = newState; // Save cap touch state
|
|
}
|
|
|
|
#endif // 0
|