Anonyme Arduinisten: Unterschied zwischen den Versionen
(→Oszi-Grafik: blafasel) |
Keine Bearbeitungszusammenfassung |
||
(39 dazwischenliegende Versionen von 8 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
{{veraltet}} | |||
Die '''Anonymen Arduinisten''' oder auch '''Institut für angewandte Inkompetenz''' <s>treffen sich nahezu '''jeden Dienstag ab ca. 19 Uhr''' im Club, um mit Arduino und anderer Elektronik zu spielen</s> trafen sich dienstags im Club. Wir verstanden uns als Selbsthilfegruppe: Arduino und Elektronik '''von Kackn00bs für Kackn00bs'''. Also waren gerade völlige Beginner willkommen bei uns mitzumachen. | |||
== Projekte == | == Projekte == | ||
Zeile 14: | Zeile 14: | ||
</blockquote> | </blockquote> | ||
< | <syntaxhighlight lang="diff"> | ||
--- LCD4Bit.orig/LCD4Bit.cpp 2006-10-16 04:29:44.000000000 +0200 | --- LCD4Bit.orig/LCD4Bit.cpp 2006-10-16 04:29:44.000000000 +0200 | ||
+++ LCD4Bit/LCD4Bit.cpp 2009-11-04 17:51:50.205659741 +0100 | +++ LCD4Bit/LCD4Bit.cpp 2009-11-04 17:51:50.205659741 +0100 | ||
Zeile 28: | Zeile 28: | ||
if (g_num_lines==1){ | if (g_num_lines==1){ | ||
</ | </syntaxhighlight> | ||
Danach hat alles sauber geklappt, das Display hat keine Mucken mehr gemacht. Allerdings haben wir das Delay später wieder rausgenommen, da <code>cursorTo()</code> ohnehin ineffizient implementiert war (siehe unten.) | Danach hat alles sauber geklappt, das Display hat keine Mucken mehr gemacht. Allerdings haben wir das Delay später wieder rausgenommen, da <code>cursorTo()</code> ohnehin ineffizient implementiert war (siehe unten.) | ||
=== Duinopong === | === Duinopong === | ||
[[Bild:Duinopong.png|thumb|right|Pong auf einem 2x40 Text-Display, auch als [[Media:Duinopong.avi|Video]]]] | |||
Die lose Verkabelung des Displays an den Arduino war etwas unpraktisch, also haben wir das Display bzw. dessen Flachbandkabel an eine Lochrasterplatine gelötet, nicht ohne über eine Lücke zwischen zwei Steckleisten auf dem Arduino-Board zu fluchen: Diese hat nämlich nicht den für die Lochrasterplatine geeigneten Abstand von 2,54 mm (0,1 Zoll). Darauf kann man also nicht eine geeignet gestaltete und mit Pins versehene Lochrasterplatine stecken. Also haben wir die beiden Steckleisten benutzt, die ins Raster passen und die andere ignoriert. | Die lose Verkabelung des Displays an den Arduino war etwas unpraktisch, also haben wir das Display bzw. dessen Flachbandkabel an eine Lochrasterplatine gelötet, nicht ohne über eine Lücke zwischen zwei Steckleisten auf dem Arduino-Board zu fluchen: Diese hat nämlich nicht den für die Lochrasterplatine geeigneten Abstand von 2,54 mm (0,1 Zoll). Darauf kann man also nicht eine geeignet gestaltete und mit Pins versehene Lochrasterplatine stecken. Also haben wir die beiden Steckleisten benutzt, die ins Raster passen und die andere ignoriert. | ||
Das verwendete Display bzw. dessen Steuerchip erlaubt das Erzeugen von 8 benutzerdefinierten Buchstaben (5x8). Warum also nicht diese benutzen um den Ball eines Pong pixelgenau in 200x16 statt 40x2 darzustellen? :-) Der eigentliche Code zum Setzen der benutzerdefinierten Characters ist nu nicht sehr schön gelungen, aber das nennt sich wohl Rapid Prototyping: | Das verwendete Display bzw. dessen Steuerchip erlaubt das Erzeugen von 8 benutzerdefinierten Buchstaben (5x8). Warum also nicht diese benutzen um den Ball eines Pong pixelgenau in 200x16 statt 40x2 darzustellen? :-) Der eigentliche Code zum Setzen der benutzerdefinierten Characters ist nu nicht sehr schön gelungen, aber das nennt sich wohl Rapid Prototyping: | ||
<syntaxhighlight lang="c"> | |||
#define CHAR_PADDLE paddle // 0 == left, 1 == right | #define CHAR_PADDLE paddle // 0 == left, 1 == right | ||
Zeile 53: | Zeile 55: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | |||
Außerdem mussten wir noch einen (ebenfalls aus dem Elektronik-Schrott geborgenen) Rotary-Encoder zur Kooperation überreden. Ein Rotary-Encoder kodiert eine Drehbewegung als Bitsequenz auf seine zwei Ausgänge, in unserem Fall hatten wir es wohl mit einem 2-Step-Rotary-Encoder zu tun: Eine Bewegung um einen "Klick" in die eine Richtung erzeugt eine Bitsequenz 00-'''01'''-11, eine Drehung in die andere Richtung die Sequenz 00-'''10'''-11 (bzw. ähnlich vom Zustand 11 nach 00). Das ist ein sogenannter [[Wikipedia:de:Gray-Code|Gray-Code]]: Es wird eigentlich nur hoch- bzw. runtergezählt, allerdings derart kodiert, dass sich immer nur ein Bit pro Änderung ändert -- was Fehler beim Auslesen minimiert. Letztlich haben wir dann ein wenig Code von [http://www.mikrocontroller.net/article/Drehgeber#Solide_L.C3.B6sung:_Beispielcode_in_C mikrocontroller.net] geborgt, um das ganze in der empfohlenen Methode umzusetzen: Ein Timer-Interrupt samplet die Werte "schnell genug" und stellt sie zum Auslesen in einer globalen Variable ''enc_value'' zur Verfügung. | Außerdem mussten wir noch einen (ebenfalls aus dem Elektronik-Schrott geborgenen) Rotary-Encoder zur Kooperation überreden. Ein Rotary-Encoder kodiert eine Drehbewegung als Bitsequenz auf seine zwei Ausgänge, in unserem Fall hatten wir es wohl mit einem 2-Step-Rotary-Encoder zu tun: Eine Bewegung um einen "Klick" in die eine Richtung erzeugt eine Bitsequenz 00-'''01'''-11, eine Drehung in die andere Richtung die Sequenz 00-'''10'''-11 (bzw. ähnlich vom Zustand 11 nach 00). Das ist ein sogenannter [[Wikipedia:de:Gray-Code|Gray-Code]]: Es wird eigentlich nur hoch- bzw. runtergezählt, allerdings derart kodiert, dass sich immer nur ein Bit pro Änderung ändert -- was Fehler beim Auslesen minimiert. Letztlich haben wir dann ein wenig Code von [http://www.mikrocontroller.net/article/Drehgeber#Solide_L.C3.B6sung:_Beispielcode_in_C mikrocontroller.net] geborgt, um das ganze in der empfohlenen Methode umzusetzen: Ein Timer-Interrupt samplet die Werte "schnell genug" und stellt sie zum Auslesen in einer globalen Variable ''enc_value'' zur Verfügung. | ||
Zeile 71: | Zeile 74: | ||
Naja und dann stellte sich noch ein weiteres Mal heraus, dass die LCD4BitLibrary Schrott ist: Das Cursor-Setzen ist gewaltig ineffizient implementiert ("Return-Home" und zig mal vor (0x14), statt einfach die "Cursor-Setzen"-Funktion (0x80) des Steuerchips zu verwenden), so dass uns das auch noch eine Weile aufhielt und wir schliesslich dann einfach die Library gefixt haben (statt gleich auf die gescheite LiquidCrystal-Lib zu nehmen...) | Naja und dann stellte sich noch ein weiteres Mal heraus, dass die LCD4BitLibrary Schrott ist: Das Cursor-Setzen ist gewaltig ineffizient implementiert ("Return-Home" und zig mal vor (0x14), statt einfach die "Cursor-Setzen"-Funktion (0x80) des Steuerchips zu verwenden), so dass uns das auch noch eine Weile aufhielt und wir schliesslich dann einfach die Library gefixt haben (statt gleich auf die gescheite LiquidCrystal-Lib zu nehmen...) | ||
< | <syntaxhighlight lang="diff"> | ||
--- LCD4Bit.orig/LCD4Bit.cpp 2006-10-16 04:29:44.000000000 +0200 | --- LCD4Bit.orig/LCD4Bit.cpp 2006-10-16 04:29:44.000000000 +0200 | ||
+++ LCD4Bit/LCD4Bit.cpp 2009-11-04 17:51:50.205659741 +0100 | +++ LCD4Bit/LCD4Bit.cpp 2009-11-04 17:51:50.205659741 +0100 | ||
Zeile 104: | Zeile 107: | ||
//scroll whole display to left | //scroll whole display to left | ||
</ | </syntaxhighlight> | ||
=== I²C === | === I²C === | ||
Zeile 112: | Zeile 115: | ||
Weil wir gerade nicht besseres zu tun hatten, dachten wir uns: Lass uns unsere Arduinos vernetzen! Gesagt, getan, wir haben die I²C-Library aus dem Arduino-Paket entdeckt und unsere Arduinos mit zwei Drähten verbunden. Mit den bereitgestellten Funktionen geht das sehr gut, man muss nur einen der Arduinos als Master arbeiten lassen. | Weil wir gerade nicht besseres zu tun hatten, dachten wir uns: Lass uns unsere Arduinos vernetzen! Gesagt, getan, wir haben die I²C-Library aus dem Arduino-Paket entdeckt und unsere Arduinos mit zwei Drähten verbunden. Mit den bereitgestellten Funktionen geht das sehr gut, man muss nur einen der Arduinos als Master arbeiten lassen. | ||
Wir haben noch GND jeweils verbunden ohne jedoch wirklich zu wissen, ob das nun elektrisch so die beste Idee ist -- vermutlich nicht ;-) | Wir haben noch GND jeweils verbunden ohne jedoch wirklich zu wissen, ob das nun elektrisch so die beste Idee ist -- vermutlich nicht ;-) -- Doch, das ist sogar notwendig, damit die beiden Controller ein gemeinsames Bezugspotential haben; sonst kommt da nur Datenmüll an. | ||
=== Dallas 1wire Bus - Temperatursensoren === | |||
Ein bisschen [https://github.com/JackMcCrack/DS18x20_Temperature/blob/master/Arduino-DS18x20_Temperature_cleanerOutput.ino Code] fragt alle Sensoren am Bus nach der aktuellen Temperatur und schreibt die SensorID und den gemessenen Wert nach Serial. Weiter Infos gibt es unter [[Temperatursensoren]]. | |||
=== Mini-LED-Cube === | |||
Wir haben uns eines Samstagbends vom entropianischen [[LED-Cube]] und [http://mosfetkiller.de/?s=miniledcube einem anderen Mini-LED-Cube] inspirieren lassen. Da wir sowieso etwas löten lernen mussten, haben wir uns schnell einen völlig schiefen 3x3x3-LED-Würfel zusammengelötet. Ganz nach dem Motto "Schön ist: was funktioniert" präsentieren wir hier unseren Mini-LED-Cube in formschöner Animation: | |||
[[Bild:Aa_kubus.gif]] | |||
Nach diesem Proof-of-Concept-Würfel löten wir uns vielleicht mal noch was Schönes :-) | |||
=== Oszi-Grafik === | === Oszi-Grafik === | ||
Zeile 121: | Zeile 135: | ||
Der erste Versuch ging ungefähr so: Wir haben mit der [[Wikipedia:de:Pulsweitenmodulation|Pulsweitenmodulation]] des Arduino "analoge" Werte auf zwei Pins (X und Y) gelegt, diese Werte mit jeweils einem [[Wikipedia:de:RC-Glied|RC-Glied]] geglättet und das ganze dann mit der XY-Funktion des Oszis anzeigen lassen. Das hat auch halbwegs geklappt, allerdings reagiert das RC-Glied nicht so gut auf schnelle Änderungen -- es gibt eher Kurven als harte Kanten bei Änderungen -- , so dass damit höchstens ein paar visuelle Effekte machbar sind. Aber es war schonmal ein Erfolg. | Der erste Versuch ging ungefähr so: Wir haben mit der [[Wikipedia:de:Pulsweitenmodulation|Pulsweitenmodulation]] des Arduino "analoge" Werte auf zwei Pins (X und Y) gelegt, diese Werte mit jeweils einem [[Wikipedia:de:RC-Glied|RC-Glied]] geglättet und das ganze dann mit der XY-Funktion des Oszis anzeigen lassen. Das hat auch halbwegs geklappt, allerdings reagiert das RC-Glied nicht so gut auf schnelle Änderungen -- es gibt eher Kurven als harte Kanten bei Änderungen -- , so dass damit höchstens ein paar visuelle Effekte machbar sind. Aber es war schonmal ein Erfolg. | ||
Als nächstens haben wir uns dann zwei Digital-Analog-Converter-Chips (DACs) besorgt, und versucht eine Schaltung in [[Wikipedia:de:EAGLE|EAGLE]] zu entwerfen. Mehr dazu wenn wir damit fertig sind. | Als nächstens haben wir uns dann zwei Digital-Analog-Converter-Chips (DACs) besorgt ([[Media:Tda8702.pdf|TDA8702]]), und versucht eine Schaltung in [[Wikipedia:de:EAGLE|EAGLE]] zu entwerfen. Mehr dazu wenn wir damit fertig sind. | ||
=== Drucker ansteuern === | |||
[[Datei:Arduino_drucker_01.jpg|thumb|right|Vom Arduino direkt zum Drucker]] | |||
Auch vor einem alten Nadeldrucker haben wir nicht halt gemacht und haben ihn direkt mit 8 Datenleitungen, 3 Controlleitungen (nSTROBE, nACK und BUSY) sowie Masse an unseren Arduino angeschlossen. Dann nur noch schnell ein wenig kaputten [http://www.beyondlogic.org/spp/parallel.htm Centronics-Handshake] implementiert und der Drucker druckte los (naja, genaugenommen hat er auch schon losgedruckt, als auf dem Arduino noch ein LED-Blink-Programm oder so lief.) | |||
Als wir dann stilvoll etwas [[Pr0n]] ausdrucken wollten, stießen wir auf ein Problem: Strings werden aus dem Programmcode im Flash nochmal in den RAM des Atmels kopiert, was unserem Gerät nicht sehr gut tat -- der Arduino tute nichts mehr und ließ sich sogar nur noch mit Mühe re-programmieren. Also lernten wir, wie man die Strings [http://arduino.cc/en/Reference/PROGMEM direkt aus dem Flash liest]. Den fertigen Sketch mit Pinbelegung etc. im Quellcode gibt's [[Media:Druckerfoo.zip|hier (Zip)]]. | |||
=== Charlieplexing === | |||
Auch wir wollten wir uns an Tri-State-Logik und im Speziellen am [[Wikipedia:Charlieplexing|Charlieplexing]] versuchen. Das war gar nicht so sehr zu verstehen und die Erweiterung auf 3 Eingänge und 4*3=12 LEDs war kein Problem. Hier der Schaltplan: | |||
[[Bild:4pins.png]] | |||
=== Blinkenthrowies === | |||
[[Datei:Blinkenthrowies.png|thumb|right|Schaltplan]] | |||
Eine weitere Aufgabe, die wir uns gegeben hatten, war die (analoge) Schaltung der [[Blinkenthrowies]] zu verstehen und einen Prototypen zu basteln. Nach einigem Kampf mit dem Steckbrett hat der Prototyp funktioniert. Nach einigem Kampf am Whiteboard setzte ein (begrenztes) Verständnis der Schaltung ein. Was zur Hölle macht die Diode da? | |||
[Felix] Arbeitspunkteinstellung für den Pseudothyristor (Kompensation des Spannungsverlusts an der Basis-Emitterdiode des oberen Transistors) und Temperaturstabilisierung. | |||
[Blueloop] Da so eine Diode ab ca. 0.7V zu leiten anfängt. Liegt in einer Schaltung wie dieser mit einem Vorwiderstand an der Diode konstant 0.7V an. Das heisst an der Stelle wo es zum Transistor geht liegt Betriebsspannung minus 0,7V (zb. bei einem 9V Block 8,3V) Wird jetzt der Kondensator über den 6k8 Ohm Widerstand langsam aufgeladen, dann kommt irgendwann der Punkt wo diese Spannung größer als diese 8,3V ist, in diesem Moment schalten die Transistoren und entladen den Kondensator über die LED. Die Diode erzeugt sozusagen die Referenz was als "Kondensator ist voll" angesehen werden soll. | |||
:[NicApicella] @Blueloop: Das war auch unsere Vermutung — aber dann die Frage: Könnte man nicht einfach die Diode durch einen Widerstand ersetzen? Und (egal ob ja oder nein) warum? | |||
::[Felix] Das geht nicht wirklich, da der Spannungsabfall der Diode relativ unabhängig von der Versorgungsspannung ist, die ja mit der Zeit sinkt; der Spannungsabfall über einem 2. Widerstand im Spannungsteiler ist hingegen linear abhängig von der Versorgungsspannung, weshalb sich der Arbeitspunkt verschieben würde. | |||
::[Blueloop] Funktionieren würde es schon, nur wenn der Spannungspunkt zu hoch ist schaltet es nie, ist er zu niedrig verschwendet es Helligkeit. So wie die Schaltung jetzt ist, ist es von der aktuellen Batteriespannung unabhängig. Allerdings ändert sich die Blinkfrquenz mit der Batteriespannung. | |||
Natürlich gäbe es auch deutlich [http://c2.com/cybords/?ComputerizedThrowie einfachere Schaltungen, die sich beispielsweise eines ATtiny zur Blinkensteuerung bedienen]; aber dann würden wir nichts dabei lernen. | |||
:[[[Neingeist]]] naja einfacher. man muss da ja auch noch den attiny programmieren, das können wir bis dato ja auch noch nicht. | |||
::[NicApicella] Wollen wir das mal probieren? Flashgerät gibt's wohl im Club (ob der tut?); Preise starten ab ca. 1 Euro für'n ATtiny. Das ginge ja in die Richtung "beliebige Atmels verbauen" bzw. Projektpersistenz! Ich fänd's gar keine so schlechte Idee. | |||
===Persistenz von Projekten (Vorbemerkungen; war: Blinkenthrowies v.2)=== | |||
Das im Club sich befindende [http://www.pollin.de/shop/dt/NTI5OTgxOTk-/Bausaetze/Diverse/ATMEL_Evaluations_Board_V2_0_1_Fertigmodul.html ATMEL Evaluations-Board] funktioniert einwandfrei: Nach kürzerem basteln konnten Neingeist & Nicola unter Zuhilfenahme des Clublaptops einen ATtiny dazu bringen, eine LED blinken zu lassen (Anschluss über COM-to-USB-Adapter an den ISP-Port). (Es war sogar ein ATtiny13, der laut Boardbeschreibung gar nicht hätte funktionieren sollen; der mag ATtiny12 und ATtiny15 wohl lieber.) Geholfen haben uns dabei [http://avra.sourceforge.net/ AVRA] (der aus ATMEL-Assembler HEX ausspuckt) und [http://www.nongnu.org/avrdude/ AVRDUDE] (zum lesen/beschreiben vom ATMEL). | |||
=== Sound === | |||
Ein paar Sound-Experimente gibt's bei [https://github.com/neingeist/arduinisten/tree/master/projekte/soundz GitHub] zu bestaunene. Der Aufbau ist recht einfach: einfach einen alten Lautsprecher mit einem Widerstand oder besser Potentiometer (für die Lautstärkekontroller) anschließen, und ab geht's. | |||
=== Minimalarduino === | |||
[[Datei:Atmega328boot1.jpg|thumb|right|Den Bootloader auftragen und kräftig verreiben]] | |||
Im wesentlichen dem Tutorial [http://arduino.cc/en/Tutorial/ArduinoToBreadboard ArduinoToBreadboard] folgen. Der Arduino Duemillanove hat praktischerweise einen Sockel, d.h. wir konnten danach auch testen, ob alles „wie orischinool“ funktioniert, indem wir den bebootloaderten ATmega328 auf den Arduino packten. Zum Testen haben wir dann einfach den Blink-Sketch draufgeworfen. Ein praktischer Zwischenschritt, um danach dann die Minimalversion auf dem Breadboard zu bauen, frei nach [http://shrimping.it/blog/shrimp/ ShrimpingIT]. [https://entropia.de/Datei:Atmega328_blink.jpg Proof!] | |||
=== ATtiny85 programmieren === | |||
Es gibt eine exquisite Anleitung bei [http://hlt.media.mit.edu/?p=1695 High-Low Tech], wie man einen ATtiny85 über einen Arduino programmiert. Ein besonders praktischer Aspekt ist hier, dass die Dinger um einen Euro kosten. Wir haben das Ding jetzt auch nur eine [https://entropia.de/Datei:Attiny85_1.jpg LED blinken] lassen um's zu testen; sie eignen sich aber auch um über V-USB + wenige Komponenten USB-Schabernack zu betreiben. | |||
== Ziele == | |||
Ziel- und Motivationsideensteinbruch: | |||
* Elektronik-Basics | |||
* Schieberegister spielen | |||
* Oszi-Grafik fertigmachen / DAC | |||
* Operationsverstärker / Mini-Synthesizer | |||
* USB spielen | |||
* USB-Tastatur-Proxy | |||
* LED-Matrix | |||
* [http://cs.nyu.edu/~jhan/ledtouch/index.html LED Touch Sensing] | |||
* PWM-Chips | |||
* Disney Sound Source | |||
* GPS-Mäuse zum Laufen bringen | |||
* ZigBee | |||
* Lochstreifenplatine/EAGLE | |||
* Baggersee verfluchen | |||
* Gehäuse basteln | |||
* Beliebige Atmels verbauen | |||
* Pong "fertig" | |||
* DTMF/Telefon | |||
* SD-Kartenleser | |||
* Beschleunigungsensoren | |||
* [http://hackaday.com/2010/07/11/16-pixel-handheld-gaming/ 16-pixel handheld gaming] | |||
== Links == | == Links == | ||
'''Allgemein:''' | |||
* [http://www.mikrocontroller.net/articles/Absolute_Beginner#Grundausstattung_f.C3.BCr_das_Elektroniklabor Grundausstattung für das Elektroniklabor] | * [http://www.mikrocontroller.net/articles/Absolute_Beginner#Grundausstattung_f.C3.BCr_das_Elektroniklabor Grundausstattung für das Elektroniklabor] | ||
* [http://www.arduino.cc/en/uploads/Hacking/Makefile makefile to build sketches from the command line without the Arduino environment] | * [http://www.arduino.cc/en/uploads/Hacking/Makefile makefile to build sketches from the command line without the Arduino environment] | ||
* http://github.com/frickel/shellduino-skel und die Doku dazu http://wiki.github.com/frickel/shellduino-skel | * http://github.com/frickel/shellduino-skel und die Doku dazu http://wiki.github.com/frickel/shellduino-skel | ||
Zum löten üben: | '''Zum löten üben:''' | ||
* [http://www.youtube.com/watch?v=wQXhny3R7lk&feature=related Professional SMT Soldering No. 2 (Revised) - Surface Mount] | * [http://www.youtube.com/watch?v=wQXhny3R7lk&feature=related Professional SMT Soldering No. 2 (Revised) - Surface Mount] | ||
* [http://www.youtube.com/watch?v=c3iPpsnHKds SMD Bauteile löten, Anleitung, TSOP] | * [http://www.youtube.com/watch?v=c3iPpsnHKds SMD Bauteile löten, Anleitung, TSOP] | ||
Zeile 134: | Zeile 219: | ||
Wichtigster Punkt dabei: Üben, üben und üben und immer genügend Flussmittel verwenden, am besten in der NoClean Ausführung, dann klebt hinterher nicht die ganze Platine. Entlötlitze sollte man auch immer da haben. | Wichtigster Punkt dabei: Üben, üben und üben und immer genügend Flussmittel verwenden, am besten in der NoClean Ausführung, dann klebt hinterher nicht die ganze Platine. Entlötlitze sollte man auch immer da haben. | ||
'''Theoretische Grundlagen:''' | |||
* [http://www.ims.kit.edu/327_617.php Vorlesung "Elektronische Schaltungen" (insbesondere Interessant: Skript! Passwort dafür: es2010)] | |||
[[Kategorie:Arduino]] | |||
[[Kategorie: |
Aktuelle Version vom 1. Juni 2019, 09:50 Uhr
Die Anonymen Arduinisten oder auch Institut für angewandte Inkompetenz treffen sich nahezu jeden Dienstag ab ca. 19 Uhr im Club, um mit Arduino und anderer Elektronik zu spielen trafen sich dienstags im Club. Wir verstanden uns als Selbsthilfegruppe: Arduino und Elektronik von Kackn00bs für Kackn00bs. Also waren gerade völlige Beginner willkommen bei uns mitzumachen.
Projekte
LCD-Display
Nach den ersten paar LED-Spielereien (z.B. fadende LEDs und Wir-lernen-was-Pull-up-Widerstände-sind) haben wir ein 40x2 Text-LCD-Display (Sharp LM40A21) aus dem Elektronik-Müll des Clubs gefischt, und zuerst mit ein paar Kabeln in der 4-Bit-Variante an den Arduino gedrahtet. Als Software bzw. Library auf dem Arduino diente uns die LCD4BitLibrary, die uns das eigenständige Auscoden des ganzen Timings erspart hat. (Das nächste Mal würden wir aber wohl gleich die LiquidCrystal-Library aus dem Arduino-Zip nehmen...) Überraschenderweise hat das sogar funktioniert, allerdings hat das Display nach einer Weile nur noch Müll angezeigt -- wir haben natürlich gleich einen Bug gefunden:
Sharp LM40A21, 40x2, using HD44780A00. Mostly worked, adding a delay(2) after the CMD_HOME in cursorTo() fixed periodically garbled display problem. The HD44780 datasheet (pdf) I looked at specifies a 1.52ms delay for the Return home command at nominal f_osc of 270kHz, but it appears that this value could be as high at 2.16ms at low end of f_osc range, 190Khz.
--- LCD4Bit.orig/LCD4Bit.cpp 2006-10-16 04:29:44.000000000 +0200
+++ LCD4Bit/LCD4Bit.cpp 2009-11-04 17:51:50.205659741 +0100
@@ -202,7 +202,8 @@
//if this is not a 2-line LCD4Bit instance, will always position on first line.
void LCD4Bit::cursorTo(int line_num, int x){
//first, put cursor home
commandWrite(CMD_HOME);
+ commandWrite(CMD_HOME);
+ delayMicroseconds(1520); // neingeist, http://www.arduino.cc/playground/Code/LCD4BitLibrary
//if we are on a 1-line display, set line_num to 1st line, regardless of given
if (g_num_lines==1){
Danach hat alles sauber geklappt, das Display hat keine Mucken mehr gemacht. Allerdings haben wir das Delay später wieder rausgenommen, da cursorTo()
ohnehin ineffizient implementiert war (siehe unten.)
Duinopong
![](/images/thumb/6/60/Duinopong.png/300px-Duinopong.png)
Die lose Verkabelung des Displays an den Arduino war etwas unpraktisch, also haben wir das Display bzw. dessen Flachbandkabel an eine Lochrasterplatine gelötet, nicht ohne über eine Lücke zwischen zwei Steckleisten auf dem Arduino-Board zu fluchen: Diese hat nämlich nicht den für die Lochrasterplatine geeigneten Abstand von 2,54 mm (0,1 Zoll). Darauf kann man also nicht eine geeignet gestaltete und mit Pins versehene Lochrasterplatine stecken. Also haben wir die beiden Steckleisten benutzt, die ins Raster passen und die andere ignoriert.
Das verwendete Display bzw. dessen Steuerchip erlaubt das Erzeugen von 8 benutzerdefinierten Buchstaben (5x8). Warum also nicht diese benutzen um den Ball eines Pong pixelgenau in 200x16 statt 40x2 darzustellen? :-) Der eigentliche Code zum Setzen der benutzerdefinierten Characters ist nu nicht sehr schön gelungen, aber das nennt sich wohl Rapid Prototyping:
#define CHAR_PADDLE paddle // 0 == left, 1 == right
// gen char
lcd.commandWrite(0x40+CHAR_PADDLE*8);
for (uint8_t i = 0; i<8; i++) {
if(i == (pos & 0x7) || i-1 == (pos & 0x7) || i+1 == (pos & 0x7) ) {
if (paddle == 0) {
lcd.print(0b00011);
} else {
lcd.print(0b11000);
}
} else {
lcd.print(0b00000);
}
}
Außerdem mussten wir noch einen (ebenfalls aus dem Elektronik-Schrott geborgenen) Rotary-Encoder zur Kooperation überreden. Ein Rotary-Encoder kodiert eine Drehbewegung als Bitsequenz auf seine zwei Ausgänge, in unserem Fall hatten wir es wohl mit einem 2-Step-Rotary-Encoder zu tun: Eine Bewegung um einen "Klick" in die eine Richtung erzeugt eine Bitsequenz 00-01-11, eine Drehung in die andere Richtung die Sequenz 00-10-11 (bzw. ähnlich vom Zustand 11 nach 00). Das ist ein sogenannter Gray-Code: Es wird eigentlich nur hoch- bzw. runtergezählt, allerdings derart kodiert, dass sich immer nur ein Bit pro Änderung ändert -- was Fehler beim Auslesen minimiert. Letztlich haben wir dann ein wenig Code von mikrocontroller.net geborgt, um das ganze in der empfohlenen Methode umzusetzen: Ein Timer-Interrupt samplet die Werte "schnell genug" und stellt sie zum Auslesen in einer globalen Variable enc_value zur Verfügung.
Gray-Code | Bedeutung |
---|---|
00 | 0 |
01 | 1 |
11 | 2 |
10 | 3 |
Naja und dann stellte sich noch ein weiteres Mal heraus, dass die LCD4BitLibrary Schrott ist: Das Cursor-Setzen ist gewaltig ineffizient implementiert ("Return-Home" und zig mal vor (0x14), statt einfach die "Cursor-Setzen"-Funktion (0x80) des Steuerchips zu verwenden), so dass uns das auch noch eine Weile aufhielt und wir schliesslich dann einfach die Library gefixt haben (statt gleich auf die gescheite LiquidCrystal-Lib zu nehmen...)
--- LCD4Bit.orig/LCD4Bit.cpp 2006-10-16 04:29:44.000000000 +0200
+++ LCD4Bit/LCD4Bit.cpp 2009-11-04 17:51:50.205659741 +0100
@@ -202,7 +202,8 @@
//if this is not a 2-line LCD4Bit instance, will always position on first line.
void LCD4Bit::cursorTo(int line_num, int x){
//first, put cursor home
- commandWrite(CMD_HOME);
+ //commandWrite(CMD_HOME);
+ //delayMicroseconds(1520); // neingeist, http://www.arduino.cc/playground/Code/LCD4BitLibrary
//if we are on a 1-line display, set line_num to 1st line, regardless of given
if (g_num_lines==1){
@@ -210,12 +211,15 @@
}
//offset 40 chars in if second line requested
if (line_num == 2){
- x += 40;
+ x += 64;
}
//advance the cursor to the right according to position. (second line starts at position 40).
- for (int i=0; i<x; i++) {
- commandWrite(0x14);
- }
+ //for (int i=0; i<x; i++) {
+ // commandWrite(0x14);
+ //}
+
+
+ commandWrite(0x80+x);
}
//scroll whole display to left
I²C
Weil wir gerade nicht besseres zu tun hatten, dachten wir uns: Lass uns unsere Arduinos vernetzen! Gesagt, getan, wir haben die I²C-Library aus dem Arduino-Paket entdeckt und unsere Arduinos mit zwei Drähten verbunden. Mit den bereitgestellten Funktionen geht das sehr gut, man muss nur einen der Arduinos als Master arbeiten lassen.
Wir haben noch GND jeweils verbunden ohne jedoch wirklich zu wissen, ob das nun elektrisch so die beste Idee ist -- vermutlich nicht ;-) -- Doch, das ist sogar notwendig, damit die beiden Controller ein gemeinsames Bezugspotential haben; sonst kommt da nur Datenmüll an.
Dallas 1wire Bus - Temperatursensoren
Ein bisschen Code fragt alle Sensoren am Bus nach der aktuellen Temperatur und schreibt die SensorID und den gemessenen Wert nach Serial. Weiter Infos gibt es unter Temperatursensoren.
Mini-LED-Cube
Wir haben uns eines Samstagbends vom entropianischen LED-Cube und einem anderen Mini-LED-Cube inspirieren lassen. Da wir sowieso etwas löten lernen mussten, haben wir uns schnell einen völlig schiefen 3x3x3-LED-Würfel zusammengelötet. Ganz nach dem Motto "Schön ist: was funktioniert" präsentieren wir hier unseren Mini-LED-Cube in formschöner Animation:
Nach diesem Proof-of-Concept-Würfel löten wir uns vielleicht mal noch was Schönes :-)
Oszi-Grafik
Ein anderer Mensch im Club hatte bereits mit unserem Oszi rumgespielt und Grafik mittels FORTH auf einem Atmel-Entwicklerboard auf dem Gerät dargestellt. Das wollten wir jetzt mit unseren Arduinos nachmachen.
Der erste Versuch ging ungefähr so: Wir haben mit der Pulsweitenmodulation des Arduino "analoge" Werte auf zwei Pins (X und Y) gelegt, diese Werte mit jeweils einem RC-Glied geglättet und das ganze dann mit der XY-Funktion des Oszis anzeigen lassen. Das hat auch halbwegs geklappt, allerdings reagiert das RC-Glied nicht so gut auf schnelle Änderungen -- es gibt eher Kurven als harte Kanten bei Änderungen -- , so dass damit höchstens ein paar visuelle Effekte machbar sind. Aber es war schonmal ein Erfolg.
Als nächstens haben wir uns dann zwei Digital-Analog-Converter-Chips (DACs) besorgt (TDA8702), und versucht eine Schaltung in EAGLE zu entwerfen. Mehr dazu wenn wir damit fertig sind.
Drucker ansteuern
Auch vor einem alten Nadeldrucker haben wir nicht halt gemacht und haben ihn direkt mit 8 Datenleitungen, 3 Controlleitungen (nSTROBE, nACK und BUSY) sowie Masse an unseren Arduino angeschlossen. Dann nur noch schnell ein wenig kaputten Centronics-Handshake implementiert und der Drucker druckte los (naja, genaugenommen hat er auch schon losgedruckt, als auf dem Arduino noch ein LED-Blink-Programm oder so lief.)
Als wir dann stilvoll etwas Pr0n ausdrucken wollten, stießen wir auf ein Problem: Strings werden aus dem Programmcode im Flash nochmal in den RAM des Atmels kopiert, was unserem Gerät nicht sehr gut tat -- der Arduino tute nichts mehr und ließ sich sogar nur noch mit Mühe re-programmieren. Also lernten wir, wie man die Strings direkt aus dem Flash liest. Den fertigen Sketch mit Pinbelegung etc. im Quellcode gibt's hier (Zip).
Charlieplexing
Auch wir wollten wir uns an Tri-State-Logik und im Speziellen am Charlieplexing versuchen. Das war gar nicht so sehr zu verstehen und die Erweiterung auf 3 Eingänge und 4*3=12 LEDs war kein Problem. Hier der Schaltplan:
Blinkenthrowies
Eine weitere Aufgabe, die wir uns gegeben hatten, war die (analoge) Schaltung der Blinkenthrowies zu verstehen und einen Prototypen zu basteln. Nach einigem Kampf mit dem Steckbrett hat der Prototyp funktioniert. Nach einigem Kampf am Whiteboard setzte ein (begrenztes) Verständnis der Schaltung ein. Was zur Hölle macht die Diode da?
[Felix] Arbeitspunkteinstellung für den Pseudothyristor (Kompensation des Spannungsverlusts an der Basis-Emitterdiode des oberen Transistors) und Temperaturstabilisierung.
[Blueloop] Da so eine Diode ab ca. 0.7V zu leiten anfängt. Liegt in einer Schaltung wie dieser mit einem Vorwiderstand an der Diode konstant 0.7V an. Das heisst an der Stelle wo es zum Transistor geht liegt Betriebsspannung minus 0,7V (zb. bei einem 9V Block 8,3V) Wird jetzt der Kondensator über den 6k8 Ohm Widerstand langsam aufgeladen, dann kommt irgendwann der Punkt wo diese Spannung größer als diese 8,3V ist, in diesem Moment schalten die Transistoren und entladen den Kondensator über die LED. Die Diode erzeugt sozusagen die Referenz was als "Kondensator ist voll" angesehen werden soll.
- [NicApicella] @Blueloop: Das war auch unsere Vermutung — aber dann die Frage: Könnte man nicht einfach die Diode durch einen Widerstand ersetzen? Und (egal ob ja oder nein) warum?
- [Felix] Das geht nicht wirklich, da der Spannungsabfall der Diode relativ unabhängig von der Versorgungsspannung ist, die ja mit der Zeit sinkt; der Spannungsabfall über einem 2. Widerstand im Spannungsteiler ist hingegen linear abhängig von der Versorgungsspannung, weshalb sich der Arbeitspunkt verschieben würde.
- [Blueloop] Funktionieren würde es schon, nur wenn der Spannungspunkt zu hoch ist schaltet es nie, ist er zu niedrig verschwendet es Helligkeit. So wie die Schaltung jetzt ist, ist es von der aktuellen Batteriespannung unabhängig. Allerdings ändert sich die Blinkfrquenz mit der Batteriespannung.
Natürlich gäbe es auch deutlich einfachere Schaltungen, die sich beispielsweise eines ATtiny zur Blinkensteuerung bedienen; aber dann würden wir nichts dabei lernen.
- [[[Neingeist]]] naja einfacher. man muss da ja auch noch den attiny programmieren, das können wir bis dato ja auch noch nicht.
- [NicApicella] Wollen wir das mal probieren? Flashgerät gibt's wohl im Club (ob der tut?); Preise starten ab ca. 1 Euro für'n ATtiny. Das ginge ja in die Richtung "beliebige Atmels verbauen" bzw. Projektpersistenz! Ich fänd's gar keine so schlechte Idee.
Persistenz von Projekten (Vorbemerkungen; war: Blinkenthrowies v.2)
Das im Club sich befindende ATMEL Evaluations-Board funktioniert einwandfrei: Nach kürzerem basteln konnten Neingeist & Nicola unter Zuhilfenahme des Clublaptops einen ATtiny dazu bringen, eine LED blinken zu lassen (Anschluss über COM-to-USB-Adapter an den ISP-Port). (Es war sogar ein ATtiny13, der laut Boardbeschreibung gar nicht hätte funktionieren sollen; der mag ATtiny12 und ATtiny15 wohl lieber.) Geholfen haben uns dabei AVRA (der aus ATMEL-Assembler HEX ausspuckt) und AVRDUDE (zum lesen/beschreiben vom ATMEL).
Sound
Ein paar Sound-Experimente gibt's bei GitHub zu bestaunene. Der Aufbau ist recht einfach: einfach einen alten Lautsprecher mit einem Widerstand oder besser Potentiometer (für die Lautstärkekontroller) anschließen, und ab geht's.
Minimalarduino
Im wesentlichen dem Tutorial ArduinoToBreadboard folgen. Der Arduino Duemillanove hat praktischerweise einen Sockel, d.h. wir konnten danach auch testen, ob alles „wie orischinool“ funktioniert, indem wir den bebootloaderten ATmega328 auf den Arduino packten. Zum Testen haben wir dann einfach den Blink-Sketch draufgeworfen. Ein praktischer Zwischenschritt, um danach dann die Minimalversion auf dem Breadboard zu bauen, frei nach ShrimpingIT. Proof!
ATtiny85 programmieren
Es gibt eine exquisite Anleitung bei High-Low Tech, wie man einen ATtiny85 über einen Arduino programmiert. Ein besonders praktischer Aspekt ist hier, dass die Dinger um einen Euro kosten. Wir haben das Ding jetzt auch nur eine LED blinken lassen um's zu testen; sie eignen sich aber auch um über V-USB + wenige Komponenten USB-Schabernack zu betreiben.
Ziele
Ziel- und Motivationsideensteinbruch:
- Elektronik-Basics
- Schieberegister spielen
- Oszi-Grafik fertigmachen / DAC
- Operationsverstärker / Mini-Synthesizer
- USB spielen
- USB-Tastatur-Proxy
- LED-Matrix
- LED Touch Sensing
- PWM-Chips
- Disney Sound Source
- GPS-Mäuse zum Laufen bringen
- ZigBee
- Lochstreifenplatine/EAGLE
- Baggersee verfluchen
- Gehäuse basteln
- Beliebige Atmels verbauen
- Pong "fertig"
- DTMF/Telefon
- SD-Kartenleser
- Beschleunigungsensoren
- 16-pixel handheld gaming
Links
Allgemein:
- Grundausstattung für das Elektroniklabor
- makefile to build sketches from the command line without the Arduino environment
- http://github.com/frickel/shellduino-skel und die Doku dazu http://wiki.github.com/frickel/shellduino-skel
Zum löten üben:
- Professional SMT Soldering No. 2 (Revised) - Surface Mount
- SMD Bauteile löten, Anleitung, TSOP
- SMD soldering / loeten QFP Loethonig
Wichtigster Punkt dabei: Üben, üben und üben und immer genügend Flussmittel verwenden, am besten in der NoClean Ausführung, dann klebt hinterher nicht die ganze Platine. Entlötlitze sollte man auch immer da haben.
Theoretische Grundlagen: