#include <Servo.h>
Servo myServo;
Servo myServo2;
#define DATA_PIN 7
#define CLK_PIN 6
#define CS_PIN 5
#define DATA_PIN2 2
#define CLK_PIN2 4
#define CS_PIN2 3
#define PIR_PIN 10 // Pin connected to the PIR motion sensor
#define SERVO_PIN 11 // Pin connected to the first servo
#define INPUT_PIN 12 // Pin connected to the switch
#define OUTPUT_PIN 13 // Output pin for digital read
#define SERVO2_PIN 9 // Pin connected to second servo
// Ghost sprite definition
const byte ghostFrames[][8] = {
{0x3F, 0x7B, 0x56, 0xFB, 0xF7, 0x5A, 0x7F, 0x3F},
{0x3F, 0x7A, 0x54, 0xFA, 0xF7, 0x5A, 0x7E, 0x3F},
{0x3F, 0x7B, 0x56, 0xFB, 0xF7, 0x5A, 0x7F, 0x3F},
{0x3F, 0x7A, 0x54, 0xFA, 0xF7, 0x5A, 0x7E, 0x3F},
{0x3F, 0x7B, 0x56, 0xFB, 0xF7, 0x5A, 0x7F, 0x3F},
{0x3F, 0x7A, 0x54, 0xFA, 0xF7, 0x5A, 0x7E, 0x3F},
};
// Pacman sprite definition
const byte pacmanFrames[][8] = {
{0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c},
{0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c},
{0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c},
{0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c},
{0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c},
{0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c},
};
// Left Happy Face
const byte left_happy[][8] = {
{0x00, 0x00, 0x20, 0x40, 0x40, 0x24, 0x02, 0x02},
{0x00, 0x00, 0x20, 0x40, 0x40, 0x24, 0x02, 0x02},
{0x00, 0x00, 0x20, 0x40, 0x40, 0x24, 0x02, 0x02},
{0x00, 0x00, 0x20, 0x40, 0x40, 0x24, 0x02, 0x02},
{0x00, 0x00, 0x20, 0x40, 0x40, 0x24, 0x02, 0x02},
{0x00, 0x00, 0x20, 0x40, 0x40, 0x24, 0x02, 0x02},
};
// Right Happy Face
const byte right_happy[][8] = {
{0x02, 0x02, 0x24, 0x40, 0x40, 0x20, 0x00, 0x00},
{0x02, 0x02, 0x24, 0x40, 0x40, 0x20, 0x00, 0x00},
{0x02, 0x02, 0x24, 0x40, 0x40, 0x20, 0x00, 0x00},
{0x02, 0x02, 0x24, 0x40, 0x40, 0x20, 0x00, 0x00},
{0x02, 0x02, 0x24, 0x40, 0x40, 0x20, 0x00, 0x00},
{0x02, 0x02, 0x24, 0x40, 0x40, 0x20, 0x00, 0x00},
};
// Left Normal Face
const byte left_normal[][8] = {
{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x02, 0x02},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x02, 0x02},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x02, 0x02},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x02, 0x02},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x02, 0x02},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x02, 0x02},
};
// Right Normal Face
const byte right_normal[][8] = {
{0x02, 0x02, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
{0x02, 0x02, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
{0x02, 0x02, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
{0x02, 0x02, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
{0x02, 0x02, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
{0x02, 0x02, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
};
//Left side of the face
const byte left_angry[][8] = {
{0x00, 0x00, 0x80, 0x58, 0x58, 0x20, 0x02, 0x02},
{0x00, 0x00, 0x80, 0x58, 0x58, 0x20, 0x02, 0x02},
{0x00, 0x00, 0x80, 0x58, 0x58, 0x20, 0x02, 0x02},
{0x00, 0x00, 0x80, 0x58, 0x58, 0x20, 0x02, 0x02},
{0x00, 0x00, 0x80, 0x58, 0x58, 0x20, 0x02, 0x02},
{0x00, 0x00, 0x80, 0x58, 0x58, 0x20, 0x02, 0x02},
};
//Right side of the face
const byte right_angry[][8] = {
{0x02, 0x02, 0x20, 0x58, 0x58, 0x80, 0x00, 0x00},
{0x02, 0x02, 0x20, 0x58, 0x58, 0x80, 0x00, 0x00},
{0x02, 0x02, 0x20, 0x58, 0x58, 0x80, 0x00, 0x00},
{0x02, 0x02, 0x20, 0x58, 0x58, 0x80, 0x00, 0x00},
{0x02, 0x02, 0x20, 0x58, 0x58, 0x80, 0x00, 0x00},
{0x02, 0x02, 0x20, 0x58, 0x58, 0x80, 0x00, 0x00},
};
// Function declarations
void sendCommand(byte address, byte data);
void sendData(byte row, byte data, int module);
bool detectMotion() {
return digitalRead(PIR_PIN) == HIGH;
}
int refreshDisplayed = 0; // Initialize the flag to false
int loopCounter = 0;
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup() {
myServo.attach(SERVO_PIN);
pinMode(PIR_PIN, INPUT);
pinMode(SERVO_PIN, OUTPUT);
pinMode(DATA_PIN, OUTPUT);
pinMode(CLK_PIN, OUTPUT);
pinMode(CS_PIN, OUTPUT);
pinMode(DATA_PIN2, OUTPUT);
pinMode(CLK_PIN2, OUTPUT);
pinMode(CS_PIN2, OUTPUT);
pinMode(INPUT_PIN, INPUT_PULLUP); // Set pin 12 as input with internal pull-up resistor
pinMode(OUTPUT_PIN, OUTPUT); // Set pin 13 as output
pinMode(SERVO2_PIN, OUTPUT); //servo that will move servo back to starting position
myServo2.attach(SERVO2_PIN);
// Initialize MAX7219
sendCommand(0x09, 0x00); // Decode mode off
sendCommand(0x0a, 0x0f); // Intensity (brightness)
sendCommand(0x0b, 0x07); // Scan limit: All rows
sendCommand(0x0c, 0x01); // Normal operation mode
}
void loop() {
// Read potentiometer value
int val = analogRead(potpin);
if (val > 512) { // Assuming 1023 is the maximum value, half of it is 512
// Display angry face animation on modules
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 8; j++) {
sendData(j + 1, left_angry[i][j], 1); // Module 1
sendData(j + 1, right_angry[i][j], 2); // Module 2
}
delay(200);
myServo2.write(0);
delay(300);
myServo2.write(90);
delay(80);
refreshDisplayed = 0; // Reset refreshDisplayed when the switch is ON
}
} else {
if (digitalRead(INPUT_PIN) == HIGH) { // Check if the switch is OFF
if (refreshDisplayed == 0) { // Display refresh frame only once
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 8; j++) {
sendData(j + 1, ghostFrames[i][j], 1); // Send data for each column to module 1
sendData(j + 1, pacmanFrames[i][j], 2); // Send data for each column to module 2
}
delay(50); // Delay between frames
}
refreshDisplayed = 1; // Set the flag to indicate that refresh frame has been displayed
}
if (!detectMotion()) {
// Display ghost animation on module 1
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 8; j++) {
sendData(j + 1, ghostFrames[i][j], 1); // Send data for each column to module 1
}
delay(200); // Delay between frames
}
// Display Pacman animation on module 2
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 8; j++) {
sendData(j + 1, pacmanFrames[i][j], 2); // Send data for each column to module 2
}
delay(50); // Delay between frames
}
} else {
// Display Happy face animation on modules
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 8; j++) {
sendData(j + 1, left_happy[i][j], 1); // Send data for each column to module 1
sendData(j + 1, right_happy[i][j], 2); // Send data for each column to module 2
}
delay(200); // Delay between frames
// Move the servo to a specific position
for (int i = 0; i < 3; i++) { // Repeat 3 times, adjust as needed
delay(80);
myServo.write(0); // Adjust the angle as needed
delay(80); // Wait for 5 seconds
myServo.write(90); // Return the servo to its initial position
delay(80); // Delay before resuming normal operation
refreshDisplayed = 0;
}
}
// After displaying the angry face animation once, switch back to ghost and pacman animations
if (loopCounter == 0) {
loopCounter++;
} else {
// Display ghost and pacman animations again
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 8; j++) {
sendData(j + 1, ghostFrames[i][j], 1); // Send data for each column to module 1
sendData(j + 1, pacmanFrames[i][j], 2); // Send data for each column to module 2
}
delay(50); // Delay between frames
}
// Reset loopCounter for next iteration
loopCounter = 0;
}
}
} if (digitalRead(INPUT_PIN) == LOW) {
// Display normal face animation
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 8; j++) {
sendData(j + 1, left_normal[i][j], 1); // Send data for each column to module 1
sendData(j + 1, right_normal[i][j], 2); // Send data for each column to module 2
}
delay(200); // Delay between frames
}
refreshDisplayed = 0; // Reset refreshDisplayed when the switch is ON
}
}
}
void sendCommand(byte address, byte data) {
digitalWrite(CS_PIN, LOW); // Enable chip select
shiftOut(DATA_PIN, CLK_PIN, MSBFIRST, address);
shiftOut(DATA_PIN, CLK_PIN, MSBFIRST, data);
digitalWrite(CS_PIN, HIGH); // Disable chip select
}
void sendData(byte row, byte data, int module) {
if (module == 1) {
digitalWrite(CS_PIN, LOW); // Enable chip select for module 1
shiftOut(DATA_PIN, CLK_PIN, MSBFIRST, row);
shiftOut(DATA_PIN, CLK_PIN, MSBFIRST, data);
digitalWrite(CS_PIN, HIGH); // Disable chip select for module 1
} else if (module == 2) {
digitalWrite(CS_PIN2, LOW); // Enable chip select for module 2
shiftOut(DATA_PIN2, CLK_PIN2, MSBFIRST, row);
shiftOut(DATA_PIN2, CLK_PIN2, MSBFIRST, data);
digitalWrite(CS_PIN2, HIGH); // Disable chip select for module 2
}
}