Linnunpöntön porttilaskuri

Olen pitänyt pönttökameraa enemmän ja vähemmän aktiivisesti vuodesta 2000 asti. Pöntöt olivat pitkään varustettuja mustavalkoisilla CCD-kameroilla, jotka tuottivat analogista komposiitti-videosignaalia. Laatu on sinänsä ihan ok, kamerat halpoja ja helppoja käyttää. Yövalaistuksesta huolehti infrapunaledit. 

Kameratekniikka on kehittynyt sittemmin niin paljon, että viime syksynä päätin rakentaa kokonaan uuden pöntön kolmella IP-kameralla; kaksi kameraa sisällä ja yksi ulkona. Kuvan laatu parani roimasti, striimaus Youtubeen helpottui, kun kuva oli valmiiksi lähiverkossa, ei tarvinnut enää videosovittimia. 



Tänä kesänä kyseisessä pöntössä oli ensimmäinen pesintä. Pönttökameralla on oma blogi: Pönttökameran päiväkirja. Uudesta pöntöstä voit lukeaa lisää tästä postauksesta.

Pesintää seuratessa tuli mieleen, että olisi mielenkiintoista tietää tarkalleen, kuinka monta kertaa päivässä linnut käyvät pöntössä pesinnän eri vaiheissa. Arvioita voi tehdä videotallenteesta, mutta se on työlästä ja epätarkkaan. Laskenta pitää siis ehdottomasti automatisoida. Helppoa kuin saippua, eikö vain?

Sen piti olla helppoa, tällaisella muutaman euron hintaisella lähestymiskytkimellä


Moduulissa on IR-LED, IR-fototransistori sekä komparaattoriksi kytketty operaatiovahvistin, jonka toimintapiste säädetään trimmerillä. Kun fototransistori havaitsee riittävästi ledin lähettämää heijastunutta valoa, ulostulon tila muuttuu nollasta ykköseksi. Ajatuksena oli irrottaa LED ja fototransistori moduulista ja johdottaa ne siten, että ne voidaan asentaa lentoaukon molemmille puolille, jolloin havaitaan aukosta kulkevan linnun aiheuttama valonsäteen katkeaminen. Mikään ei voisi mennä pieleen.

Alumiiniprofiilista, muovilevystä ja epoksista syntyi kätevästi tällaiset säänkestävät kotelot komponenteille. Profiili varjostaa pahimman auringon valon, mutta on alareunasta avoin, jotta roskia ei pääse kertymään valon tielle.


Nämä sitten johdotettiin kätevästi pöntön etuseinän laudan läpi ja pontissa tällä tavoin.


Kiinnitys seinälautaan ja testaus. Hyvin toimii!
 

Lopuksi lauta takaisin pöntön seinään, LEDin ja fototransistorin kytkentä taloon menevän kaapelin vapaisiin pareihin, Raspberry Pi:n ohjelmointi rekisteröimään kaikki anturin havahtumiset jne.


Asennus toimi edelleen hyvin. Illalla. Seuraavana päivänä se toimi testattessa vähän miten sattui. Sitä seuraavana, aurinkoisena päivänä, kytkin ei toiminut ollenkaan, paitsi fototransistori melkein kokonaan peitettynä. Se paljastui aivan liian herkäksi auringonvalolle eikä ollut sovelias tällaiseen käyttöön.

Takaisin suunnitteluvaiheeseen. Jospa heivaisi operaatiovahvistimoduulin kokonaan, laittaisi Arduinon vilkuttamaan LEDiä ja mittaamaan fototransistorin tuottamaan jännitettä erikseen LED sytytettynä ja sammutettuna ja vertaamaan näitä kahta lukemaa. Auringon valon ei pitäisi haitata, koska nyt mittaamme kirkkauden vaihtelua LEDin vilkutuksen tahdissa. Jos vilkkumista ei havaita, tulkitaan linnun olevan lentoaukossa.

Syntyi tämän näköinen asennelma, jossa on ruuviterminaali LEDille, fototransistorille sekä Raspebby Pi:lle arduinon tarvitsemaa 5V käyttöjännitettä varten sekä IO-pinnille, jota Rasberryssä pyörivä Python-ohjelma tarkkailee.


