LED till köks-nanot

Vi har ett litet nanokar på 30 liter i köket som än så länge fått hålla till godo med den belysning som följde med. Det är en Aquael Leddy Smart på 6W, jag är dock inte säker på om det är en Sunny eller Plant, det är lite för liten skillnad i färgtemperatur. Den räcker i vilket fall inte till på långa vägar och valet mellan att köpa några till, köpa helt annan belysning eller bygga själv var enkelt. Fram med lödpennan!

Dioder hade jag redan hemma och ebay försedde mig med en kylfläns att limma dem på och en liten väggvårta på 12V/2A för att driva det hela för totalt 150:- inkl frakt och några veckors väntan.

2016-03-12 10.20.17

Det blev fyra kallvita, två royal blue och två röda vilka tillsammans ska ge drygt 35 lumen per liter. Än så länge sitter den lite temporärt med buntband på den gamla belysningen men vi ska ordna något bättre vad det lider. Det ska bli spännande och se om vår Hygrophila polysperma orkar färga ut och visa att den är en Rosanervig!

2016-03-12 10.25.57

Share

Mera lördagspyssel

Det blev lite lödning idag också. När jag ändå hade prylar till det så blev det en nivåvakt som den är tänkt också. Man hänger den helt enkelt på kanten av akvariet och när det börjar bli dags att stänga av vattnet tjuter den ilsket.

DSC_0210

För att enkelt kunna fylla på vatten vill man ha kranen vid akvariet så att man slipper springa fram och tillbaka, i mitt fall dessutom mellan våningarna. Lite prylar från Clas fixade det.

DSC_0212

Nu har jag separata system för att tömma och fylla med lite styrning och kontroll så att man inte behöver passa så mycket. Vattenbytena kommer förhoppningsvis gå både fortare och enklare framöver!

Share

Aktuell LED-status

Vi har numera fyra ramper igång enligt modellen som jag beskrivit här tidigare. Två går i kar med mycket växter (ett sydamerikanskt och ett asiatiskt) och två används för malawi, både huvudkaret och yngelkaret. Alla har numera tre typer av dioder, kallvit (över 10 000K), röd (660 nm) och blå (450 nm) och styr förstås värmaren i respektive kar.

Växtkaren har ca 0,3W/liter och ca 20 lumen/liter vilket passar bra för växter som inte har extrema krav (vi använder inte CO2) när vi har tänt ca 10 timmar per dygn. Malawikaren har ca 0,2W/liter och ca 10 lumen/liter då det inte är mer växter än lite anubias och vallisneria i dem.

Jag är nöjd med både färger och tillväxt på fiskar och växter i karen och nörden i mig gillar att jag kan se temperaturen i karen i vår hallspegel… 🙂

Share

Lördagslödning

DSC_0194

Precis som jag hoppades fick jag tillfälle att dra igång lödpennan. Jag har nu en styrning som slår av pumpen när vattennivån har sjunkit nog mycket. Kretsschemat har jag skamlöst stulit från Vellemans byggsats:

Velleman

Summern är ersatt med ett relä med ett lämpligt motstånd i serie för att få rätt volttal för drivningen av spolen. Konstruktionen är oerhört känslig så sladden på bilden är utbytt mot två ståltrådar som jag kan stoppa ner en bit isär i akvariet. Det visade sig när jag testade att vattnet som hängde kvar på sladden räckte för att reläet skulle dra…

Som du förstår är det jättedumt och totalt förbjudet att hantera 230V på det här sättet!

Hela bygget är ett tankeexperiment som inte finns i verkligheten och som inte ska tas efter. Eller nåt… En slang och en kran hittade jag i mina lådor på vinden så nu är det bara pumpen som saknas för att mitt nya system för vattenbyte ska vara klart.

Share

Vattenbyte

