Archive for the ‘deutsch’ Category

Fotovoltaik Förderung

Tuesday, August 11th, 2009

Ich bin ja dabei, noch dieses Jahr eine Fotovoltaik-Anlage bei uns aufs Dach bauen zu lassen. Dazu gibt es die Klimafonds-Photovoltaik-Förderung, die ich beantragt habe. Die Presse hat ja dazu berichtet, dass der Server zusammengebrochen ist.
Der Nachfolgeartikel widerspricht sich, was den Zeitpunkt der Ausschöpfung der Förderung dieses Jahr betrifft, dort steht "Allein die Steiermark und Niederösterreich hätten innerhalb der ersten acht Stunden der Aktion 50 Millionen Euro benötigt" (zur Verfügung standen nur 18 Millionen) und etwas später "Dass es etwa einen Arbeitstag lang dauerte, bis die 18 Millionen an die Konsumenten gebracht wurden, lag am Zusammenbruch des Servers…"
Anyway, hier möchte ich jetzt kurz meine Aufzeichnungen während der Beantragung wiedergeben. Ich war kurz vor 10:00 Uhr online. Um kurz vor 11:30 hatte ich das Formular erfolgreich abgeschickt. Ein Log:
Schon am Vorabend und auch noch um kurz vor 10:00 am 4.8. hatte die Seite <http://www.klimafonds.gv.at/home/foerderungen/photovoltaik.html> einen seltsamen Tomcat-Error der auf einen Fehler in der Datenbank schliessen lässt (ein Duplicate Key). Der Link zur Anmeldung <http://www.service-publicconsulting.at/pv/> mit dem Titel "Photovoltaikförderungsantrag" war aber navigierbar und hatte ein Redirect auf <http://www.pv-service-publicconsulting.at/kkpv/> dieser wiederum führte aber zu einer Überlastungsseite <http://www.service-publicconsulting.at/pv/index_offline.html>
Nach einiger Zeit führen alle Seiten, also <http://www.service-publicconsulting.at/pv/> <http://www.service-publicconsulting.at/pv/index.html> <http://www.service-publicconsulting.at/pv/index_offline.html>
zum selben Text mit einem Link "Photovoltaikförderungsantrag (derzeit nicht verfügbar)"
Dann etwa eine Stunde später (kurz nach 11:00):
"Photovoltaikförderungsantrag (derzeit überlastet)"
Etwa um 11:15 hatten dann die direkten Links <http://www.service-publicconsulting.at/pv/> <http://www.service-publicconsulting.at/pv/index.html>
wieder ein Redirect auf <http://www.pv-service-publicconsulting.at/kkpv/> die wiederum auf <http://www.service-publicconsulting.at/pv/index_offline.html> redirectete.
Kurz darauf (kurz vor 11:30) ging dann erstmalig das Anmeldeformular als Redirect von <http://www.pv-service-publicconsulting.at/kkpv/>
Nach erfolgreicher Anmeldung bekam ich auch einen Email-Zustellversuch auf meinem Server, der aber wegen Greylisting nicht durchkam:


Aug  4 11:29:34 debian3264m postfix/smtpd[18583]: NOQUEUE: reject:
       RCPT from k969.ims-firmen.de[213.174.47.182]: 450 4.7.1
       <ralf@zoo.priv.at>: Recipient address rejected: Greylisted, see

http://isg.ee.ethz.ch/tools/postgrey/help/zoo.priv.at.html;

       from=<pv.service@kommunalkredit.at> to=<ralf@zoo.priv.at>
       proto=ESMTP helo=<bruce.connex.cc>

10 Minuten später kam dann auch die Email durch:


Aug  4 11:39:13 debian3264m postfix/smtpd[19080]: 3D5AE814E:
       client=k969.ims-firmen.de[213.174.47.182]
Aug  4 11:39:13 debian3264m postfix/cleanup[19086]: 3D5AE814E:
       message-id=<1144469538.1283.1249378174385.JavaMail.tomcatkk@bruce.connex.cc>
Aug  4 11:39:13 debian3264m postfix/smtpd[19080]: disconnect from
       k969.ims-firmen.de[213.174.47.182]
Aug  4 11:39:13 debian3264m postfix/qmgr[29847]: 3D5AE814E:
       from=<pv.service@kommunalkredit.at>, size=5844, nrcpt=1 (queue active)
Aug  4 11:39:13 debian3264m postfix/local[19087]: 3D5AE814E:
       to=<web11_ralf@static.88-198-162-230.clients.your-server.de>,
       orig_to=<ralf@zoo.priv.at>, relay=local, delay=0.28,
       delays=0.25/0/0/0.03, dsn=2.0.0, status=sent (delivered to command:
       /usr/bin/procmail -f-)
Aug  4 11:39:13 debian3264m postfix/qmgr[29847]: 3D5AE814E: removed

Hoffen wir mal, dass sich der Aufwand von 1.5 Stunden gelohnt hat. Die Gewährung von Förderungen von der Reihenfolge der Antragstellung bei einem kaputten Server abhängig zu machen lässt natürlich viele Vermutungen über Ungerechtigkeiten zu: Woher weiss ich, dass andere nicht früher durchgekommen sind? Vielleicht haben andere Bewerber noch einige Zeit lang ein Meldung wegen Überlastung bekommen, während andere schon munter ihren Antrag ausgefüllt haben? Wäre man schneller gewesen, wenn man einen Robot programmiert hätte? Vielleicht waren Robots an der Überlastung schuld?
Mir wäre da eine Frist und eine Ziehung unter notarieller Aufsicht deutlich lieber, damit würde klar zugegeben dass es ein Glücksspiel ist …