Arduinon ohjelma laaditaan siten, että otetaan ensin kymmenen mittausta LEDin palaessa ja lasketaan ne yhteen. Sammutetaan LED ja otetaan toiset kymmenen mittausta. Jos näissä summissa ei ole selvää eroa, valonsäde on katkenneena. Oskilloskooppi näytti, että yksi mittausjakso kestää 6,25 msm eli Nano kykenee tekemään 160 jaksoa sekunnissa. 


Varmuuden vuoksi ja häiriöden varalta, jos mittaus havahtuu, tehdään vielä viisi mittausjaksoa, ja jos myös ne kaikki osoittavat valonsäteen katkenneen, annetaan hälytys, jonka Raspberry sitten rekisteriöi. 

Mittaus toimi suunnitellusti, se havahtui kun valonsäde katkesi. Asia kunnossa? Asennus pönttöön ja todennus, toimii!

No aurinko nousi amulla ja pilasi tämänkin idean. Tällä kertaa niin päin, että Auringon paistaessa pöntön etuseinälle, mittaus havahtui ja jäi havahtuneeksi, ikään kuin valonsäde olisi ollut katkaistuna koko ajan. Ei ollut, mutta fototransistori osoittautui niin herkäksi, että se saturoitui päivänvalossa. eikä reahoinut LEDin vilkkumiseen mitenkään. Ei silloinkaan, kun Aurinko ei paistanut suoraan kohti.

Tarvittiin epäherkempi ilmaisin. Valovastus on aivan liian hidas, joten jäljelle jää fotodiodi. Ostetaan muutama sellainen ja kokeillaan. Ostetaan myös muutama IR-led varmuuden vuoksi. Pääkaupunkiseudulla on elektroniikkaliikkeet käyneet vähiin. Nyt kun Bebek lopetti Helsingin liikkeensä ja Yleiselektroniikka lopetti jo aiemmin koko vähittäismyynnin, täällä on enää tasan kaksi: RadioDuo Herttoniemessä ja Partco Vantaalla, josta tällä kertaa löytyi sopivat komponentit.


Nettikaupoista saa tietenkin mitä vain, mutta jos nopeasti haluaa, on kätevää käydä suoraan liikkeestä hakemassa.

Vaihdetaan fototransistorin tilalle fotodiodi. Estosuuntaan kytketyn fotodiodin vuotovirta kasvaa valon voimakkuuden lisääntyessä. Diodille voidaan syöttää virtaa Ardionon 5V ulostulosta ja kytkeä se vastuksen kautta Arduinon maahan. Mittaamalla jännitettä vastuksen yli, saadaan valon voimakkuutta vastaava jännite.

Myötäsuuntaan kytkettäessä fotodiodi toimii kunten valokenno, tuottaen virtaa, jonka voimakkuus muuttuu valon mukana. Virta on pieni, mutta silti mitattavissa.

Kokeillaan kumpaakin kytkentätapaa. Estosuuntaan kytkeminen osoittautui paremmaksi. Diodi osoittautui odotusten mukaisesti epäherkemmäksi kuin transistori, mutta saturoitui silti kirkkaassa auringonpaisteessa. Ei hyvä.

Koska LED toimii jossain määrin fotodiodin tavoin, vähän hullu idea, mutta päätin kokeilla IR-LEDiä ilmaisimena. Yllättäen se osoittautui parhaaksi ilmaiseksi tähän mennessä. Koska LED on tehty tuottamaan valoa eikä ilmaisemaan sitä, se on vielä epäherkempi tässä käytössä kuin fotodiodi. Tuo yllä olevassa kuvassa oleva LED valikoitui siis ilmaisimeksi seuraavassa kokeilussa. LEDin koteloin samoin kuin aiemmin, mutta vähän pidemmällä varjostavalla alumiiniprofiililla, jotta mahdollisimman paljon auringon valoa saadaan blokatuksi pois. 


Tällä kertaa testasin asennuksen perusteellisesti, ennen kuin asensin paikalleen pönttöön. Ulkona pihalla, suorassa auringonpaisteessa. Toimi luotettavasti. Ilmaisin antoi suuremman lukeman aina, kun LED oli päällä. Molemmat lukeman kasvoivat, mitä enemmän auringon valoa ilmaisimeen kohdistui, mutta niiden ero pysyi samana, mikä on erittäin hyvä lähtökohta luotettavan toiminnan varmistamiseksi. Ilmaisin saturoitui vasta, jos sen sai kohdistettua aivan suoraan Aurinkoon, mutta sellaista ei käytännössä tapahdu koskaan, joten nyt tämä anturijärjestely lopultakin oli toimiva.

