Är lite osäker på vad som menas med map funktionen tyvärr. Använder Jason's sketch som finns publicerad på reefcentral (länk). Efter en del modifering så ser min sketch ut så här: // Natural Reef Aquarium Lighting V2.5.6 // 30/11/2013 // Developed by J. Harp (nUm - RTAW Forums, Numlock10 - Reef Central Forums) // Formulas based off of information from NOAA website for sunrise / sunset times. // Includes Lunar Simulation. // Compiled in Arduino 1.5.2 // // Testing; // Moon Correction (was inverted) // Will not calculate string values if Channel count is 0 to save on processor time // Float Map for moonlight with corrected formula // // Future Development: // Weather Simulation // // Please feel free to use this and modify as you see fit, if you have any comments or suggestions please let me know via messages on the forums listed above. // #include <math.h> #include <Wire.h> #define DS1307_I2C_ADDRESS 0x68 // RTC variables byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year, psecond; // LED variables (Change to match your needs) byte bluePins[] = { 6 }; // PWM pins for blues byte whitePins[] = { 10, 11 }; // PWM pins for whites byte uvPins[] = { 5, 9 }; // PWM pins for UVs byte moonPins[] = { 3 }; // PWM pins for moonlights byte blueChannels = 1; // how many PWMs for blues (count from above) byte whiteChannels = 2; // how many PWMs for whites (count from above) byte uvChannels = 2; // how many PWMs for uv (count from above) byte moonChannels = 1; // how many PWMs from moon (count from above) byte BluePWMHigh[] = { 255 }; // High value for Blue PWM each vale is for each string - if your values are noraml this is 255, if your values are inverted this is 0 byte BluePWMLow[] = { 0 }; // Low value for Blue PWM - if your values are noraml this is 0, if your values are inverted this is 255 float BlueFull[] = { 25 }; // Value in degrees (sun angle) that each Blue string will be at max output (Larger = more sunlight) byte WhitePWMHigh[] = { 255, 255 }; // High value for White PWM - if your values are noraml this is 255, if your values are inverted this is 0 byte WhitePWMLow[] = { 0, 0 }; // Low value for White PWM - if your values are noraml this is 0, if your values are inverted this is 255 float WhiteFull[] = { 37.5, 37.5 }; // Value in degrees (sun angle) that each White string will be at max output (Larger = more sunlight) byte UVPWMHigh[] = { 255, 255 }; // High value for UV PWM - if your values are noraml this is 255, if your values are inverted this is 0 byte UVPWMLow[] = { 0, 0 }; // Low value for UV PWM - if your values are noraml this is 0, if your values are inverted this is 255 float UVFull[] = { 30, 30 }; // Value in degrees (sun angle) that each UV string will be at max output (Larger = more sunlight) byte MoonPWMHigh[] = { 20 }; // High value for Moon PWM - if your values are noraml this is 255, if your values are inverted this is 0 byte MoonPWMLow[] = { 0 }; // Low value for Moon PWM - if your values are noraml this is 0, if your values are inverted this is 255 // Set for the location of the world you want to replicate. float latitude = -17.730211; // + to N Defualt - (-19.770621) Heart Reef, Great Barrier Reef, QLD, Australia float longitude = 177.127218; // + to E Defualt - (149.238532) int TimeZone = 12; // + to E Defulat - (10) // Sunlight Variables int delayTime = -150; // start time delay in minutes, - will push the day back, + will bring the day forward float floatMap(float x, float in_min, float in_max, int out_min, int out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } int SunLight(byte _ledPin, byte _ledHigh, byte _ledLow, float _fullSun, byte _year, byte _month, byte _day, byte _hour, byte _min, byte _sec) { float a = floor((14.0 - _month) / 12.0); float y = _year + 4800.0 - a; float m = _month + (12.0 * a) - 3.0; float AH; int result; float JC = (((_day + floor(((153.0 * m) + 2.0) / 5.0) + (365.0 * y) + floor(y / 4.0) - floor(y / 100.0) + floor(y / 400.0) - 32045.0) + ((_hour / 24.0) + (_min / 1444.0) + (_sec / 86400.0))) - 2451556.08) / 36525.0; float GMLS = fmod(280.46646 + JC*(36000.76983 + JC * 0.0003032), 360.0); float GMAS = 357.52911 + JC * (35999.05029 - 0.0001537 * JC); float EEO = 0.016708634 - JC * (0.000042037 + 0.0000001267 * JC); float SEoC = sin((GMAS * M_PI) / 180.0)*(1.914602 - JC * (0.004817 + 0.000014 * JC)) + sin(((2.0 * GMAS) * M_PI) / 180.0) * (0.019993 - 0.000101 * JC) + sin(((3.0 * JC) * M_PI) / 180.0) * 0.000289; float STL = GMLS + SEoC; float STA = GMAS + SEoC; float SRV = (1.000001018 * (1.0 - EEO * EEO)) / (1.0 + EEO * cos((STA * M_PI) / 180.0)); float SAL = STL - 0.00569 - 0.00478 * sin(((125.04 - 1934.136 * JC) * M_PI) / 180.0); float MOE = 23.0 + (26.0 + ((21.448 - JC * (46.815 + JC * (0.00059 - JC * 0.001813)))) / 60.0) / 60.0; float OC = MOE + 0.00256 * cos(((215.04 - 1934.136 * JC) * M_PI) / 180.0); float SD = (asin(sin((OC * M_PI) / 180.0) * sin((SAL * M_PI) / 180.0))) * (180.0 / M_PI); float vy = tan(((OC / 2.0) * M_PI) / 180.0) * tan(((OC / 2.0) * M_PI) / 180.0); float EQoT = (4.0 * (vy * (sin(2.0 * ((GMLS * M_PI) / 180.0)) - 2.0 * EEO * sin((GMAS * M_PI) / 180.0) + 4.0 * EEO * vy * sin((GMAS * M_PI) / 180.0) * cos(2.0 * ((GMLS * M_PI) / 180.0)) - 0.5 * vy * vy * sin(4.0 * ((GMLS * M_PI) / 180.0)) - 1.25 * EEO * EEO * sin(2 * ((GMAS * M_PI) / 180))))) * (180 / M_PI); float HAS = acos(cos((90.833 * M_PI) / 180.0) / (cos((latitude * M_PI) / 180.0) * cos((SD * M_PI) / 180.0)) - tan((latitude * M_PI) / 180.0) * tan((SD * M_PI) / 180.0)) * (180.0 / M_PI); float SN = (720.0 - 4.0 * longitude - EQoT + TimeZone * 60.0); float SR = SN - HAS * 4.0; float SS = SN + HAS * 4.0; float STD = 8.0 * HAS; float TST = fmod((((_hour)+(_min / 60.0) + (_sec / 3600.0)) / 24.0) * 1440.0 + EQoT + 4.0 * longitude - 60.0 * TimeZone, 1440.0) + delayTime; if (TST / 4 < 0.0) { AH = ((TST / 4.0) + 180.0); } else { AH = ((TST / 4.0) - 180.0); } float SZA = (acos(sin((latitude * M_PI) / 180.0) * sin((SD * M_PI) / 180.0) + cos((latitude * M_PI) / 180.0) * cos((SD * M_PI) / 180.0) * cos((AH * M_PI) / 180.0))) * (180.0 / M_PI); float SEA = 90.0 - SZA; if (SEA <= 0.0) { result = _ledLow; } if (SEA > 0.0 && SEA < _fullSun) { result = map(SEA, 0, _fullSun, _ledLow, _ledHigh); } if (SEA >= _fullSun) { result = _ledHigh; } analogWrite(_ledPin, result); return result; } int MoonLight(byte _ledPin, byte _ledHigh, byte _ledLow, byte _year, byte _month, byte _day, byte _hour, byte _min, byte _sec) { int result; float a = floor((14.0 - _month) / 12.0); float y = _year + 4800.0 - a; float m = _month + (12.0 * a) - 3.0; float mJDN = ((_day + ((153.0 * m + 2.0) / 5.0) + (365.0 * y) + (y / 4.0) - ( y / 100.0) + (y / 400.0) - 32045.0) + 730483.71); float mJDR = (_hour / 24.0) + (_min / 1444.0) + (_sec / 86400.0); float mJD = mJDN + mJDR; float moon = fmod((mJD - 2456318.69458333), 29.530589); if (moon <= 14.7652945) { result = floatMap(moon, 0.0, 14.7652945, _ledHigh, _ledLow); } if (moon >= 14.7652946) { result = floatMap(moon, 14.7652946, 29.530589, _ledLow, _ledHigh); } analogWrite(_ledPin, result); return result; } /***** RTC Functions *******/ /***************************/ // Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) { return ((val / 10 * 16) + (val % 10)); } // Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return ((val / 16 * 10) + (val % 16)); } // Gets the date and time from the ds1307 void getDateDs1307(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write(0); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 7); *second = bcdToDec(Wire.read() & 0x7f); *minute = bcdToDec(Wire.read()); *hour = bcdToDec(Wire.read() & 0x3f); *dayOfWeek = bcdToDec(Wire.read()); *dayOfMonth = bcdToDec(Wire.read()); *month = bcdToDec(Wire.read()); *year = bcdToDec(Wire.read()); } void setup() { delay(500); Serial.begin(57600); Wire.begin(); } void loop() { getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year); if (psecond != second){ psecond = second; Serial.print(rtcHrs); Serial.print(":"); Serial.print(rtcMins); Serial.print(":"); Serial.print(second); Serial.print(" "); Serial.print(dayOfMonth); Serial.print("/"); Serial.print(month); Serial.print("/"); Serial.println(year); update_leds(); } } void update_leds(){ int i; byte value; if (blueChannels > 0){ Serial.println("Blue LED's"); for (i = 0; i < blueChannels; i++) { value = SunLight(bluePins[i], BluePWMHigh[i], BluePWMLow[i], BlueFull[i], year, month, dayOfMonth, rtcHrs, rtcMins, second); Serial.print(map(value, BluePWMLow[i], BluePWMHigh[i], 0, 100)); Serial.print("% "); } Serial.println(); } if (whiteChannels > 0){ Serial.println("White LED's"); for (i = 0; i < whiteChannels; i++) { value = SunLight(whitePins[i], WhitePWMHigh[i], WhitePWMLow[i], WhiteFull[i], year, month, dayOfMonth, rtcHrs, rtcMins, second); Serial.print(map(value, WhitePWMLow[i], WhitePWMHigh[i], 0, 100)); Serial.print("% "); } Serial.println(); } if (uvChannels > 0){ Serial.println("UV LED's"); for (i = 0; i < uvChannels; i++) { value = SunLight(uvPins[i], UVPWMHigh[i], UVPWMLow[i], UVFull[i], year, month, dayOfMonth, rtcHrs, rtcMins, second); Serial.print(map(value, UVPWMLow[i], UVPWMHigh[i], 0, 100)); Serial.print("% "); } Serial.println(); } if (moonChannels > 0){ Serial.println("Moon Value"); for (i = 0; i < moonChannels; i++) { value = MoonLight(moonPins[i], MoonPWMHigh[i], MoonPWMLow[i], year, month, dayOfMonth, rtcHrs, rtcMins, second); Serial.print(map(value, MoonPWMLow[i], MoonPWMHigh[i], 0, 100)); Serial.print("% "); } Serial.println(); } } Jag har idag satt ner max till 20 och kommer att nöja mig med detta. Stilo's sketch verkar dock väldigt intressant. Dock så saknar jag där möjligheten att följa solens årscykel. Jag har idag min satt så att den följer Fiji's soluppgångar/nedgångar (hela året). Mvh Patrik