#define TOUCH_SENSOR_PIN 14 // Connect OUT pin of TTP223 to GPIO 14
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
TwoWire i2cLeft(0);
TwoWire i2cRight(1);
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 displayLeft(SCREEN_WIDTH, SCREEN_HEIGHT, &i2cLeft, OLED_RESET);
Adafruit_SSD1306 displayRight(SCREEN_WIDTH, SCREEN_HEIGHT, &i2cRight, OLED_RESET);
int eyeY = 12;
int eyeWidth = 40;
int eyeHeight = 40;
int eyeX_L = 44;
int targetOffsetX_L = 0, targetOffsetY_L = 0;
int offsetX_L = 0, offsetY_L = 0;
int moveSpeed_L = 3;
int blinkState_L = 0;
int blinkDelay_L = 4000;
unsigned long lastBlinkTime_L = 0, moveTime_L = 0;
int eyeX_R = 44;
int targetOffsetX_R = 0, targetOffsetY_R = 0;
int offsetX_R = 0, offsetY_R = 0;
int moveSpeed_R = 3;
int blinkState_R = 0;
int blinkDelay_R = 4000;
unsigned long lastBlinkTime_R = 0, moveTime_R = 0;
unsigned long lastTouchTime = 0; // When touch was last detected
unsigned long keepAliveDuration = 5000; // Keep showing for 5 seconds
void setup() {
Serial.begin(115200);
pinMode(TOUCH_SENSOR_PIN, INPUT);
i2cLeft.begin(8, 9);
i2cRight.begin(17, 18);
displayLeft.begin(SSD1306_SWITCHCAPVCC, 0x3C);
displayRight.begin(SSD1306_SWITCHCAPVCC, 0x3C);
displayLeft.clearDisplay();
displayRight.clearDisplay();
Serial.println("TTP223 Touch Sensor + Dual OLED Eyes");
}
void loop() {
int touchState = digitalRead(TOUCH_SENSOR_PIN);
if (touchState == HIGH) {
lastTouchTime = millis(); // Update last touch time
}
if (millis() - lastTouchTime <= keepAliveDuration) {
unsigned long currentTime = millis();
handleBlink(currentTime, blinkState_L, lastBlinkTime_L, blinkDelay_L);
handleMovement(currentTime, moveTime_L, targetOffsetX_L, targetOffsetY_L, blinkState_L);
smoothMove(offsetX_L, offsetY_L, targetOffsetX_L, targetOffsetY_L, moveSpeed_L);
drawEyeDisplay(displayLeft, eyeX_L + offsetX_L, eyeY + offsetY_L, eyeWidth, eyeHeight, blinkState_L);
handleBlink(currentTime, blinkState_R, lastBlinkTime_R, blinkDelay_R);
handleMovement(currentTime, moveTime_R, targetOffsetX_R, targetOffsetY_R, blinkState_R);
smoothMove(offsetX_R, offsetY_R, targetOffsetX_R, targetOffsetY_R, moveSpeed_R);
drawEyeDisplay(displayRight, eyeX_R + offsetX_R, eyeY + offsetY_R, eyeWidth, eyeHeight, blinkState_R);
Serial.println("Yes");
delay(30);
}
else {
displayLeft.clearDisplay();
displayRight.clearDisplay();
displayLeft.display();
displayRight.display();
Serial.println("No");
}
}
void handleBlink(unsigned long currentTime, int &blinkState, unsigned long &lastBlink, int blinkDelay) {
if (currentTime - lastBlink > blinkDelay && blinkState == 0) {
blinkState = 1;
lastBlink = currentTime;
}
if (currentTime - lastBlink > 150 && blinkState == 1) {
blinkState = 0;
lastBlink = currentTime;
}
}
void handleMovement(unsigned long currentTime, unsigned long &moveTime, int &targetX, int &targetY, int blinkState) {
if (currentTime - moveTime > random(1500, 3000) && blinkState == 0) {
int dir = random(0, 6);
if (dir == 0) { targetX = -8; targetY = 0; }
else if (dir == 1) { targetX = 8; targetY = 0; }
else if (dir == 2) { targetX = 0; targetY = -6; }
else if (dir == 3) { targetX = 0; targetY = 6; }
else { targetX = 0; targetY = 0; }
moveTime = currentTime;
}
}
void smoothMove(int &offsetX, int &offsetY, int targetX, int targetY, int speed) {
offsetX += (targetX - offsetX) / speed;
offsetY += (targetY - offsetY) / speed;
}
void drawEyeDisplay(Adafruit_SSD1306 &display, int x, int y, int w, int h, int blinkState) {
display.clearDisplay();
if (blinkState == 0) {
display.fillRoundRect(x, y, w, h, 8, WHITE);
} else {
display.fillRect(x, y + h / 2 - 2, w, 4, WHITE);
}
display.display();
}