Vi har numera flera akvarium och den sammanlagda vattenvolymen överstiger två kubikmeter. Det innebär att det vattenbyte som ska göras varje vecka (minst i några fall) omfattar runt 750 liter. Även om man har en trädgårdsslang som hävert tar det lite tid… För att snabba upp det hela planerar jag lite olika byggen och ändringar varav det första är en styrning av en pump för att snabbare tömma ur rätt mängd vatten ur de olika karen. I veckan kom det hem lite prylar, i helgen hoppas jag få tid att löda lite!

DSC_0193

Share

Jessie ställer till det

Raspi_Colour_R

Ett år har gått och det är dags för uppdaterade instruktioner, se inlägget Jessie är förlåten.

Häromdagen la mitt SD-kort av i spegeln och den vägrade att starta som den skulle. Sådant händer men då är det bara att installera om, heller hur? Fel. Senaste versionen av Raspbian, Jessie, har ingen Chromium och därför måste man byta webbläsare. Här kommer lite uppdaterade instruktioner för hur jag gjorde.

Installera Raspbian enligt instruktionerna på http://www.raspberrypi.org/. Efter grundinstallationen loggar du in, kör raspi-config och ställer in att den ska starta till Desktop, inloggad som Pi. Passa även på att ställa in rätt inställningar för tidszon, tangentbord mm.

För att allt runt spegeln ska fungera behövs det lite anpassningar och kompletteringar:

1. Installera resterande programvara

sudo apt-get update && apt-get upgrade -y
sudo apt-get install apache2 apache2-doc apache2-utils
sudo apt-get install libapache2-mod-php5 php5 php-pear php5-xcache
sudo apt-get install epiphany-browser
sudo apt-get install xautomation

2. Vrid på skärmen. En spegel har man oftast på högkant, därför måste vi vrida bilden 90 grader. Editera /boot/config.txt och lägg till

gpu_mem=128
display_rotate=1

Avkommentera även raden med hdmi_force_hotplug=1.

3. Editera /home/pi/.config/lxsession/LXDE-pi/autostart och se till att den innehåller

@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
# @xscreensaver -no-splash
@xset s off
@xset -dpms
@xset s noblank
@epiphany-browser http://mirror01
@xte 'sleep 60' 'key F11' -x:0

Epiphany har inget äkta kiosk-läge men med hjälp av xte (ingår i xautomation) skickar jag F11 till den efter en minut vilket sätter den i fullskärm vilket är nästan samma sak. Som du ser har jag döpt min paj till mirror01, har du ett fiffigare namn skriver du in det.

Vädertjänsten, openweathermap.org, har också börjat ställa krav på att man har ett konto för att man ska få hämta väder. Det är fortfarande gratis (om man inte vill hämta ofta) men man behöver en API-nyckel. Den lägger man in i config.js enligt:

// Weather
var weatherParams = {
    'q':'Forshaga,Sweden',
    'units':'metric',
    'lang':lang,
    'cnt':'6',
    'APPID':'DinAPI-Nyckel'
};

Nu ska det bara vara att starta om så ska den visa upp startsidan (om det finns någon) i fullskärm, roterad 90 grader.

Share

Ramp #2

DSC_0013

Nu har det första karet varit igång några veckor och har alla växter och invånare på plats. LED-rampen har nio grupper för dagsljus där varje grupp består av fyra dagsljusdioder (10-12000K) och två djupröda (655-660nm). Normalt har jag sex av grupperna tända vilket verkar ge en lagom balans med tanke på algtillväxten. Jag har dessutom en grupp med sex blå dioder (460-470nm) som är tända som månljus ett par timmar före och efter dagsljuset.

Temperaturbiten har byggts på så att doppvärmaren styrs av ett av reläen. Jag vill hålla 26°C i karet så värmaren slås på när det är 25,94°C och av när det är 26,05°C. Värmarens egen termostat är satt på 27°C så fallerar min styrning blir det antingen rumstemperatur eller 27°C, inget av det är katastrofalt. Naturligtvis får jag ett mail om avvikelsen är för stor.

DSC_0014

