/* This is the code for the FlapClocK. The code is working perfectly, but there are lot of improvement possibilities. Code written by Dr.Tõnis check my website: http://drtgadgets.wixsite.com/drtonis/what Google+: https://plus.google.com/118202782399172306091 Facebook: https://www.facebook.com/drTonis My FlapClocK consists of 9 different segments. Each segment has it's own motor and a power control transistor and a hall sensor to determine the zero point */ // I use StepperMotor library for ULN2003 Driver #include // Define motor connection pins // StepperMotor motor(In1,In2,In3,In4); // Probably there is a better way to define 9 motors... StepperMotor motor1(22,24,26,28); // motor 1 (segment 0) StepperMotor motor2(31,33,35,37); // motor 2 (segment 1) StepperMotor motor3(18,19,52,53); // motor 3 StepperMotor motor4(23,25,27,29); // motor 4 StepperMotor motor5(30,32,34,36); // motor 5 StepperMotor motor6(14,15,16,17); // motor 6 StepperMotor motor7(5, 4, 3, 2); // motor 7 StepperMotor motor8(6, 7, 8, 9); // motor 8 StepperMotor motor9(10,11,12,13); // motor 9 (segment 8) // power switches // these transistors are to turn off the power from the // stepper motor drivers. assume it's not really neccessary, // I still implemented it so // {Segment 0, 1, 2, 3, 4, 5, 6, 7, 8} const int PowerSwitches[9] = {45, 43, 41, 48, 47, 46, 40, 42, 44}; // 2N2222 pins are connected as following: // http://circuit-diagramz.com//wp-content/uploads/2017/02/2N2222-transistor1.jpg // pin1 --> emitter --> gnd // pin2 --> base --> arduino signal // pin3 --> collector --> stepperd driver ground // Analog read // these are the input reading from the hall sensors // A4 and A5 are for SDA, SCA so that we can use RTC // {Segment 0, 1, 2, 3, 4, 5, 6, 7, 8} const int AnalogPins[9] = {A7, A8, A9, A2, A1, A0, A13, A14, A15}; // correction factor for each flap // after testing I noticed that the steps number for each flap // was not always correct. thus, I introduced a correction factor. // each segment is exactly the same, thus I was able to use the // same correction with each segment. // NumberOfSteps[DialNr] = {correction steps} const int NumberOfSteps[30] = {0, 22, 34, 66, 88, // --> Dial number 0, 1, 2, 3, 4, 130, 212, 434, 476, 518, // --> 5 6 7 8 9 420, 462, 504, 546, 608, // --> 10 11 12 13 14 630, 672, 774, 816, 868, // --> 15 16 17 18 19 740, 792, 844, 896, 948, // --> 20 21 22 23 24 1000, 1052, 1104, 1156, 1158}; // --> 25 26 27 28 29 // Help parameters int StepsValue; int ShowNr = 0; // which screen (Screens[ShowNr][]) // Real Time Clock library #include "RTClib.h" // Real Time Clock RTC_DS1307 RTC; // wire library #include // Screens (what will be shown) /* I had 8 shows that was shown after each other. the number indicates which flap will be shown. the one with the magnet will be 0 my symbols were in the following order: 0 0 1 . 2 _ 3 A 4 B 5 C 6 D 7 E 8 F 9 G 10 H 11 L 12 M 13 N 14 P 15 R 16 S 17 T 18 U 19 W 20 Y 21 1 22 2 23 3 24 4 25 5 26 6 27 7 28 8 29 9 */ int Screens[8][9] = { {21, 17, 16, // I T S 30, 30, 1, // x x . (x- time, will be defined from the RTC) 30, 30, 2}, // x x _ {1, 2, 1, // . _ . 2, 1, 2, // _ . _ 2, 18, 2}, // _ 0 _ {6, 15, 1, 17, 0, 13, 21, 16, 2}, {10, 3, 11, 11, 0, 2, 2, 2, 2}, {19, 21, 7, 9, 7, 10, 17, 7, 16}, {30, 30, 1, 30, 30, 2, 2, 2, 2}, {1, 2, 1, 2, 1, 2, 2, 18, 2}, {6, 15, 1, 17, 0, 13, 21, 16, 2}}; // setup void setup(){ // activate serial Serial.begin(115200); // Wire Wire.begin(); // Start Real Time Clock RTC.begin(); // Adjust time format to the last set value (last code update) // To set the computer time RTC.adjust(DateTime(__DATE__, __TIME__)); // To set the specific time 00:00:00 on the 1st of Jan 2017 // RTC.adjust(DateTime(2017, 1, 1, 0, 0, 0)); // go through all the single segments for(int i = 0; i < 9; i++) { // Make power control pin as output pinMode(PowerSwitches[i], OUTPUT); // Turn all power switches off digitalWrite(PowerSwitches[i], LOW);} // Set motor step durations motor1.setStepDuration(1); motor2.setStepDuration(1); motor3.setStepDuration(1); motor4.setStepDuration(1); motor5.setStepDuration(1); motor6.setStepDuration(1); motor7.setStepDuration(1); motor8.setStepDuration(1); motor9.setStepDuration(1); // Delay to settle everything delay(500); // Zero all the screens (in my case that means they will be all blank (Dial 2)) // SegmenNr --> the segment number for (int SegmentNr = 0; SegmentNr < 9 ; SegmentNr++) { Zero(SegmentNr);} // Screens --> the code to define what will be shown // correct the screen numbering for (int i = 0; i < 8 ; i++) { // I had 3 hall sensor not very well placed and the reading wasn't as // good as with others. Thus, the "zero" position was always 1 more than // the other screens. to make my life easier I corrected the screens // afterwards Screens[i][2] = Screens[i][2] - 1; Screens[i][3] = Screens[i][3] - 1; Screens[i][4] = Screens[i][4] - 1; if (Screens[i][2] == -1) Screens[i][2] = 29; if (Screens[i][3] == -1) Screens[i][3] = 29; if (Screens[i][4] == -1) Screens[i][4] = 29;} } // the main loop void loop(){ DateTime TimeDate = RTC.now(); // Read current time int Hour = TimeDate.hour(); // get the hour value int Minute = TimeDate.minute(); // get the minute value // find the flap number for the hour and minute // time is in forma XX:XX --> // (10Hour)(1Hour):(10Minute)(1Minute) int 10Hour = int(Hour/10) + 20; // numbers 1 start from dial 21 if (10Hour == 20) 10Hour = 0; // number 0 is dial 0 int 1Hour = int(Hour%1) + 20; if (1Hour == 20) 1Hour = 0; int 10Minute = int(Minute/10) + 20; if (10Minute == 20) 10Minute = 0; int 1Minute = int(Minute%1) + 20; if (1Minute == 20) 1Minute = 0; // Set the time dials Screens[0][3] = 10Hour; Screens[0][4] = 1Hour; Screens[0][6] = 10Minute; Screens[0][7] = 1Minute; Screens[4][0] = 10Hour; Screens[4][1] = 1Hour; Screens[4][3] = 10Minute; Screens[4][4] = 1Minute; // select segment "SegmentNr" and show position from Screens for (int SegmentNr = 0; SegmentNr < 9 ; SegmentNr++) { GoTo(SegmentNr, Screens[ShowNr][SegmentNr]); } // delay between the screens delay(5000); // go to the next screen ShowNr = ShowNr + 1; if (ShowNr > 7) ShowNr = 0; } // Find zero point void Zero(int SegmentNr) { // help parameer. if Zero position (end stop) is found // EndStop == 1 int EndStop = 0; // help parameter. if magnet is here the hall sensor // reading is over the set tresholdvalue (LimitValue) // if reading > LimitValue magnetIsHere == 1 int MagnetIsHere = 0; // define the hall sensor tresholdvalue. if the analog read is over this // we know tha the magnet is here int LimitValue = 750; // 3 hall sensors were badly placed and the maximum reading was much // lower than other, thus I needed to correct them if (DialNr == 2) LimitValue = 600; if (DialNr == 3) LimitValue = 575; if (DialNr == 4) LimitValue = 575; // turn the motor as long we haven't found the magnet while (EndStop != 1){ // turn power on (only for the defined segment) digitalWrite(PowerSwitches[SegmentNr], HIGH); // read the hall sensor value int AnalogValue = analogRead(AnalogPins[SegmentNr]); // write it to the serial (for debugging) Serial.print("sensor = "); Serial.println(AnalogValue); // move the stepper 8 steps furher int StepsValue = 8; if (DialNr == 0) motor1.step(-StepsValue); if (DialNr == 1) motor2.step(-StepsValue); if (DialNr == 2) motor3.step(-StepsValue); if (DialNr == 3) motor4.step(-StepsValue); if (DialNr == 4) motor5.step(-StepsValue); if (DialNr == 5) motor6.step(-StepsValue); if (DialNr == 6) motor7.step(-StepsValue); if (DialNr == 7) motor8.step(StepsValue); // placed the connection wires backwards if (DialNr == 8) motor9.step(StepsValue); // placed the connection wires backwards // after the magnet is found MagnetIsHere == 1 and if the // hall sensor value is below the limit we stop rotating the // cylinder if ((AnalogValue < LimitValue) && (MagnetIsHere == 1)) EndStop = 1; if (AnalogValue > LimitValue) { // if the read hall sensor value is over the limit change help // paramter "MagnetIsHere" to 1 MagnetIsHere = 1; } else { MagnetIsHere = 0; } } // end while loop // turn the power off (all motors) for(int i = 0; i < 9; i++) { digitalWrite(PowerSwitches[i], LOW); } } // Go to specified flap void GoTo(int SegmentNr, int DialNr) { // first find the zero point (magnet) Zero(SegmentNr); // turn motor power on digitalWrite(PowerSwitches[SegmentNr], HIGH); // move the motor StepsValue steps StepsValue = 328 * (DialNr) + NumberOfSteps[DialNr]; if (DialNr == 0) motor1.step(-StepsValue); if (DialNr == 1) motor2.step(-StepsValue); if (DialNr == 2) motor3.step(-StepsValue); if (DialNr == 3) motor4.step(-StepsValue); if (DialNr == 4) motor5.step(-StepsValue); if (DialNr == 5) motor6.step(-StepsValue); if (DialNr == 6) motor7.step(-StepsValue); if (DialNr == 7) motor8.step(StepsValue); if (DialNr == 8) motor9.step(StepsValue); // Turn power off digitalWrite(PowerSwitches[ScreenNR], LOW); }