Alla olevassa kuvassa testauksessa käytetty Arduino-koodi, ja sen tuottama käyrä. Koodi ottaa kymmenen lukemaa ilmaisimelta LEDin palaessa ja toiset kymmenen LEDin ollessa sammutettuna.


Kuvassa näkyvän mittausjakson aikana ilmaisinta on käännetty kohti Aurinkoa, joten taso on noussut. Näillä lukemilla on eroa n. 25. Arduinon 10-bittinen AD-muunnin mittaa 0-5 V antaen lukemia välillä 0-1023, joten jännitteenä 25 on vain n. 0,12 V. Onko se mahdollista siirtää luotettavasti pöntöstä taloon sisälle kulkevassa kaapelissa, n. 10 metrin matkan, jää nähtäväksi.

Päätin vetää uuden kaapelin. Kela Cat-5 -kaapelia lojui nurkissa, se lienee ok. Parikierretyt johtimet eivät ole kovin herkkiä indusoimaan häiriöjännitteitä itseenä. Kokeilin kuitenkin ensin. Kelalla ollessaan kaapeli ilmeisesti indusoi itse itseensä jotain, koska signaaliin tuli piikkejä tuohon yllä olevan kuvan kanttiaallon nurkkiin. Oikaistuna pitkin takapihaa, kaapeli toimi paremmin, piikkejä ei enää esiintynyt. 

Siispä kaapeli välikattoon ja siitä koekäyttöön. Adruino mittasi nyt kaikkea muuta kuin mitä olisi pitänyt. 0,12 V:n signaalista ei löytynyt jälkeäkään. Tilalla oli jotain taajutta, jostain, mahdollisesti välikatossa kulkevista talon sähköjohdoista indusoitunutta 50 Hz:n hurinaa. 

Jäljellä oli kolme vaihtoehtoa:

1. Vaihtaa kaapeli paremmin suojatuun. Ei, en ryömi toista kertaa katossa.

2. Lisätä kaapelin akupäähän vahvistin ja siirtää signaali suuremmalla jännitteellä. Tämä melko varmasti toimisikin, onnistuisi yksinkertaisesti operaatiovahvistimella. Signaali/häiriösuhde muuttuisi sellaiseksi, että signaali tulisi perille. En nyt jaksa väkertää enää vahvistinta, ja jostain pitäisi saada käyttöjännitekin. 5V on turhan vähän. Pitäisi saada 12V, tai vaikka 30V, minkä LM358 muistaakseni kestää. No olisihan kameroiden PoE-jännite ehkä käytettävissä, mutta olkoot.

3. Sijoittaa Arduino pönttöön ja tuoda sisään Arduinon ulostulo, 0-5 V, joka sitten pudotetaan jännitejakajalla Raspberryn vaatimaan tasoon 3,3 V. Periaatteessa halusin Adruinon sisälle, jotta siihen pääsee käsiksi ja sen voisi tarvittaessa ohjelmoita uudelleen käymättä pöntössä räpläämässä. Toisaalta, ohjelmointitarvetta tuskin tulee, ja ulkolämpömittari on osoittanut Arduinon varsin luotettavaksi. Tämä vaihtoehto tuli valituksi.


Tuohon se mahtui hyvin, pöntön konehuoneen takaseinälle. Kolmesta 10 kΩ vastuksesta syntyi kätevästi jännitejakaja, jossa jännite putoaa vihreän piuhan 5 voltista 3,3 volttiin keltaiselle. Raspberry tiettävästi kärähtää, jos sinne työntää 5V. 


Laskuri on toiminut nyt luotettavasti muutaman päivän kaikissa kesäisen vuorokauden valaistusolosuhteissa. Lintuja ei ole käynyt, mutta olen itse käynyt välilla harjanvarrella laukaisemassa laskurin, ja ne kerrat ovat kaikki rekisteröityneet, eikä haamulaukaisuja ole tullut. 

Alla käytetyt koodit, Arduino ja Python (Raspberry). Python-koodi käynnistetään Crontabilla tasatunnein. Koodi toimii 3595 sekuntia, tallentaa tunnin aikana kertyneet laskurin lukeman ja pysähtyy. Cron käynnistää se pian taas uudelleen.

