Components and supplies
1
Stepper Motor
1
on-off-on momentary switch single-contact
1
Hook Up Wire Kit, 22 AWG
1
Arduino Nano R3
3
LED (generic)
Tools and machines
1
Soldering iron (generic)
1
Solder Wire, Lead Free
1
Tape, Electrical Insulation
1
PCB Holder, Soldering Iron
1
Solder Flux, Soldering
Project description
Code
Code for Arduino Nano
arduino
The Arduino-code used in my model. Feel free to use and modify.
1/* 2 * "Servo-Angle-and-Stepper-Speed-controled-by-TimeData-Array-in-a-endless-loop" 3 * 4 * Keeps a 1:120 - "Windmill"-model moving. Turns the blades in slightly different speeds 5 * and is moving the blades "into the wind". 6 * Additional lighting makes the model visible in "nights". 7 * 8 * A servo-motor will be handled to reach certain angles after certain times. 9 * Working with free fillable arrays TimeSteps[] in seconds and ServoAngles[] in 10 * degrees between 0° and 180°. 11 * This will be done continously. After reaching last dataset, again start the first... 12 * The acting speed of the servo will be influenced in ServoSpeed[] array. 13 * Alternatively a momentary button is usable to shorten the times / switch 14 * over from one servo-angle in the dataset to the next. 15 * 16 * All times the internal LED will be kept blinking 0,5s / 0,5s. 17 * Monitoring via serial monitoring on PC-screen (if connected). 18 * 19 * Project Windmill by N.W.Petzold - 01-2020 20 */ 21 #include <Servo.h> 22 #include <Stepper.h> 23// Important: Keep all times the amount of integer-values per array even to the other arrays! 24// Count it carafully! 25// All Timesteps will be multipied with 1000 -later- to use command "millis". 26// Example with 15 data (0-14 counting) and 15 the also reset-value. 27 28int DataCounter = 0; 29int ResetCountVal = 15; // This is the amount of datasets in the arrays, for automatic restart. 30int TimeSteps[] = {15,10,20,15,10,25,20,25, 10, 15, 30, 20,15,25,15}; // in seconds (millis will be calculated) 31int ServoAngles[] = {90, 80,70,55,60,65,75,90,120,140,100,80,90,55,70}; // Dergrees between 0 and 180 32long ServoSpeed[] = {30,50,40,30,40,50,60,70, 80, 90, 50, 30,35,40,50}; // delay between each degree in millis 33int StepperSpeed[] ={30,40,30,30,30,40,50,40, 30, 30, 30, 30,45,40,40}; // value between 0 and 100 34/* 35 * ATTENTION! 36 * Pin-Usage as follows: 37 * - Stepper: 2,3,4,5 38 * - LED's : 6,7 39 * - Servo : 10 40 * - Buttons: 11,12 41 * 42 */ 43int ServoPin = 10; // here is the servomotor data-line connected. 44Servo myservo; // create servo object to control a servo 45// 46const int stepsPerRevolution = 400; 47Stepper myStepper(stepsPerRevolution, 2, 3, 4, 5); 48// 49// Variable Values permanently changing if program runs: 50// SERVO 51unsigned long previousSERVOMillis = 0; 52unsigned long SERVOinterval = 0; // will be loaded with "TimeSteps" 53unsigned long currentSERVOMillis = 0; 54// 55unsigned long previousAngleMillis = 0; 56unsigned long AngleInterval = 0; // will be needed in the "servohandler" 57unsigned long currentAngleMillis = 0; 58// 59// Values for keeping the internal LED constantly blinking 60const int ledPin = LED_BUILTIN; 61int ledState = LOW; 62unsigned long previousLEDMillis = 0; 63unsigned long currentLEDMillis = 0; 64const long LEDinterval = 500; 65// 66// 67int counter = 0; 68int buttonState; 69// adapt in the arrays the amount of Buttons you want to use. 70// Reset at "2": 0/1 = On / Off --> higher reset values makes more possible with one button! 71// But than the %2 (modulo 2 - command) does not work in the button-subroutine 72int lastButtonState[4]; 73int buttonPushCounter[4]; // how often was a certain keypad-key pushed... see serial monitor 74int buttonToggling[4]; //array stores button-pushes as "numbers" 0...9 or higher as you programmed till "reset" value 75int buttonCountRes[ ] = {4,3,2,2}; // type in when the counter shall restart e.g. 2 for value [0] or 9 for value [3] leads to "0". 76// 77// Toggle-Buttons-visualisation 78const int LED1 = 6; // D6 // comment out, what you do not need 79const int LED2 = 7; // D7 80// 81// Toggled momentarily push-buttons 82const int Button1 = 11; // D11 83const int Button2 = 12; // D12 84// 85// end of declarations 86// 87// 88void ServoHandler(int NewAngle, int LastAngle, long AngleDelay){ 89 int AngleToBeSet; 90 // 91 currentAngleMillis = millis(); 92 AngleInterval = previousAngleMillis + AngleDelay; // will be loaded with "TimeSteps" 93 if(currentAngleMillis >= AngleInterval){ 94 if (NewAngle > LastAngle) {LastAngle++; AngleToBeSet = LastAngle; Serial.print(DataCounter); Serial.print(".Step - Servo-Angle + : "); Serial.print(AngleToBeSet); Serial.print(" Wait: [sec.] "); Serial.println(TimeSteps[DataCounter]);} 95 if (NewAngle < LastAngle) {LastAngle--; AngleToBeSet = LastAngle; Serial.print(DataCounter); Serial.print(".Step - Servo-Angle - : "); Serial.print(AngleToBeSet); Serial.print(" Wait: [sec.] "); Serial.println(TimeSteps[DataCounter]);} 96 myservo.write(AngleToBeSet); 97 98 previousAngleMillis = currentAngleMillis; 99} // end if... 100} // end ServoHandler 101// 102// 103void ButtonCounter(int buttonState1, int lastButtonState1, int buttonNo) { 104 int x = 0; 105 int counter = 0; 106 // STATUS CHANGED 107 if (buttonState1 != lastButtonState1) { 108 if (buttonState1 == 1) { 109 buttonPushCounter[buttonNo]++; 110 if (buttonPushCounter[buttonNo] >= buttonCountRes[buttonNo]) {buttonPushCounter[buttonNo] = 0;} 111 //delay(20); 112 if (buttonPushCounter[0] == 0){digitalWrite(LED1,LOW); digitalWrite(LED2,LOW);} // Two LED's : 1 off, 2 off 113 if (buttonPushCounter[0] == 1){digitalWrite(LED1,HIGH);digitalWrite(LED2,LOW);} // 1 on 2 off 114 if (buttonPushCounter[0] == 2){digitalWrite(LED1,LOW); digitalWrite(LED2,HIGH);} // 1 off 2 on 115 if (buttonPushCounter[0] == 3){digitalWrite(LED1,HIGH);digitalWrite(LED2,HIGH);} // Reset is 4, 1 on 2 on 116 // 117 if (buttonPushCounter[0] == 0){Serial.println("LED1 Off / LED2 Off");} 118 if (buttonPushCounter[0] == 1){Serial.println("LED1 ON / LED2 Off");} 119 if (buttonPushCounter[0] == 2){Serial.println("LED1 Off / LED2 ON");} 120 if (buttonPushCounter[0] == 3){Serial.println("LED1 ON / LED2 ON");} 121 // 122 if (buttonPushCounter[1] == 0){Serial.println("Servo and Stepper moving");} 123 if (buttonPushCounter[1] == 1){Serial.println("Servo OFF Stepper moving");} 124 if (buttonPushCounter[1] == 2){Serial.println("Servo OFF Stepper OFF");} 125 // 126 } // end if buttonstate ==1 ... 127 } // end if buttonstate != ... 128 lastButtonState[buttonNo] = buttonState1; 129 130} // End of button handling sequence. 131// 132void setup() { 133 // Internal LED 134 pinMode(ledPin, OUTPUT); 135 pinMode(LED1,OUTPUT); 136 pinMode(LED2,OUTPUT); 137 pinMode(Button1,INPUT); 138 pinMode(Button2,INPUT); 139 140 currentLEDMillis = millis(); 141 currentSERVOMillis = millis(); 142 143 // Servo-Motor 144 pinMode(ServoPin, OUTPUT); 145 myservo.attach(ServoPin); // attaches the servo on pin 9 to the servo object 146 // 147 // Buttons 148 buttonState = 0; 149 lastButtonState[0] = 0; 150 lastButtonState[1] = 0; 151 // 152 // Serial Monitor 153 Serial.begin(9600); 154 Serial.println("Program started."); 155 // 156 DataCounter = 0; 157} // end of "setup()" 158 159void loop() { 160 // put your main code here, to run repeatedly: 161 // Buttons 162 buttonState = digitalRead(Button1); 163 ButtonCounter(buttonState, lastButtonState[0], 0); 164 buttonState = digitalRead(Button2); 165 ButtonCounter(buttonState, lastButtonState[1], 1); 166 167 /* Change here the "usage of the lights" as you may need: 168 * for "on/off"-(TOGGLING)-only the "buttonCountRes" shall be 2. 169 * if (buttonToggling[0] == 0){digitalWrite(LED1,LOW);} 170 * if (buttonToggling[0] == 1){digitalWrite(LED1,HIGH);} 171 * ... and so one for the other buttons[1]...[3] 172 */ 173 // Now go though Datasets: start at zero till "ResetCountVal"... 174 currentSERVOMillis = millis(); // actual "running time" value 175 // 176 SERVOinterval = (TimeSteps[DataCounter]*1000); // Value from Array will be prepared for "millis"-comparison 177 if (currentSERVOMillis - previousSERVOMillis >= SERVOinterval) { // if interval is over, do something 178 previousSERVOMillis = currentSERVOMillis; 179 /* Servo handling: 180 * The servo handling has to be outside of this IF-loop! 181 * Because here we do not act as fast as possible - with only one value to be set. 182 * We act with variable speed with short break between each degree, till target-angle is reached. 183 * myservo.read(); gives the actual (written-)position on arduino output-pin. 184 * The target-position is in the array at actual counter position ServoAngles[DataCounter]. 185 * The "speed" is the waiting time between the single servo steps to make the moving more or less slowly. 186 */ 187 // 188 // Next Dataset / Reset if end of array reached. 189 DataCounter++; 190 if (DataCounter>=ResetCountVal){DataCounter=0;} 191 } // closing "if" 192 // Blocking or Enabling Movement of SERVO... 193 if (buttonPushCounter[1] == 0){ // if buttonPushCounter is not 1 or 2 Servo is moving 194 ServoHandler(ServoAngles[DataCounter],myservo.read(),ServoSpeed[DataCounter]); 195 } 196// end of Servo handling 197// 198// STEPPER Handling 199 // Blocking or Enabling Movement of STEPPER... 200 if (buttonPushCounter[1] == 0 or buttonPushCounter[1] == 1) { // if buttonPushCounter is 2 Stepper is moving 201 myStepper.setSpeed(StepperSpeed[DataCounter]); 202 myStepper.step(stepsPerRevolution / 100); 203 } 204// Stepper handling finished. 205// 206// Internal LED handling: 207currentLEDMillis = millis(); 208 if (currentLEDMillis - previousLEDMillis >= LEDinterval) { 209 previousLEDMillis = currentLEDMillis; 210 // if the LED is off turn it on and vice-versa: 211 if (ledState == LOW) { 212 ledState = HIGH; 213 } else { 214 ledState = LOW; 215 } // closing else... 216 } // closing "if..." 217 // set the LED with the ledState of the variable: 218 digitalWrite(ledPin, ledState); 219// internal LED handling finished 220// 221} // end of "loop()" routine
Downloadable files
Parts and connections.
To put the real components welded into the model, keep the wiring short and well insulated.
Parts and connections.
Parts and connections.
To put the real components welded into the model, keep the wiring short and well insulated.
Parts and connections.
Comments
Only logged in users can leave comments