Verletzung der Netzneutralität durch Inode/UPC

Monday, June 15th, 2009

Seit einiger Zeit bekommt man von Inode/UPC einen automatischen Nameserver (DNS) zugeteilt der bei offensichtlichen Tippfehlern (wenn ein Benutzer sich beim Namen einer Webseite verschreibt) eine Werbe- und Suchmaschine von UPC zurückliefert — statt dem Benutzer mitzuteilen, dass es diese Domain nicht gibt.

Diese Verhalten eines der wichtigsten Services im Internet — der Namensauflösung — verletzt klar die Netzneutralität wie auch schon im Jahr 2007 von Ed Felten in seinem Blog im Falle Verizon festgestellt wurde. Verizon hat wohl seither auf diese Praxis — nach vielen Protesten — wieder verzichtet. Berechtigterweise wurde UPC für diese Praxis für den Big Brother Award nominiert — die gesammelten Daten gehen offensichtlich an einen ausländischen Werbeunternehmer. Zumindest in einem Fall kommt es bei diesem Verhalten zu Probleme bei Telefonie im Internet wie einem Forum Posting zu entnehmen ist.

Schlimmer noch: UPC liefert falschen Information auch für Domains die ganz klar von jemand anderem reserviert sind. Wenn ich also nonexistent.source-forge.org ansurfe komme ich auch auf die Werbeseite von UPC — obwohl source-forge.org (ja mit Bindestrich) von dem grossen Open Source Projekthoster sourceforge reserviert ist. Hoffentlich lässt es da mal jemand auf ein Gerichtsverfahren wegen unlauterem Wettbewerb ankommen. Wäre vermutlich recht lukrativ, jedenfalls bei anderen Firmen als Sourceforge.

Mir war das bisher nicht aufgefallen, aber offensichtlich wurden ehemalige Inode-Kunden erst vor kurzem umgestellt, UPC-Telekabel Kunden offensichtlich schon früher.

Heute habe ich mich bei der UPC-Hotline beschwert. Man werde an dem Fall arbeiten und “den Fehler” beheben. Leider könne man mir keine Ticket-Nummer geben unter welcher ich meine Beschwerde nochmal urgieren kann — aber ich könne ja “in einigen Tagen” wieder anrufen. Ein Rückruf wurde mir versprochen, mal sehen ob da was kommt. Ich habe den Hotline-Bearbeiter freundlich darauf hingewiesen, dass es sich ja nicht um einen unbekannten Fehler handeln kann, wenn UPC dafür bereits für den Big Brother Award nominiert wurde.

Inzwischen habe ich einen Workaround gefunden: UPC hat die alten, funktionierenden Nameserver nicht abgeschaltet, in obigem Link des ip-phone-forums findet man funktionierende DNS-Server: 195.34.133.25 und 195.34.133.26 die man fix einstellen kann. Weitere Tips finden sich als Antwort auf mein Posting an die LUGA-Mailingliste. Die alternative ist, gleich einen eigenen Nameserver zu betreiben (unter Linux sehr einfach möglich) oder auf alternative Namenshierarchien umzusatteln wie z.B. opennicproject — auch wenn man bei Verwendung von Alternativen von einer deutschen Ministerin gleich als pädophil eingestuft wird. Es ist kaum zu glauben, was manche Politiker für einen Schwachsinn von sich geben.

Warum ich nicht mit Skype telefoniere

Thursday, May 28th, 2009

Nachdem ich immer mal wieder gefragt werde, was meine Skype-ID sei, hier meine Gründe, warum ich Skype nicht verwende:

Die Firma Skype hat früher Peer-to-Peer Filesharing-Software hergestellt (mit dem Namen "KaZaA"), Filesharing-Programme dienen zum Tauschen von Musik und anderen elektronischen Inhalten. Diese Software hat nachgewiesenermassen sogenannte “Spyware” enthalten (vgl. auch diverse Tips, wie man diese ausschalten können soll). Unter Spyware verstehen wir Programme, die unbemerkt vom Eigentümer eines Rechners diesen Rechner ausspioniert und die ausspionierten Daten via Internet an den Programmierer der Spyware schickt. Zu den ausspionierten Daten zählen Statistiken über das Besuchen von Websites bis zu Passwörtern. Was genau die von der KaZaA Spyware ausspionierten Daten sind entzieht sich meiner Kenntnis. Ich vertraue solchen Leuten meine Telefongespräche nicht an.

Es gibt eine unabhängige Analysen von Skype 2005 und 2006, nach der in der analysierten Skype-Version keine Hinweise auf Spyware gefunden wurden. Das kannn sich inzwischen geändert haben und diese Analyse sagt nichts über die Sicherheit von Skype aus:

Skype (und vorher schon KaZaA) enthalten Mechanismen, um automatisch neue Software-Versionen (teilweise ohne Wissen oder sogar Zustimmung des Benutzers) zu installieren. In einer solchen neuen Version könnte Spyware enthalten sein — oder auch nur eine Software-Fehler der vorher nicht enthalten war. Damit ist man den Herstellern der Software ausgeliefert, da es unter der Kontrolle von Skype ist, was in neuen Versionen enthalten sein wird. Man könnte auch sagen: Nach Installation von Skype gehört Dir Dein Computer nicht mehr.

