Hi guys,
fairly new to coding and decided to have a go at making a split flap clock, I am good at 3d design and such but my coding side is lacking slighty. I am attempting to use alexyu132 on githubs code to run it. I will add the code i am trying to run below, but basically all its doing is flipping the minutes clock 2 whole rotations due to the feature that calls it to abort when it does 2 rotations without reaching the endstop which is a hall effect sensor set to be at 0. I am not asking for anyone to GIVE me the answer but any tips would be appreciated.
// Flip clock driver code
#include <RTClib.h>
#define STEPS_PER_REV 4096
#define STEPPER_DELAY 1400
#define USE_DST_EU
#define timeZone 1
#define UPLOAD_OFFSET 5
#define POLLING_DELAY 50
#define ENDSTOP_DEBOUNCE_READS 3
const byte stepper_pins[][4] = { {13, 12, 11, 10},
{9, 8, 7, 6},
{2, 3, 4, 5} };
// Hall effec sensor definitions
//Hours, Minutes (Tens), Minutes (Ones)
const byte endstop_pins[] = {A6, A7, A3};
// Homing settings
// Set these to the number that is displayed after the endstop is triggered.
const byte starting_digits[] = {0, 0, 0};
// The following parameter configures how much the stepper turns after homing.
const unsigned int starting_offset[] = {0, 0, 0};
// Position in steps of each stepper (relative to homing point)
unsigned int stepper_pos[] = {0, 0, 0};
byte drive_step[] = {0, 0, 0};
RTC_DS3231 rtc;
#if defined(USE_DST_EU)
unsigned int year_old = 0;
DateTime dst_start, dst_end;
#endif
void e_stop() {
#if defined(LED_PIN)
while(1) {
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);
delay(1000);
}
#else
abort();
#endif
}
void disable_stepper(const byte stepper_num) {
digitalWrite(stepper_pins[stepper_num][0], LOW);
digitalWrite(stepper_pins[stepper_num][1], LOW);
digitalWrite(stepper_pins[stepper_num][2], LOW);
digitalWrite(stepper_pins[stepper_num][3], LOW);
}
void half_step(const byte stepper_num) {
const byte pos = drive_step[stepper_num];
digitalWrite(stepper_pins[stepper_num][0], pos < 3);
digitalWrite(stepper_pins[stepper_num][1], ((pos + 6) % 8) < 3);
digitalWrite(stepper_pins[stepper_num][2], ((pos + 4) % 8) < 3);
digitalWrite(stepper_pins[stepper_num][3], ((pos + 2) % 8) < 3);
drive_step[stepper_num] = (pos + 1) % 8;
}
// Take the specified amount of steps for a stepper connected to the specified pins, with a
// specified delay (in microseconds) between each step.
void step_num(const byte stepper_num, unsigned int steps, const unsigned int wait) {
stepper_pos[stepper_num] = (stepper_pos[stepper_num] + steps) % STEPS_PER_REV;
while(steps > 0) {
half_step(stepper_num);
steps--;
delayMicroseconds(wait);
}
}
// Step until the endstop is pressed and released, and update the stepper position to 0.
// If homing doesn't end after 2 rotations, the endstop is assumed to have failed and the program aborts.
void step_to_home(const byte stepper_num, const unsigned int wait) {
unsigned int total_steps = 0;
byte endstop_repeats = 0;
// Step until endstop reads low ENDSTOP_DEBOUNCE_READS times in a row
while(endstop_repeats < ENDSTOP_DEBOUNCE_READS) {
endstop_repeats = digitalRead(endstop_pins[stepper_num]) == LOW ? endstop_repeats + 1 : 0;
half_step(stepper_num);
total_steps++;
if(total_steps > STEPS_PER_REV * 2u) {
disable_stepper(stepper_num);
e_stop();
}
delayMicroseconds(wait);
}
endstop_repeats = 0;
}
// Step to the specified position. If the current position is greater than the target position, this
// function will re-home and then step to the target position.
void step_to_position(const byte stepper_num, unsigned int target_pos, const unsigned int wait) {
if (target_pos == stepper_pos[stepper_num]) {
return;
}
// Limit target position to between 0 and STEPS_PER_REV-1
target_pos %= STEPS_PER_REV;
if (target_pos < stepper_pos[stepper_num]) {
step_to_home(stepper_num, wait);
step_num(stepper_num, target_pos, wait);
} else {
step_num(stepper_num, target_pos - stepper_pos[stepper_num], wait);
}
}
// Steps to the specified digit on the display
// To save power, stepper is powered off after running, so exact positional accuracy is not maintained.
// This is allowable since the displays self-calibrate via the endstops every rotation.
void step_to_digit(const byte stepper_num, const byte digit, const unsigned int wait) {
// The ones display has 10 flaps, the others have 12 flaps
const byte num_flaps = (stepper_num == 2) ? 10 : 12;
const byte num_digits = (stepper_num == 0) ? 12 : (stepper_num == 1) ? 6 : 10;
const unsigned int target_pos = starting_offset[stepper_num] + (unsigned int)((num_digits + digit - starting_digits[stepper_num]) % num_digits) * STEPS_PER_REV/num_flaps;
}
bool DST_EU(int year, int month, int day, int hour)
{
// There is no DST in Jan, Feb, Nov, Dec
if(month < 3 || month > 10)
{
return false;
}
//There is always DST in Apr, May, Jun, Jul, Aug, Sep
if(month > 3 && month < 10)
{
return true;
}
//Determin if its summertime accoridng to the European normation
if(month == 3&&(hour+24*day)>=(1+timeZone+24*(31-(5*year/4+4)%7)) || month==10&&(hour+24*day)<(1+timeZone+24*(31-(5*year/4+1)%7)))
{
return true;
}
else
{
return false;
}
}
void setup () {
// Setting stepper pins to output
for (byte i = 0; i < 3; i++) {
for (byte j = 0; j < 4; j++) {
pinMode(stepper_pins[i][j], OUTPUT);
}
}
// Set endstop pins as input with pullups enabled
pinMode(endstop_pins[0], INPUT_PULLUP);
pinMode(endstop_pins[1], INPUT_PULLUP);
pinMode(endstop_pins[2], INPUT_PULLUP);
if (!rtc.begin()) {
e_stop();
}
if (rtc.lostPower()) {
// Set the time to the compile time + offset
DateTime compile_time = DateTime(F(__DATE__), F(__TIME__)) + TimeSpan(UPLOAD_OFFSET);
#if defined(USE_DST_EU)
// Checking if compile time is in DST
uint16_t year = compile_time.year();
// //DST for US
// // DST starts on the second Sunday of March, 2AM
// // Get beginning of second week and then offset to Sunday
DateTime dst_start = DateTime(year, 3, 8, 2, 0, 0);
dst_start = dst_start + TimeSpan((7-dst_start.dayOfTheWeek()) % 7, 0, 0, 0);
//
// // DST ends on the first Sunday of November, 2AM
// // Get first day of month and then offset to Sunday
DateTime dst_end = DateTime(year, 11, 1, 2, 0, 0);
dst_end = dst_end + TimeSpan((7-dst_end.dayOfTheWeek()) % 7, 0, 0, 0);
//
// // If compile time is between DST start and end, then subtract 1 hour to get standard time
compile_time = compile_time >= dst_start && compile_time < dst_end ? (compile_time - TimeSpan(0,1,0,0)) : compile_time;
#endif
#if defined(USE_DST_EU)
if(DST_EU(compile_time.year(), compile_time.month(), compile_time.day(), compile_time.hour()))
{
compile_time = compile_time - TimeSpan(0,1,0,0);
}
#endif
rtc.adjust(compile_time);
}
// If the minute displays share an endstop pin (necessary on the Pro Micro), we need to make sure both of their endstops are unpressed before homing.
// We can do this by alternatingly stepping each display in small increments until the endstop pin reads high.
unsigned int total_steps = 0;
// Step to home digit
step_to_home(2, STEPPER_DELAY);
step_to_digit(2, starting_digits[2], STEPPER_DELAY);
step_to_home(1, STEPPER_DELAY);
step_to_digit(1, starting_digits[1], STEPPER_DELAY);
step_to_home(0, STEPPER_DELAY);
step_to_digit(0, starting_digits[0], STEPPER_DELAY);
}
void loop () {
DateTime now = rtc.now();
byte hr = now.hour() % 12;
byte tens = now.minute() / 6;
byte ones = now.minute() % 10;
if (hr > 12){
hr = hr - 12;
}
#if defined(USE_DST_US)
// Calculate new DST cutoffs if the year changes
if(now.year() != year_old) {
// DST starts on the second Sunday of March, 2AM
dst_start = DateTime(now.year(), 3, 31, 0, 0, 0);
dst_start = dst_start + TimeSpan((7-dst_start.dayOfTheWeek()) % 7, 0, 0, 0);
// DST ends on the first Sunday of November, 1AM (standard time)
dst_end = DateTime(now.year(), 10, 28, 0, 0, 0);
dst_end = dst_end + TimeSpan((7-dst_end.dayOfTheWeek()) % 7, 0, 0, 0);
year_old = now.year();
}
// If current time is between the DST cutoffs, add 1 to the hour digit
hr = (now >= dst_start && now < dst_end) ? (hr + 1) % 12 : hr;
#endif
#if defined(USE_DST_EU)
//DST for EU
if(DST_EU(now.year(), now.month(), now.day(), now.hour()))
{
hr = now.hour() + 1;
}
#endif
step_to_digit(2, ones, STEPPER_DELAY);
step_to_digit(1, tens, STEPPER_DELAY);
step_to_digit(0, hr, STEPPER_DELAY);
delay(POLLING_DELAY);
}