Bird cage LED daylight simulation system (9 / 10 steg)
Steg 9: resultat
Installation av lamporna var lite av en smärta, eftersom samtliga burar behövs för att vara försedd med LED-moduler och ledningar, och ledningarna av samtliga 14 burar hade för fint kopplas till den kontrollerande enheten... Men efter en dags arbete, och en hel del löda fåglarna kunde flyttas till sina nyligen upplysta burar!
Detta var ca 3 månader sedan. Och jag är glad att säga att systemet har fungerat utan problem! I under tiden fåglarna har börjat avel -> vilket innebär att de är faktiskt nöjd med belysning :)
Så: om du gillar detta instructable, har frågor eller kommentarer: Låt mig veta vad du tycker!
Om jag misslyckades med att kredit någon: detta var oavsiktlig. så låt mig veta!
Och ha kul att skapa!
Patrick
Den fullständiga koden för fågel belysningssystemet (även levereras som bifogad fil)
/ * BirdLight
Dagtid simulering för fågelburar
Hårdvara: Arduino + I2C 16 x 4 LCD + SPI DS1302 + BD509 transistorer
Använder en logaritmisk 12 bitars LUT för att försiktigt öka / minska ljusstyrka under
Dag och natt till dag övergångar.
Copyright 2013 - Patrick Bronneberg
Denna skiss är fri programvara; Du kan vidaredistribuera det och/eller
ändra den enligt villkoren i den GNU Lesser allmänna offentliga
Licens som offentliggörs av Free Software Foundation; antingen
version 2.1 av licensen, eller (vid ditt alternativ) någon senare version.
Denna skiss är fördelad i hopp om att det kommer att vara användbar,
men utan garantier; utan att ens underförstådd garanti om
SÄLJBARHET eller lämplighet för ett visst ändamål. Se GNU
Lesser General Public License för mer details.* /
/ *---(Import behövs bibliotek)---* /
#include < wire.h >
#include < lcd.h >
#include
< Liquidcrystal_i2c.h > / / F Malpartida NewLiquidCrystal bibliotek
#include < ds1302.h >
#include < softtimer.h >
#include < softpwmtask.h >
#include
< pcimanager.h >< /pcimanager.h >< /softpwmtask.h >< /softtimer.h >< /ds1302.h >< /liquidcrystal_i2c.h >< /lcd.h >< /wire.h >< /p >< p > / *---(konfiguration)---* /
CONST double Night_Level = 5.0;
CONST double Day_Level = 99,0;
CONST unsigned int Day_Start_Hour = 7.
CONST unsigned int Day_Start_Min = 0;
CONST unsigned int Day_End_Hour = 21;
CONST unsigned int Day_End_Min = 40; < /p >< p > / *---(deklarera konstanter)---* /
#define av 0
#define på 1
#define RTC_MULTIPLIER 4 / / 4 förändringar fick för varje steg på kodaren < /p >< p > #define LCD_I2C_ADDR 0x27 / / definiera I2C adress för PCF8574A
#define LCD_BACKLIGHT_PIN 3 / / PIN-koden ska användas för att styra LCD bakgrundsbelysning (från i2c expander) < /p >< p > const int LED_PWM_PIN = 9; PIN-koden som PWM lamporna är kopplade till
#define LEDValue OCR1A / / Använd 12 bitars timer1 för PWM ljusreglering < /p >< p > const int PWMMax = 4095; Ställ in maximal ljusstyrka för PWM
Definiera en logaritmisk LUT för PWM ljusreglering
CONST int PWMLut [] = {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,9,9,9,10,11,
13,15,16,17,19,21,23,25,26,27,29,31,32,33,35,37,39,41,43,45,47,49,51,53,55,57,
60,63,66,69,71,74,77,80,84,88,91,94,98,102,106,110,114,118,123,128,133,138,143,
148,154,160,166,172,179,185,192,199,207,214,222,230,239,248,257,266,276,286,296,
306,317,329,341,353,366,379,392,406,421,436,451,466,483,500,518,536,555,574,595,
616,638,661,684,707,732,757,784,811,840,869,900,931,964,997,1032,1067,1105,1144,
1184,1224,1267,1311,1357,1404,1453,1503,1555,1609,1665,1722,1782,1843,1907,1973,
2042,2112,2185,2260,2339,2419,2503,2589,2679,2771,2867,2965,3069,3174,3284,3397,
3514,3629,3761,3905,4024,4079,4094}.
Definiera storleken på lut: Observera att heltal 16bits så 2 byte
CONST int lutSize = sizeof (PWMLut) / 2; < /p >< p > / *---(Declare staten enum)---* /
#define STARTUP_STATE 1
#define CONFIGURATION_STATE 2
#define DAY_STATE 3
#define NIGHT_STATE 4
#define DAY_NIGHT_TRANSITION 5
#define NIGHT_DAY_TRANSITION 6 < /p >< p > / *---(deklarera objekt)---* /
LiquidCrystal_I2C lcd(LCD_I2C_ADDR,2,1,0,4,5,6,7);
DS1302 rtc (3, 4, 5); Realtidsklocka på stift 3,4,5 (SPI) < /p >< p > / / 20 minuter, 70% övergång, 168 LUT steg -> (20 * 60 * 1000) / (0,7 * 168)
Uppgift dayToNightTask (10000, dayToNightTransition);
Uppgift nightToDayTask (10000, nightToDayTransition);
Uppgift defaultDisplayTask (10000, displayDefault);
Uppgift timerTask (20000, checkTimer);
Uppgift displayTask (30000, bildskärm).
Uppgift backlightTask (30000, toggleBacklight);
Uppgift startupTask (10000, startades);
Uppgift configurationTask (200, konfiguration); < /p >< p > / *---(förklarar globala variabler)---* /
int ledBrightnessLevel = 0;
booleska isBacklightEnabled = false;
booleska isConfigDisplayed = false;
booleska startupCalled = false;
int currentState = 0;
int dayLevel = 0;
int nightLevel = 0;
int lastPosition = 0;
int sleepRuns = 0; < /p >< p > void setup()
{
Initiera LED PWM
pinMode(LED_PWM_PIN,OUTPUT);
TCCR1A = (1 << COM1A1) | (1 << WGM11); Aktivera snabb PWM på OC1A (Pin 9)
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10); Läge 14 snabb PWM / (TOP = ICR1), före skala = 1
ICR1 = PWMMax; Som det bästa värdet för 12-bitars PWM
Ställa in klockan till run-läge och inaktivera skrivskydd
RTC.halt(false);
rtc.writeProtect(false);
Följande rader kan kommenteras ut för att använda värden redan lagrade i DS1302
rtc.setDOW(SATURDAY); Ange dagen av veckan (ENUM kapital engelska fullständigt namn av dagen)
rtc.setTime (16, 12, 0); Ställa in tiden (24hr format)
rtc.setDate (4, 1, 2014); Ange datum dd mm åååå
LCD.BEGIN (16,4); initiera lcd
Ställa in bakgrundsljus pin, starta funktionshindrade
lcd.setBacklightPin(LCD_BACKLIGHT_PIN,POSITIVE); < /p >< p > / / nollställa displayen
LCD.Clear();
Beräkna nivåer från konfigurerade procentsatser
dayLevel = LutPercentageToLevel(Day_Level);
nightLevel = LutPercentageToLevel(Night_Level);
Visa aktuell tid
SoftTimer.add(&displayTask);
Start enheten
ChangeState(STARTUP_STATE);
Serial.BEGIN(9600);
Serial.println ("Wim's Vogelparadijs");
} < /p >< p > void ChangeState (int newState)
{
SoftTimer.add(&backlightTask);
Lämna aktuella tillstånd
Switch (currentState)
{
fall STARTUP_STATE:
SoftTimer.remove(&startupTask);
bryta;
fall CONFIGURATION_STATE:
bryta;
fall DAY_STATE:
SoftTimer.remove(&timerTask);
SoftTimer.remove(&defaultDisplayTask);
bryta;
fall NIGHT_STATE:
SoftTimer.remove(&timerTask);
SoftTimer.remove(&defaultDisplayTask);
bryta;
fall DAY_NIGHT_TRANSITION:
SoftTimer.remove(&dayToNightTask);
bryta;
fall NIGHT_DAY_TRANSITION:
SoftTimer.remove(&nightToDayTask);
bryta;
}
Ange ny stat
växel (newState)
{
fall STARTUP_STATE:
SoftTimer.add(&startupTask);
bryta;
fall CONFIGURATION_STATE:
DrawSettingsUI();
bryta;
fall DAY_STATE:
SoftTimer.add(&timerTask);
SoftTimer.add(&defaultDisplayTask);
DrawSettingsUI();
bryta;
fall NIGHT_STATE:
SoftTimer.add(&timerTask);
SoftTimer.add(&defaultDisplayTask);
bryta;
fall DAY_NIGHT_TRANSITION:
ledBrightnessLevel = dayLevel;
SoftTimer.add(&dayToNightTask);
bryta;
fall NIGHT_DAY_TRANSITION:
ledBrightnessLevel = nightLevel;
SoftTimer.add(&nightToDayTask);
bryta;
}
Spara aktuella tillstånd
currentState = newState;
} < /p >< p > dubbel LutLevelToPercentage (int lutLevel)
{
återgå lutLevel * 100,0 / lutSize;
} < /p >< p > int LutPercentageToLevel (dubbel lutPercentage)
{
avkastning (int)((lutSize/100.0)*lutPercentage);
} < /p >< p > void display(Task* me)
{
lcd.setCursor(1,0); Börja med tecknet 0 på rad 0
LCD.Print(RTC.getDateStr(FORMAT_SHORT,FORMAT_LITTLEENDIAN,'/'));
lcd.setCursor(10,0); Börja med tecknet 0 på rad 0
LCD.Print(RTC.getTimeStr(FORMAT_SHORT));
} < /p >< p > void toggleBacklight(Task* me)
{
om (isBacklightEnabled)
{
lcd.setBacklight(OFF);
isBacklightEnabled = false;
Ta bort aktiviteten efter att ha kört en gång
SoftTimer.remove(me);
}
annat
{
lcd.setBacklight(ON);
isBacklightEnabled = sant;
}
} < /p >< p > void displayDefault(Task* me)
{
om (isConfigDisplayed)
{
DrawDayNightUI();
isConfigDisplayed = false;
}
annat
{
DrawSettingsUI();
isConfigDisplayed = sant;
}
} < /p >< p > void checkTimer(Task* me)
{
Tid tid = rtc.getTime();
int currentLevel = 0;
Switch (currentState)
{
fall DAY_STATE:
currentLevel = dayLevel;
om (time.hour == Day_End_Hour & & time.min == Day_End_Min)
{
Börja minska ljusstyrka
ChangeState(DAY_NIGHT_TRANSITION);
}
bryta;
fall NIGHT_STATE:
currentLevel = nightLevel;
om (time.hour == Day_Start_Hour & & time.min == Day_Start_Min)
{
Börja öka ljusstyrka
ChangeState(NIGHT_DAY_TRANSITION);
}
bryta;
}
Ställa in nuvarande ljusstyrkan på lysdioderna
analogWrite (LED_PWM_PIN, PWMLut[currentLevel]);
} < /p >< p > void DrawSettingsUI()
{
LCD.Home();
Skriva ut vår meny på LCD
lcd.setCursor(0,1); Börja med tecknet 0 på linje 1
LCD.Print ("DAG--NACHT");
char timerString [20].
sprintf (timerString, "% 02d: % 02d || %0 2D:% 02d ", Day_Start_Hour, Day_Start_Min, Day_End_Hour, Day_End_Min);
lcd.setCursor(0,2); Börja med tecknet 0 på linje 1
LCD.Print(timerString);
char levelString [20].
sprintf (levelString, "% 02d %% || %0 2D %% ", (int) Day_Level, (int) Night_Level);
lcd.setCursor(0,3); Börja med tecknet 0 på linje 1
LCD.Print(levelString);
} < /p >< p > void DrawDayNightUI()
{
Skriva ut ljusreglering informationen på lcd
lcd.setCursor(0,1); Börja med tecknet 0 på linje 1
LCD.Print ("---STATUS---");
lcd.setCursor(0,2); Börja med tecknet 0 på linje 2
int ljusstyrka = 0;
Switch (currentState)
{
fall DAY_STATE:
LCD.Print ("MODUS: DAG");
ljusstyrka = Day_Level;
bryta;
fall NIGHT_STATE:
LCD.Print ("MODUS: NACHT");
ljusstyrka = Night_Level;
bryta;
}
lcd.setCursor(0,3); Börja med tecknet 0 på linje 3
char levelString [17].
sprintf (levelString, "Intensiteit: % 02d %%", ljusstyrka);
LCD.Print(levelString);
} < /p >< p > void DrawDimmingUI (int nivå)
{
int ljusstyrka = (int)LutLevelToPercentage(level);
Skriva ut ljusreglering informationen på lcd
lcd.setCursor(0,1); Börja med tecknet 0 på linje 1
LCD.Print ("---DIMMEN---");
lcd.setCursor(0,2); Börja med tecknet 0 på linje 2
LCD.Print("");
lcd.setCursor(0,3); Börja med tecknet 0 på linje 3
char levelString [17].
sprintf (levelString, "Intensiteit: % 02d %%", ljusstyrka);
LCD.Print(levelString);
} < /p >< p > void DrawStartupUI()
{
Skriva ut ljusreglering informationen på lcd
lcd.setCursor(0,1); Börja med tecknet 0 på linje 1
LCD.Print ("Wim's");
lcd.setCursor(0,2); Börja med tecknet 0 på linje 2
LCD.Print ("Vogelparadijs");
lcd.setCursor(0,3); Börja med tecknet 0 på linje 3
LCD.Print ("Versie: v1.0b");
} < /p >< p > boolean CheckIsDay()
{
Om kallas för andra gången, transit till rätt staten
Tid tid = rtc.getTime();
om ((time.hour > Day_Start_Hour & & time.hour < Day_End_Hour) ||
(time.hour == Day_Start_Hour & & time.min > = Day_Start_Min) ||
(time.hour == Day_End_Hour & & time.min < Day_End_Min))
{
return true;
}
{
returnera false;
}
} < /p >< p > void startup(Task* me)
{
om (startupCalled)
{
Om kallas för andra gången, transit till rätt staten
Tid tid = rtc.getTime();
om (CheckIsDay())
{
ChangeState(DAY_STATE);
}
annat
{
ChangeState(NIGHT_STATE);
}
}
annat
{
startupCalled = sant;
DrawStartupUI();
}
} < /p >< p > void dayToNightTransition(Task* me)
{
Boolean klar = ChangeLedBrightness (nightLevel, -1);
om (avslutat)
{
ChangeState(NIGHT_STATE);
}
} < /p >< p > void nightToDayTransition(Task* me)
{
Boolean klar = ChangeLedBrightness (dayLevel, 1);
om (avslutat)
{
ChangeState(DAY_STATE);
}
} < /p >< p > boolean ChangeLedBrightness (int finishedLevel, int ledFadeAmount)
{
DrawDimmingUI(ledBrightnessLevel);
den nuvarande ljusstyrkan
analogWrite (LED_PWM_PIN, PWMLut[ledBrightnessLevel]); < /p >< p > / / ändra ljusstyrkan för nästa gång genom öglan:
ledBrightnessLevel = ledBrightnessLevel + ledFadeAmount; < /p >< p > //Check om ljusreglering är slutförd
om ((ledFadeAmount > 0 & & ledBrightnessLevel > = finishedLevel)
|| (ledFadeAmount < 0 & & ledBrightnessLevel < = finishedLevel))
{
Klar!
return true;
}
Ännu inte klar
returnera false;
} < /p >