Dann wird immer wieder behauptet, die Kommunikation mit Skype sei verschlüsselt. Das mag ja stimmen. Der Grund ist aber wohl nicht die Privatsphäre des Nutzers, sondern die Absicht, zu verhindern, dass andere Software schreiben, die das Skype-Protokoll spricht. Denn was nützt mir die Verschlüsselung wenn ich nicht weiss, wer den Schlüssel besitzt? Der Benutzer von Skype besitzt den Schlüssel jedenfalls nicht.

Zum Abhören hat Kurt Sauer, Leiter der Sicherheitsabteilung von Skype, auf die durch ZDNet gestellte Frage, ob Skype die Gespräche abhören könne, ausweichend geantwortet: "Wir stellen eine sichere Kommunikationsmöglichkeit zur Verfügung. Ich werde Ihnen nicht sagen, ob wir dabei zuhören können oder nicht." (vgl. den Artikel in der deutschen Wikipedia dazu bzw. direkt das ZDNET-Interview.

Hinzu kommt, dass sich Skype an keinerlei etablierte Standards im Bereich der Sprachkommunikation über Internet-Protokolle hält, ja wie Skype genau funktioniert ist nicht offengelegt, es kann also keine andere Firma derzeit Programme bauen, die mit Skype-Software zusammen funktioniert. Solche "Closed Source" Programme fördern Monopolstellungen und sind — ähnlich wie z.B. Monopolstellungen im Bereich von Nahrungsmitteln wie Genmais von Monsanto — mit erhöhter Wachsamkeit zur Kenntnis zu nehmen. Die etablierten Standards im Bereich der Sprachkommunikation stehen Punkto Sprachqualität u.a. Skype in nichts nach.

Skype hat — aus seiner Peer-to-Peer Vergangenheit — Mechanismen um durch Firewalls zu "tunneln". Diese Techniken, auch als "Firewall Piercing" bekannt, sind für die Sicherheit einer Firma gefährlich, oder wie humorvoll von einem Kollegen formuliert: "Firewall Piercings können sich entzünden und eitern".

Es gibt etablierte Standards zur Sprachkommunikation wie z.B. SIP (Session Initiation Protocol) für den Verbindungsaufbau. Es gibt Open Source Implementierungen für "Softphones", das sind — ähnlich wie Skype — Programme mit welchen über einen Computer telefoniert werden kann. Ein Beispiel ist Qutecom (früher "Wengo Phone"), eine Suche nach "Softphone" in Google sollte noch einige andere zutage fördern. Es gibt natürlich auch kommerzielle Anbieter solcher Programme (teilweise als Closed Source), der Knackpunkt liegt in einem gemeinsamen Protokoll bei dem alle mitmachen können. Es gibt inzwischen auch "Hard" phones, also ein Ding was wie ein Telefon aussieht, aber hinten einen Ethernet-Anschluss hat und SIP spricht. Sehr preiswert ist das Budgetone von Grandstream, ein weiterer Anbieter ist z.B. Snom und Cisco hat einige kleinere Anbieter wie Sipura gekauft.

Ich habe selbst keine grosse Erfahrungen mit solchen Softphones auf Windows oder MAC Plattformen. Für Erfahrungsberichte bin ich dankbar.

Dann gibt es Anbieter, die Vermittlungstätigkeiten für solche Softphones anbieten. Ein Beispiel ist sipgate, andere finden sich auf voip-info.org. Man meldet sich dort an, kann gratis mit anderen Softphones über das Internet telefonieren, bekommt bei einigen Anbietern sogar kostenlos eine Telefonnummer über die man vom Festnetz aus angerufen werden kann. Das "Businessmodell" dieser Anbieter sind Anrufe vom Internet ins Festnetz. Die kosten dann etwas, sind aber immer noch deutlich günstiger als z.B. die Telekom in Deutschland oder Österreich.

Ein weiterer SIP-Dienst ist ekiga.net vom Team des gleichnamigen Open Source Soft-Phones Ekiga, ich bin dort z.B. als rsc@ekiga.net erreichbar.

Ausserdem ist ein öffentlicher Verzeichnisdienst ENUM im Aufbau, wo man seine eigene Telefonnummer weiterverwenden kann. Damit wird es in Zukunft möglich sein, einfach eine Telefonnummer einzugeben und über das Internet den gewünschten Teilnehmer zu erreichen.

Inzwischen gibt es auch eine Open Source Telefonanlage, Asterisk. Asterisk kann sowohl ans Festnetz (ISDN aber auch eine analoge Leitung) angeschlossen werden, als auch an Internet-Telefonie mit verschiedenen Standards (SIP, IAX, H323) teilnehmen. Die Telefon-Software läuft auf einem ganz normalen handelsüblichen PC — Modelle mit niedrigem Stromverbrauch sind zu empfehlen, da ja eine Telefonanlage Tag und Nacht in Betrieb sein soll. Asterisk "spricht" bereits heute ENUM. Ausserdem kann man über Einsteckkarten ganz normale "analoge" Telefonapparate anschliessen. Dann kann man verschiedene SIP-Anbieter gleichzeitig und einen Festnetzanschluss an der selben Telefonanlage betreiben und mit einem ganz normalen Analogtelefon, oder auch mit einem Komfort-ISDN-Telefon, einem Hard-Phone (z.B. Snom), oder einfach mit einem Softphone — telefonieren. Man kann die Telefonanlage suchen lassen, ob ein bestimmter Teilnehmer über das Internet erreichbar ist oder nur über das Festnetz. Der Anrufende muss nicht mal merken ob über Festnetz oder Internet telefoniert wird.

Das geniale an Asterisk (und das Erfolgsrezept von vielen anderen Open Source Projekten) ist sein modularer Aufbau: Für verschiedene anzuschliessende Geräte oder Protokolle kann man einen "Channel Treiber" schreiben und Asterisk kann danach mit einem neuen Gerät kommunizieren. So kann ein Spezialist für ein bestimmtes Gerät oder Protokoll einen neuen Gerätetreiber beitragen.

Man kann Asterisk-Telefonanlagen miteinander vernetzen — auch über eine verschlüsselte Verbindung über das Internet, ein sogenanntes "Virtual Private Network" (VPN). Dann kann man telefonieren ohne dass Dritte die Verbindung abhören können — eine solche Installation setzt allerdings Absprachen zwischen den Betreibern der zu vernetzenden Telefonanlagen voraus.

Neuere Techniken erlauben, vorhandene SIP-Infrastruktur zu benutzen und trotzdem ohne vorherige Absprache verschlüsselt zu telefonieren. Der Schlüssel wird dabei direkt zwischen den beiden Teilnehmern ausgehandelt. Philip Zimmermann, der Autor von PGP, hat dafür den Standard ZRTP vorgeschlagen, der inzwischen bei der Internet Engineering Task-Force (dem Gremium das Internet-Standards macht) zur Standardisierung eingereicht ist.

Ich selbst verwende Asterisk seit einigen Jahren statt meiner alten ISDN-Telefonanlage.

Vorträge mISDN und Open Money

Tuesday, April 21st, 2009

Auf den Linuxwochen hatte ich einen Vortrag zu mISDN, Abstract und Folien auf meiner Homepage. Auf dem Linuxtag in Graz werde ich nächsten Samstag den Vortrag zu Open Money (natürlich in aktualisierter Form, es tut sich ja einiges) halten.

Dämmerungsgesteuerte Hühnerstalltür mit Arduino

Thursday, January 8th, 2009

Seit einiger Zeit haben wir Hühner. Da wir öfter mal am Abend alle weg sind und dann niemand die Tür vom Hühnerstall zumacht — die Hühner gehen, im Gegensatz zu den Enten die wir früher hatten, von selber bei Dämmerung in den Stall — brauchten wir eine Lösung, die automatisch die Tür schließt. Es gibt fertige Hühnerställe mit einer zeitgesteuerten Tür — aber weder mit Dämmerungsschalter noch eine Türelektronik einzeln.

-)

