With this experiment I wanted to create a helipad for “night flights” with my indoor helicopter. Bascially this requires 4 knight rider effects. However if I set it up just with a basic knight rider sketch the lights are always out of sync. This is due to different startup times of the Arduinos. Even if the sketches would start in perfect sync they would start to drift out of sync sooner or later. I already investigated this in the crystal deviations and crystal deviations 2 experiments.
Since the Blinkenlight shield already occupies 20 of the 20 IO pins synchronization is somewhat tricky. There are several options to achieve the desired synchronization. One set of options revolves around the idea of enabling one of the 3 IO pins that the Arduino does not use for IO. All of these options have the drawback that they will require hardware modifications and/or a HV programmer. So I was searching for options to multiplex input and output behavior to some pins.
Here is my first take on it. This sketch will be loaded into all 4 Arduinos. In addition I connect pin 19 of all Arduinos with each other. Please do not do this until you have uploaded this sketch. If you want to protect your Arduinos from shorting each other use 1k resistors for decoupling. If you upload the sketch before connecting pins 19 this is not requiered though. Take care to not upload anything else while the pins are connected.
// // www.blinkenlight.net // // Copyright 2011 Udo Klein // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see http://www.gnu.org/licenses/ const uint8_t step_delay = 500; const uint8_t phases = 8; const uint8_t led_count = 20; const uint8_t sync_input_pin = led_count - 1; void display_phase(uint8_t phase) { for (uint8_t pin=0; pin< led_count; ++pin) { if ((pin+phase) % phases == sync_input_pin % phases) { digitalWrite(pin, HIGH); pinMode(pin, OUTPUT); } else { if (pin > 1) { // pins 0 and 1 are pulled by the 1k resistors from the FTDI chip pinMode(pin, INPUT); } digitalWrite(pin, LOW); } } } void soft_delay(uint32_t ms) { uint32_t start_time = millis(); while (millis()-start_time < ms && !digitalRead(sync_input_pin)) {}; } void setup() { } void loop() { display_phase(0); delay(step_delay); display_phase(1); delay(step_delay); for (uint8_t phase = 2; phase < phases; ++phase) { display_phase(phase); soft_delay(step_delay); } }
Let us see how this sketch manages to synchronize while using all pins as outputs.
The basic idea is to toggle between 5V output and high impedance input. 5V will of course light any connected LED. Since high impedance input will not source any current it will not drive any LED. Thus it is clear that toggling LEDs on and off is possible this way. The only exception are LEDs 0 and 1. The reason is explained in the high-Z experiment.
For the sync pin it is also clear that if any other sync pin will switch to 5V it will sense a high. But what happens if all other pins are also inputs? Then the LEDs will pull the pins below the threshold for sensing a LOW signal. Thus this can also be detected.
The only thing that remains is to continously monitor if any sketch is out of sync. The trigger condition is if a sync pins senses high during the “soft delay” phase. In this is detected the current sketch is assumed to be to slow. Thus the delay will be skipped immediately. This makes the sketch catch up.
You may wonder why there are two “standard” delays. One of them is required during the 5V output phase in order to not skip during this phase. The second one is required for the first phase after the 5V output phase. This is required to ensure that the first Arduino to finish this phase will not fall through to the next 5V output phase.
Have a look how it all turns out. Attention: lower the volume because the helicopter is really loud. And have pity with my poor landing skills. It was dark and I had lots of turbulence while filming.
Could make sense to drive 4 blinkenlights from a single Arduino, why not taking transistors into consideration and a few wires on a breadboard? Could be the money saving approach.
Except if you are me. I have enough Blinkenlighties and Blinkenlight Shields around. So why bother with additional hardware or setup time if I have already everything at hand?