Components and supplies
Transistor NPN (BC547 or similar)
200 ohm 1206 SMD resistor
TF card U disk MP3 player / decoder module
Plastic pipe 10mm diameter
Green 1206 SMD LED
12V relay (A12W-K)
DC-DC adjustable step-down voltage regulator with LM2596
Illuminated tactile switch Blue
SX1509 IO expander module
Illuminated tactile switch Green
12V/1A power adapter
Electrical installation boxes
Arduino Nano R3
DC jack female panel mount
Red 1206 SMD LED
PCF8574T (SMD)
4 channel I2C Logic Level Converter Bi-Directional Module 5V to 3.3V
Terminal Adapter Board For Arduino Nano 3.0
Yellow 1206 SMD LED
Illuminated tactile switch Red
Plastic plate 2mm thick, 93x73cm
PCF8575 IO Expander Module I2C To 16 IO
Buzzer, Piezo
Diode BA159
White (cold) 1206 SMD LED
Tools and machines
Soldering iron (generic)
Drill, Screwdriver
Project description
Code
SX1509 library
Main code
arduino
1#include <Wire.h> 2#include <SparkFunSX1509.h> // Include SX1509 library 3 4const int SX_RESET = 16; // reset pins of SX1509s 5const int RAILWAY_SOUND = 6; // control pin of relay for mp3 power 6const int PCF_INT = 2; // interrupt from PCF8575 7 8// D4 & D5 = software serial for level shifter / ESP8266; not implemented yet 9 10// SX1509 I2C address (set by ADDR1 and ADDR0 (00 by default): 11const byte SX1509_0 = 0x3E; // SX1509 I2C address 12const byte SX1509_1 = 0x70; // SX1509 I2C address 13SX1509 io0; // Create an SX1509 object to be used throughout 14SX1509 io1; // Create an SX1509 object to be used throughout 15 16// SX1509_0 Pin definition: 17const byte SX1509_0_RWL0 = 6; // rail red left 18const byte SX1509_0_RWR0 = 5; // rail red right 19const byte SX1509_0_RWW0 = 7; // rail white 20const byte SX1509_0_RWL1 = 14; // rail red left 21const byte SX1509_0_RWR1 = 15; // rail red right 22const byte SX1509_0_RWW1 = 13; // rail white 23 24const byte SX1509_0_PEDR0 = 10; //pedestrian red #3a 25const byte SX1509_0_PEDG0 = 11; //pedestrian green #3a 26const byte SX1509_0_PEDR1 = 9; //pedestrian red #3b 27const byte SX1509_0_PEDG1 = 8; //pedestrian green #3b 28const byte SX1509_0_PEDR2 = 1; //pedestrian red #4a 29const byte SX1509_0_PEDG2 = 0; //pedestrian green #4a 30const byte SX1509_0_PEDR3 = 2; //pedestrian red #4b 31const byte SX1509_0_PEDG3 = 3; //pedestrian green #4b 32 33// SX1509_1 Pin definition: 34const byte SX1509_1_RWL0 = 6; // rail red left 35const byte SX1509_1_RWR0 = 5; // rail red right 36const byte SX1509_1_RWW0 = 7; // rail white 37const byte SX1509_1_RWL1 = 14; // rail red left 38const byte SX1509_1_RWR1 = 13; // rail red right 39const byte SX1509_1_RWW1 = 15; // rail white 40 41const byte SX1509_1_PEDR0 = 8; //pedestrian red #1a 42const byte SX1509_1_PEDG0 = 9; //pedestrian green #1a 43const byte SX1509_1_PEDR1 = 10; //pedestrian red #1b 44const byte SX1509_1_PEDG1 = 11; //pedestrian green #1b 45const byte SX1509_1_PEDR2 = 0; //pedestrian red #2a 46const byte SX1509_1_PEDG2 = 1; //pedestrian green #2a 47const byte SX1509_1_PEDR3 = 3; //pedestrian red #2b 48const byte SX1509_1_PEDG3 = 2; //pedestrian green #2b 49 50 51 52// addresses of PCF8574 IC 53const byte PCF8574[] = {0x39, 0x3b, 0x3d, 0x3f}; 54 55#define PCF8575 (0x20) //address of PCF8575 (button input, illuminated buttons LED output) 56 57 58const byte RED = 10; 59const byte YLW = 20; 60const byte GRN = 30; 61 62unsigned long previousMillis = 0; 63const long interval = 20; 64byte blink_int = 0; 65byte sec20 = 0; 66boolean blink_state = false; 67 68const byte numChars = 64; 69char recChars[numChars]; // an array to store the received data 70boolean newData = false; 71 72byte cur_light = 0; 73byte b; 74String s; 75boolean pcf_int_trigger = false; 76byte dbnc = 0; 77boolean sound = false; 78 79boolean red_btn = false; // LED of red button 80boolean grn_btn = false; // LED of green button 81boolean blu_btn = false; // LED of blue button 82 83byte mode = 1; // 0 = orange lights blink, 1 - program, 2 - test 84byte rail_mode = 1; // 0 = off, 1 - white, 2 - red 85byte prog_step = 0; 86byte next_step = 1; 87 88 89 90void setup() 91{ 92 pinMode(RAILWAY_SOUND, OUTPUT); 93 digitalWrite(RAILWAY_SOUND, LOW); 94 pinMode(SX_RESET, OUTPUT); 95 digitalWrite(SX_RESET, HIGH); 96 97 pinMode(PCF_INT, INPUT_PULLUP); 98 attachInterrupt(digitalPinToInterrupt(PCF_INT), PCF_INT_ISR, FALLING); //interrupt when any of buttons is pressed 99 100 Wire.begin(); 101 102 pcf8575_write(word(B11111111,B11111111)); //set all IOs as inputs 103 104 Serial.begin(9600); 105 while (!Serial); 106 Serial.println("\ 107I2C Scanner"); 108 109 110 if (!io0.begin(SX1509_0, SX_RESET)) { 111 Serial.println("SX1509_0 not found"); 112 } 113 114 if (!io1.begin(SX1509_1, SX_RESET)) { 115 Serial.println("SX1509_1 not found"); 116 } 117 118 sx_init(); 119 120 set_rail(); 121} 122 123 124 125 126void sx_init() { 127 // Use the internal 2MHz oscillator. 128 // Set LED clock with divider (2MHz / (2^(divider-1)): 129 // divider = 2 means 1MHz LED clock (2MHz / (2^(2-1)) 130 // divider = 3 means 500kHz LED clock (2MHz / (2^(3-1)) 131 // divider = 4 means 250kHz LED clock (2MHz / (2^(4-1)) 132 133 // 0x1-0xE: fOSCout = Fosc / 2 ^ (outputFreq - 1) Hz 134 135 const byte divider = 4; 136 137 io0.init(); 138 io1.init(); 139 140 io0.clock(INTERNAL_CLOCK_2MHZ, divider, INPUT, 1); //250kHz clock 141 io1.clock(INTERNAL_CLOCK_2MHZ, divider, INPUT, 1); //250kHz clock 142 143 //set IOs for pedestrian lights as digital outputs 144 //IOs for railway lights will be set as analogue outputs with breath funcion later 145 io0.pinMode(SX1509_0_PEDR0, OUTPUT); 146 io0.pinMode(SX1509_0_PEDG0, OUTPUT); 147 io0.pinMode(SX1509_0_PEDR1, OUTPUT); 148 io0.pinMode(SX1509_0_PEDG1, OUTPUT); 149 io0.pinMode(SX1509_0_PEDR2, OUTPUT); 150 io0.pinMode(SX1509_0_PEDG2, OUTPUT); 151 io0.pinMode(SX1509_0_PEDR3, OUTPUT); 152 io0.pinMode(SX1509_0_PEDG3, OUTPUT); 153 154 io1.pinMode(SX1509_1_PEDR0, OUTPUT); 155 io1.pinMode(SX1509_1_PEDG0, OUTPUT); 156 io1.pinMode(SX1509_1_PEDR1, OUTPUT); 157 io1.pinMode(SX1509_1_PEDG1, OUTPUT); 158 io1.pinMode(SX1509_1_PEDR2, OUTPUT); 159 io1.pinMode(SX1509_1_PEDG2, OUTPUT); 160 io1.pinMode(SX1509_1_PEDR3, OUTPUT); 161 io1.pinMode(SX1509_1_PEDG3, OUTPUT); 162} 163 164 165 166 167void loop() 168{ 169 unsigned long currentMillis = millis(); 170 if (currentMillis - previousMillis >= interval) {//every 20ms / 50x sec 171 previousMillis = currentMillis; 172 173 sec20++; 174 if (dbnc > 0) { 175 dbnc --; 176 } 177 178 if (sec20 == 50) { // 50 x 20 miliseconds elapsed, i.e. new second 179 // **************************** NEW SECOND **************************** 180 sec20 = 0; 181 182 if (next_step > 0) {next_step--;} //counter for traffic lights program 183 if (next_step == 0 || mode == 0 || mode == 2) { //when counter reaches zero, it's time for next program step. In mode=0 and mode=2 it's every second. 184 program_step(); 185 } 186 } 187 188 blink_int++; 189 if (blink_int == 34) { 190 blink_state = true; 191 if (mode == 0) { // mode = 0 means only orange lights are flashing with cca. 700ms ON / 700ms OFF interval 192 set_leds(0, 5*32 + 5*4); 193 set_leds(1, 5*32 + 5*4); 194 set_leds(2, 5*32 + 5*4); 195 set_leds(3, 5*32 + 5*4); 196 } 197 } 198 199 if (blink_int == 69) { 200 blink_state = false; 201 blink_int = 0; 202 if (mode == 0) { 203 set_leds(0, 5*32 + 5*4); 204 set_leds(1, 5*32 + 5*4); 205 set_leds(2, 5*32 + 5*4); 206 set_leds(3, 5*32 + 5*4); 207 } 208 } 209 210 if (blink_int == 1) { 211 digitalWrite(LED_BUILTIN, HIGH); 212 } else { 213 digitalWrite(LED_BUILTIN, LOW); 214 } 215 } 216 217 //check if any of buttons was pressed 218 if (pcf_int_trigger) { 219 pcf_int_trigger = false; 220 b = pcf8575_read(); 221 b = b | B11101010; // mask only for the buttons 222 if (b != 255 && dbnc == 0) { //some button was pressed 223 Serial.println(b, BIN); 224 dbnc = 8; //set debounce period 225 //blue.0 226 //red.4 227 //grn.2 228 if (bitRead(b, 4) == 0) { //RED button pressed, change railway lights mode 229 rail_mode++; 230 if (rail_mode > 2) { 231 rail_mode = 1; 232 } 233 set_rail(); 234 } else if (bitRead(b, 2) == 0) {//GREEN button pressed, change traffic lights mode 235 mode++; 236 next_step = 1; 237 prog_step = 0; 238 if (mode > 2) { 239 mode = 0; 240 } 241 Serial.print("Mode changed: "); 242 Serial.println(mode); 243 } else if (bitRead(b, 0) == 0) {//BLUE button pressed, it does nothing so far 244 //nothing yet 245 } 246 } 247 } 248 249 //check serial port input buffer 250 CheckSerial(); 251} 252 253 254 255void button_lights() { 256 //sets illuminated buttons LEDs according to variables red_btn, grn_btn and blu_btn 257 byte lights; 258 lights = pcf8575_read(); 259 if (red_btn) { 260 bitClear(lights, 3); 261 } else { 262 bitSet(lights, 3); 263 } 264 265 if (grn_btn) { 266 bitClear(lights, 5); 267 } else { 268 bitSet(lights, 5); 269 } 270 271 if (blu_btn) { 272 bitClear(lights, 1); 273 } else { 274 bitSet(lights, 1); 275 } 276 lights = lights | B00010101; //set button input IOs always as inputs 277 pcf8575_write(word(0xFF,lights)); 278} 279 280 281 282 283 284 285 286void set_ped_group(byte group, byte color) { 287 //there are 4 groups of LEDs for pedestrian signals 288 //in every group the signals change simultaneously 289 290 boolean rval; 291 boolean gval; 292 if (color == RED) { 293 rval = 0; // RED lights on 294 gval = 1; // GRN lights off 295 } else { 296 rval = 1; 297 gval = 0; 298 } 299 300 301 if (group == 0) { 302 io1.digitalWrite(SX1509_1_PEDR1, rval); 303 io1.digitalWrite(SX1509_1_PEDG1, gval); 304 io1.digitalWrite(SX1509_1_PEDR2, rval); 305 io1.digitalWrite(SX1509_1_PEDG2, gval); 306 } else if (group == 1) { 307 io1.digitalWrite(SX1509_1_PEDR3, rval); 308 io1.digitalWrite(SX1509_1_PEDG3, gval); 309 io0.digitalWrite(SX1509_0_PEDR0, rval); 310 io0.digitalWrite(SX1509_0_PEDG0, gval); 311 } else if (group == 2) { 312 io0.digitalWrite(SX1509_0_PEDR1, rval); 313 io0.digitalWrite(SX1509_0_PEDG1, gval); 314 io0.digitalWrite(SX1509_0_PEDR2, rval); 315 io0.digitalWrite(SX1509_0_PEDG2, gval); 316 } else if (group == 3) { 317 io0.digitalWrite(SX1509_0_PEDR3, rval); 318 io0.digitalWrite(SX1509_0_PEDG3, gval); 319 io1.digitalWrite(SX1509_1_PEDR0, rval); 320 io1.digitalWrite(SX1509_1_PEDG0, gval); 321 } 322} 323 324void ped_off() { 325 //turn off all pedestrian signals 326 io0.digitalWrite(SX1509_0_PEDR0, 1); 327 io0.digitalWrite(SX1509_0_PEDG0, 1); 328 io0.digitalWrite(SX1509_0_PEDR1, 1); 329 io0.digitalWrite(SX1509_0_PEDG1, 1); 330 io0.digitalWrite(SX1509_0_PEDR2, 1); 331 io0.digitalWrite(SX1509_0_PEDG2, 1); 332 io0.digitalWrite(SX1509_0_PEDR3, 1); 333 io0.digitalWrite(SX1509_0_PEDG3, 1); 334 io1.digitalWrite(SX1509_1_PEDR0, 1); 335 io1.digitalWrite(SX1509_1_PEDG0, 1); 336 io1.digitalWrite(SX1509_1_PEDR1, 1); 337 io1.digitalWrite(SX1509_1_PEDG1, 1); 338 io1.digitalWrite(SX1509_1_PEDR2, 1); 339 io1.digitalWrite(SX1509_1_PEDG2, 1); 340 io1.digitalWrite(SX1509_1_PEDR3, 1); 341 io1.digitalWrite(SX1509_1_PEDG3, 1); 342} 343 344 345 346 347 348 349void CheckSerial() { 350 //serial port input routine, used only for debugging 351 static byte ndx = 0; 352 char endMarker = '\n'; 353 char endMarker2 = '\r'; 354 char rc; 355 byte pgroup, pcolor; 356 357 while (Serial.available() > 0 && newData == false) { 358 rc = Serial.read(); 359 360 if (rc != endMarker && rc != endMarker2) { 361 recChars[ndx] = rc; 362 ndx++; 363 if (ndx >= numChars) { 364 ndx = numChars - 1; 365 } 366 } 367 else { 368 recChars[ndx] = '\\0'; // terminate the string 369 ndx = 0; 370 newData = true; 371 } 372 } 373 374 if (newData == true) { 375 int slen = strlen(recChars); 376 if (slen > 1) { 377 String usbreply = recChars; 378 379 usbreply.trim(); 380 slen = usbreply.length(); 381 382 if (usbreply == "TRED") { 383 rail_mode = 2; 384 set_rail(); 385 } else if (usbreply == "TREDB") { 386 rail_mode = 3; 387 set_rail(); 388 } else if (usbreply == "WHITE") { 389 rail_mode = 1; 390 set_rail(); 391 } else if (usbreply == "RED") { 392 set_leds(cur_light, 32 + 4); 393 } else if (usbreply == "YLW") { 394 set_leds(cur_light, 4*32 + 4*4 + 0); 395 } else if (usbreply == "GRN") { 396 set_leds(cur_light, 3*32 + 3*4 + 1); 397 } else if (usbreply == "REDYLW") { 398 set_leds(cur_light, 2*32 + 2*4 + 0); 399 } else if (usbreply.startsWith("CL")) { 400 usbreply = usbreply.substring(2); 401 cur_light = usbreply.toInt(); 402 Serial.println("CURRENT LIGHT: " + String(cur_light)); 403 } else if (usbreply == "SXRST") { 404 digitalWrite(SX_RESET, LOW); 405 delay(2); //2ms RESET 406 digitalWrite(SX_RESET, HIGH); 407 sx_init(); 408 Serial.println("SXs were RESET"); 409 } else if (usbreply == "SX0READ") { 410 SX1509_print_regs(SX1509_0); 411 } else if (usbreply == "SX1READ") { 412 SX1509_print_regs(SX1509_1); 413 } else if (usbreply.startsWith("PG")) { 414 s = usbreply.substring(2,3); 415 pgroup = s.toInt(); 416 s = usbreply.substring(3,4); 417 pcolor = s.toInt(); 418 pcolor = pcolor * 10; 419 Serial.println("PED GROUP: " + String(pgroup) + ", color: " + String(pcolor)); 420 set_ped_group(pgroup, pcolor); 421 } 422 423 } 424 newData = false; 425 } 426} 427 428 429 430 431void set_rail() { 432 if (rail_mode == 0) { 433 //nothing yet 434 } else if (rail_mode == 1) { 435 436 //set railway lights as GO - white lights blinking/breathing, red lights off 437 438 red_btn = false; 439 button_lights(); 440 digitalWrite(RAILWAY_SOUND, LOW); 441 io0.pinMode(SX1509_0_RWL0, OUTPUT); 442 io0.pinMode(SX1509_0_RWR0, OUTPUT); 443 io0.digitalWrite(SX1509_0_RWL0, HIGH); 444 io0.digitalWrite(SX1509_0_RWR0, HIGH); 445 io0.pinMode(SX1509_0_RWL1, OUTPUT); 446 io0.pinMode(SX1509_0_RWR1, OUTPUT); 447 io0.digitalWrite(SX1509_0_RWL1, HIGH); 448 io0.digitalWrite(SX1509_0_RWR1, HIGH); 449 io0.pinMode(SX1509_0_RWW0, ANALOG_OUTPUT); 450 io0.breathe(SX1509_0_RWW0, 600, 700, 5, 5); // Breathe interval: 600ms LOW, 700ms HIGH, 5ms to rise from low to high, 5ms to fall from high to low 451 io0.pinMode(SX1509_0_RWW1, ANALOG_OUTPUT); 452 io0.breathe(SX1509_0_RWW1, 600, 700, 5, 5); 453 io1.pinMode(SX1509_1_RWL0, OUTPUT); 454 io1.pinMode(SX1509_1_RWR0, OUTPUT); 455 io1.digitalWrite(SX1509_1_RWL0, HIGH); 456 io1.digitalWrite(SX1509_1_RWR0, HIGH); 457 io1.pinMode(SX1509_1_RWL1, OUTPUT); 458 io1.pinMode(SX1509_1_RWR1, OUTPUT); 459 io1.digitalWrite(SX1509_1_RWL1, HIGH); 460 io1.digitalWrite(SX1509_1_RWR1, HIGH); 461 io1.pinMode(SX1509_1_RWW0, ANALOG_OUTPUT); 462 io1.breathe(SX1509_1_RWW0, 600, 700, 5, 5); 463 io1.pinMode(SX1509_1_RWW1, ANALOG_OUTPUT); 464 io1.breathe(SX1509_1_RWW1, 600, 700, 5, 5); 465 } else if (rail_mode == 2) { 466 467 //set railway lights as STOP - white lights off, red lights blinking/breathing 468 469 red_btn = true; 470 button_lights(); 471 472 io0.sync(); 473 io1.sync(); 474 digitalWrite(RAILWAY_SOUND, HIGH); 475 io0.pinMode(SX1509_0_RWW0, OUTPUT); 476 io0.digitalWrite(SX1509_0_RWW0, HIGH); 477 io0.pinMode(SX1509_0_RWW1, OUTPUT); 478 io0.digitalWrite(SX1509_0_RWW1, HIGH); 479 io0.pinMode(SX1509_0_RWL0, ANALOG_OUTPUT); 480 io0.breathe(SX1509_0_RWL0, 500, 500, 40, 40); // Breathe interval: 500ms LOW, 500ms HIGH, 40ms to rise from low to high, 40ms to fall from high to low 481 io0.pinMode(SX1509_0_RWL1, ANALOG_OUTPUT); 482 io0.breathe(SX1509_0_RWL1, 500, 500, 40, 40); 483 io1.pinMode(SX1509_1_RWW0, OUTPUT); 484 io1.digitalWrite(SX1509_1_RWW0, HIGH); 485 io1.pinMode(SX1509_1_RWW1, OUTPUT); 486 io1.digitalWrite(SX1509_1_RWW1, HIGH); 487 io1.pinMode(SX1509_1_RWL0, ANALOG_OUTPUT); 488 io1.breathe(SX1509_1_RWL0, 500, 500, 40, 40); 489 io1.pinMode(SX1509_1_RWL1, ANALOG_OUTPUT); 490 io1.breathe(SX1509_1_RWL1, 500, 500, 40, 40); 491 delay(650); 492 io0.pinMode(SX1509_0_RWR0, ANALOG_OUTPUT); 493 io0.pinMode(SX1509_0_RWR1, ANALOG_OUTPUT); 494 io1.pinMode(SX1509_1_RWR0, ANALOG_OUTPUT); 495 io1.pinMode(SX1509_1_RWR1, ANALOG_OUTPUT); 496 io0.breathe(SX1509_0_RWR0, 500, 500, 40, 40); 497 io0.breathe(SX1509_0_RWR1, 500, 500, 40, 40); 498 io1.breathe(SX1509_1_RWR0, 500, 500, 40, 40); 499 io1.breathe(SX1509_1_RWR1, 500, 500, 40, 40); 500 } else if (rail_mode == 3) { 501 502 //test mode, just to show how lights work without breathe function 503 red_btn = true; 504 button_lights(); 505 io0.sync(); 506 io1.sync(); 507 508 io0.pinMode(SX1509_0_RWW0, OUTPUT); 509 io0.digitalWrite(SX1509_0_RWW0, HIGH); 510 io0.pinMode(SX1509_0_RWW1, OUTPUT); 511 io0.digitalWrite(SX1509_0_RWW1, HIGH); 512 io1.pinMode(SX1509_1_RWW0, OUTPUT); 513 io1.digitalWrite(SX1509_1_RWW0, HIGH); 514 io1.pinMode(SX1509_1_RWW1, OUTPUT); 515 io1.digitalWrite(SX1509_1_RWW1, HIGH); 516 517 io0.pinMode(SX1509_0_RWL0, OUTPUT); 518 io0.pinMode(SX1509_0_RWL1, OUTPUT); 519 io1.pinMode(SX1509_1_RWL0, OUTPUT); 520 io1.pinMode(SX1509_1_RWL1, OUTPUT); 521 io0.pinMode(SX1509_0_RWR0, OUTPUT); 522 io0.pinMode(SX1509_0_RWR1, OUTPUT); 523 io1.pinMode(SX1509_1_RWR0, OUTPUT); 524 io1.pinMode(SX1509_1_RWR1, OUTPUT); 525 io0.blink(SX1509_0_RWL0, 600, 600); 526 io0.blink(SX1509_0_RWL1, 600, 600); 527 io1.blink(SX1509_1_RWL0, 600, 600); 528 io1.blink(SX1509_1_RWL1, 600, 600); 529 delay(600); 530 io0.blink(SX1509_0_RWR0, 600, 600); 531 io0.blink(SX1509_0_RWR1, 600, 600); 532 io1.blink(SX1509_1_RWR0, 600, 600); 533 io1.blink(SX1509_1_RWR1, 600, 600); 534 } 535} 536 537 538 539 540 541 542 543void program_step() { 544 if (rail_mode == 2) { //whaen railway lights are red, all car traffic in every direction is set to RED signals, all pedestrian signals are GREEN 545 set_leds(0, 1*32 + 1*4); 546 set_leds(1, 1*32 + 1*4); 547 set_leds(2, 1*32 + 1*4); 548 set_leds(3, 1*32 + 1*4); 549 set_ped_group(0, GRN); 550 set_ped_group(1, GRN); 551 set_ped_group(2, GRN); 552 set_ped_group(3, GRN); 553 return; 554 } 555 556 if (mode == 1) { 557 if (prog_step == 0) { 558 set_leds(0, 4*32 + 4*4); 559 set_leds(1, 4*32 + 4*4); 560 set_leds(2, 4*32 + 4*4); 561 set_leds(3, 4*32 + 4*4); 562 set_ped_group(0, RED); 563 set_ped_group(1, RED); 564 set_ped_group(2, RED); 565 set_ped_group(3, RED); 566 next_step = 5; 567 } else if (prog_step == 1) { 568 set_leds(0, 1*32 + 2*4); 569 set_leds(1, 1*32 + 1*4); 570 set_leds(2, 1*32 + 2*4); 571 set_leds(3, 1*32 + 1*4); 572 next_step = 3; 573 } else if (prog_step == 2) { 574 set_leds(0, 1*32 + 3*4 + 1); 575 set_leds(1, 1*32 + 1*4); 576 set_leds(2, 1*32 + 3*4 + 1); 577 set_leds(3, 1*32 + 1*4); 578 set_ped_group(0, GRN); 579 set_ped_group(1, RED); 580 set_ped_group(2, GRN); 581 set_ped_group(3, RED); 582 next_step = 12; 583 } else if (prog_step == 3) { 584 set_ped_group(0, RED); 585 set_ped_group(1, RED); 586 set_ped_group(2, RED); 587 set_ped_group(3, RED); 588 next_step = 8; 589 } else if (prog_step == 4) { 590 set_leds(0, 1*32 + 4*4); 591 set_leds(1, 1*32 + 1*4); 592 set_leds(2, 1*32 + 4*4); 593 set_leds(3, 1*32 + 1*4); 594 next_step = 3; 595 } else if (prog_step == 5) { 596 set_leds(0, 1*32 + 1*4); 597 set_leds(1, 2*32 + 1*4); 598 set_leds(2, 1*32 + 1*4); 599 set_leds(3, 2*32 + 1*4); 600 next_step = 3; 601 } else if (prog_step == 6) { 602 set_leds(0, 1*32 + 1*4); 603 set_leds(1, 3*32 + 1*4); 604 set_leds(2, 1*32 + 1*4); 605 set_leds(3, 3*32 + 1*4); 606 next_step = 15; 607 } else if (prog_step == 7) { 608 set_leds(0, 1*32 + 1*4); 609 set_leds(1, 4*32 + 2*4); 610 set_leds(2, 1*32 + 1*4); 611 set_leds(3, 4*32 + 2*4); 612 next_step = 3; 613 } else if (prog_step == 8) { 614 set_leds(0, 1*32 + 1*4); 615 set_leds(1, 1*32 + 3*4 + 1); 616 set_leds(2, 1*32 + 1*4); 617 set_leds(3, 1*32 + 3*4 + 1); 618 set_ped_group(0, RED); 619 set_ped_group(1, GRN); 620 set_ped_group(2, RED); 621 set_ped_group(3, GRN); 622 next_step = 12; 623 } else if (prog_step == 9) { 624 set_ped_group(0, RED); 625 set_ped_group(1, RED); 626 set_ped_group(2, RED); 627 set_ped_group(3, RED); 628 next_step = 8; 629 } else if (prog_step == 10) { 630 set_leds(0, 1*32 + 1*4); 631 set_leds(1, 1*32 + 4*4); 632 set_leds(2, 1*32 + 1*4); 633 set_leds(3, 1*32 + 4*4); 634 set_ped_group(0, RED); 635 set_ped_group(1, RED); 636 set_ped_group(2, RED); 637 set_ped_group(3, RED); 638 next_step = 3; 639 } else if (prog_step == 11) { 640 set_leds(0, 1*32 + 1*4); 641 set_leds(1, 1*32 + 1*4); 642 set_leds(2, 1*32 + 1*4); 643 set_leds(3, 1*32 + 1*4); 644 next_step = 3; 645 } else if (prog_step == 12) { 646 set_leds(0, 2*32 + 1*4); 647 set_leds(1, 1*32 + 1*4); 648 set_leds(2, 2*32 + 1*4); 649 set_leds(3, 1*32 + 1*4); 650 next_step = 3; 651 } else if (prog_step == 13) { 652 set_leds(0, 3*32 + 1*4); 653 set_leds(1, 1*32 + 1*4); 654 set_leds(2, 3*32 + 1*4); 655 set_leds(3, 1*32 + 1*4); 656 next_step = 15; 657 } else if (prog_step == 14) { 658 set_leds(0, 4*32 + 1*4); 659 set_leds(1, 1*32 + 1*4); 660 set_leds(2, 4*32 + 1*4); 661 set_leds(3, 1*32 + 1*4); 662 next_step = 3; 663 } 664 665 prog_step++; 666 if (prog_step > 14) { 667 prog_step = 1; 668 } 669 670 671 672 } else if (mode == 2) { 673 if (prog_step == 1) { 674 set_leds(0, 0); 675 set_leds(1, 0); 676 set_leds(2, 0); 677 set_leds(3, 0); 678 ped_off(); 679 } else if (prog_step == 2) { 680 set_leds(0, 1*32 + 1*4); 681 set_leds(1, 1*32 + 1*4); 682 set_leds(2, 1*32 + 1*4); 683 set_leds(3, 1*32 + 1*4); 684 set_ped_group(0, RED); 685 set_ped_group(1, RED); 686 set_ped_group(2, RED); 687 set_ped_group(3, RED); 688 } else if (prog_step == 3) { 689 set_leds(0, 4*32 + 4*4); 690 set_leds(1, 4*32 + 4*4); 691 set_leds(2, 4*32 + 4*4); 692 set_leds(3, 4*32 + 4*4); 693 set_ped_group(0, GRN); 694 set_ped_group(1, GRN); 695 set_ped_group(2, GRN); 696 set_ped_group(3, GRN); 697 } else if (prog_step == 4) { 698 set_leds(0, 3*32 + 3*4); 699 set_leds(1, 3*32 + 3*4); 700 set_leds(2, 3*32 + 3*4); 701 set_leds(3, 3*32 + 3*4); 702 set_ped_group(0, RED); 703 set_ped_group(1, RED); 704 set_ped_group(2, RED); 705 set_ped_group(3, RED); 706 } else if (prog_step == 5) { 707 set_leds(0, 1); 708 set_leds(1, 1); 709 set_leds(2, 1); 710 set_leds(3, 1); 711 set_ped_group(0, GRN); 712 set_ped_group(1, GRN); 713 set_ped_group(2, GRN); 714 set_ped_group(3, GRN); 715 } 716 prog_step++; 717 if (prog_step > 5) { 718 prog_step = 1; 719 } 720 721 722 723 } else { // mode = 0, orng blinking 724 ped_off(); 725 set_leds(0, 5*32 + 5*4); 726 set_leds(1, 5*32 + 5*4); 727 set_leds(2, 5*32 + 5*4); 728 set_leds(3, 5*32 + 5*4); 729 next_step = 10; 730 } 731} 732 733 734 735void SX1509_print_regs(byte devAdd) { 736 //only for debug 737 b = SX1509_readB(devAdd, 0x1e); 738 Serial.print("RegClock (1E): "); 739 print_val(b); 740 741 b = SX1509_readB(devAdd, 0x1f); 742 Serial.print("RegMisc (1F): "); 743 print_val(b); 744 745 b = SX1509_readB(devAdd, 0x21); 746 Serial.print("RegLEDDriverEnableA (21): "); 747 print_val(b); 748 749 b = SX1509_readB(devAdd, 0x20); 750 Serial.print("RegLEDDriverEnableB (20): "); 751 print_val(b); 752 753 b = SX1509_readB(devAdd, 0x44); 754 Serial.print("REG_T_ON_7 (44): "); 755 print_val(b); 756 757 b = SX1509_readB(devAdd, 0x45); 758 Serial.print("REG_I_ON_7 (45): "); 759 print_val(b); 760 761 b = SX1509_readB(devAdd, 0x46); 762 Serial.print("REG_OFF_7 (46): "); 763 print_val(b); 764 765 b = SX1509_readB(devAdd, 0x47); 766 Serial.print("REG_T_RISE_7 (47): "); 767 print_val(b); 768 769 b = SX1509_readB(devAdd, 0x48); 770 Serial.print("REG_T_FALL_7 (48): "); 771 print_val(b); 772} 773 774void print_val(byte b) { 775 Serial.println(b); 776 Serial.println(b, HEX); 777 Serial.println(b, BIN); 778} 779 780 781 782 783 784 785 786void set_leds(byte pole, byte pattern) { 787 byte Pleds; 788/* 789 LEFT: 790 0 - off 791 1 - RED 792 2 - RED+ORNG 793 3 - GRN 794 4 - ORNG 795 5 - ORNG blink 796 797 RIGHT: 798 0 - off 799 1 - RED 800 2 - RED+ORNG 801 3 - GRN 802 4 - ORNG 803 5 - ORNG blink 804 805 PEDESTRIAN CROSSING WARNING ORANGE LIGHT: 806 0 - off 807 1 - on 808 2 - blink 809 810 LLLRRRPP 811 LLLx32 + RRRx4 + PP 812*/ 813 814 //Left 815 b = pattern & B11100000; 816 b = b >> 5; 817 818 if (b == 0) { 819 Pleds = 0; 820 } else if (b == 1) { 821 Pleds = 16; //red 822 } else if (b == 2) { 823 Pleds = 16+64; // red+orng 824 } else if (b == 3) { 825 Pleds = 32; //grn 826 } else if (b == 4) { 827 Pleds = 64; 828 } else if (b == 5) { 829 if (blink_state) { 830 Pleds = 64; 831 } else { 832 Pleds = 0; 833 } 834 } 835 836 //Right 837 b = pattern & B00011100; 838 b = b >> 2; 839 840 if (b == 0) { 841 //Pleds += 0; 842 } else if (b == 1) { 843 Pleds += 8; //red 844 } else if (b == 2) { 845 Pleds += 8+1; // red+orng 846 } else if (b == 3) { 847 Pleds += 2; //grn 848 } else if (b == 4) { 849 Pleds += 1; 850 } else if (b == 5) { 851 if (blink_state) { 852 Pleds += 1; 853 } else { 854 //Pleds += 0; 855 } 856 } 857 858 //Pedestrian warning orng 859 b = pattern & B00000011; 860 861 if (b == 0) { 862 //Pleds += 0; 863 } else if (b == 1) { 864 Pleds += 4; //pedestrian 865 } else if (b == 2) {// blink 866 if (blink_state) { 867 Pleds += 4; 868 } 869 } 870 871 Pleds = ~Pleds; 872 873 pole = constrain(pole, 0, 3); 874 Wire.beginTransmission(PCF8574[pole]); 875 Wire.write(Pleds); 876 Wire.endTransmission(); 877} 878 879 880// Function for writing two Bytes to the I2C expander device 881void pcf8575_write(uint16_t data) 882{ 883 Wire.beginTransmission(PCF8575); 884 Wire.write(lowByte(data)); 885 Wire.write(highByte(data)); 886 Wire.endTransmission(); 887} 888 889 890 891//uint16_t pcf8575_read() 892byte pcf8575_read() 893{ 894 byte dataReceived[2]; //a two byte array to hold our data 895 uint16_t dat_rec; 896 Wire.beginTransmission(PCF8575); 897 Wire.endTransmission(); 898 Wire.requestFrom(PCF8575, 2); //request two bytes of data 899 if (Wire.available()){ 900 dataReceived[0] = Wire.read(); //read byte 1 901 dataReceived[1] = Wire.read(); //read byte 2 902 } 903 904 dat_rec = word(dataReceived[0], dataReceived[1]); 905 //return dat_rec; 906 return dataReceived[0]; //we use only one half of PCF8575, so only first byte is enough 907} 908 909 910byte SX1509_readB(byte devAdd, byte regAdd) 911{ 912 byte readValue; 913 unsigned int timeout = 1000; 914 915 Wire.beginTransmission(devAdd); 916 Wire.write(regAdd); 917 Wire.endTransmission(); 918 Wire.requestFrom(devAdd, (byte) 1); 919 920 while ((Wire.available() < 1) && (timeout != 0)) 921 timeout--; 922 923 if (timeout == 0) 924 return 0x55; 925 926 readValue = Wire.read(); 927 928 return readValue; 929} 930 931 932 933 934void SX1509_writeB(byte devAdd, byte regAdd, byte writeVal) 935{ 936 Wire.beginTransmission(devAdd); 937 Wire.write(regAdd); 938 Wire.write(writeVal); 939 Wire.endTransmission(); 940} 941 942 943//IO interrupt routine 944void PCF_INT_ISR() { 945 pcf_int_trigger = true; 946}
SX1509 library
Main code
arduino
1#include <Wire.h> 2#include <SparkFunSX1509.h> // Include SX1509 library 3 4const 5 int SX_RESET = 16; // reset pins of SX1509s 6const int RAILWAY_SOUND = 6; // control 7 pin of relay for mp3 power 8const int PCF_INT = 2; // interrupt from PCF8575 9 10// 11 D4 & D5 = software serial for level shifter / ESP8266; not implemented yet 12 13// 14 SX1509 I2C address (set by ADDR1 and ADDR0 (00 by default): 15const byte SX1509_0 16 = 0x3E; // SX1509 I2C address 17const byte SX1509_1 = 0x70; // SX1509 I2C address 18SX1509 19 io0; // Create an SX1509 object to be used throughout 20SX1509 io1; // Create an 21 SX1509 object to be used throughout 22 23// SX1509_0 Pin definition: 24const 25 byte SX1509_0_RWL0 = 6; // rail red left 26const byte SX1509_0_RWR0 = 5; // rail 27 red right 28const byte SX1509_0_RWW0 = 7; // rail white 29const byte SX1509_0_RWL1 30 = 14; // rail red left 31const byte SX1509_0_RWR1 = 15; // rail red right 32const 33 byte SX1509_0_RWW1 = 13; // rail white 34 35const byte SX1509_0_PEDR0 = 10; //pedestrian 36 red #3a 37const byte SX1509_0_PEDG0 = 11; //pedestrian green #3a 38const byte 39 SX1509_0_PEDR1 = 9; //pedestrian red #3b 40const byte SX1509_0_PEDG1 = 8; //pedestrian 41 green #3b 42const byte SX1509_0_PEDR2 = 1; //pedestrian red #4a 43const byte SX1509_0_PEDG2 44 = 0; //pedestrian green #4a 45const byte SX1509_0_PEDR3 = 2; //pedestrian red #4b 46const 47 byte SX1509_0_PEDG3 = 3; //pedestrian green #4b 48 49// SX1509_1 Pin definition: 50const 51 byte SX1509_1_RWL0 = 6; // rail red left 52const byte SX1509_1_RWR0 = 5; // rail 53 red right 54const byte SX1509_1_RWW0 = 7; // rail white 55const byte SX1509_1_RWL1 56 = 14; // rail red left 57const byte SX1509_1_RWR1 = 13; // rail red right 58const 59 byte SX1509_1_RWW1 = 15; // rail white 60 61const byte SX1509_1_PEDR0 = 8; //pedestrian 62 red #1a 63const byte SX1509_1_PEDG0 = 9; //pedestrian green #1a 64const byte SX1509_1_PEDR1 65 = 10; //pedestrian red #1b 66const byte SX1509_1_PEDG1 = 11; //pedestrian green 67 #1b 68const byte SX1509_1_PEDR2 = 0; //pedestrian red #2a 69const byte SX1509_1_PEDG2 70 = 1; //pedestrian green #2a 71const byte SX1509_1_PEDR3 = 3; //pedestrian red #2b 72const 73 byte SX1509_1_PEDG3 = 2; //pedestrian green #2b 74 75 76 77// addresses of PCF8574 78 IC 79const byte PCF8574[] = {0x39, 0x3b, 0x3d, 0x3f}; 80 81#define PCF8575 (0x20) 82 //address of PCF8575 (button input, illuminated buttons LED output) 83 84 85const 86 byte RED = 10; 87const byte YLW = 20; 88const byte GRN = 30; 89 90unsigned long 91 previousMillis = 0; 92const long interval = 20; 93byte blink_int = 0; 94byte 95 sec20 = 0; 96boolean blink_state = false; 97 98const byte numChars = 64; 99char 100 recChars[numChars]; // an array to store the received data 101boolean newData 102 = false; 103 104byte cur_light = 0; 105byte b; 106String s; 107boolean pcf_int_trigger 108 = false; 109byte dbnc = 0; 110boolean sound = false; 111 112boolean red_btn = false; 113 // LED of red button 114boolean grn_btn = false; // LED of green button 115boolean 116 blu_btn = false; // LED of blue button 117 118byte mode = 1; // 0 = orange lights 119 blink, 1 - program, 2 - test 120byte rail_mode = 1; // 0 = off, 1 - white, 2 - red 121byte 122 prog_step = 0; 123byte next_step = 1; 124 125 126 127void setup() 128{ 129 pinMode(RAILWAY_SOUND, 130 OUTPUT); 131 digitalWrite(RAILWAY_SOUND, LOW); 132 pinMode(SX_RESET, OUTPUT); 133 134 digitalWrite(SX_RESET, HIGH); 135 136 pinMode(PCF_INT, INPUT_PULLUP); 137 attachInterrupt(digitalPinToInterrupt(PCF_INT), 138 PCF_INT_ISR, FALLING); //interrupt when any of buttons is pressed 139 140 Wire.begin(); 141 142 143 pcf8575_write(word(B11111111,B11111111)); //set all IOs as inputs 144 145 Serial.begin(9600); 146 147 while (!Serial); 148 Serial.println("\ 149I2C Scanner"); 150 151 152 if (!io0.begin(SX1509_0, 153 SX_RESET)) { 154 Serial.println("SX1509_0 not found"); 155 } 156 157 if (!io1.begin(SX1509_1, 158 SX_RESET)) { 159 Serial.println("SX1509_1 not found"); 160 } 161 162 sx_init(); 163 164 165 set_rail(); 166} 167 168 169 170 171void sx_init() { 172 // Use the internal 173 2MHz oscillator. 174 // Set LED clock with divider (2MHz / (2^(divider-1)): 175 176 // divider = 2 means 1MHz LED clock (2MHz / (2^(2-1)) 177 // divider = 3 means 178 500kHz LED clock (2MHz / (2^(3-1)) 179 // divider = 4 means 250kHz LED clock (2MHz 180 / (2^(4-1)) 181 182 // 0x1-0xE: fOSCout = Fosc / 2 ^ (outputFreq - 1) Hz 183 184 185 const byte divider = 4; 186 187 io0.init(); 188 io1.init(); 189 190 io0.clock(INTERNAL_CLOCK_2MHZ, 191 divider, INPUT, 1); //250kHz clock 192 io1.clock(INTERNAL_CLOCK_2MHZ, divider, 193 INPUT, 1); //250kHz clock 194 195 //set IOs for pedestrian lights as digital outputs 196 197 //IOs for railway lights will be set as analogue outputs with breath funcion later 198 199 io0.pinMode(SX1509_0_PEDR0, OUTPUT); 200 io0.pinMode(SX1509_0_PEDG0, OUTPUT); 201 202 io0.pinMode(SX1509_0_PEDR1, OUTPUT); 203 io0.pinMode(SX1509_0_PEDG1, OUTPUT); 204 205 io0.pinMode(SX1509_0_PEDR2, OUTPUT); 206 io0.pinMode(SX1509_0_PEDG2, OUTPUT); 207 208 io0.pinMode(SX1509_0_PEDR3, OUTPUT); 209 io0.pinMode(SX1509_0_PEDG3, OUTPUT); 210 211 212 io1.pinMode(SX1509_1_PEDR0, OUTPUT); 213 io1.pinMode(SX1509_1_PEDG0, OUTPUT); 214 215 io1.pinMode(SX1509_1_PEDR1, OUTPUT); 216 io1.pinMode(SX1509_1_PEDG1, OUTPUT); 217 218 io1.pinMode(SX1509_1_PEDR2, OUTPUT); 219 io1.pinMode(SX1509_1_PEDG2, OUTPUT); 220 221 io1.pinMode(SX1509_1_PEDR3, OUTPUT); 222 io1.pinMode(SX1509_1_PEDG3, OUTPUT); 223} 224 225 226 227 228void 229 loop() 230{ 231 unsigned long currentMillis = millis(); 232 if (currentMillis 233 - previousMillis >= interval) {//every 20ms / 50x sec 234 previousMillis = currentMillis; 235 236 237 sec20++; 238 if (dbnc > 0) { 239 dbnc --; 240 } 241 242 if (sec20 243 == 50) { // 50 x 20 miliseconds elapsed, i.e. new second 244 // **************************** 245 NEW SECOND **************************** 246 sec20 = 0; 247 248 if (next_step 249 > 0) {next_step--;} //counter for traffic lights program 250 if (next_step 251 == 0 || mode == 0 || mode == 2) { //when counter reaches zero, it's time for next 252 program step. In mode=0 and mode=2 it's every second. 253 program_step(); 254 255 } 256 } 257 258 blink_int++; 259 if (blink_int == 34) { 260 blink_state 261 = true; 262 if (mode == 0) { // mode = 0 means only orange lights are flashing 263 with cca. 700ms ON / 700ms OFF interval 264 set_leds(0, 5*32 + 5*4); 265 266 set_leds(1, 5*32 + 5*4); 267 set_leds(2, 5*32 + 5*4); 268 set_leds(3, 269 5*32 + 5*4); 270 } 271 } 272 273 if (blink_int == 69) { 274 blink_state 275 = false; 276 blink_int = 0; 277 if (mode == 0) { 278 set_leds(0, 279 5*32 + 5*4); 280 set_leds(1, 5*32 + 5*4); 281 set_leds(2, 5*32 + 5*4); 282 283 set_leds(3, 5*32 + 5*4); 284 } 285 } 286 287 if (blink_int == 288 1) { 289 digitalWrite(LED_BUILTIN, HIGH); 290 } else { 291 digitalWrite(LED_BUILTIN, 292 LOW); 293 } 294 } 295 296 //check if any of buttons was pressed 297 if (pcf_int_trigger) 298 { 299 pcf_int_trigger = false; 300 b = pcf8575_read(); 301 b = b | B11101010; 302 // mask only for the buttons 303 if (b != 255 && dbnc == 0) { //some button was 304 pressed 305 Serial.println(b, BIN); 306 dbnc = 8; //set debounce period 307 308 //blue.0 309 //red.4 310 //grn.2 311 if (bitRead(b, 4) == 0) 312 { //RED button pressed, change railway lights mode 313 rail_mode++; 314 if 315 (rail_mode > 2) { 316 rail_mode = 1; 317 } 318 set_rail(); 319 320 } else if (bitRead(b, 2) == 0) {//GREEN button pressed, change traffic lights 321 mode 322 mode++; 323 next_step = 1; 324 prog_step = 0; 325 326 if (mode > 2) { 327 mode = 0; 328 } 329 Serial.print("Mode 330 changed: "); 331 Serial.println(mode); 332 } else if (bitRead(b, 0) 333 == 0) {//BLUE button pressed, it does nothing so far 334 //nothing yet 335 336 } 337 } 338 } 339 340 //check serial port input buffer 341 CheckSerial(); 342} 343 344 345 346void 347 button_lights() { 348 //sets illuminated buttons LEDs according to variables red_btn, 349 grn_btn and blu_btn 350 byte lights; 351 lights = pcf8575_read(); 352 if (red_btn) 353 { 354 bitClear(lights, 3); 355 } else { 356 bitSet(lights, 3); 357 } 358 359 360 if (grn_btn) { 361 bitClear(lights, 5); 362 } else { 363 bitSet(lights, 364 5); 365 } 366 367 if (blu_btn) { 368 bitClear(lights, 1); 369 } else { 370 371 bitSet(lights, 1); 372 } 373 lights = lights | B00010101; //set button input 374 IOs always as inputs 375 pcf8575_write(word(0xFF,lights)); 376} 377 378 379 380 381 382 383 384void 385 set_ped_group(byte group, byte color) { 386 //there are 4 groups of LEDs for pedestrian 387 signals 388 //in every group the signals change simultaneously 389 390 boolean 391 rval; 392 boolean gval; 393 if (color == RED) { 394 rval = 0; // RED lights 395 on 396 gval = 1; // GRN lights off 397 } else { 398 rval = 1; 399 gval 400 = 0; 401 } 402 403 404 if (group == 0) { 405 io1.digitalWrite(SX1509_1_PEDR1, 406 rval); 407 io1.digitalWrite(SX1509_1_PEDG1, gval); 408 io1.digitalWrite(SX1509_1_PEDR2, 409 rval); 410 io1.digitalWrite(SX1509_1_PEDG2, gval); 411 } else if (group == 1) 412 { 413 io1.digitalWrite(SX1509_1_PEDR3, rval); 414 io1.digitalWrite(SX1509_1_PEDG3, 415 gval); 416 io0.digitalWrite(SX1509_0_PEDR0, rval); 417 io0.digitalWrite(SX1509_0_PEDG0, 418 gval); 419 } else if (group == 2) { 420 io0.digitalWrite(SX1509_0_PEDR1, rval); 421 422 io0.digitalWrite(SX1509_0_PEDG1, gval); 423 io0.digitalWrite(SX1509_0_PEDR2, 424 rval); 425 io0.digitalWrite(SX1509_0_PEDG2, gval); 426 } else if (group == 3) 427 { 428 io0.digitalWrite(SX1509_0_PEDR3, rval); 429 io0.digitalWrite(SX1509_0_PEDG3, 430 gval); 431 io1.digitalWrite(SX1509_1_PEDR0, rval); 432 io1.digitalWrite(SX1509_1_PEDG0, 433 gval); 434 } 435} 436 437void ped_off() { 438 //turn off all pedestrian signals 439 440 io0.digitalWrite(SX1509_0_PEDR0, 1); 441 io0.digitalWrite(SX1509_0_PEDG0, 1); 442 443 io0.digitalWrite(SX1509_0_PEDR1, 1); 444 io0.digitalWrite(SX1509_0_PEDG1, 1); 445 446 io0.digitalWrite(SX1509_0_PEDR2, 1); 447 io0.digitalWrite(SX1509_0_PEDG2, 1); 448 449 io0.digitalWrite(SX1509_0_PEDR3, 1); 450 io0.digitalWrite(SX1509_0_PEDG3, 1); 451 452 io1.digitalWrite(SX1509_1_PEDR0, 1); 453 io1.digitalWrite(SX1509_1_PEDG0, 1); 454 455 io1.digitalWrite(SX1509_1_PEDR1, 1); 456 io1.digitalWrite(SX1509_1_PEDG1, 1); 457 458 io1.digitalWrite(SX1509_1_PEDR2, 1); 459 io1.digitalWrite(SX1509_1_PEDG2, 1); 460 461 io1.digitalWrite(SX1509_1_PEDR3, 1); 462 io1.digitalWrite(SX1509_1_PEDG3, 1); 463} 464 465 466 467 468 469 470void 471 CheckSerial() { 472 //serial port input routine, used only for debugging 473 static 474 byte ndx = 0; 475 char endMarker = '\ 476'; 477 char endMarker2 = '\ '; 478 479 char rc; 480 byte pgroup, pcolor; 481 482 while (Serial.available() 483 > 0 && newData == false) { 484 rc = Serial.read(); 485 486 if (rc 487 != endMarker && rc != endMarker2) { 488 recChars[ndx] = rc; 489 ndx++; 490 491 if (ndx >= numChars) { 492 ndx = numChars - 1; 493 } 494 495 } 496 else { 497 recChars[ndx] = '\\0'; // terminate the 498 string 499 ndx = 0; 500 newData = true; 501 } 502 } 503 504 505 if (newData == true) { 506 int slen = strlen(recChars); 507 if (slen 508 > 1) { 509 String usbreply = recChars; 510 511 usbreply.trim(); 512 slen 513 = usbreply.length(); 514 515 if (usbreply == "TRED") { 516 rail_mode 517 = 2; 518 set_rail(); 519 } else if (usbreply == "TREDB") { 520 rail_mode 521 = 3; 522 set_rail(); 523 } else if (usbreply == "WHITE") { 524 rail_mode 525 = 1; 526 set_rail(); 527 } else if (usbreply == "RED") { 528 set_leds(cur_light, 529 32 + 4); 530 } else if (usbreply == "YLW") { 531 set_leds(cur_light, 532 4*32 + 4*4 + 0); 533 } else if (usbreply == "GRN") { 534 set_leds(cur_light, 535 3*32 + 3*4 + 1); 536 } else if (usbreply == "REDYLW") { 537 set_leds(cur_light, 538 2*32 + 2*4 + 0); 539 } else if (usbreply.startsWith("CL")) { 540 usbreply 541 = usbreply.substring(2); 542 cur_light = usbreply.toInt(); 543 Serial.println("CURRENT 544 LIGHT: " + String(cur_light)); 545 } else if (usbreply == "SXRST") { 546 547 digitalWrite(SX_RESET, LOW); 548 delay(2); //2ms RESET 549 digitalWrite(SX_RESET, 550 HIGH); 551 sx_init(); 552 Serial.println("SXs were RESET"); 553 554 } else if (usbreply == "SX0READ") { 555 SX1509_print_regs(SX1509_0); 556 557 } else if (usbreply == "SX1READ") { 558 SX1509_print_regs(SX1509_1); 559 560 } else if (usbreply.startsWith("PG")) { 561 s = usbreply.substring(2,3); 562 563 pgroup = s.toInt(); 564 s = usbreply.substring(3,4); 565 pcolor 566 = s.toInt(); 567 pcolor = pcolor * 10; 568 Serial.println("PED GROUP: 569 " + String(pgroup) + ", color: " + String(pcolor)); 570 set_ped_group(pgroup, 571 pcolor); 572 } 573 574 } 575 newData = false; 576 } 577} 578 579 580 581 582void 583 set_rail() { 584 if (rail_mode == 0) { 585 //nothing yet 586 } else if (rail_mode 587 == 1) { 588 589 //set railway lights as GO - white lights blinking/breathing, 590 red lights off 591 592 red_btn = false; 593 button_lights(); 594 digitalWrite(RAILWAY_SOUND, 595 LOW); 596 io0.pinMode(SX1509_0_RWL0, OUTPUT); 597 io0.pinMode(SX1509_0_RWR0, 598 OUTPUT); 599 io0.digitalWrite(SX1509_0_RWL0, HIGH); 600 io0.digitalWrite(SX1509_0_RWR0, 601 HIGH); 602 io0.pinMode(SX1509_0_RWL1, OUTPUT); 603 io0.pinMode(SX1509_0_RWR1, 604 OUTPUT); 605 io0.digitalWrite(SX1509_0_RWL1, HIGH); 606 io0.digitalWrite(SX1509_0_RWR1, 607 HIGH); 608 io0.pinMode(SX1509_0_RWW0, ANALOG_OUTPUT); 609 io0.breathe(SX1509_0_RWW0, 610 600, 700, 5, 5); // Breathe interval: 600ms LOW, 700ms HIGH, 5ms to rise from low 611 to high, 5ms to fall from high to low 612 io0.pinMode(SX1509_0_RWW1, ANALOG_OUTPUT); 613 614 io0.breathe(SX1509_0_RWW1, 600, 700, 5, 5); 615 io1.pinMode(SX1509_1_RWL0, 616 OUTPUT); 617 io1.pinMode(SX1509_1_RWR0, OUTPUT); 618 io1.digitalWrite(SX1509_1_RWL0, 619 HIGH); 620 io1.digitalWrite(SX1509_1_RWR0, HIGH); 621 io1.pinMode(SX1509_1_RWL1, 622 OUTPUT); 623 io1.pinMode(SX1509_1_RWR1, OUTPUT); 624 io1.digitalWrite(SX1509_1_RWL1, 625 HIGH); 626 io1.digitalWrite(SX1509_1_RWR1, HIGH); 627 io1.pinMode(SX1509_1_RWW0, 628 ANALOG_OUTPUT); 629 io1.breathe(SX1509_1_RWW0, 600, 700, 5, 5); 630 io1.pinMode(SX1509_1_RWW1, 631 ANALOG_OUTPUT); 632 io1.breathe(SX1509_1_RWW1, 600, 700, 5, 5); 633 } else if 634 (rail_mode == 2) { 635 636 //set railway lights as STOP - white lights off, red 637 lights blinking/breathing 638 639 red_btn = true; 640 button_lights(); 641 642 643 io0.sync(); 644 io1.sync(); 645 digitalWrite(RAILWAY_SOUND, HIGH); 646 647 io0.pinMode(SX1509_0_RWW0, OUTPUT); 648 io0.digitalWrite(SX1509_0_RWW0, HIGH); 649 650 io0.pinMode(SX1509_0_RWW1, OUTPUT); 651 io0.digitalWrite(SX1509_0_RWW1, HIGH); 652 653 io0.pinMode(SX1509_0_RWL0, ANALOG_OUTPUT); 654 io0.breathe(SX1509_0_RWL0, 655 500, 500, 40, 40); // Breathe interval: 500ms LOW, 500ms HIGH, 40ms to rise from 656 low to high, 40ms to fall from high to low 657 io0.pinMode(SX1509_0_RWL1, ANALOG_OUTPUT); 658 659 io0.breathe(SX1509_0_RWL1, 500, 500, 40, 40); 660 io1.pinMode(SX1509_1_RWW0, 661 OUTPUT); 662 io1.digitalWrite(SX1509_1_RWW0, HIGH); 663 io1.pinMode(SX1509_1_RWW1, 664 OUTPUT); 665 io1.digitalWrite(SX1509_1_RWW1, HIGH); 666 io1.pinMode(SX1509_1_RWL0, 667 ANALOG_OUTPUT); 668 io1.breathe(SX1509_1_RWL0, 500, 500, 40, 40); 669 io1.pinMode(SX1509_1_RWL1, 670 ANALOG_OUTPUT); 671 io1.breathe(SX1509_1_RWL1, 500, 500, 40, 40); 672 delay(650); 673 674 io0.pinMode(SX1509_0_RWR0, ANALOG_OUTPUT); 675 io0.pinMode(SX1509_0_RWR1, 676 ANALOG_OUTPUT); 677 io1.pinMode(SX1509_1_RWR0, ANALOG_OUTPUT); 678 io1.pinMode(SX1509_1_RWR1, 679 ANALOG_OUTPUT); 680 io0.breathe(SX1509_0_RWR0, 500, 500, 40, 40); 681 io0.breathe(SX1509_0_RWR1, 682 500, 500, 40, 40); 683 io1.breathe(SX1509_1_RWR0, 500, 500, 40, 40); 684 io1.breathe(SX1509_1_RWR1, 685 500, 500, 40, 40); 686 } else if (rail_mode == 3) { 687 688 //test mode, just 689 to show how lights work without breathe function 690 red_btn = true; 691 button_lights(); 692 693 io0.sync(); 694 io1.sync(); 695 696 io0.pinMode(SX1509_0_RWW0, OUTPUT); 697 698 io0.digitalWrite(SX1509_0_RWW0, HIGH); 699 io0.pinMode(SX1509_0_RWW1, OUTPUT); 700 701 io0.digitalWrite(SX1509_0_RWW1, HIGH); 702 io1.pinMode(SX1509_1_RWW0, OUTPUT); 703 704 io1.digitalWrite(SX1509_1_RWW0, HIGH); 705 io1.pinMode(SX1509_1_RWW1, OUTPUT); 706 707 io1.digitalWrite(SX1509_1_RWW1, HIGH); 708 709 io0.pinMode(SX1509_0_RWL0, 710 OUTPUT); 711 io0.pinMode(SX1509_0_RWL1, OUTPUT); 712 io1.pinMode(SX1509_1_RWL0, 713 OUTPUT); 714 io1.pinMode(SX1509_1_RWL1, OUTPUT); 715 io0.pinMode(SX1509_0_RWR0, 716 OUTPUT); 717 io0.pinMode(SX1509_0_RWR1, OUTPUT); 718 io1.pinMode(SX1509_1_RWR0, 719 OUTPUT); 720 io1.pinMode(SX1509_1_RWR1, OUTPUT); 721 io0.blink(SX1509_0_RWL0, 722 600, 600); 723 io0.blink(SX1509_0_RWL1, 600, 600); 724 io1.blink(SX1509_1_RWL0, 725 600, 600); 726 io1.blink(SX1509_1_RWL1, 600, 600); 727 delay(600); 728 io0.blink(SX1509_0_RWR0, 729 600, 600); 730 io0.blink(SX1509_0_RWR1, 600, 600); 731 io1.blink(SX1509_1_RWR0, 732 600, 600); 733 io1.blink(SX1509_1_RWR1, 600, 600); 734 } 735} 736 737 738 739 740 741 742 743void 744 program_step() { 745 if (rail_mode == 2) { //whaen railway lights are red, all 746 car traffic in every direction is set to RED signals, all pedestrian signals are 747 GREEN 748 set_leds(0, 1*32 + 1*4); 749 set_leds(1, 1*32 + 1*4); 750 set_leds(2, 751 1*32 + 1*4); 752 set_leds(3, 1*32 + 1*4); 753 set_ped_group(0, GRN); 754 set_ped_group(1, 755 GRN); 756 set_ped_group(2, GRN); 757 set_ped_group(3, GRN); 758 return; 759 760 } 761 762 if (mode == 1) { 763 if (prog_step == 0) { 764 set_leds(0, 765 4*32 + 4*4); 766 set_leds(1, 4*32 + 4*4); 767 set_leds(2, 4*32 + 4*4); 768 769 set_leds(3, 4*32 + 4*4); 770 set_ped_group(0, RED); 771 set_ped_group(1, 772 RED); 773 set_ped_group(2, RED); 774 set_ped_group(3, RED); 775 next_step 776 = 5; 777 } else if (prog_step == 1) { 778 set_leds(0, 1*32 + 2*4); 779 set_leds(1, 780 1*32 + 1*4); 781 set_leds(2, 1*32 + 2*4); 782 set_leds(3, 1*32 + 1*4); 783 784 next_step = 3; 785 } else if (prog_step == 2) { 786 set_leds(0, 1*32 787 + 3*4 + 1); 788 set_leds(1, 1*32 + 1*4); 789 set_leds(2, 1*32 + 3*4 + 790 1); 791 set_leds(3, 1*32 + 1*4); 792 set_ped_group(0, GRN); 793 set_ped_group(1, 794 RED); 795 set_ped_group(2, GRN); 796 set_ped_group(3, RED); 797 next_step 798 = 12; 799 } else if (prog_step == 3) { 800 set_ped_group(0, RED); 801 set_ped_group(1, 802 RED); 803 set_ped_group(2, RED); 804 set_ped_group(3, RED); 805 next_step 806 = 8; 807 } else if (prog_step == 4) { 808 set_leds(0, 1*32 + 4*4); 809 set_leds(1, 810 1*32 + 1*4); 811 set_leds(2, 1*32 + 4*4); 812 set_leds(3, 1*32 + 1*4); 813 814 next_step = 3; 815 } else if (prog_step == 5) { 816 set_leds(0, 1*32 817 + 1*4); 818 set_leds(1, 2*32 + 1*4); 819 set_leds(2, 1*32 + 1*4); 820 821 set_leds(3, 2*32 + 1*4); 822 next_step = 3; 823 } else if (prog_step 824 == 6) { 825 set_leds(0, 1*32 + 1*4); 826 set_leds(1, 3*32 + 1*4); 827 828 set_leds(2, 1*32 + 1*4); 829 set_leds(3, 3*32 + 1*4); 830 next_step 831 = 15; 832 } else if (prog_step == 7) { 833 set_leds(0, 1*32 + 1*4); 834 835 set_leds(1, 4*32 + 2*4); 836 set_leds(2, 1*32 + 1*4); 837 set_leds(3, 838 4*32 + 2*4); 839 next_step = 3; 840 } else if (prog_step == 8) { 841 set_leds(0, 842 1*32 + 1*4); 843 set_leds(1, 1*32 + 3*4 + 1); 844 set_leds(2, 1*32 + 1*4); 845 846 set_leds(3, 1*32 + 3*4 + 1); 847 set_ped_group(0, RED); 848 set_ped_group(1, 849 GRN); 850 set_ped_group(2, RED); 851 set_ped_group(3, GRN); 852 next_step 853 = 12; 854 } else if (prog_step == 9) { 855 set_ped_group(0, RED); 856 set_ped_group(1, 857 RED); 858 set_ped_group(2, RED); 859 set_ped_group(3, RED); 860 next_step 861 = 8; 862 } else if (prog_step == 10) { 863 set_leds(0, 1*32 + 1*4); 864 865 set_leds(1, 1*32 + 4*4); 866 set_leds(2, 1*32 + 1*4); 867 set_leds(3, 868 1*32 + 4*4); 869 set_ped_group(0, RED); 870 set_ped_group(1, RED); 871 872 set_ped_group(2, RED); 873 set_ped_group(3, RED); 874 next_step 875 = 3; 876 } else if (prog_step == 11) { 877 set_leds(0, 1*32 + 1*4); 878 879 set_leds(1, 1*32 + 1*4); 880 set_leds(2, 1*32 + 1*4); 881 set_leds(3, 882 1*32 + 1*4); 883 next_step = 3; 884 } else if (prog_step == 12) { 885 set_leds(0, 886 2*32 + 1*4); 887 set_leds(1, 1*32 + 1*4); 888 set_leds(2, 2*32 + 1*4); 889 890 set_leds(3, 1*32 + 1*4); 891 next_step = 3; 892 } else if (prog_step 893 == 13) { 894 set_leds(0, 3*32 + 1*4); 895 set_leds(1, 1*32 + 1*4); 896 897 set_leds(2, 3*32 + 1*4); 898 set_leds(3, 1*32 + 1*4); 899 next_step 900 = 15; 901 } else if (prog_step == 14) { 902 set_leds(0, 4*32 + 1*4); 903 904 set_leds(1, 1*32 + 1*4); 905 set_leds(2, 4*32 + 1*4); 906 set_leds(3, 907 1*32 + 1*4); 908 next_step = 3; 909 } 910 911 prog_step++; 912 if 913 (prog_step > 14) { 914 prog_step = 1; 915 } 916 917 918 919 } else 920 if (mode == 2) { 921 if (prog_step == 1) { 922 set_leds(0, 0); 923 set_leds(1, 924 0); 925 set_leds(2, 0); 926 set_leds(3, 0); 927 ped_off(); 928 } 929 else if (prog_step == 2) { 930 set_leds(0, 1*32 + 1*4); 931 set_leds(1, 932 1*32 + 1*4); 933 set_leds(2, 1*32 + 1*4); 934 set_leds(3, 1*32 + 1*4); 935 936 set_ped_group(0, RED); 937 set_ped_group(1, RED); 938 set_ped_group(2, 939 RED); 940 set_ped_group(3, RED); 941 } else if (prog_step == 3) { 942 set_leds(0, 943 4*32 + 4*4); 944 set_leds(1, 4*32 + 4*4); 945 set_leds(2, 4*32 + 4*4); 946 947 set_leds(3, 4*32 + 4*4); 948 set_ped_group(0, GRN); 949 set_ped_group(1, 950 GRN); 951 set_ped_group(2, GRN); 952 set_ped_group(3, GRN); 953 } else 954 if (prog_step == 4) { 955 set_leds(0, 3*32 + 3*4); 956 set_leds(1, 3*32 957 + 3*4); 958 set_leds(2, 3*32 + 3*4); 959 set_leds(3, 3*32 + 3*4); 960 961 set_ped_group(0, RED); 962 set_ped_group(1, RED); 963 set_ped_group(2, 964 RED); 965 set_ped_group(3, RED); 966 } else if (prog_step == 5) { 967 set_leds(0, 968 1); 969 set_leds(1, 1); 970 set_leds(2, 1); 971 set_leds(3, 1); 972 973 set_ped_group(0, GRN); 974 set_ped_group(1, GRN); 975 set_ped_group(2, 976 GRN); 977 set_ped_group(3, GRN); 978 } 979 prog_step++; 980 if (prog_step 981 > 5) { 982 prog_step = 1; 983 } 984 985 986 987 } else { // mode = 988 0, orng blinking 989 ped_off(); 990 set_leds(0, 5*32 + 5*4); 991 set_leds(1, 992 5*32 + 5*4); 993 set_leds(2, 5*32 + 5*4); 994 set_leds(3, 5*32 + 5*4); 995 996 next_step = 10; 997 } 998} 999 1000 1001 1002void SX1509_print_regs(byte devAdd) 1003 { 1004 //only for debug 1005 b = SX1509_readB(devAdd, 0x1e); 1006 Serial.print("RegClock 1007 (1E): "); 1008 print_val(b); 1009 1010 b = SX1509_readB(devAdd, 0x1f); 1011 Serial.print("RegMisc 1012 (1F): "); 1013 print_val(b); 1014 1015 b = SX1509_readB(devAdd, 0x21); 1016 Serial.print("RegLEDDriverEnableA 1017 (21): "); 1018 print_val(b); 1019 1020 b = SX1509_readB(devAdd, 0x20); 1021 Serial.print("RegLEDDriverEnableB 1022 (20): "); 1023 print_val(b); 1024 1025 b = SX1509_readB(devAdd, 0x44); 1026 Serial.print("REG_T_ON_7 1027 (44): "); 1028 print_val(b); 1029 1030 b = SX1509_readB(devAdd, 0x45); 1031 Serial.print("REG_I_ON_7 1032 (45): "); 1033 print_val(b); 1034 1035 b = SX1509_readB(devAdd, 0x46); 1036 Serial.print("REG_OFF_7 1037 (46): "); 1038 print_val(b); 1039 1040 b = SX1509_readB(devAdd, 0x47); 1041 Serial.print("REG_T_RISE_7 1042 (47): "); 1043 print_val(b); 1044 1045 b = SX1509_readB(devAdd, 0x48); 1046 Serial.print("REG_T_FALL_7 1047 (48): "); 1048 print_val(b); 1049} 1050 1051void print_val(byte b) { 1052 Serial.println(b); 1053 1054 Serial.println(b, HEX); 1055 Serial.println(b, BIN); 1056} 1057 1058 1059 1060 1061 1062 1063 1064void 1065 set_leds(byte pole, byte pattern) { 1066 byte Pleds; 1067/* 1068 LEFT: 1069 0 - off 1070 1071 1 - RED 1072 2 - RED+ORNG 1073 3 - GRN 1074 4 - ORNG 1075 5 - ORNG blink 1076 1077 1078 RIGHT: 1079 0 - off 1080 1 - RED 1081 2 - RED+ORNG 1082 3 - GRN 1083 4 - ORNG 1084 1085 5 - ORNG blink 1086 1087 PEDESTRIAN CROSSING WARNING ORANGE LIGHT: 1088 0 - off 1089 1090 1 - on 1091 2 - blink 1092 1093 LLLRRRPP 1094 LLLx32 + RRRx4 + PP 1095*/ 1096 1097 1098 //Left 1099 b = pattern & B11100000; 1100 b = b >> 5; 1101 1102 if (b == 0) { 1103 1104 Pleds = 0; 1105 } else if (b == 1) { 1106 Pleds = 16; //red 1107 } else if 1108 (b == 2) { 1109 Pleds = 16+64; // red+orng 1110 } else if (b == 3) { 1111 Pleds 1112 = 32; //grn 1113 } else if (b == 4) { 1114 Pleds = 64; 1115 } else if (b == 5) 1116 { 1117 if (blink_state) { 1118 Pleds = 64; 1119 } else { 1120 Pleds 1121 = 0; 1122 } 1123 } 1124 1125 //Right 1126 b = pattern & B00011100; 1127 b = b >> 1128 2; 1129 1130 if (b == 0) { 1131 //Pleds += 0; 1132 } else if (b == 1) { 1133 Pleds 1134 += 8; //red 1135 } else if (b == 2) { 1136 Pleds += 8+1; // red+orng 1137 } else 1138 if (b == 3) { 1139 Pleds += 2; //grn 1140 } else if (b == 4) { 1141 Pleds += 1142 1; 1143 } else if (b == 5) { 1144 if (blink_state) { 1145 Pleds += 1; 1146 1147 } else { 1148 //Pleds += 0; 1149 } 1150 } 1151 1152 //Pedestrian warning 1153 orng 1154 b = pattern & B00000011; 1155 1156 if (b == 0) { 1157 //Pleds += 0; 1158 1159 } else if (b == 1) { 1160 Pleds += 4; //pedestrian 1161 } else if (b == 2) {// 1162 blink 1163 if (blink_state) { 1164 Pleds += 4; 1165 } 1166 } 1167 1168 Pleds 1169 = ~Pleds; 1170 1171 pole = constrain(pole, 0, 3); 1172 Wire.beginTransmission(PCF8574[pole]); 1173 1174 Wire.write(Pleds); 1175 Wire.endTransmission(); 1176} 1177 1178 1179// Function for 1180 writing two Bytes to the I2C expander device 1181void pcf8575_write(uint16_t data) 1182{ 1183 1184 Wire.beginTransmission(PCF8575); 1185 Wire.write(lowByte(data)); 1186 Wire.write(highByte(data)); 1187 1188 Wire.endTransmission(); 1189} 1190 1191 1192 1193//uint16_t pcf8575_read() 1194byte 1195 pcf8575_read() 1196{ 1197 byte dataReceived[2]; //a two byte array to hold our data 1198 1199 uint16_t dat_rec; 1200 Wire.beginTransmission(PCF8575); 1201 Wire.endTransmission(); 1202 1203 Wire.requestFrom(PCF8575, 2); //request two bytes of data 1204 if (Wire.available()){ 1205 1206 dataReceived[0] = Wire.read(); //read byte 1 1207 dataReceived[1] = Wire.read(); 1208 //read byte 2 1209 } 1210 1211 dat_rec = word(dataReceived[0], dataReceived[1]); 1212 1213 //return dat_rec; 1214 return dataReceived[0]; //we use only one half of PCF8575, 1215 so only first byte is enough 1216} 1217 1218 1219byte SX1509_readB(byte devAdd, byte 1220 regAdd) 1221{ 1222 byte readValue; 1223 unsigned int timeout = 1000; 1224 1225 Wire.beginTransmission(devAdd); 1226 1227 Wire.write(regAdd); 1228 Wire.endTransmission(); 1229 Wire.requestFrom(devAdd, 1230 (byte) 1); 1231 1232 while ((Wire.available() < 1) && (timeout != 0)) 1233 timeout--; 1234 1235 1236 if (timeout == 0) 1237 return 0x55; 1238 1239 readValue = Wire.read(); 1240 1241 1242 return readValue; 1243} 1244 1245 1246 1247 1248void SX1509_writeB(byte devAdd, byte 1249 regAdd, byte writeVal) 1250{ 1251 Wire.beginTransmission(devAdd); 1252 Wire.write(regAdd); 1253 1254 Wire.write(writeVal); 1255 Wire.endTransmission(); 1256} 1257 1258 1259//IO interrupt 1260 routine 1261void PCF_INT_ISR() { 1262 pcf_int_trigger = true; 1263}
Downloadable files
Schematic of railway traffic light with 3 LEDs
Schematic of railway traffic light with 3 LEDs
Schematic of railway traffic light with 3 LEDs
PCB of pedestrian traffic light with 2 LEDs
PCB of pedestrian traffic light with 2 LEDs
PCB of pedestrian traffic light with 2 LEDs
Schematic of pedestrian traffic light with 2 LEDs
Schematic of pedestrian traffic light with 2 LEDs
Schematic of pedestrian traffic light with 2 LEDs
PCB of railway traffic light with 3 LEDs
PCB of railway traffic light with 3 LEDs
PCB of railway traffic light with 3 LEDs
Schematic of main traffic light with 7 LEDs and PCF8574T
Schematic of main traffic light with 7 LEDs and PCF8574T
Schematic of main traffic light with 7 LEDs and PCF8574T
PCB of main traffic light with 7 LEDs and PCF8574T
PCB of main traffic light with 7 LEDs and PCF8574T
PCB of main traffic light with 7 LEDs and PCF8574T
Schematic of pedestrian traffic light with 2 LEDs
Schematic of pedestrian traffic light with 2 LEDs
Schematic of pedestrian traffic light with 2 LEDs
PCB of railway traffic light with 3 LEDs
PCB of railway traffic light with 3 LEDs
PCB of railway traffic light with 3 LEDs
Schematic of main traffic light with 7 LEDs and PCF8574T
Schematic of main traffic light with 7 LEDs and PCF8574T
Schematic of main traffic light with 7 LEDs and PCF8574T
PCB of pedestrian traffic light with 2 LEDs
PCB of pedestrian traffic light with 2 LEDs
PCB of pedestrian traffic light with 2 LEDs
Schematic
Complete schematic
Schematic
PCB of main traffic light with 7 LEDs and PCF8574T
PCB of main traffic light with 7 LEDs and PCF8574T
PCB of main traffic light with 7 LEDs and PCF8574T
Schematic of railway traffic light with 3 LEDs
Schematic of railway traffic light with 3 LEDs
Schematic of railway traffic light with 3 LEDs
Comments
Only logged in users can leave comments