v.l.n.r Kokoschka, Leuchtfeder, Gertrude :-)


Mein Sohn Max und ich haben also gemeinsam die Tür mit Mechanik und Elektronik und Software selber gemacht.

Alle verwendeten Teile sind bei Conrad erhältlich, wo wir es noch rekonstruieren können geben wir die Bestellnummern und den Link zum Artikel an. Conrad ist zwar relativ teuer, dafür bekommt man für dieses Einmalprojekt alle Teile bei einem Händler und wer was nachbauen will kann im deutschsprachigen Raum über einheitliche Teilenummern auf die gleichen Teile zugreifen, sei es in Österreich, der Schweiz oder Deutschland.

Einige Teile unserer Lösung eignen sich sicher auch für andere Projekte, nicht viele Leute werden eine Hühnerstalltüre brauchen …

Die Hühnerstalltüre funktioniert jetzt schon ein paar Wochen. Anfängliche mechanische Probleme (Tür verklemmte sich einige Male beim Herunterfahren) sind wohl gelöst. Unsere Software hat einen Zeitcheck falls beim Runter- oder Rauffahren doch mal was schiefgeht.

In der Folge beschreiben wir den Aufbau, getrennt nach Mechanik, Elektronik und Software — die Aufteilung zwischen Mechanik und Elektronik ist etwas willkürlich, wir haben die ganze Elektromechanik
(Motor, Schalter) zur Mechanik gerechnet.

Die Mechanik

Mit einem Getriebemotor wird eine Welle über einen Zahnriemen-Antrieb (Übersetzung nochmal 4:1) angetrieben. Der Getriebemotor ist schon 148:1 untersetzt. Die Welle läuft auf Kugellagern, die in einem Holzrahmen montiert sind. Die Lagerflansche sind einfach mit Heisskleber in den ausgestemmten Teil der Holzlatten geklebt. Vorsicht, keinen Heisskleber ins Lager bringen…

Die Übersetzung wurde so gewählt, dass wir eine bis zu 800g schwere Tür mit einer Welle mit Radius 5mm gut hochziehen können. Das Drehmoment des verwendeten Motors ist etwa 1,2 Ncm, mit der 4:1 Übersetzung mit dem Zahnriemen kommen wir auf 4.8 Ncm.

Die Welle wickelt dann eine Nylonschnur auf, die an der Tür angebunden ist. Die Nylonschnur hat einen Durchmesser von 2mm, die Welle wurde mit einem 2mm Titanbohrer gebohrt. Zum Bohren der Welle haben wir einen Stellring verwendet, einfach durch das Schraubenloch des Stellringes gebohrt, der Stellring war mit Klebeband fixiert.

