~ 30 Jan 2012, 03:53
Take a programmer, add some electronics, and a poor houseplant. What would you get?
Or, "Gardening meets Programming, ver. 2.0".
As the previous attempt to make the poinsettia blossom didn't succeed, it was time to approach it more gently.
First, let me tell you (in my defence) that it isn't just me who's messing with the poor plant. Its development basically halted long ago, and its stealthy attempts to slip through a little new leaf or appendage would be faced with inevitable trimming, as my mother would trim it anytime she sees anything above the 20cm height-line. You know, riots need to be put down as early as possible :)
However, this summer I changed places, and the flower was now within my guardianship, so I let it grow. And gosh, it did :)
Well, that meant that the Thing's black box had to be upgraded. I also had some difficulty installing the crane in the new appartment.
In the end, I followed another approach: let's just keep the flower in shade, and illuminate it by other means, 10 hours a day.
1. I needed to provide a light source, which would be suitable for photosynthesis. Luckily, NASA had already researched that (f.e.), and they recommend using LEDs for that purpose, for efficiency and resource reasons. LEDs produce very little heat, thus the lighting won't incur any additional evaporation. The optimal light color is also known, this patent recommends red, orange and blue LEDs, in proportions of 12:6:1.
2. I bought some ultra-bright LEDs. Calculating the actual number of LEDs turned out to be a fairly complex deal, as one gets quickly submerged in the miriad of photometric units: lumens, lux, candelas, Watts per steradian... After double-checking my calculations with some other people, I placed 17 red, 8 yellow and two blue LEDs, each having 10000mcd of brightness. The aimed for around 2000 lux at peak, which was achieved (as checked with a dSLR-used-as-a-light-meter).
3. I prototyped on a breadboard:
4. And later moved it on a perfboard:
5. I analized some graphs of the sun's brightness when measured around sunrise. The light intensity shoots up no less than 1000 times (more like 10k in fact). I did some PWM to implement smooth "warming" of my artificial sun (see the video below). I only managed getting ~1000:1 contrast, and the initial part of the "sunrise" sequence is a bit buggy. I also programmed the yellow diodes to be lagging 20 minutes behind the red ones, and similarly for the blue ones, which are offset by an hour. The intent of this was simulating the different light color of the sun around sunrise/sunset. Not very convincing though, to be fair.
6. I cannibalized an old lamp:
and got some screws and plates out of a Meccano set:
... and here I ran a test blink on my strange "lamp":
7. Timekeeping is done with a specialized date/time chip - DS132 - and a quartz resonator. The sunrise/sunset times are correct year-round; they correspond to the actual times in San Antonio, Texas (used this one-year online calculator). These could be calculated algorithmically, but since the PIC is not exactly fit for floating-point math, sines/cosines, etc., I found it better to keep all the sunrise/sunset data in a static array, in a delta-compressed manner.
DS1302 continues to keep accurate time even after a power failure, as it supports backup power. This would normally be a battery, but I chose to just place a big electrolytic cap, which the DS1302 would charge while the main power is OK:
4700µF is more than enough, it can keep the clock alive for a bit more than a day.
8. Finally, I placed the poinsettia in a dark corner, with the "lamp" hanged around 30 cm above it (there has to be some space between them, as the light beam of these LEDs is quite narrow - so the space is needed to get more even illumination on the whole plant).
Finally, it's time to plug the power adapter in the socket, and the lamp follows the programmed daylight cycle, each day on...
And here's the sunrise, captured on video: Youtube.
The whole thing ("project: Daylight" I call it) wastes around a watt. The LEDs don't heat up at all.
The plant doesn't show signs of impendent blossom. It's been hooked up for around a month and a half now.
If flowers were capable of commiting suicide, this one would've been long gone.
• A whole project written in C. Not a single line of assembly for this one, just C, using the Hi-tech compiler. Well, this time I can't account for every last byte of the memory, but as long as the memory still suffices - it's not a problem¹.
• Inter-chip communication, the DS1302 specifically. What I did could classify as writing a driver, albeit a very simple one. Anyhow, a lot of unknown areas, related to hardware communcation, did clear up to me.
• Thinking photometrically: the lux, lumen, candela, and the geometric meaning of all these.
• Non-volatile memory (EEPROM) in projects like this. The PIC has it built-in, and thanks to that, I realized some kind of a zero-button user interface. I wanted to have two functions available: the normal one, and a test "blinker" function. This would have required either a button, or a DIP-switch. Well, the smarter way to convey our intention to the hardware, using only the On/Off switch can be something like that:
1. Turn the switch On.
2. Quickly turn it off again.
3. Turn it on. If the time between 1) and 2) was less than a second, enter in the test function mode, otherwise continue normally. Here's where the non-volatile memory comes into play. At bootup, the software quickly raises some flag in the EEPROM, and a second later turns it down again (if we're still alive). The next power-up can see whether the flag was cleared and decide accordingly.
• The compiler is your friend. Not long ago, I was a big fan of filling my sources with that cute magic-number arrays, which have been conveniently computed by some throwaway script. Well, I'm now for moving as much as possible inside the C/C++ code, wherever practical. The compiler can compute a lot of things all by himself, at compile time. So, no more magic numbers - but code/macros and the like - which derive the said magic numbers. For example: the DS1302 needs power, otherwise it loses track of time and thinks its Jan 1st, 2000. This may happen when placing it initially, or when moving it to the circuit board, or even by mistake. Well, I could've prepped a special build, which initializes it with the correct date/time, but that would be too hacky, as it doesn't leave a track how the DS1302 was ever initialized in the final code. Instead, one can use the __DATE__/__TIME__ pseudovars, which the C compiler is so nice to provide, and derive the correct dates/times from them. Thus, initialization is just a rapid recompile/program/run succession, and, more importantly, code is easier to maintain.
• MPLabX under Linux. Not the greatest IDE on Earth, but it gets work done.
¹ That kind of thinking is, of course, completely flawed, and leads to abominations. You could end up writing in C# if you stick to it for too long :)
#1 by nickysn, posted on 30 Jan 2012, 16:15
Внимавай само Apple да не решат да те съдят заради 0-бутонния интерфейс ;)