Definitely not a small calculator. In inches, it has a height of 23 inch, is 18-inch-wide and 10-inch deep. For fans of the metric system: a height of 58 cm, 46 cm wide and 25 cm deep. Operates with values up to 1024, and can count and multiply, as multiplying can be seen as repeated counting. (5 x 7 becomes 7+7+7+7+7)
Does not use batteries or a solar panel. Does not use any power source at all, except gravity. The numbers are represented with marbles, as well the input values as the result.
I found an example of this principle on the web and I decided to build one myself. With some modifications, as a mechanical calculator needs the look of a machine. And as it uses no electricity, the machine may have an appearance as it could have been used in the 19th century.
https://www.youtube.com/watch?v=JLzRKFEMAyg
(As one goal of the machine was to make people familiar with binary numbers, there is much attention for setting up the numbers)
The movie above does not give any clues away. The movie below will show you the entire principle:
https://www.youtube.com/watch?v=OM0y-dR-Ndo
Most of the building part is easy and can be understood by looking at the pictures. There are only two parts with a little higher range of difficulty: the flipflops and the mechanics to operate the sliders.
At first, the flipflops were entirely made of wood, but reacted a little unpredictable. With sums like 3 + 3, the flipflops need to act very accurate, as the flipflop on line 2 must deal with 3 marbles: one is stored in its memory, one as handed over from line 1, and one comes from the upper slider. To solve the inaccuracy, I added some aluminum strip on top. After this adjustment, all operations became accurate.
The other part with a higher level of difficulty are the sliders and the handles to move them. Inspired by the old-fashioned cash registers, I’d like a handle for operating the machine. As there are two sliders (a top slider to make it easy to place a value, and a result slider to hold the marbles on the sum-line) which work together, I’ve used two handles: a “count-up” handle, which adds the marbles to the central part of the machine (you can call it memory), but also opens the lower slider to let marbles pass which are no longer needed in the memory. As you store two marbles after each other on the row with value “1”, only one marble on the row with value “2” is needed in memory: the other falls down, and as the result slider is open, it won’t stay on the sum-line but falls down to the marble reservoir. The second handle shows the result, by closing the lower slider, and turns all flipflops to their start position. If a flipflip was holding a marble, it will fall down, and remain on the sum-line. There you can read (or count) the result of the sum.
As the upper slider is always closed when no handle is used, it has a spring that automatically close the slider. The lower slider remains in its last position. (Actually always open, except when a result must be shown)
The movement of the handles is transferred by nylon rope and handmade pulleys. Pulleys are not necessary, but an easy way to keep the rope where it belongs. As the accuracy is not 100% (all had been sawn by hand, I have no CNC router), it turned out to be a little problem to turn all flipflops to their original state. To solve that I used some thick copper-wire between the hinging unit and the plug of the flipflops.
Home automation for only $22.13! Sounds too good to be true, and actually you will need something more: 433 MHz power switches (Dutch: klikaanklikuit modules) to use the wireless opportunities. But without, you still can use 8 relays with your cellphone or any device with internet.
A few months ago, a friend came to me for some help with his home-automation wish: control everything in his apartment with only one remote. So we started this project.
The list of needed parts:
1 Arduino Mega clone | $ 7.10 |
1 ESP 8266 WIFI module | $ 1.24 |
1 set RX / TX 433 mhz. | $ 0.37 |
1 block with 8 relays | $ 3.88 |
1 power-unit | $ 4.41 |
1 OLED screen | $ 3.23 |
1 push button | $ 0.71 |
1 small piece of PCB | $ 0.18 |
And, of course some scrap wood and other materials. I used plexiglass for my casing. I like to see the connected parts, but at the lower level it's no weak current: depending on your country, the relays will switch 110-230 volts. So the entire package I made will be stored in a wooden box once its operational.
After the unit is powered, it will connect to a WIFI network. The OLED screen looks pretty small, but can be read very easily. Once connected, it shows the IP address where you can find it's control center. It's a local address, so only available when you are connected to the same network. Of course it's possible to configure your access point to make it visible from outside your network, but the whole world gets the ability to switch off your coffee machine. So be warned...
Once your cellphone, tablet or laptop has loaded the website, it can control everything connected to the relays and the radio transmitter. The website uses AJAX for sending the commands, so there is no delay for reloading the website every time you turn a switch.
The Arduino Mega and the Wemos D1 mini |
We started this project first with a Wemos D1 mini. It has some major advantaged above the Arduino Mega:
We discovered also some disadvantages:
Some problems can be solved by using an extension board. You offer one or two pins, to get four till eight in return. We decided to switch to an Arduino Mega clone because of the next advantages:
Beside the advantages, there are also some disadvantages. The main problem is the small amount of memory (8 kb for storing vars) and the combination with the ESP8266 WIFI unit. The connection between them needs to be read as text (char or strings), and you even have to store/collect messages to interpret them once they're completed. And last but not least: the website itself needs to be stored on the Arduino also. More text to store.
AT+RST
OK WIFI DISCONNECT ets Jan 8 2013,rst cause:2, boot mode:(3,7) load 0x40100000, len 1856, room 16 tail 0 chksum 0x63 load 0x3ffe8000, len 776, room 8 tail 0 chksum 0x02 load 0x3ffe8310, len 552, room 8 tail 0 chksum 0x79 csum 0x79 2nd boot version : 1.5 SPI Speed : 40MHz SPI Mode : DIO SPI Flash Size & Map: 8Mbit(512KB+512KB) jump to run user1 @ 1000
Ai-Thinker Technology Co. Ltd. ready
Above the response after a given AT+RST command (a reset)
The storage of text (Strings) is complicated on an Arduino. It's the only var with unknown memory usage when it's declared. Besides that, you clone (and double the usage of memory) very often when working with strings: pass it through a function, edit it, etc.
Once your memory is filled up, your Arduino will behave strange: resets without warning, program crashes, unexpected return-values from functions, and almost every time no signals from the serial ports anymore...
For this project there will be 5 modules connected to the Arduino. Most of the pin assignments are not critical. In other words: most of the destination pins can be changed, but a modification of the program will be necessary. In my case, I've decided to choose the pins on the short side of the PCB, to make shorter connections and to prevent the wires to mess up.
This module is used to connect your Arduino to the internet, or in this case: to your local network. As mentioned above, it communicates with two serial lines (RX and TX). This is the only module needing 3.3 Volt, instead of 5.(!) That means that not only the VCC should be treated in a different way (do not connect it to your 5V power supply, connect it to the 3.3V pin of your Arduino), but also you need some resistors on the RX line to lower the voltage.
It's also mentionable that this WIFI module only uses the 2.4 GHz band and is not able to connect to the modern 5.0 GHz band. As far as I can see that won't be a problem right now, as I don't know one single router with only the 5 GHz band.
In this project we use pin 18 and 19 to connect to the Arduino. Those are not critical, as an Arduino has four sets of serial ports:
The communication pins on the Mega |
RX 0 and TX 0 have been set aside, as they will be used for program uploading and the serial connection (with the monitor, plotter and IDE) on your computer.
The other ones are not in use. I do not know if they are exactly interchangeable, but I've chosen RX1 and TX1. If you want to change to another set of lines, change the program, and replace all "Serial1." commands to "Serial2." (or "Serial3." of course).
The first time I received one of these OLED modules, I got surprised by the fact that its size is no problem at all! As they are really small (below 1 inch), you would expect the need of glasses to read them. But actually four lines of text is no problem at all.
The old modules (without I2C) used lots of wires (4 or 8 data lines), but the I2C versions are easy. GND, VCC and a SCI and SDA are needed.
Is the pin configuration critical? An Arduino Mega has one set of SCI and SDA pins. These function like a bus -the I2C bus-. Therefore it is not necessary to change pins when you want to add something more on that bus, devices can share a bus. Communication will be separated by the use of an address. That means that you'll have to check the address of your screen and correct it in the program. (More explanation in the check your module section)
Normally you'll buy them as a set, and even you don't need the receiver in your final setup: don't throw it away. You will need it to get the codes from the remote controls of your wireless switches. As you can see, there is a small hole on the FS1000a with the description ANT near it. You can add an antenna to it when the unit cannot reach the desired distance. Tests over here showed no problem over 10 meter, so I did not attach one.
I used pin 53 on the Arduino, but every pin can be used. You only have to change the program on this line:
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
#define pinTX 53
Change the 53 to another free pin when desired.
This is a button which only creates a circuit during the push. It is meant as a wake-up-button for the screen, as I do not want it to display info 24/7. Once the button is pressed, it lights up de display for 60 seconds. As you may know, the button needs to be connected with a pull down resistor.
Another alternative is to use a switch (on / off), and connect it on the 5V line of the OLED, to interrupt the circuit, and the OLED is turned off for real. (Notice that the pushbutton system does not interrupt the power, the program stops using the screen)
It can be really frustrating when you put everything together in a nice casing, with all wires cut to the desired length, and you discover problems... So I suggest to test all modules separate and together before wiring if permanent. Use a breadboard and some Dupont cables to wire it up, and use the test programs to make sure everything works fine.
After wiring it up, use the next program when connected to your computer. Your serial monitor should tell you the results of an attempt to connect to your WIFI network.
void setup() {
Serial.begin(9600); //<--This is the connection with your computer.
Serial1.begin(115200); //<--This is the connection speed with your ESP.
// WiFi SSID and Password
String SSIDstring = ("#####"); //Replace ##### with your network name / SSID
String PASSstring = ("#############"); //Replace ########### with the password of your network
useESP("AT+RST\r\n", 2000);
useESP("AT+CWMODE=1\r\n", 2000);
useESP("AT+CWLAP\r\n", 8000);
useESP("AT+CWJAP=\"" + SSIDstring + "\",\"" + PASSstring +"\"", 6000);
useESP("AT+CIPSTATUS\r\n", 2000);
useESP("AT+CIPMUX=1\r\n", 1000);
useESP("AT+CIPSERVER=1,80\r\n", 1000);
useESP("AT+CIFSR\r\n", 1000);
}
void loop() {
}
String useESP(String command, const int timeout) {
String response = "";
Serial.println("==================================================");
Serial.println("The Arduino sends the next command to the ESP8266:");
Serial.println(command);
Serial1.print(command); //<-- This is the real command to send to the ESP
Serial.println("..................................................");
Serial.println("Waiting for response...");
long int time = millis();
while( (time + timeout) > millis()) {
while(Serial1.available()) {
char c = Serial1.read();
response += c;
}
}
Serial.print(response);
return response;
}
The program communicates using serial 1 (TX1 and RX1) with the ESP8266. The program will show you the given command, and the response of the ESP8266.
Under normal circumstances, you should see the reset (RST) command, after which the ESP generates a summary. You also see a list of networks in your area, and the program tries to connect to your network. If that is possible, it will show you the given IP address. (a reference of usable commands can be found here)
When it does not connect, you still will get output on your monitor. (Otherwise your Arduino cannot communicate with your computer). If there is no response from your ESP8266 at all:
When there is response, but totally unreadable, too short or the word "busy..":
To test the FS1000a, we need 3 more things:
Attach the receiver to 5V and ground, and connect one of the middle two data-pins to Arduino pin 2. You will nead an extra library if for your Arduino, so make sure RC-Switch is installed (of not, get it!).
The library of RC-Switch can handle the protocol we need. But not all power outlet sockets use the same protocol. It will be possible that you need another library of other hardware for your wireless switches, but the "klikaanklikuit" devices over here work.
Once you've setup the breadboard. just start the "ReceiveDemo_Advanced" script on your IDE. (Examples > RC-Switch > ReceiveDemo_Advanced)
Now you can use one of your remotes (maybe disable the receivers before...) and take a look at the information on your serial monitor:
Decimal: 3700159 (24Bit) Binary: 001110000111010110111111 Tri-State: not applicable PulseLength: 306 microseconds Protocol: 1
Raw data: 9536,268,900,280,912,840,320,864,308,868,304,280,896,292,884,284,880,308,872,884,288,876,300,864,332,268,900,848,320,272,908,848,336,840,324,860,312,276,908,264,908,852,328,844,100,16,92,444,512,
Maybe I take some risk by showing you one of my codes, because everyone with an Arduino / FS1000a combination can broadcast a "3700159" code of 306 microseconds in front of my house to activate the SoundBlaster radio...
Learn all codes from your remote(s). As you can see the pair of codes (on and off for one device) are almost identical, only the "off"-code is one lower. (In my case: you can turn the SoundBlaster off with 3700158)
Now we take our breadboard again, and setup for the transmitter: de FS1000a. Wired as mentioned in the section before, you can run the next test:
#include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); #define pinTX 53 #define pulseLength 306 #define bitLength 24 #define protocol 1 void setup() { mySwitch.enableTransmit(pinTX); mySwitch.setPulseLength(pulseLength); mySwitch.setProtocol(protocol); } void loop() { mySwitch.send(3700159, bitLength); delay(2000); mySwitch.send(3700158, bitLength); delay(2000); }
With this script, the power outlet socket will be turned on and off every four seconds.
Troubleshooting:
The OLED is connected to two special pins: the I2C-bus. As in computers more devices can share one bus, because communication will use addresses. So you need to find the address of your screen first. That can be done with an I2C Scanner. Once you've got it, you can test your screen with the Adafruit SSD1306 library example. (Make sure you also install the Adafruit GFX library) If you'll get the warning to fix your SSD1306 library, open up the Adafruit_SSD1306.h file in your editor. The only line uncommented should be the line with your screen resolution:
/*=========================================================================
SSD1306 Displays
-----------------------------------------------------------------------
The driver is used in multiple displays (128x64, 128x32, etc.).
Select the appropriate display below to create an appropriately
sized framebuffer, etc. SSD1306_128_64 128x64 pixel display SSD1306_128_32 128x32 pixel display SSD1306_96_16 -----------------------------------------------------------------------*/
#define SSD1306_128_64 //<<-- My resolution, this line is oncommented
// #define SSD1306_128_32 //<<-- Not my resolution, this line is commented
// #define SSD1306_96_16 //<<-- Not my resolution, this line is commented
(Normally, this file can be found on your hard drive: users\#username#\documents\Arduino\libraries\Adafruit_SSD1306\ )
As you wired as mentioned before, you can use the program below to test your relays. When using for testing purposes, we do not attach the relays to outlet sockets. The relays have LED's on board, so testing is possible without the dangerous alternating current from your wall socket.
void setup() {
for (int i = 22; i < 36; i = i + 2){
pinMode (i, OUTPUT);
digitalWrite (i, HIGH);
} void loop() {
for (int i = 22; i < 36; i = i + 2){
digitalWrite (i), LOW); //<-- Turn relay ON
delay(1000);
}
for (int i = 22; i < 36; i = i + 2){
digitalWrite (i), HIGH); //<-- Turn relay OFF
delay(1000);
}
}
Running these code let all relays go on and off.
Troubleshooting:
Testing the push button
Although there is nothing spectacular about testing a pushbutton, I will test it. When having troubles with the main program, there is nothing more frustrating than "things you would expect to work, but they didn't". So use the button example in the IDE (examples > 2.0 Digital > Button) to check your connections.
The main script can be used after some adjustments. The next data will be different for everybody:
Besides those points, when you can work with HTML it is also possible to change the website, add or remove tabs, change the tab-icons or the turn on and off buttons. On the next page of this article you will find information about the website, as most is hidden in a JS file.
The devices
Make a list with all devices you want to control, and sort them as you want to see them on the website (first device is first item on first tab, second device is second item on first tab, and so on).
For all wireless devices, two codes are needed. One to turn off, and one to turn on. If you use devices which use only a single code like a pushbutton (door openers for example), add the code twice: once on the list of codes to turn on, and once on the list of codes to turn off.
The setup part of the RC Switch contains the pulseLength, which maybe can be different from mine. The pulselength of your wireless switches can be found with the test-program "ReceiveDemo_Advanced" mentioned on the page before.
The OLED screen is bus connected, and will only be able to work when the correct address had been entered in the program:
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //<-- The address(0x0C) can be different on other OLED screens.
Besides that, run the test-program at least once. It will also warn you when your library "Adafruit_SSD1306.h" needs an adjustment for your resolution. See the module-checking page..
Download the Home Automation script
The script serves a website, which has dependencies to three other files:
I can imagine you need to change ha.js, as it contains the images. And most people won’t use the same TV, light, bed and door icon I do. So you need to have access to a web server to store ha.css and ha.js. On the next page, you can find the zip files of these two files.
For testing purposes or “just wanting the same version I have”, you can use the ones stored on the 2muchtime server. (Link to the addresses above, not to their zip-file)
And off course: using your own files means you have to change the script on your Arduino: recplace the URLs in the string of the website with your own locations.
To reduce the risks, the program sends a very small website, about 450-500 characters (depending on the devices):
<!DOCTYPE html> <head> <link href="https://2muchtime.org/projects/ha/ha.css" rel="stylesheet" /> <script src="https://ajax/googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> </head> <body> <div id="c" style="display:hidden"> 2muchtime Domotica,*,Television,Moodlight,Light near window,TV light,*,Moodlight bed,Bedside table light,*,Desk light,Light at backside, General,Light above table,*,Front door </div> </body> <script src="https://2muchtime.org/projects/ha/ha.js"></script> </html>
Above the website as will be server by the Arduino to your browser.
The website has dependencies to three files: jQuery, a CSS file and a JavaScript file. All will be served from another server.
The JavaScript file is used for the next purposes:
The files can be found here:
Download the Javascript file (zip)
A daylight simulator for fish tank, completely adjustable to any biotope. Can produce Kelvin colors, as well as RGB colors. I've done this project twice. In 2014, with an Arduino and a LED PWM dimmer shield. Today, LED's with the 2812 protocol become more popular, as they have their own PMW dimmer for every single led. You can control hundreds of LED's without an extra shield. The program on the Arduino Mega can handle both systems, and with a little tweak every RGB LED driver with the capability of being controlled by an Arduino will work.
For almost 10 years now I have a small fish tank (60 liter / 16 gallon) on the place where once my TV stood. No bad deal as the TV was never used, and "the big dark square" caused by it was not an asset to my interior. The tank has a couple of small fish and shrimps. And lots of snails. For the lightning, I switched from tubes to white LED's and finally RGB LED's. The reason? This system offers me "a different kind of view" almost every (couple of) hour. The color of light can quite change the view, as some colors let things light up, as other colors just ignore them. The spider wood -brown- does not stand out in the regular daylight (6500 K), but when the light gets warmer (yellow - red) it takes a key role in the tank.
People who like it, can try to rebuild this project. It's much cheaper than the light computers sold in shops. Depending on your choices, you can calculate the possible amount of money needed on the third page. The page before (actually the next page right now) contains some information on LED's, and I may say those were learning points for me.
LED's are a very unique source of light. And before building up this daylight simulator, it's better to take note of the pro's and cons of them....
Off course there are different kind of LED's with all their own characteristics. The LED's I am talking about are RGB LED's, and more specific: the ones sold as LED strips.
As RGB LED's are actual 3 LED's in one housing, they do not really produce white light: they blend red, green and blue to create the desired color. These three colors are rather pure: their spectrum is small. On the left side, the spectrum of an RGB LED, right the spectrum of a light tube for fish tanks. The white line in both spectra shows the spectrum which is needed for photosynthesis.
Blending the light with an RGB controller cannot fill-up the gaps: Parts of the spectrum which are absent cannot be repaired. The TL on the right does a better job, although it's also not perfect. So, if your tank contains plants which need of good light, you can consider using tube lights for at least a couple of hours a day.
On the web, you can find manufacturers with nice stories about high efficiency, lots of light... The small RGB LED's on strip do not have a high rate of efficiency, and the promised light output may be a little lower. The movie of my tank is made with 300 RGB LED's on a strip, of the type WS2812 IC 5050 RGB LED, with the specs below:
Color | Wavelength | Luminous intensity | Current | Voltage | mW |
Red | 620-630 nm | 550-700 mcd | 20 mA | 2.0 V | 40 mW |
Green | 515-530 nm | 1100-1400 mcd | 20 mA | 3.1 V | 62 mW |
Blue | 465-475 nm | 200-400 mcd | 20 mA | 3.3 V | 66 mW |
As my white point seems to be red: 100%, green: 71%, and blue: 35%, every LED uses 40 + 44 + 23 = 107 milliwatt. For all LED's together, we are talking about 32 Watt. And the level of light is definitely below the light of one 18-watt TL.
The lifespan of a LED is very long. But actually, lifespan is the wrong term. Most of the time, LED's do not stop working, they just shine less bright. Technically they are not broken, and their lifespan hasn't ended yet. But still they become unusable. The picture shows two led strips (not RGB, white LED strips). One is unused, the other has been used for about 10.000 hours (3 years).
Nowadays, LED's become cheaper and cheaper. But for this project, you need some things more, all with their own lifespan. And as I mentioned above, you won't save money on electricity either, I guess.
LED systems like this have the advantage like all DIY projects that they have a high rate of replaceability: one thing damaged, one thing replaced. My old light hood of the tank was made for tube light, and had its starter unit sealed in. Unreplaceable. Therefore, a broken starter-unit charged me for almost $ 80.00.
As I am a DIY person and not a high skilled electrician, I prefer the fact that my light hood only uses 5 Volts. (or 12 Volts, depending on the kind of strips) Besides that, I also like the fact that the temperature in the hood does not raise to destructive levels anymore. And off course the biggest advantage: the customizable colors. Even if you use a standard RGB controller and 5-10 meters of strip with no color changing at all: you can change the appearance of your tank with one button press. With tubes and other lightsources you even get surprised when you first light them and the color is a little "different as expected", Get used to it, you will see that color for long times.
As most of the TL lights have the same efficiency, many tank-owners think about "watt per liter/gallon". Nowadays there are so many light sources with different specifications, that it becomes difficult to compare them. What about lux, lumen, candela and mcd? Take a look at the picture below. The red and white desk light have the same intensity of light, and blue and white have the same size of beam... So, all are different.
Talking about lux is talking about intensity. As you can see, the white and the red light have the same intensity. Because of its wider beam, red produces more light, but still has the same intensity. Therefore, Lux is impractical to determine the amount of light sources needed.
Candela is the luminous intensity in a given direction per steradian. In other words: the total amount of light within a certain direction (a steradian). This is actually also a quantity of light-intensity. In the picture, white and red have the same amount of Candela, blue has more.
One MCD (micro Candela) is 1/1000th of Candela.
Lumen tells you something about the total amount of light which emits from the light souce. In the example above, red and blue have the same amount of Lumen, white has a lower amount. The fact that blue has a smaller beam causes its beam to have a higher intensity. For your tank, you need to use the amount of lumen to decide the amount of light sources. It is possible to calculate lumen if you know candela or lux, as you also know the radiation angle of the source. Conversion can be done on many sites on the internet (click).
Different kind of set-ups
As most people with the fish tank syndrome, I like to limit the use of technics, and when I use it, I'll try to make it invisible. In this case, I made a small remote (45 x 30 x 8 mm). That is the only visible part. My Arduino itself and the power supply have been put away from the water, and stay out of sight. (Some people think the small wooden remote is the light computer, but unformtunately that's not possible)
The big choice to make is "what to use as a RGB LED driver", as can be seen in the image right:
This version has one central LED driver. Depending on the size of your tank, it must be able to handle 100s of LED's. The version I have, used 12 V RGB LED strip, and when the driver was powered, it also powered the Arduino with 5 Volt. Depending on the LED strip (common anode or common cathode) there is a central ground or +12V to the strips, and three wires for the colors. The remote has a small cable with 5-7 wires in it (I used an old PC cable). The OLED screen uses 4 wires (two wires for the I2C bus, and a +5V and a ground), the button 1, 2 or 3. (The button needs a connection to an Arduino pin, a +5V and a ground for a pulldown resistor). It is possible to share the power lines with the OLED, but if you have enough wires in your cable: let both devices have their own power, to reduce the risk of interference. If you have a cable with 6 wires, then I suggest to share the +5V, and give the button its own ground.
The advantage of this setup it the possibility to use cheap LED's. Those strips with the world-famous 5050 LED's are a very cheap solution. However, you need a driver (or more drivers) to control them. That driver probably is the most expensive part of your setup.
On the other hand, you can use RGB LED strips with the 2812 protocol. Those LED strips are more expensive, but every LED on the strip has its own driver embedded. It used tree wires: +5V, ground and Din (data in) and do (data out). The do of every single LED is connected to the din of the next LED. With only 3 wires, these strips have individually addressable LED's! This program does not make use of that property, but if fact it's possible to create different zones with different light. (Moonlight only at the front? More light in zones with critical plants?)
At first I had some reservations. At what speed do all those small controllers pass the signal? Would there be a delay between the first and the last led? Any research on the web learned that the speed of this system is so fast, that you would be able to use it for a videowall. (You can let your fish watch "Finding Nemo" from your light hood, as you like) This LED's are also used for DIY Ambilight systems and effect lightning for disco's, so there seems to be no problem at all.
The main advantage seems the lack of a central LED driver. On the other hand, these LED's are more expensive. For my tank with 300 LED's, the costs for the driver and the LED's are:
System with driver and 5050 LED's |
System with 2812 LED's |
|
300 LED's | $ 9.70 | $ 26.40 |
Driver | $ 18.00 | - |
Sum | $ 27.70 | $ 26.40 |
As you can see, for tanks like mine there is no real difference at all. For smaller tanks, the 2812 system would be even cheaper! Bigger tanks won't make more benefit, as the driver I've used was able to control 30 Watt of LED's, which means that 600 LED's need a second driver.
Another advantage -when you use strips of 5V- is the less complex power supply. The first system uses 12V strips (as the driver also uses 12V), the second system uses 5V strips, so all can be plugged in to the power supply without any restrictions.
The program on the Arduino can handle both scenario's, but when you want to use something else to drive the LED's make sure you know how to let your Arduino communicate with the driver.
This version of the daylight sim uses the next parts:
I use an Arduino Mega, but it will work with other ones or even clones. There is only one restriction: your board needs to have an I2C bus (on the Mega pin 20/21) to use the OLED.
The wiring is shown below, but only the I2C is critical.
The LED strips get power from both sides of the strip, and the data line is wired like a snake. All LED's behind each other, no serial connections. (important!) The pushbutton needs a pulldown resistor to the ground, I use a 10K resistor, which works fine.
As I wanted to hide al Tec stuff, I made a remote with only the pushbutton and the OLED in a small case with 50 cm of cable. I have used an old PC cable from some device with 6 wires in it. So, the button and the OLED (7 wires together) share their +5 V. That seems to work. In the past, I had troubles with an LCD-screen and a shared ground. For me that's the reason to try to avoid sharing grounds.
When you buy a strip of white LED's, there may/ be some specification about its color on the package. Cold light, warm white or something like 6600K. On RGB LED's of course there won't be such a description, but that does not mean that all strips are equal. Due to bad quality, it is possible to get different colors on one strip, even when that's not your intention. There is a difference in power consumption between red, green and blue LED's, and I noticed a slightly different / warmer color to the end of the strip due to underpowered blue LED's. Working with regular RGB strips, you have one common line (anode or cathode) which contains the total amount of energy for all LED's. And most of the time it's just a PCB line. As you may cut the strips to fit in your light hood, you may consider using a better conductor parallel to your strip.
And for the 2812 strips, it's even worse. Both power lines (+ and ground) are equal for all LED's, so I'll advice to make a central + and ground point in your light hood, and connect all parts of strip separate. The data line cannot be passed by, as it is also responsible for the addresses of the LED's. There must be one long line from the first LED to the last one, without any serial connections in it. As this line is digital with a very low power, I have not recognized problems with that line for being too long.
When you have a little problem to get all your RGB LED's exactly the same color, I'll suggest to do the calibration with the final light hood, to correct the warmth or cold of the light and set the average color to your desired value. And off course it's also possible this way to correct deviations in color because something in the light hood is reflecting your light with a slightly different color. The only problem can be that this calibration program uses the serial line of the Arduino for feedback and input, so during calibration there must be a device with an Arduino EDI be connected to it.
By the way, this kind of calibration is necessary to let the Arduino convert Kelvin colors to RGB-values needed for the LED's. If you want to use the program by only entering RGB codes (which is also possible, because colors like "blue moonlight" cannot be expressed in Kelvin), calibrating is not necessary. The final program only uses the calibration data when translating Kelvin.
The calibration program:
//LED calibration //https://www.2muchtime.org #include <Adafruit_NeoPixel.h> //<-- 2812 #define PIN 6 //<-- 2812 Adafruit_NeoPixel strip = Adafruit_NeoPixel(300, PIN, NEO_GRB + NEO_KHZ800); //<-- 2812 int pixels = 300; int red = 200; int green = 200; int blue = 200; void setup() { Serial.begin(9600); strip.begin(); //<-- 2812 strip.show(); //<-- 2812 Serial.println ("RGB LED calibration"); Serial.println ("To change a color, send it with your serial monitor."); Serial.println ("For example, R181 changes the intensity of red to 181 (values between 0 - 255)"); } void loop() { for (int i = 0; i <= pixels; i++){ strip.setPixelColor(i,strip.Color(red, green, blue)); //<-- 2812 } strip.show(); //<-- 2812 Serial.println ("The current color is:"); Serial.println ("Red: " + String(red) ); Serial.println ("Green: " + String(green)); Serial.println ("Blue: " + String(blue)); boolean waitForInput = true; while (waitForInput) { if (Serial.available()){ waitForInput = false; } } delay(100); char c = Serial.read(); int h = Serial.read() - 48; int t = Serial.read() - 48; int e = Serial.read() - 48; Serial.read(); Serial.read(); //Takes the last 2 characters (\r\n) of the input out the buffer if (c == 'R' || c == 'r'){ red = (h * 100) + (t * 10) + e;
} if (c== 'G' || c == 'g'){ green = (h * 100) + (t * 10) + e; } if (c == 'B' || c == 'b'){ blue = (h * 100) + (t * 10) + e; } }
Download the Daylight simulator
All lines above marked with a //<--2812, are especially meant for the usage with the Adafruit Neopixel library. (It has to be installed!). If you use another way of controlling your LED's, skip that rules and replace them with code for your situation.
When the program runs, it uses the serial line to communicate. It tells you the current color, and you can pass information using the serial line to your Arduino, to change the color. All commands exist of 4 characters: you start with an R, G or B to tell which color you want to change, with thereafter a value of 3 digits! (use leading zero's! the value of 7 is typed as 007). After sending the command, you'll see the color of the light change immediately, and on your serial monitor the new values of R, G and B are shown.
Just enter values until you are satisfied with the neutral color of white, but also with the brightness. Depending on your LED's, it is possible that your amount of light is too bright. For my situation and LED's, I came to a neutral color of white with the next setting:
The final program is meant to be used with a timer-clock for daily turn on and off. At night time, the Arduino is unpowered. At startup -and the Arduino has no sense of time- it begins to reach the destination-color of block 1.
The program uses 48 blocks, and every block is in the regular situation half an hour. Theoretically you can program 24 hours, but as the program is not accurate with time, it does not work to leave it powered. (The cycle will start over again, by the way. After block 48 the program returns to block one.) So, 48 blocks is the maximum, and for a normal daylight-cycle you won't need them all. Decide the length of time for your cycle, and let the timer-clock turn off the power a little later.
The blocks are visible in the program, and can be adjusted to your own fish tank:
if (block == 1) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 20000; brightness = 25; }
if (block == 2) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 18000; brightness = 51; }
if (block == 3) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 16000; brightness = 76; }
if (block == 4) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 14000; brightness = 102; }
if (block == 5) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 12000; brightness = 128; }
if (block == 6) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 10000; brightness = 153; }
if (block == 7) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 8000; brightness = 178; }
if (block == 8) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 7000; brightness = 204; }
if (block == 9) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6800; brightness = 230; }
if (block == 10) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6600; brightness = 255; }
if (block == 11) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6600; brightness = 255; }
if (block == 12) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6600; brightness = 255; }
if (block == 13) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6600; brightness = 255; }
if (block == 14) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6600; brightness = 255; }
if (block == 15) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6500; brightness = 255; }
if (block == 16) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6400; brightness = 255; }
if (block == 17) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 6200; brightness = 255; }
if (block == 18) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 5000; brightness = 255; }
if (block == 19) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 4000; brightness = 255; }
if (block == 20) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 2400; brightness = 255; }
if (block == 21) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 1800; brightness = 191; }
if (block == 22) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 1400; brightness = 128; }
if (block == 23) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 1000; brightness = 64; }
if (block == 24) { newRed = 0; newGrn = 3; newBlu= 15; kelvin = 0; brightness = 0; }
if (block == 25) { newRed = 0; newGrn = 2; newBlu= 12; kelvin = 0; brightness = 0; }
if (block == 26) { newRed = 0; newGrn = 0; newBlu= 10; kelvin = 0; brightness = 0; }
if (block == 27) { newRed = 0; newGrn = 0; newBlu= 7; kelvin = 0; brightness = 0; }
if (block == 28) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 29) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 30) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 31) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 32) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 33) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 34) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 35) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 36) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 37) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 38) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 39) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
if (block == 40) { newRed = 0; newGrn = 0; newBlu= 0; kelvin = 0; brightness = 0; }
If you fill out a kelvin value and brightness, it will replace the given newRed, newGrn and newBlu with the calculated (and calibrated) colors, taking note of the brightness. A brightness of zero causes all colors set to dark. On the other hand: as you can see with my moonlight in block 24-27, setting Kelvin to zero let the program use the red, green and blue from the same block. Those values will not be calibrated, the program uses the RGB colors you tell.
The given colors are interpreted as the destination color of that block. During the time of a block (normally half an hour), it will change the color equably from the color at the start of the block to the block-destination. For the first block, the start color is black (R:0, G:0, B:0). During the first block, the light slowly turns on and at the last moment of that block, the destination color is reached.
So make sure your timer runs one block longer that the last block with a value. In my example: block 27 is the last moonlight block. At the end of block 27, the lights are a faint color of blue. But at the end of block 28, the entire darkness is reached. Therefore, let your Arduino run for (used blocks + 1) x half an hour. So my program runs in 14 hours.
Just a few lines above the blocks, you will find the calibration-data:
//Led calibration
//Use these to calibrate your leds, if you're not satisfied with the color white or to lower the max brightnes.
//Use values between 0-255. All the values in the kelvinscale will be recalculated with this values.
//Set each to 255 to not affect the values below.
setWhitePointRed = 240;
setWhitePointGrn = 181;
setWhitePointBlu = 90;
Here you can enter the discovered value of neutral white light. (See page before)
To change the duration of a block, modify the blocktime var. It is set at 9000. On a normal base, the program uses timeticks of 0,2 sec, so 9.000 is equal to half an hour.
You can download the program below, wire everything up as written in "My Setup", but some adjustments are necessary:
(*) Look in the program for the line below, and correct the address:
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
Download the Daylight simulator