Das Einfädeln der Nylonschnur kann man sich erleichtern, indem man die Nylonschnur mit einem Feuerzeug an einer Stelle erhitzt und auseinanderzieht, die entstehende Spitze eignet sich recht gut zum Einfädeln.

Motor: Eigentlich wollten wir ursprünglich einen kleineren Motor, da der jetzt verwendete Motor bis zu 2A Strom zieht (bei hoher Last — unsere Tür ist relativ leicht, dadurch ist die Last und damit der Strom recht niedrig). Das könnte mal zuviel für den verwendeten H-Bridge Motorcontroller werden.

Die Tür selbst hat einen Magneten, der in zwei Stellungen (Tür ganz oben bzw. ganz unten) jeweils einen Magnetschalter auslöst.

Für das Justieren (von Hand Türe rauf- bzw. runterfaheren) gibt es zwei Taster die an digitalen Inputs des Arduino angeschlossen sind.

Mechanischer Aufbau

Mechanischer Aufbau

Teileliste Mechanik:

  • 222366 Getriebemotor
  • 222374 Alternativ: kleinerer Motor
  • 237205 Welle 8mm
  • 216011 Lagerflansch für Kugellager
  • 225550 Stellringe 8mm
  • 214493 Kugellager
  • 226043 Zahnriemenscheibe 40 Zähne, für Welle 8mm
  • 226106 Zahnriemenscheibe 10 Zähne, für Welle 6mm (an Motor)
  • 226084 Zahnriemen
  • 753360 Magnetschalter
  • Taster ein (2X)

Im folgenden Bild sieht man die Tür im Zustand “NACHT” (zu). Die Magnetschalter und der Magnet an der Tür sind gut zu erkennen. Oben im Bild ist ein Stück Sperrholz auf Abstandshaltern so montiert, dass die Schnur durchläuft und beim Hochfahren die Tür an die Hüttenwand gedrückt wird.

Hühnerstalltür im geschlossenen Zustand mit Magnet und Magnetschaltern

Hühnerstalltür im geschlossenen Zustand mit Magnet und Magnetschaltern

Die Elektronik

Der Dämmerungsschalter ist mit einem einfachen Photowiderstand in einem Spannungsteiler mit einem 10k Widerstand realisiert. Der Photowiderstand ist über ein Lautsprecherkabel mit Heisskleber im Holzdach montiert. Oberhalb des Photowiderstands ist ein Acryl-Welldach. Die Magnetschalter sind an digitale Eingangspins des Arduino angeschlossen.

Die Motorsteuerung erfolgt über eine H-Bridge Schaltung in einem IC. Die Elektronik dazu findet auf einer Lochraster-Platine Platz. Die einfache H-Bridge benötigt keine externen Teile. Wie man das mit dem Arduino verdrahtet ist ganz gut auf der Seite der Physical Computing Labs der Tisch School of the Arts beschrieben — ist auch der erste Link auf den ich beim googlen nach “Arduino Motor Control” gestoßen bin.

Wir wollen aber — wegen des größeren Motors — auf eine größere H-Bridge, die braucht externe Schaltdioden (das Datenblatt des L298N schlägt Dioden mit höchstens 200ns reverse recovery time (trr) vor, wir werden die BYV 2100 verwenden mit einer trr von 12.5ns)

Teileliste Elektronik:

Alternative größere H-Bridge:

  • 156128 L298N H-Bridge Dual 2A bzw parallelgeschaltet 3A
  • 160005 BYV 2100 Schnelle Dioden dazu

Die Software

Der Dämmerungsschalter sollte laut Wikipedia bei ca. 100 lux das Öffnen der Tür veranlassen und bei höchstens 3.4 lx (Dark limit of civil twilight under a clear sky) das Schließen. In dem Wikipedia-Artikel ist eine Tabelle, die einen sehr dunklen Tag mit 100lx angibt, die deutsche Version enthält leider keine ausführliche Tabelle. In unseren Experimenten war ein Meßwert des Arduino von 200 für “Jetzt ist es dunkel, Tür zu” und von 300 für “Jetzt ist es hell, Tür auf” gut — auch in den jetzt dunklen Wintertagen (auch bei einem Gewitter) bleibt die Tür tagsüber offen und schliesst zuverlässig bei Dunkelheit. In einer klaren Vollmondnacht blieb die Tür zu.

Die Steuerung ist als Zustandsautomat (State Machine) realisiert. Jenachdem welcher Magnetschalter beim Einschalten Kontakt hat, startet der Automat im Zustand “TAG” bzw. “NACHT”. Wird keiner der Magnetschalter gesehen, gehen wir in den Zustand “ERROR”. Dieser Zustand bildet auch alle anderen Fehlerzustände ab, die im Betrieb auftreten können. Dabei setzen wir eine Fehlermeldung, die dann über die serielle Schnittstelle des Arduino (USB Serial) ausgegeben wird.

Der Zustandsautomat verwendet Statusfunktionen: In einem bestimmten Zustand wird die zugehörige Zustandsfunktion ausgeführt. Wenn diese Funktion 0 zurückliefert, geht der Automat in den nächsten Zustand, sonst bleibt er im alten Zustand.

Durch die Verwendung von Statusfunktionen (und keiner speziellen Funktion beim Zustandsübergang) haben wir zwei zusätzliche Zustände um den Motor einzuschalten, dieser Zustand (START_RAUF bzw. START_RUNTER) schaltet den Motor ein und geht sofort in den nächsten Zustand über.