Arduino:


// Linnunpöntön porttilaskuri
// 23.7.2023

int arvo1, arvo2, arvo3, arvo4, i;

#define LED 2
#define herkkyys 50

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(13 , OUTPUT);
  Serial.begin(9600);
}

void loop() {
  digitalWrite(LED, LOW);
  arvo1 = 0;
  delay(2);
  for (i=0; i<10; i++){
    //delay(0);
    arvo1 = arvo1 + analogRead(A7);
  }

  digitalWrite(LED, HIGH);
  arvo2 = 0;
  delay(2);
  arvo2 = 0;
  for (i=0; i<10; i++){
    //delay(0);
    arvo2 = arvo2 + analogRead(A7);
  }  

  if((arvo1-arvo2) < herkkyys){
    if (arvo3 < 12){ 
      arvo3 += 1;
      delay(5);
    }
  }
  else{
    arvo3 = 0;
  }
  if(arvo3>5){
    digitalWrite(13, HIGH);
    delay(5);
  }
  else{
    digitalWrite(13,LOW);
  }
 
}
//Loppu

Python:


# Pöntön porttilaskuri
# 9.7.2023
#
import RPi.GPIO as GPIO
import time, datetime

# Aika, jonka kuluttua ohjelma lopetetaan ja kirjataa tuntilukema tiedostoon. Käynnistetään Crontabilla
ajoAika = 3600-4

# Pienin sensorin peittoaika, joka noteerataan
viiveAika = 0.3 

# Input-pinnin arvo, joka ilmaisee havahtumisen, 1 tai 0.
input = 1

aikaLeima = datetime.datetime.now().isoformat()[0:19]
aikaLeimaTunti = datetime.datetime.now().isoformat()[0:13] + ':00'
alkuAika = time.time()
laskuri = 0
print(aikaLeima)
print(alkuAika)
print(aikaLeimaTunti)

sensor = 17 # IR-tunnistimen pinni

GPIO.setmode(GPIO.BCM)
GPIO.setup(sensor,GPIO.IN)
print(GPIO.input(sensor))

i=1

def increase_number_in_file(file_name):
    # Lukee tiedoston ja lukee sieltä numeron
    with open(file_name, 'r') as file:
        number = int(file.read())

    # Lisää yhden numeron arvoon
    number += 1

    # Tallentaa päivitetyn numeron takaisin tiedostoon
    with open(file_name, 'w') as file:
        file.write(str(number))
        file.close()

# Ajetaan tätä silmukkaa niin kauan kuin ajoAika määrittää
while time.time()-alkuAika < ajoAika:
    time.sleep(0.2)
    if GPIO.input(sensor) == input: #Tarkkaillaan sensorin tilaa
        trigAika = time.time()
        #Odotetaan havahtumisen jälkeen luupissa, kunnes tila muuttuu takaisin tai ajoaika loppuu
        while GPIO.input(sensor) == input and time.time()-alkuAika < ajoAika: 
            time.sleep(0.1)
        viipyma = time.time()-trigAika
        #Kirjataan havainto, mikäli viiveAika on ylittynyt
        if viipyma > viiveAika:
            laskuri = laskuri + 1
            aikaLeima = datetime.datetime.now().isoformat()[0:19]
            print(viipyma)
            #Talletaan havainnon kellonaika ja kesto
            tiedosto=open('/polku/ponttolaskuri/ponttolaskuri_aika.dat', "a")
            tiedosto.write(aikaLeima + ';' + str(round(viipyma, 2)) + "\n")
            tiedosto.close()
            #Lisätään vuorokausilaskuriin yksi
            increase_number_in_file('/polku/ponttolaskuri/laskuri.dat')
            time.sleep(1) # Viive ennen uuden seurantaloopin aloitusta

# Lisätään ajoajan havainnot tuntitilastoon ennen ohjelman sulkemista
tiedosto=open('/polku/ponttolaskuri/ponttolaskuri_tunti.dat', "a")
tiedosto.write(aikaLeimaTunti + ';' + str(laskuri) + "\n")
tiedosto.close()

# Loppu

Kommentit

Tämän blogin suosituimmat tekstit

Vacuum Tube Tesla Coil Staccato Controller with Arduino

Käämintäkone