Idag fick även det andra karet en ramp av samma modell. Då kar nummer två är tänkt för malawiciklider (jo, det fattas en del inredning) rekommenderade Oceanakvarium ett blåare ljus. Varje grupp för dagsljus består därför av fyra dagsljusdioder (10-12000K), en djupröd (655-660nm) och en blå diod (460-470nm).

Koden har delats upp i två delar, en för ljuset och en för temperaturen:

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import datetime
import syslog
import smtplib
from random import randint
from time import strftime

syslog.syslog('Aqua-light started')

# Definiera tider
moon_on = datetime.datetime(2015, 1, 1, 8, 30)
sunrise_on = datetime.datetime(2015, 1, 1, 10, 30)
noon_on = datetime.datetime(2015, 1, 1, 15, 30)
noon_off = datetime.datetime(2015, 1, 1, 16, 30)
sunset_on = datetime.datetime(2015, 1, 1, 20, 30)
moon_off = datetime.datetime(2015, 1, 1, 23, 30)

# Klasser
class sunClass:
	def __init__(self):
		#2,3,17,5,6,7,8,9,10
		self.sun = [2,17,5,7,8,10]
		self.sunLength = len(self.sun)
		self.noon = [3,6,9]
		self.noonLength = len(self.noon)
	def init(self):
		syslog.syslog('sunClass.init called')
		for x in range (0, self.sunLength):
				GPIO.setup(self.sun[x], GPIO.OUT)
		for x in range (0, self.noonLength):
				GPIO.setup(self.noon[x], GPIO.OUT)
	def off(self):
		syslog.syslog('sunClass.off called')
		for x in range (0, self.sunLength):
			GPIO.output(self.sun[x], LEDOff)
		for x in range (0, self.noonLength):
			GPIO.output(self.noon[x], LEDOff)
	def sunrise(self, runtime):
		syslog.syslog('Sunrise started')
		for x in range (0, self.sunLength):
			GPIO.output(self.sun[x], LEDOn)
			if x == 1: moon.off()
			if x != self.sunLength - 1: time.sleep(runtime/(self.sunLength-1))
		syslog.syslog('Sunrise ended')
	def sunset(self, runtime):
		syslog.syslog('Sunset started')
		for x in range (0, self.sunLength):
			GPIO.output(self.sun[x], LEDOff)
			if x == self.sunLength-2: moon.on()
			if x != self.sunLength - 1: time.sleep(runtime/(self.sunLength-1))
		syslog.syslog('Sunset ended')
	def middag(self, status):
		if (status): syslog.syslog('Noon on')
		else: syslog.syslog('Noon off')
		for x in range (0, self.noonLength):	
			if (status): 
				GPIO.output(self.noon[x], LEDOn)
			else: 
				GPIO.output(self.noon[x], LEDOff) 
	def shadow(self, runtime):
		syslog.syslog('Shadow started')
		for x in range (0, self.sunLength+3):
			if x < self.sunLength: GPIO.output(self.sun[x], LEDOff)
			if x > 2: GPIO.output(self.sun[x - 3], LEDOn)
			time.sleep(runtime / (self.sunLength+3))
		syslog.syslog('Shadow ended')

class moonClass:
	def __init__(self):
		self.moon = 11
	def init(self):
		syslog.syslog('moonClass.init called')
		GPIO.setup(self.moon, GPIO.OUT)
	def off(self):
		syslog.syslog('moonClass.off called')
		GPIO.output(self.moon, LEDOff)	
	def on(self):
		syslog.syslog('moonClass.on called')
		GPIO.output(self.moon, LEDOn)	
		
# Variabler
sun = sunClass()
moon = moonClass()
LEDOn = 0
LEDOff = 1

# Funktioner
			
# Initiera GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
sun.init()
moon.init()
syslog.syslog('GPIO initialized')