Die Verdrahtung mit dem Arduino, also an welchen Pins welche Peripherie angeschlossen ist, sind über define’s am Beginn des Programms festgelegt.

Die Logik für die digitalen Inputs verwendet die Arduino-internen Pull-Up Widerstände. Daher ist die Logik invertiert: Wenn der Taster (oder ein Magnetschalter) geschlossen ist, liefert der entsprechende digitale Input eine 0.

Beim Testen haben wir festgestellt, dass bei laufendem Motor gelegentlich eine gedrückte Taste — oder ein geschlossener Magnetschalter detektiert wird. Daher haben wir in Software alle digitalen Inputs entprellt (Funktion debounced_read). Vermutlich sollten wir vor der H-Bridge noch einen Entstörkondensator vorsehen.

Die beiden Taster zum manuellen Rauf- und Runterfahren setzen ein Flag das den Zustandsautomaten neu initialisiert — dadurch muss man nach dem manuellen Kalibrieren kein Reset ausführen: Einfaches Drücken der Rauf- bzw. Runter-Taste reicht, um ein neues Initialisieren durchzuführen.

Im Error-Status warten wir 100ms nach dem Ausgeben der Fehlermeldung. Durch dieses Delay merkt man bei Drücken des Rauf- bzw. Runter-Knopfes sofort, ob sich das Gerät im Error-Zustand befindet: Wenn ein Error-Zustand vorliegt, bewegt sich der Motor nicht sofort, sondern erst nach einem kurzen Delay. Wenn der Zustandsautomat korrekt initialisiert ist, bewegt sich der Motor sofort.

Während der Entwicklung habe ich mit etwas mit einem Bug der Arduino-Entwicklungsumgebung gekämpft: Um Function-Style casts (Typumwandlungen die wie eine Funktion aussehen) zu ermöglichen, macht die Entwicklungsumgebung Code-Rewriting und fügt insbesondere einige Preprozessor-Defines ein, die es verhindern, einen Funktionspointer in C zu deklarieren. Der Workaround ist ein “#undef int” vor der Funktionspointer-Deklaration einzufügen. Gleich am Anfang kann man das nicht machen, da das Code-Rewriting ein #include direkt vor dem ersten Statement (nach allen #include und #define Direktiven) einfügt. Dieses “Feature” hat durch obskure Fehlermeldungen einiges an Zeit gekostet, was mich veranlasst hat, einen Beitrag im Arduino Forum dazu zu schreiben.

