Elektronik_Header_3

 

AtTiny-Würfel reloaded

Basierend auf dem Würfel-Design von 2009 und Sammlung von Erfahrung im Umgang mit AtTinys und deren Stromsparmodi habe ich jetzt ein Programm für meinen Würfel erstellt, das den Betrieb mit einer Knopfzelle erlaubt.

Da der Code diesmal im Arduino-Umfeld entstehen soll, wird ein anderer Programmierer zum Einsatz kommen, der Programmieranschluss muss also überarbeitet werden. Ich habe deshalb zuerst die unsäglichen Programmier-Strippen entfernt - der Link zeigt den PIC-Würfel - der AtTiny-Würfel hatte noch eine Strippe mehr:

AtTiny-Würfel mit Programmier-Strippen

Dafür wurde ein Stecker im 1 mm Raster eingebaut, wie das schon beim FS20 S3 Erfolg zeitigte.

Programmieranschluss - 1 mm Raster Stecker

Der Batteriehalter nimmt eine 3 V Lithium Mangan Knopfzelle der Größe CR16xx auf. Der von mir eingesetzte Keystone 502 Knopfzellenhalter passt gut für eine CR1616, soll aber auch dickere Zellen (CR1620, CR1625, CR1632) aufnehmen. Eine CR1632 kontaktiert zwar gut, “passt” allerdings meiner Meinung nach nicht, die Zelle sitzt schräg in der Halterung. Andere Knopfzellengrößen habe ich nicht getestet.

Der Halter hat einen Abstand von der Platinenunterseite da ich die Führungsstifte nicht in Löchern versenkt habe. Durch diesen Abstand kann der Stecker teilweise unterhalb des Batteriehalters angeordnet werden und ist von oben unsichtbar.

Batteriehalter und Programmieranschluss

Der linke Pin, Pin 6 des Steckers, führt GND. Diesen Pin habe ich vorsichtig direkt hinter dem Plastikkörper nach unten abgeknickt und durch ein Loch in die Massefläche am Taster geführt und dort festgelötet. Anschließend wurde der Stecker mit Sekundenkleber an der Platine befestigt. Die restlichen Signale sind mit Kupferlackdrähten “unsichtbar” unterhalb des Batteriehalters an den Stecker geführt.

Die für die Verbindung des Steckers zur Schaltung notwendigen Löcher in der Platine sind im Layout nicht vorgesehen und wurden nachträglich mit einem 0,8 mm Bohrer in oder neben die vorhandenen Pads für den Programmer-Anschluss gebohrt.

Die Draufsicht zeigt, die Anschlüsse sind nur durchgesteckt und von oben kaum sichtbar:

AtTiny13 Würfel mit Programmieranschluss (unsichtbar)

Gegenüber der ersten Abbildung des AtTiny-Würfels sind die SMD-Vorwiderstände der LEDs hier durch bedrahtete Typen ersetzt. Den gewünschten Wert von jetzt 1,3 kΩ gegenüber dem vorgesehenen Wert von 1 kΩ und dem damals verbauten Wert von 680 Ω hatte ich nicht in SMD vorrätig.

Auch hier passt der für den FS20 S3 erstellte Programmieradapter:

Programmieradapter

Die Anschlussbelegung wurde sinnigerweise identisch wie beim FS20 S3 gewählt :-)


Wie die Arduino-IDE vorbereitet werden muss, um einen AtTiny13 programmieren zu können, ist im Netz beschrieben, darauf möchte ich hier nicht näher eingehen.
Nur soviel: In der Arduino IDE muss unter Voreinstellungen der Download-Link auf einen passenden Tiny-Core gesetzte werden.

Ich habe ”Optiboot” von James Sleeman verwendet. Der Eintrag unter “Zusätzliche Boardverwalter-URLs” in den Voreinstellungen muss dann

https://raw.githubusercontent.com/sleemanj/optiboot/master/dists/package_gogo_diy_attiny_index.json

lauten. Danach kann im Boardverwalter AtTiny13 gesucht und dessen Unterstützung installiert werden.

Hinweis: Im Zuge der Implementierung des Programms bin ich darauf gestoßen, dass das Einschalten des internen PullUp an Pin5 (PB0) nicht ausreicht, es muss ein externer PullUp eingelötet werden. Ich habe hierfür einen 30 kΩ Widerstand verwendet.

    Aktualisierung
    Der Grund für das fehlerhafte Verhalten des internen PullUp war meine Sparfuchs -Lösung zum Abschalten aller LEDs auf einen Schlag. Ich habe dafür “PORTB = 0” verwendet. Die LEDs wurden auch abgeschaltet, allerdings wurde durch diese Bedienung auch der Eingang mit PullUp für den Taster auf 0 gesetzt.

    Laut Datenblatt kann auf einem als Eingang geschalteten Pin durch Ausgabe des entsprechenden Wertes ein Software-Interrupt ausgelöst werden. Das habe ich durch Schreiben einer “0” (Null) auf dem gesamten Port B getan.
    In Folge wurden im Programmlauf etliche IRQs mehr ausgelöst, als mein Programm erwartet hat, daher die Fehlfunktion.
    Das ist jetzt geändert, der externe PullUp kann entfallen.