# Initiera state
now = datetime.datetime.now()
sun.off()
moon.off()
state = 0
if now.time() > moon_on.time(): state = 1
if now.time() > sunrise_on.time(): state = 2
if now.time() > noon_on.time(): state = 3
if now.time() > noon_off.time(): state = 4
if now.time() > sunset_on.time(): state = 5
if now.time() > moon_off.time(): state = 0
if state == 1 or state == 5:
	moon.on()
elif state <> 0:
	sun.sunrise(0)
if state == 3:
	sun.middag(True)
syslog.syslog('Initial state is %d' % state)

# Huvudloop
while True:
	now = datetime.datetime.now()
	if state == 0:
		# Night mode, wait for morning moon
		if now.time() > moon_on.time() and now.time() < moon_off.time():
			state = 1
			syslog.syslog('Entering state 1')
			moon.on()
	elif state == 1:
		# Morning moon, wait for sunrise
		if now.time() > sunrise_on.time():
			state = 2
			syslog.syslog('Entering state 2')
			sun.sunrise(3600)
	elif state == 2:
		# Daytime, random shadows, wait for noon
		if randint(1, 60) == 1:
			sun.shadow(60)
		if now.time() > noon_on.time():
			state = 3
			syslog.syslog('Entering state 3')
			sun.middag(True)
	elif state == 3:
		# Noon, wait for second daytime
		if now.time() > noon_off.time():
			state = 4
			syslog.syslog('Entering state 4')
			sun.middag(False)
	elif state == 4:
		# Second daytime, random shadows, wait for sunset
		if randint(1, 60) == 1:
			sun.shadow(60)
		if now.time() > sunset_on.time():
			state = 5
			syslog.syslog('Entering state 5')
			sun.sunset(3600)
	elif state == 5:
		# evening moon, wait for night 
		if now.time() > moon_off.time(): 
			state = 0
			syslog.syslog('Entering state 0')
			moon.off()
	time.sleep(60)
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import datetime
import syslog
import smtplib
from time import strftime

syslog.syslog('Aqua-temp started')

# Definiera temperaturgranser
alarmLow = 25.5
alarmHigh = 26.5
tempLow = 25.9
tempHigh = 26.1

# Klasser
		
# Variabler
heatOn = 0
heatOff = 1
heater = 22
tempLarm = False
heatStatus = False

# Funktioner
def sendMail(subject, msg):
	fromaddr = 'Rikard Elofsson <elof@elof.com>'
	toaddr  = 'Rikard Elofsson <elof@elof.com>'
	message = ('From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s' % (fromaddr, toaddr, subject, msg))
	username = 'rikard.elofsson@gmail.com'
	password = 'jättehemligt'

	server = smtplib.SMTP('smtp.gmail.com:587')
	server.starttls()
	server.login(username,password)
	server.sendmail(fromaddr, toaddr, message)
	server.quit()
	syslog.syslog('Mail sent')

def writeTemp(temp):
	tfile = open('/var/www/html/index.html', 'w')
	tfile.write('<html><head>')
	tfile.write('<title>Info f&ouml;r kar 1</title>')
	tfile.write('<META HTTP-EQUIV="refresh" CONTENT="60">')
	tfile.write('</head><body>')
	tfile.write(strftime("%Y-%m-%d %H:%M:%S"))
	tfile.write('<h1>Temperaturen i kar 1 &auml;r '+str(temp)+'&deg;C</h1>')
	tfile.write('<h2>V&auml;rmaren &auml;r ')
	if heatStatus: tfile.write('p&aring;</h2>') 
	else: tfile.write('av</h2>')
	tfile.write('<p><a href="/mrtg/kar1.html">Historik</a>')
	tfile.write('</body></html>')
	tfile.close()
	