Die verwendeten Timer-Routinen (#include <timer.h> und der Typ Arduino_Timer) dienen dazu, auf eine bestimmte Zeit nach dem Aufruf von millis() zu warten — auch wenn die von millis verwendete Variable inzwischen überläuft. Der Timer lässt sich fragen, ob der gewünschte Zeitpunkt schon erreicht ist. Ursprünglich habe ich diese Routinen geschrieben, weil Version 0011 (und früher) der Arduino Entwicklungsumgebung einen Bug hatte, so dass der Timer zu früh überlief. Die entsprechenden Timer Routinen (für Version 0011 oder ab 0012) gebe ich gern auf Anfrage weiter.

#include <timer.h>
#include <stdio.h>

# define LED          13
# define MAGNET_OBEN   7
# define MAGNET_UNTEN  8
# define FOTO          0
# define MOTOR         9
# define MOTOR_DIR1    4
# define MOTOR_DIR2    3
# define MOTOR_MIN  0x7F
# define KNOPF_RAUF   12
# define KNOPF_RUNTER  2

# define HELL        300
# define FINSTER     200

# define STATUS_TAG          0
# define STATUS_ABEND        1
# define STATUS_NACHT        2
# define STATUS_MORGEN       3
# define STATUS_START_RAUF   4
# define STATUS_RAUFFAHREN   5
# define STATUS_START_RUNTER 6
# define STATUS_RUNTERFAHREN 7
# define STATUS_ERROR        8

int status   = STATUS_ERROR;
char errbuf [80];
char *errmsg = "";
int neuinitialisieren     = 1;
int debounce_magnet       = 0;
int debounce_knopf_runter = 0;
int debounce_knopf_rauf   = 0;

# define TIMER_MS       10000 // 10 seconds debounce 300000 // 5 minutes
# define FAHRZEIT_MS    75000 // max 75 seconds for up/down of door
Arduino_Timer timer (TIMER_MS);

int debounced_read (int iopin, int *counter)
{
    if (!digitalRead (iopin))
    {
        if ((*counter)++ >= 10)
        {
            *counter = 0;
            return 0;
        }
    }
    else
    {
        *counter = 0;
    }
    return 1;
}

void motor_an ()
{
    digitalWrite (LED,   HIGH);
    digitalWrite (MOTOR, HIGH);
}

void motor_aus ()
{
    digitalWrite (LED,   LOW);
    digitalWrite (MOTOR, LOW);
}

void linksrum ()
{
    digitalWrite (MOTOR_DIR1, LOW);
    digitalWrite (MOTOR_DIR2, HIGH);
}

void rechtsrum ()
{
    digitalWrite (MOTOR_DIR1, HIGH);
    digitalWrite (MOTOR_DIR2, LOW);
}

// Wir benutzen Status-Funktionen fuer jeden Status unserer Maschine:
// Wenn die Funktion 0 zurueckliefert, geht die Maschine in den naechsten
// Zustand, sonst bleibt sie im gleichen Zustand.

int fahren (int magnet)
{
    if (!debounced_read (magnet, &debounce_magnet))
    {
        return 1;
    }
    if (timer.is_reached (millis ()))
    {
        motor_aus  ();
        timer.stop ();
        errmsg = "Zeitueberschreitung fahren";
        status = STATUS_ERROR;
        return 0;
    }
    return 0;
}

int starte_rauffahren ()
{
    if (digitalRead (MAGNET_UNTEN))
    {
        errmsg = "Hochfahren: Tuere nicht unten";
        status = STATUS_ERROR;
        return 0;
    }
    timer.start (millis (), FAHRZEIT_MS);
    debounce_magnet = 0;
    rechtsrum ();
    motor_an  ();
    return 1;
}

int rauffahren ()
{
    return fahren (MAGNET_OBEN);
}

int starte_runterfahren ()
{
    if (digitalRead (MAGNET_OBEN))
    {
        errmsg = "Hochfahren: Tuere nicht oben";
        status = STATUS_ERROR;
        return 0;
    }
    timer.start (millis (), FAHRZEIT_MS);
    debounce_magnet = 0;
    linksrum  ();
    motor_an  ();
    return 1;
}

int runterfahren ()
{
    return fahren (MAGNET_UNTEN);
}

int nacht ()
{
    int val;
    motor_aus ();
    val = analogRead (FOTO);
    Serial.println (val);
    if (val > HELL)
    {
        timer.start (millis ());
        return 1;
    }
    return 0;
}

int tag ()
{
    int val;
    motor_aus ();
    val = analogRead (FOTO);
    Serial.println (val);
    if (val < FINSTER)
    {
        timer.start (millis ());
        return 1;
    }
    return 0;
}

int abend ()
{
    int val;
    motor_aus ();
    val = analogRead (FOTO);
    if (val > FINSTER)
    {
        status = STATUS_TAG;
        return 0;
    }
    if (timer.is_reached (millis ()))
    {
        timer.stop ();
        return 1;
    }
    return 0;
}

int morgen ()
{
    int val;
    motor_aus ();
    val = analogRead (FOTO);
    if (val < HELL)
    {
        status = STATUS_NACHT;
        return 0;
    }
    if (timer.is_reached (millis ()))
    {
        timer.stop ();
        return 1;
    }
    return 0;
}

int error ()
{
    motor_aus ();
    Serial.println (errmsg);
    delay (100);
    return 0;
}

# undef int
struct state {
    int status;
    int next_status;
    int (*statefun)();
};

// Stati muessen in der Reihenfolge der numerischen Zustandswerte sein
// Zustaende muessen lueckenlos nummeriert sein
struct state stati [] =
{ { STATUS_TAG,          STATUS_ABEND,        tag                 }
, { STATUS_ABEND,        STATUS_START_RUNTER, abend               }
, { STATUS_NACHT,        STATUS_MORGEN,       nacht               }
, { STATUS_MORGEN,       STATUS_START_RAUF,   morgen              }
, { STATUS_START_RAUF,   STATUS_RAUFFAHREN,   starte_rauffahren   }
, { STATUS_RAUFFAHREN,   STATUS_TAG,          rauffahren          }
, { STATUS_START_RUNTER, STATUS_RUNTERFAHREN, starte_runterfahren }
, { STATUS_RUNTERFAHREN, STATUS_NACHT,        runterfahren        }
, { STATUS_ERROR,        STATUS_ERROR,        error               }
};



void setup ()
{
    pinMode (LED,         OUTPUT);
    pinMode (MAGNET_OBEN,  INPUT);
    pinMode (MAGNET_UNTEN, INPUT);
    pinMode (MOTOR,       OUTPUT);
    pinMode (MOTOR_DIR1,  OUTPUT);
    pinMode (MOTOR_DIR2,  OUTPUT);
    pinMode (KNOPF_RUNTER, INPUT);
    pinMode (KNOPF_RAUF,   INPUT);

    digitalWrite (MOTOR,   LOW);
    linksrum ();
    digitalWrite (LED,     HIGH);

    digitalWrite (MAGNET_OBEN,  HIGH); // enable pull-up resistor
    digitalWrite (MAGNET_UNTEN, HIGH); // enable pull-up resistor
    digitalWrite (KNOPF_RUNTER, HIGH); // enable pull-up resistor
    digitalWrite (KNOPF_RAUF,   HIGH); // enable pull-up resistor
    Serial.begin (115200);
    if (FINSTER >= HELL)
    {
        status = STATUS_ERROR;
        errmsg = "FINSTER >= HELL";
    }
    Serial.print ("initial state: ");
    Serial.println (status);
}

void loop ()
{
    struct state *st = &stati [status];
    if (!debounced_read (KNOPF_RUNTER, &debounce_knopf_runter))
    {
        debounce_knopf_runter = 10;
        linksrum  ();
        motor_an  ();
        neuinitialisieren = 1;
        return;
    }
    else if (!debounced_read (KNOPF_RAUF, &debounce_knopf_rauf))
    {
        debounce_knopf_rauf = 10;
        rechtsrum ();
        motor_an  ();
        neuinitialisieren = 1;
        return;
    }
    else if (neuinitialisieren)
    {
        motor_aus ();
        errmsg = "Unbekannte Tuerposition bei Start";
        status = STATUS_ERROR;
        if (!digitalRead (MAGNET_OBEN))
        {
            status = STATUS_TAG;
        }
        else if (!digitalRead (MAGNET_UNTEN))
        {
            status = STATUS_NACHT;
        }
        neuinitialisieren = 0;
        debounce_knopf_rauf = debounce_knopf_runter = 0;
        Serial.print ("Initialized to: ");
        Serial.println (status);
        return;
    }
    // Hard-coded error state must work if state-table is broken
    if (status >= STATUS_ERROR)
    {
        error ();
        return;
    }
    if (st->status != status)
    {
        status = STATUS_ERROR;
        sprintf
            ( errbuf
            , "Error in state-table, expected %d got %d"
            , status
            , st->status
            );
        errmsg = errbuf;
        return;
    }
    if (st->statefun ())
    {
        status = st->next_status;
    }
    if (status != st->status)
    {
        sprintf (errbuf, "new state: %d->%d", st->status, status);
        Serial.println (errbuf);
    }
}

Die vier Grundfreiheiten der Gnu General Public License

Tuesday, December 9th, 2008

Weil ich immer mal wieder gefragt werde, was die Hauptmerkmale von Open Source Lizenzen, insbesondere der Gnu General Public License (GPL) [Deutsche Übersetzung hier] sind, eine ganz gute (deutsche) Erklärung steht in einer Gerichtseingabe von einem Anwaltsbüro, ich gebe das hier wieder:

[Die GPL ist ein Lizenzsystem,] das den Hauptzweck verfolgt, eine möglichst große Verbreitung einer bestimmten Software zu ermöglichen und ausdrücklich zuzulassen, dass Veränderungen an dieser Software vorgenommen werden. Dies aus der Intention, dass sich eine Software stetig dadurch verbessert, dass sie von jedem, der Probleme der Software erkennt, optimiert werden kann.

Die GPL basiert auf den vier sogenannten “Grundfreiheiten” die die Basis der GPL bilden. Diese Grundfreiheiten sind Bestandteil der Lizenz.

Die erste Grundfreiheit gewährt dem Nutzer das Recht, das Programm ohne jede Einschränkung für jeden Zweck zu nutzen. Ausdrücklich ist hierbei auch die kommerzielle Nutzung von dem Nutzungsrecht umfasst.

Die zweite Grundfreiheit wiederum gewährt dem Nutzer das Recht, unter bestimmten Einschränkungen hinsichtlich des sogenannten Quellcodes […] das Programm zu verbreiten, also kostenlos oder gegen Entgeld zu kopieren und in den Verkehr zu bringen. Nicht erlaubt ist lediglich, Lizenzgebühren für die Nutzung des Programms zu erheben.

Die dritte Grundfreiheit besagt, dass das Programm studiert und den eigenen Bedürfnissen angepasst werden darf.

Letztlich besagt die vierte Grundfreiheit, dass auch die veränderten Versionen des Programms unter den Voraussetzungen der vorgenannten Regelungen in Verkehr gebracht werden können.

Die GPL ist damit eine Sicherheit für den Nutzer: Niemand — auch der ursprüngliche Hersteller der Software — kann die Nutzungsrechte einschränken. Kein “Vendor-lock-in” keine versteckten Kosten in Form von Lizenzgebühren. Sollte der ursprüngliche Anbieter für Wartung zu teuer werden, kann jederzeit der Anbieter gewechselt werden.

Die Software darf (sogar für kommerzielle Zwecke) auch weitergegeben werden — lediglich die Rechte, die man selbst an der Software hat, darf man dem Empfänger nicht vorenthalten.

Lassen Sie uns Ihr Vermoegen hochheben

Friday, November 28th, 2008

… mit dem Titel habe ich heute eine Spam-Email bekommen — erinnert sehr an den englischen Begriff “Shoplifting” — oder an die alten Witze ala “Die Telekom will an die Börse — auch an Ihre” :-)

