Innostuin pitkästä aikaa ohjelmoimaan Atmelin 2313 mikrokontrolleria C:llä, ja silmiini osui tuollainen sivu:
http://minkbot.blogspot.com/2009/08/arduino-ir-receiver-with-interrupts.html
Koodi siis vastaanottaa rc5-infrapunasignaalia keskeytyksiä hyväksikäyttämällä.
Tuota selaillessa huomasin seuraavanlaisen funktion, jonka toimintaa en ymmärrä.
unsigned long elapsedSince(unsigned long since, unsigned long now) { return since &lh; now ? now-since : 0xFFFFFFFFUL - (now - since); }
Löytyisikö apuja, mitä tuo return-rivi oikeen tarkoittaa?
palauttaa long arvon 1mikrosekunnin kellopulsseista. (nykyinen pulssimäärä - edellinen)
arvo since on edellinen kontrollerilta luettu kellopulssimäärä, nykyinen on juuri luettu.
tuollahan linkissäsi oli esimerkki tästä:
unsigned long elapsedSince(unsigned long since, unsigned long now) { return since &lh; now ? now-since : 0xFFFFFFFFUL - (now - since); } unsigned long elapsedSince(unsigned long since) { return elapsedSince( since, micros() ); } // compute elapsed time since last change unsigned elapsed; { unsigned long timeStamp = micros(); elapsed = elapsedSince(isrLastTimeStamp,timeStamp); isrLastTimeStamp = timeStamp; }
(linkki micros() )
http://www.arduino.cc/en/Reference/Micros
micros()
Description
Returns the number of microseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 70 minutes. On 16 MHz Arduino boards (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution of eight microseconds.
Note: there are 1,000 microseconds in a millisecond and 1,000,000 microseconds in a second.
Ihan ensiksi kannattaa huomata, että &lh; on takuulla väärin kirjoitettu <, joka nettisivulla tarkoittaa merkkiä <. Oikea rivi olisi siis seuraava:
return since < now ? now-since : 0xFFFFFFFFUL - (now - since);
Tämän merkityksen voi taas ensiksi opetella jostain C(++)-oppaasta. If-lauseilla sama menisi näin:
if (since < now) { return now - since; } else { return 0xFFFFFFFFUL - (now - since); }
0xFFFFFFFFUL taas on unsigned long -tyyppinen heksadesimaaliluku 0xFFFFFFFF eli kymmenjärjestelmässä 4294967295 eli etumerkittömän 32-bittisen kokonaisluvun maksimiarvo.
Mitenkään aihetta tuntematta ja koodin alkuperään perehtymättä sanoisin, että jälkimmäisessä osassa on jotain mätää. Nythän sen voisi kirjoittaa yhtä hyvin myös since - now - 1
, mikä ei vaikuta järkevältä. Jos luvut pyörähtävät odotetulla tavalla ympäri, pelkkä ensimmäinen return-rivi riittäisi. Muussa tapauksessa vähennyslaskun oikeaan tulokseen pääsisi seuraavasti:
if (since <= now) { return now - since; } return 0xFFFFFFFFUL - (since - now - 1);
:D FFFFFFFFUL (eli HHHHHHHUMALASSA ruotsiksi)
Kiitokset kaikille vastanneille, apu tuli nopeasti!
Tuo &lh; oli se mikä meni yli hilseen.
Homma etenee :)
Miksei vain
return (unsigned long)(now - since);
?
Torgo kirjoitti:
Miksei vain
return (unsigned long)(now - since);?
Todennäköisesti siksi, että jos kontrollerin reaktio ylivuotoon ei olekaan lukuarvon pyörähdys vaan saturaatio, tuolla saadaan pakotettua arvo pyörähtämään.
tkarkkainen kirjoitti:
Todennäköisesti siksi, että jos kontrollerin reaktio ylivuotoon ei olekaan lukuarvon pyörähdys vaan saturaatio, tuolla saadaan pakotettua arvo pyörähtämään.
Meinaat siis että kontrollerilla ei pystyisi laskemaan negatiivisia arvoja, vaan laskutoimitus pysähtyisi nollaan? Ei, kyllä tuo laskee myös negatiiviset luvut kahden komplementtina. Ja jos negatiivinen kahden komplementti palautetaan positiivisena, saadaan oikea tulos, koska bittikuvio on sama.
Ainoa idea tuossa olisi, että kello pyörähtäessään ympäri, ei aloitakaan nollasta vaan ykkösestä. Tai sitten pyörähdys tapahtuu jo 0xfffffffe:ssä. Tämä selittäisi tuon Metabolixinkin huomaaman erikoisuuden, että ympäripyörähdyksen tapauksessa palautetaan yhtä pienempi arvo, kuin jos kello ei pyörähdä ympäri. Mutta siinäkin tapauksessa ensimmäisen testin täytyisi verrata myös yhtäsuuruutta, jotta nollan ero saadaan myös selville.
Edit.
Ja nyt kun tarkemmin katsoo, niin tuossahan on molemmissa ehdoissa (now - since). Siis jos se saturoituisi nollaan, niin tuloksena olisi joka kerta 0xffffffff. Ja jos se pyörähtää ympäri, niin saadaankin etäisyys 0xffffffff:stä. Eli tulos on väärin joka tapauksessa.
noh. quote tosta micro() funktiosta
"This number will overflow (go back to zero), after approximately 70 minutes."
tuo else ehtohan tapahtuu vai kerran / 70min, koska tämän jälkeen now arvo tallennetaan since muuttujaan jolloin seuraavalla kerralla now on taas suurempi kuin since.
lasku kyllä näyttäisi väärältä, eikös siinä kuitenkin tulisi olla:
4294967295 + ( now - since ), 4294967295 - (now-since):n sijaan
(tai sitte tuo metabolixin 4294967295 - (since - now - 1) )
koska tulos (now - since ) on negatiivinen jos now on pienempi kuin since, ja tupla miinus muuttuu plussaksi.
plussalla saataisiin järkevää vastaustakin aikaiseksi
esim:
4294967295 + ( 10 - 4294965555) = elapsed: 1750 mikrosekuntia
(miinuksella ei mitään järkevää tulosta):
4294967295 - ( 10 - 4294965555) = elapsed: 8589932849 mikrosekuntia. ja menee yli alueen aika hyvin ;)
Torgo kirjoitti:
Meinaat siis että kontrollerilla ei pystyisi laskemaan negatiivisia arvoja, vaan laskutoimitus pysähtyisi nollaan?
En meinaa, että kontrollerilla ei yleisesti ottaen voisi laskea negatiivisia lukuja. Tarkoitin, että kontrollereissa ja varsinkin DSP-prossuissa on tuo saturaatiotoiminnallisuus käytettävissä, jos niin halutana, ja että alkuperäinen koodaaja olisi ehkä ajatellut varautua siihen jotenkin. Tarkastin asian, ja pienemmissä AVR:issä ei ilmeisesti ole tuota saturoivaa aritmetiikkaa käytössä.
Tarkempi tarkastelu osoitti myös, että saturoituvan laskennan käyttäminen edellyttää hyvin pitkälti sen huomioimista koodissa, ja sitä tuossa ei ole tehty. Eli siis: brainfarttia ainakin minun päässäni (no pun intended). Mainittakoon vielä, että Metabolixin viesti oli jotenkin päässyt ohittumaan siinä vaiheessa, kun edellisen viestini kirjoitin.
Eli unohtakaa koko saturaatiopölinä tässä tapauksessa. Metabolix ratkaisi asian nähdäkseni oikein, kun huomioidaan, mitä tosiaan ollaan tekemässä. Ja Torgo, sinun ratkaisusi (now-since) on myös täsmälleen sama kuin Metabolixin, tosin yksinkertaisemmassa muodossa.
On se kumma, miten paljon sitä oppii, kun möläyttelee asioita miettimättä ollenkaan, mitä sanoo tai mihin vastaa :/
Aihe on jo aika vanha, joten et voi enää vastata siihen.