Der im AtTiny13 vorhandene Speicher für das Programm ist mit 1 kByte nicht üppig bemessen, so dass ich im ersten Ansatz wirklich nur einen einfachen Zufallszahlengenerator mit entsprechenden Anzeigeroutinen und den Deep Sleep Mode implementiert habe. Für mehr war kein Platz, da muss ich noch ein bisschen optimieren, denke ich.

Aber immerhin kann mit diesem Programm der AtTiny-Würfel jetzt endlich auch mit Batteriebetrieb eingesetzt werden, denn ohne Anzeige der Augenzahl, also im Sleep Mode, verbraucht der Microcontroller maximal 0,1 µA oder 100 nA.

Bei 55 mAh Kapazität einer CR 1616 Knopfzelle (beispielhaft von VARTA) sollte der Würfel also viele Jahre (berechnet ca. 50-60 Jahre) im Sleepmode durchhalten. Genaugenommen liegt dieser gemessene “Verbrauch” noch unterhalb der Selbstentladung solcher Zellen.

Im Betrieb, also in den kurzen Zeiten wenn das Programm die Augenzahl errechnet und anzeigt, liegt der Strom bei 4..15 mA.


Der in der Arduino-Umgebung eingesetzte Zufallszahlengenerator erzeugt prinzipiell  keine echten Zufallszahlen, sondern nur eine pseudozufällige Aneinanderreihung von Zahlen. Bei jedem Einschalten des Würfels, also dem Einsetzen einer neuen Batterie, werden immer Zahlen in der gleichen Reihenfolge ausgegeben werden. Das wäre eigentlich kein Grund zum Jammern, die Batterie muss ja nur selten getauscht werden, aber es gibt Abhilfe, also wird sie implementiert.

Um den Zufallszahlengenerator zufälliger zu machen, muss er über einen Startwert randomisiert werden. Dieser Startwert bestimmt den Einstiegspunkt in die pseudozufällige, immer gleiche Zahlenfolge, wodurch die erzeugten Zahlenwerte dann tatsächlich zufällig erscheinen.

In einem Microcontroller sind allerdings die Möglichkeiten zur Erzeugung eines zufälligen Startwertes naturgemäß eher eingeschränkt. Die Literatur schlägt vor, einen unbeschalteten Analogeingang einzulesen. Durch elektromagnetische Einstrahlung könnte eine zufällige Zahl zwischen 0 und 1023 erzeugt werden. Untersuchungen haben aber ergeben, dass diese Methode bei weitem nicht so zufällige Werte ergibt wie man erwarten könnte. Zudem würde die Aktivierung der Analog-Funktionalität den Stromverbrauch erhöhen und vor allem die Programmgröße negativ beeinflussen (der AtTiny13 hat nur 1024 Byte Programmspeicher, der bereits von Anzeigefunktionen und Tastenabfrage zu 90% gefüllt ist).

Selbst der Versuch, über die Tastendruckdauer eine Variabilität einzubringen ist an den engen Speichergrenzen gescheitert.

Letztlich kam ich nur voran, indem ich Standardfunktionen der Arduino Umgebung durch  direkte Portmanipulationen ersetzt habe. Durch folgendes Konstrukt habe ich ausreichend Platz gewonnen, um einen Zähler zu implementieren, der einmalig nach Einsetzen der Batterie eine Zahl aus der Dauer des Tastendrucks ableitet, die zur Randomisierung des Zufallszahlengenerators herangezogen wird:

// Optimierungen
#undef digitalRead()
#define
digitalRead(pinnummer) ((PINB) & (1 << (pinnummer)))

Der Trick kann funktionieren, da die Macher von Arduino in ihren Libs immer versuchen, alle Eventualitäten zu berücksichtigen. So ist z.B. beim Einlesen eines digitalen Eingangs berücksichtigt, dass dieser Eingang mit einem der Timer verknüpft sein könnte. Um diese Möglichkeit korrekt abzuhandeln, ist Einiges an Code in der Library vorgesehen, das bei jedem Aufruf von digitalRead() mit in das resultierende Programm eingebaut wird.

Da ich weiß, dass mein Eingang ausschließlich zum Einlesen des Status des Tasters verwendet wird, muss ich solche Eventualitäten nicht berücksichtigen, kann also den Pin direkt abfragen und somit wertvollen Programmspeicher einsparen.

Einen ähnlichen Trick habe ich beim Setzen der Ausgangs-Bits der LEDs verwendet, musste aber feststellen, dass die Implementierung von bitSet() bereits optimal umgesetzt ist. Hierdurch konnte keine Einsparung am resultierenden Code erreicht werden - im Gegenteil, die im Code noch als Kommentar vorhandenen Befehle
bitSet(PORTB, LEDXuY) würden das Programm in der Tat um 4 Byte kleiner machen.
Nur die auskommentierte Zeile mit PORTB = 0 darf auf keinen Fall aktiviert werden!

Das geänderte Programm stelle ich als C-Sourcen in Arduino Syntax zur Verfügung.


Übrigens: Der interne PullUp ist natürlich doch in der Lage, den Eingangspin des Tasters sauber auf High zu ziehen, der Grund für das Versagen dieses Ansatzes ist ein Anderer.

Der oben bereits verlinkte Code enthält das erneut geänderte Programm mit eingeschaltetem internem PullUp am Taster. Der externe Widerstand muss nicht eingebaut werden.

Viel Spaß!


Besucher seit
25.11.2000

>