Telering Online Rechnung

Monday, October 27th, 2008

Neulich hab ich meine Telering-Rechnung von meinem Mobiltelefon auf Online umgestellt, weil ich seit fast einem halben Jahr eh keine Papierrechnung von denen mehr bekomme (Anruf bei Hotline um abzuklären, warum die Papierrechnung nicht mehr kommt war nur Zeitverschwendung und im Kundenbereich kann man die Rechnung runterladen).

Letzten Freitag bekomm’ ich ein SMS, dass meine Telering-Rechung da ist — es gibt ja fast nix wichtigeres auf der Welt als eine Telering-Rechung, daher ist es unerlässlich, den Kunden auf allen verfügbaren Kanälen darauf aufmerksam zu machen, dass die Rechnung da ist (fehlt eigentlich nur, dass ich einen Anruf bekomme :-):

tele.ring Rechnungs-Info!
Ihre aktuelle Rechnung ist online. Abrufbar unter my.telering.at > Rechnung. LG Ihr tele.ring Team

Ich ärgere mich also über die Störung und versuche die Absendernummer 1554020000001 des SMS anzurufen — und — am anderen Ende ist eine Österreichische Wettervorhersage.

Also habe ich bei der Hotline die Rechnung wieder auf Papier zurückgestellt (online-Rechung heisst offensichtlich Email und SMS) — möglicherweise kommt sie ja jetzt wieder — nach einmal hin und her Umstellen auf Online und zurück.


Impressum/Kontakt