#include <Servo.h>
Servo servoX; // create servo object to control a servo
Servo servoY;
const int servoYpin = 6; // the digital pin used for the servo
const int servoXpin = 5; // the digital pin used for the servo
const int LEDpin = 3;
uint8_t servos;
uint8_t servoXstart = 90;
uint8_t servoXpos; // inital position / 8 variable to read the servoXposue from the analog pin
uint8_t servoXprev;
uint16_t servoXtravel;
uint8_t servoYstart = 90;
uint8_t servoYpos; // initial position / 8variable to read the servoXposue from the analog pin
uint8_t servoYprev;
uint16_t servoYtravel;
uint8_t Xslope;
uint8_t Yslope;
bool servoXstate = false;
bool servoYstate = false;
uint8_t fadedir; // for led state
uint8_t servoXstep;
uint8_t servoYstep;
#define ON 4
#define OFF 0
#define UP 1
#define HOLD 2
#define DOWN 3
//////////////////////////////TIMING//////////////////////////////////
uint8_t eventOn;
uint8_t event_min = 3;
uint8_t event_max = 3;
uint8_t servospeed = 20;
uint8_t led_predelay = 250; // milliseconds
uint8_t LEDdown = 25; // x degrees before end of travel LED is triggered to fade down
uint8_t fadespeed = 8; // 5 good value larger value is slower fade
//////////////////////////////END TIMING/////////////////////////////
int long currMillis;
int long preveventMillis;
int long prevspeedMillis;
int long prevLEDevent;
int long previousFadeMillis;
uint8_t sine_increment;
const uint8_t sine_table[96] PROGMEM = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 10, 11, 12, 14, 15, 16, 18, 19, 21, 23, 25, 27, 29, 32,
35, 38, 42, 63, 72, 83, 122, 152, 169, 181, 190, 198, 203, 208, 212, 216, 220, 223, 225, 228, 230, 232, 234, 236, 237, 239, 240, 242,
243, 244, 245, 246, 247, 248, 248, 249, 250, 250, 251, 251, 252, 252, 253, 253, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255 };
uint8_t servoArraypos;
const int Arraypos = 3;
const int moveArray[2][3] PROGMEM = {
// row 0 is Y servo 1 to 180 degrees row 1 is X servo 45 to 135 degrees
/* 0 */ { 0, 90, 180 },
/* 1 */ { 45, 90, 135 },
};
void setup() {
Serial.begin(115200);
delay(700);
servoX.attach(servoXpin, 530, 2500);
servoY.attach(servoYpin, 530, 2500);
randomSeed(analogRead(A1)); // floating ADC1 - pin 12 of attiny84
servoX.write(servoXstart);
servoY.write(servoYstart);
servoXstep = servoXstart;
servoYstep = servoYstart;
servoArraypos = 0;
servoXstate = false;
servoYstate = false;
servos = OFF;
fadedir = OFF;
Serial.println("starting program");
delay(1000);
}
void loop() {
// /*
currMillis = millis();
event();
move_servos();
LEDevent();
doTheFade();
LEDhold();
// */
//servo_sweep();
}
void event() {
if ((servos == OFF) && (currMillis - preveventMillis > eventOn * 1000)) { // both servos are false and event time is met
Serial.println("event triggered");
if (servoArraypos > (Arraypos - 1)) // if end of array is met reset to beginning
servoArraypos = 0;
servoXpos = pgm_read_byte(&moveArray[1][servoArraypos]); // assign new target postion from the array
servoYpos = pgm_read_byte(&moveArray[0][servoArraypos]);
Serial.print("array position = "), Serial.println(servoArraypos);
Serial.print(" current X position = "), Serial.print((servoX.read())), Serial.print(" assigned X position = "), Serial.print(servoXpos), Serial.print(" current Y position = "), Serial.print((servoY.read())), Serial.print(" assigned Y position = "), Serial.println(servoYpos);
delay(500);
servoXtravel = abs(servoXprev - servoXpos);
servoYtravel = abs(servoYprev - servoYpos);
if (servoXpos > servoX.read())
Xslope = UP, Serial.println(" X sloping UP ");
else
Xslope = DOWN, Serial.println(" X sloping DOWN ");
delay(500);
if (servoYpos > servoX.read())
Yslope = UP;
else
Yslope = DOWN;
servos = ON;
servoXstate = true;
servoYstate = true;
fadedir = ON;
prevLEDevent = currMillis;
eventOn = random(event_min, event_max); // chose new event time randomly for next time around
}
}
void move_servos() {
if ((servos == ON) && (currMillis - prevspeedMillis > servospeed)) { // if one or both servos are true and time is met to advance step of servo
if ((servoXstate == false) && (servoYstate == false)) {
servos = OFF;
preveventMillis = currMillis;
servoArraypos++; // advance for next time around
}
if (servoXstep == servoXpos)
servoXstate = false;
if (servoYstep == servoYpos)
servoYstate = false;
if (servoXstate == true) {
if (Xslope == UP)
servoXstep++;
else
servoXstep--;
servoX.write(servoXstep);
}
if (servoYstate) {
if (Yslope == UP)
servoYstep++;
else
servoYstep--;
servoY.write(servoYstep);
}
//Serial.print("current Xposition = "), Serial.print(servoX.read()); Serial.print("Servo X step ="), Serial.println(servoXstep);
prevspeedMillis = currMillis;
}
}
void LEDevent() {
if ((fadedir == ON) && (currMillis - prevLEDevent >= led_predelay)) { // led trigger is true and time lapses till fade direction is flagged to up
Serial.println("led predelay met");
fadedir = UP;
sine_increment = 0;
}
}
void doTheFade() {
if (fadedir == UP) {
if (currMillis - previousFadeMillis >= fadespeed) {
//Serial.println("led fade up");
int brightness = pgm_read_byte(&sine_table[sine_increment]); // Read element from the array
analogWrite(LEDpin, brightness);
// // Serial.print (sine_increment); Serial //.print(" "); Serial //.println(brightness); // for monitoring Serial // plot
sine_increment++;
if (sine_increment > 95) {
fadedir = HOLD;
}
previousFadeMillis = currMillis;
}
}
if (fadedir == DOWN) {
if (currMillis - previousFadeMillis >= fadespeed) {
//Serial.println("Led fade down");
int brightness = pgm_read_byte(&sine_table[sine_increment]); // Read element from the array
analogWrite(LEDpin, brightness);
// // Serial.print (sine_increment); Serial //.print(" "); Serial //.println(brightness); // for monitoring Serial // plot
sine_increment--;
if (sine_increment <= 0) {
fadedir = OFF;
preveventMillis = currMillis;
}
previousFadeMillis = currMillis;
}
}
}
void LEDhold() {
if (fadedir == HOLD) { // LEDhold is in the loop() and when another function fades up the
// led's fadedir is changed from ON to HOLD allowing for entering the LEDhold() function
if (servoYtravel > servoXtravel) { // if Y servo has more total travel than X servo
if (servoYpos > servoYprev) // and if its target postion (servoYpos) is greater than its previous position
if (servoYstep >= (servoYpos - LEDdown)) // and if its current position (angle is encreasing) is greater than or equal to the target postion minus 15 degrees
fadedir = DOWN; // then fade led down
if (servoYpos < servoYprev) // if the target position (servoYpos) is less than the previous position
if (servoYstep <= (servoYpos + LEDdown)) // its current position (angle is decreasing) is less than or equal to the target postion plus 15 degrees
fadedir = DOWN;
}
if (servoXtravel > servoYtravel) { // if Y servo has more total travel than X servo
if (servoXpos > servoXprev) // and if its target postion (servoYpos) is greater than its previous position
if (servoXstep >= (servoXpos - 15)) // and if its current position (angle is encreasing) is greater than or equal to the target postion minus 15 degrees
fadedir = DOWN; // then fade led down
if (servoXpos < servoXprev) // if the target position (servoYpos) is less than the previous position
if (servoXstep <= (servoXpos + LEDdown)) // its current position (angle is decreasing) is less than or equal to the target postion plus 15 degrees
fadedir = DOWN;
}
}
}
void servo_sweep() {
for (int pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
servoX.write(pos), servoY.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15 ms for the servo to reach the position
}
delay(850);
for (int pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
servoX.write(pos), servoY.write(pos);
delay(15); // waits 15 ms for the servo to reach the position4
}
delay(2000);
}