def checkTemp():
	global tempLarm
	global heatStatus
	
	tfile = open("/sys/bus/w1/devices/28-0000065bd235/w1_slave", 'r')
	text = tfile.read()
	tfile.close()

	secondline = text.split("\n")[1]
	temperaturedata = secondline.split(" ")[9]
	temperature = float(temperaturedata[2:])
	temperature = float(int((temperature/100)+0.5))/10

	if (temperature < alarmLow or temperature > alarmHigh):
		if not tempLarm:
			syslog.syslog('Temp is wrong')
			sendMail("Temperaturen ar felaktig", "Temperaturen i kar 1 ar nu "+str(temperature))
			tempLarm = True
	else:
		if tempLarm:
			syslog.syslog('Temp is normal again')
			sendMail("Temperaturen ar normal", "Temperaturen i kar 1 ar nu "+str(temperature))
			tempLarm = False

	if (temperature <= tempLow):
		if not heatStatus:
			syslog.syslog('Temp is '+str(temperature)+'. Heater switched on')
			GPIO.output(heater, heatOn)
			heatStatus = True
	if (temperature >= tempHigh):
		if heatStatus:
			syslog.syslog('Temp is '+str(temperature)+'. Heater switched off')
			GPIO.output(heater, heatOff)
			heatStatus = False
	
	writeTemp(temperature)
	
# Initiera GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(heater, GPIO.OUT)
GPIO.output(heater, heatOff)
syslog.syslog('GPIO initialized, heater switched off')

# Huvudloop
while True:
	checkTemp()
	time.sleep(60)
Share

Spegelram

DSC_0001

Igår var vi till Deje trä och köpte lite eklister, idag blev det montering. Det var ju det där med att såga rakt, gera i rätt vinkel och hålla fingrarna borta från spikpistolen också… Nåja, den kom upp på väggen i alla fall:

DSC_0003

Share

Temperatur #2

Skärmklipp

Det som kan mätas ska loggas, därför har jag installerat MRTG på akvariets Raspberry Pi. Med hjälp av följande mrtg.cfg:

######################################################################
# Multi Router Traffic Grapher -- Sample Configuration File
######################################################################
# This file is for use with mrtg-2.5.4c

# Global configuration
WorkDir: /var/www/mrtg
WriteExpires: Yes
RunAsDaemon: Yes
Interval: 5

Title[^]: Temperaturstatistik for 

Title[kar1]: kar 1
PageTop[kar1]: <h1>Temperaturen i kar 1</h1>
Target[kar1]: `/usr/local/bin/aquacontrol/mrtg.py`
MaxBytes[kar1]: 4000
Options[kar1]: growright,gauge,expscale
Factor[kar1]: 0.01
YLegend[kar1]: Temperatur
YTicsFactor[kar1]: 0.01
ShortLegend[kar1]: C
Legend1[kar1]: Temperatur i grader celcius
Legend2[kar1]: 
Legend3[kar1]: Maximal 5 Minute Incoming Traffic
Legend4[kar1]: Maximal 5 Minute Outgoing Traffic
LegendI[kar1]: &nbsp;Temp:
LegendO[kar1]: 

och ett litet pythonskript:

#!/usr/bin/python
from time import strftime

tfile = open("/sys/bus/w1/devices/28-0000065bd235/w1_slave", 'r')
text = tfile.read()
tfile.close()

secondline = text.split("\n")[1]
temperaturedata = secondline.split(" ")[9]
temperature = float(temperaturedata[2:])
temperature = int(temperature / 10)

print(str(temperature))
print("0")
print(strftime("%Y-%m-%d %H:%M:%S"))
print("Temperatur i kar 1")

loggas temperaturen och visas upp i fina grafer för senaste dygnet, veckan, månaden och året.

Share

Spegelglas

DSC_0201

I fredags hämtade jag glasskivan från glasmästaren och idag har jag gjort mina första stapplande steg i den ädla konsten att applicera film på glas. Jag har aldrig varit någon större fan av solskyddsfilm på bilar så det här var premiären med såpvatten, trasor och kreditkort. Blev sådär men jag har gott om film och det är enkelt att göra om.

DSC_0202-e1429462796410-576x1024

Nu börjar man få en känsla för hur det kommer se ut och fungera.

 

Share