kartonman

Multi-track Level Crossing With Four Gates

Sep 13th, 2021 (edited)
1,308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.62 KB | None | 0 0
  1. /*This is for 3 tracks. Depending on how you wire your control board, you can have lights flash eiher on the roadside lights only
  2. or on the gate bars and roadside lights.There is a counter in the program that allows the gates and lights to operate properly when two or
  3. three trains pass through the crossing concurrently. Important documentation that tells you how to set this up, wire it and a video
  4. are at https://steamtraininfo.com/arduino-level-crossing-with-four-gates
  5. */
  6. /* The circuit board for this level crossing can be seen at the link above. The colors written in this sketch correspond
  7. to the wire colors that you see on image of that circuit board.*/
  8.  
  9. #define GATE_SPEED 120 // [ms] lower number is higher servo speed
  10. #define BLINK_SPEED 400 // [ms] smaller number is faster blinking
  11. #define GATE_DELAY 2000 // [ms] time between start blinking and gate closing
  12. #define END_OF_TRAIN_DELAY 2000 // [ms] time to wait before deciding this was the end of the train
  13. #define GATE_OPEN_ANGLE 90
  14. #define GATE_CLOSED_ANGLE 10
  15. #define NUM_SENSORS 6 // two sensors per track, one left and one right of the gate
  16. byte sensor_pin[NUM_SENSORS] = {2, 3, 4, 5, 6, 7};
  17. /* sensor pin colors blue, white, purple, brown, yellow, gray*/
  18. #define LED1_PIN 9 //blue
  19. #define LED2_PIN 10 //white
  20. #define Bell 11 // green
  21. #define SERVO_PIN 12 //orange
  22. #define Flash1 A0 //gray
  23. #define Flash2 A1 //purple
  24. #define Flash3 A2 //brown
  25. #define Flash4 A3 //yellow
  26.  
  27.  
  28.  
  29.  
  30. byte state = 1, train_counter, n;
  31. byte led1, led2, ledf1, ledf2, ledf3, ledf4, blink_enabled;
  32. byte angle = GATE_OPEN_ANGLE;
  33. byte setpoint = GATE_OPEN_ANGLE;
  34. byte sensor_state[NUM_SENSORS]; // 0 idle, 1 detect arrival, 2 detect departure, 3 detect end of train
  35. byte end_of_train[NUM_SENSORS]; // 0 idle, 1 end of train detected
  36. unsigned long time_to_blink;
  37. unsigned long time_to_close_gate;
  38. unsigned long time_for_servo_step;
  39. unsigned long time_end_of_train[NUM_SENSORS];
  40.  
  41. #include <Servo.h>
  42. Servo gate_servo;
  43.  
  44. void setup() {
  45. pinMode(LED1_PIN, OUTPUT);
  46. pinMode(LED2_PIN, OUTPUT);
  47. pinMode(Flash1, OUTPUT);
  48. pinMode(Flash2, OUTPUT);
  49. pinMode(Flash3, OUTPUT);
  50. pinMode(Flash4, OUTPUT);
  51. pinMode(Bell, OUTPUT);
  52. pinMode(LED2_PIN, OUTPUT);
  53.  
  54.  
  55.  
  56. pinMode(Bell, OUTPUT);
  57. for (byte i = 0; i < NUM_SENSORS; i++) pinMode(sensor_pin[i], INPUT_PULLUP);
  58. gate_servo.attach(SERVO_PIN);
  59. gate_servo.write(angle);
  60. Serial.begin(9600);
  61. Serial.println("Railway Crossing Control Ready");
  62. Serial.println();
  63. Serial.println("Waiting for train");
  64. for (byte i = 0; i < NUM_SENSORS; i++) sensor_state[i] = 1; // enable sensors for train detection
  65. }
  66.  
  67. void loop() {
  68.  
  69. for (byte i = 0; i < NUM_SENSORS; i++) {
  70. if (sensor_state[i] == 1) { // detect arrival of new train
  71. if (!digitalRead(sensor_pin[i])) { // train detected
  72. train_counter++;
  73. sensor_state[i] = 0;
  74. if (i % 2) n = i - 1; else n = i + 1;
  75. sensor_state[n] = 2; // buddy sensor departure detection enabled
  76. Serial.print("Arrival: ");
  77. Serial.println(i);
  78. Serial.print("Trains: ");
  79. Serial.println(train_counter);
  80. }
  81. }
  82. else if (sensor_state[i] > 1) {
  83. if (!digitalRead(sensor_pin[i])) { // departure detected
  84. time_end_of_train[i] = millis() + (unsigned long)END_OF_TRAIN_DELAY;
  85. if (i % 2) n = i - 1; else n = i + 1;
  86. sensor_state[n] = 1; // buddy sensor enabled again
  87. if (sensor_state[i] == 2) {
  88. Serial.print("Departure: ");
  89. Serial.println(i);
  90. }
  91. sensor_state[i] = 3;
  92. }
  93. if (sensor_state[i] == 3) // decide if end of train has passed based on a timer
  94. if (millis() > time_end_of_train[i]) end_of_train[i] = 1;
  95. if (end_of_train[i]) { // this takes care train_counter-- is executed only once
  96. train_counter--;
  97. end_of_train[i] = 0;
  98. sensor_state[i] = 1;
  99. Serial.print("Trains: ");
  100. Serial.println(train_counter);
  101. }
  102. }
  103. }
  104.  
  105. switch (state) {
  106. case 1: // gate open, not blinking, waiting for train arrival
  107. if (train_counter) state = 12;
  108. break;
  109.  
  110. case 12: // train arrival detected, blinking
  111. Serial.println("Binking started");
  112. blink_enabled = 1;
  113. time_to_close_gate = millis() + (unsigned long)GATE_DELAY;
  114. state = 2;
  115. break;
  116.  
  117. case 2: // blinking, wait until it's time to close the gate
  118. if (millis() > time_to_close_gate) state = 23; // gate delay time has passed
  119. break;
  120.  
  121. case 23: // close the gate
  122. Serial.println("Gate closing");
  123. gate_servo.attach(SERVO_PIN);
  124. setpoint = GATE_CLOSED_ANGLE;
  125. state = 3;
  126. break;
  127.  
  128. case 3: // gate is closing, blinking
  129. if (angle == setpoint) {
  130. Serial.println("Gate closed");
  131. state = 4;
  132. }
  133. break;
  134.  
  135. case 4: // gate fullly closed, blinking, waiting for train departure
  136. if (train_counter == 0) state = 45;
  137. break;
  138.  
  139. case 45: // train departure detected, open the gate, blinking
  140. Serial.println("Gate opening");
  141. gate_servo.attach(SERVO_PIN);
  142. setpoint = GATE_OPEN_ANGLE;
  143. state = 5;
  144. break;
  145.  
  146. case 5: // wait until gate is fully opened, blinking
  147. if (train_counter) state = 23;
  148. if (angle == setpoint) state = 51;
  149. break;
  150.  
  151. case 51: // gate is fully opened, stop blinking
  152. // for (byte i = 0; i < NUM_SENSORS; i++) sensor_state[i] = 1;
  153. blink_enabled = 0;
  154. led1 = 0;
  155. led2 = 0;
  156. ledf1 = 0;
  157. ledf2 = 0;
  158. ledf3 = 0;
  159. ledf4 = 0;
  160. gate_servo.detach(); // to avoid servo flutter
  161. state = 1;
  162. Serial.println("Gate open, blinking stopped");
  163. Serial.println();
  164. Serial.println("Waiting for train");
  165. break;
  166. }
  167.  
  168. if (millis() > time_for_servo_step) {
  169. time_for_servo_step = millis() + (unsigned long)GATE_SPEED;
  170. if (angle < setpoint) angle++;
  171. if (angle > setpoint) angle--;
  172. gate_servo.write(angle);
  173. }
  174.  
  175. if (blink_enabled == 1) {
  176. if (millis() > time_to_blink) {
  177. time_to_blink = millis() + (unsigned long)BLINK_SPEED;
  178. led1 = !led1;
  179. led2 = !led1;
  180. ledf1 = !ledf1;
  181. ledf2 = !ledf2;
  182. ledf3 = !ledf3;
  183. ledf4 = !ledf4;
  184. }
  185. }
  186.  
  187. digitalWrite(LED1_PIN, led1);
  188. digitalWrite(LED2_PIN, led2);
  189. digitalWrite(Flash1, ledf1);
  190. digitalWrite(Flash2, ledf2);
  191. digitalWrite(Flash1, ledf3);
  192. digitalWrite(Flash2, ledf4);
  193. digitalWrite(Bell, HIGH);
  194. }
Advertisement
Add Comment
Please, Sign In to add comment