-
Notifications
You must be signed in to change notification settings - Fork 1
Die Entwicklung des TiNo2
Der Atmega328p war nicht mehr zu bekommen. Ein neuer, verfügbarer Prozessor muss her. Zuerst hab ich mir eine Kopie angesehen, den LGT8F328. Es ist der Versuch eines Klons, aber schon das Pinout passt nicht in bestehende Layouts. Der Chip wurde offensichtlich auf Geschwindigkeit und nicht auf niedrigen Stromverbrauch optimiert, daher für mein Projekt ungeeignet.
Anforderungen:
- gleiche oder bessere technische Daten aufweisen als ATmega328p, z.B. Stromverbrauch.
- grosser Flash Speicher z.B. um ein LoRaWAN Node zu realisieren.
- Es sollte es ein Paket für die Arduino IDE geben.
- niedriger Preis.
- in einer Bauform lieferbar, die man auch als Amateur verarbeiten kann (also kein BGA)
- verfügbar und lieferbar.
Meine Wahl fiel auf die megaAVR 0-Series Prozessoren.
Die technischen Daten des ATmega4808 sind mit dem Atmega328P vergleichbar, mit zahlreichen, teilweise sehr brauchbaren Verbesserungen.
- Eine wirklich gute Sache ist das SRAM von 4kBytes beim Atmega3208 und sogar 6kByte beim Atmega4808. Beim Atmega328P waren es nur 2kByte, wobei ich dieses Limit mit dem TiNo schon erreicht habe.
- Beim Stromverbrauch ist man anscheinend im aktiven Modus sowie im Ruhemodus an eine Grenze gekommen. Die Werte im Datenblatt unterscheiden sich nur marginal vom Atmega328P.
- Das EEPROM hat sich auf 256 Byte (plus 64 Byte "Userrow") reduziert. Das schmerzt, weil ich bisher eine umfangreiche Tabelle im EEPROM gespeichert hatte welche die Drift des 32 MHz Quarzes des RFM Moduls modelliert.
- Schade finde ich dass der ADC immer noch nur 10 Bit Auflösung hat. Das reicht für die Batterieüberwachung im TiNo, aber für andere Aufgaben wäre eine 12 bit Auflösung wirklich wünschenswert. Als hätte Microchip meinen Wunsch erhört, haben sie die Nachfolge Serie AVR-DD mit einem 12-Bit ADC ausgestattet.
Daneben findet man bei dem neuen Prozessor eine Reihe neuer Funktionen,
- das "Event System",
- eine konfigurierbare Logik, CCL = custom configurable logic
- CIP = Core Independent Peripherals"
Alle diese Funktionsbausteine funktionieren völlig unabhängig vom Prozessor, nachdem sie konfiguriert sind.
Damit kann man z.B. eine LED blinken lassen während der Prozessor schläft, als einfachstes Beispiel. Für die Verwendung dieser Möglichkeiten beim TiNo2 fehlt mir allerdings im Moment die Phantasie. Eine Anwendung könnte sein, Pulse eines Anemometers zu zählen, den Prozessor regelmäßig aufzuwecken und den Zählerstand auslesen.
Ob und wie das geht weiß ich im Moment noch nicht.
Die Angaben im Datenblatt kann ich nicht nachvollziehen. Im Datenblatt ist ein Hinweis, dass die Maximalwerte den Limits in der Produktion entsprechen. Das deutet darauf hin dass Microchip einfach einen Takt anlegt und den unprogrammierten Chip vermisst. Das ist natürlich unrealistisch. Ich verwende zum Messen ein Testprogramm, aktiviere den internen Taktoszillator und messe den Strom während einer ewigen Schleife.
Takt[MHz] | gemessen@3.3V[mA] | Datenblatt |
---|---|---|
1 | 0.91 | |
4 | 2.17 | |
5 | 2.70 | 1.6 |
8 | 3.76 | 2.6 |
10 | 4.72 | 3.2 |
16 | 6.62 | |
20 | 7.44 |
im TiNo2 sind diese Werte sogar noch etwas höher, wohl weil der Sketch viele verschiedene Operationen ausführt, Peripherie anspricht und nicht einfach nur in einer Endlosschleife dreht.
Atmega4808, Atmega3208 und Atmega1608 werden mit dem MegaCoreX unterstützt. Daneben gibt es noch einen Core für einen "Arduino Nano Every", welcher im Prinzip auch funktionieren könnte. Im Prinzip funktionieren einfache Sketches des Atmega328P unverändert auch auf dem Atmega3208. Da die Peripherie der Atmega 0-Serie aber komplett neu ist, wird es bei Timern/PWM, Ruhemodi, Interrupts oder ADC komplizierter, und man muss sich mit dem Datenblatt beschäftigen, soweit man die Möglichkeiten des Chips verstehen will. Hier möchte ich ausdrücklich Stefan Wagner für die Beispiel Sketches danken. Er hat mit dem "Wagiminator" das erste Makerboard zur Verfügung gestellt, und einige grundlegende Code Schnipsel mit dazu die sehr wertvoll für mich sind.
Schlafmodus ist durch den MegaCoreX verfügbar. Der Timer wird mit dem Internen 32 KHz Oszillator betrieben oder per externem 32.768kHz Quarz. In beiden Modi messe ich einen Ruhestrom von etwas unter 2uA.
Mit der RTC und dem dem PIT (Periodic Interrupt Timer) ist ein perfekter Mechanismus vorhanden um den TiNo regelmäßig aus dem Schlaf aufzuwecken und Messungen machen zu lassen. Danke an Stefan Wagner für den Code Schnipsel.
es gibt einen einzigen ADC mit 10 bit. Seine Eingänge und Referenzspannugen kann man auswählen. Nicht alle Pins sind Analogeingänge. Als Referenzspannungen hat man intern 0.55V, 1.1V, 1.5V, 2.4V, 4.3V oder die Versorgungsspannung zur Auswahl. Als ADC Eingang stehen neben 15 möglichen GPIO's auch die interne Referenzspannung und ein Temperatursensor zur Verfügung. Damit kann man ohne externe Bauteile und ganz einfach die Batteriespannung überwachen, mit etwa 10mV Auflösung, wie gehabt. Den Temperatursensor kann man vergessen, trotz Werkskalibrierung liefert der Sensor Messungen von etwa +/- 3 Grad Abweichung von der Referenz.
Wie bisher programmiert die Arduino IDE die Fuses zusammen mit dem Bootloader. Die wichtigste Fuse ist dabei die Auswahl zwischen internem 16MHz oder 20 MHz Osczillator. Ist die Fuse auf 20MHz eingestellt, kann man Code kompilieren der auch mit 10 oder 5 MHz arbeitet, weil der Compiler nur den Frequenzteiler vorgibt (hier 2 oder 4). Beim TiNo ist 16MHz per Fuse voreingestellt. Der Standard Sender Sketch wird für 4 oder 1 MHz Takt kompiliert.
Der Chip operiert mit einem internen 20MHz bzw. 16 MHz Oszillator. Niedrigere Taktfrequenzen erreicht man indem man den Takt herunter teilt. Dies geschieht in der Arduino IDE per Auswahl im Menu. Hinweis an Designer: Die eigentliche F_CPU wird zur Laufzeit in der Function init() eingestellt, die sich in der Core Datei wiring.c findet. Der Atmega4808 hat - anders als sein Vorgänger - KEINEN Quarzoszillator verbaut. Man kann ihn mit einem externen Takt füttern, dazu benötigt man aber einen externen TCXO oder so. Der TiNo2 arbeitet mit dem interen Oszillator, per Fuse auf 16 MHz eingestellt. Beim alten TiNo musste man die Fuses umprogrammieren für den Empfänger Sketch. Das ist jetzt nicht mehr notwendig. Ich wähle für den Empfänger 16MHz und für den Sender 1 MHz Takt.
Anders als beim Atmega328P gibt es keine expliziten externen Interrupts. Es gibt Interrupts für einen ganzen Port. Ein Port fasst immer 8 Pins zusammen. Es gibt Ports von A bis F. Wenn ein Port Interrupt ausgelöst wird, kann man in einem Interrupt-Flag-Register sehen welcher Pin den Interrupt ausgelöst hat. Die Flanke bei der ein Interrupt auslöst kann man nur bei 2 Pins pro Port definieren, nämlich an Pins Px2 und Px6. Das sind die "voll asynchronen Pins". Bei den anderen muss man selbst herausfinden welche Flanke den Interrupt ausgelöst hat, und man muss den Interrupt auf BOTHEDGES stellen, was in der Arduino IDE der Einstellung CHANGE entspricht. Sonst funktioniert der Interrupt nicht. Siehe Datenblatt 16.3.3.1 und Fussnote 2 unter der Tabelle in Abschnitt 4.1. Das ist tricky! Die "voll asynchronen" Pins sind beim TiNo übrigens nur Pins 10,14,18, und 22. Die anderen theoretisch vorhandenen voll asynchronen Pins haben andere Funktionen wie z.B. I2C oder SPI Bus.
Die I2C Bibliotheken vom TiNo konnte ich 1:1 auf den TiNo2 übertragen. Es gab keinerlei Probleme. Anders als beim TiNo möchte ich aber nur noch Bibliotheken unverändert übernehmen. Deshalb wird es beim TiNo2 keine I2C Emulation ("SoftI2C" oder "SoftwareWire") geben. Alle verwendeten Bibliotheken stützen sich auf "Wire", dem im MegaCoreX integrierten TWI Interface.
SHT21, HTU21D und SHT31 sind in die Jahre gekommen. Von Sensirion gibt es einen interessanten Ersatz, den SHTC3, welcher in etwa die selben Daten aufweist wie ein SHT21, aber speziell für batteriebetriebene Anwendungen als low-cost IC konzipiert ist.
Inzwischen gibt es auch die neue Reihe SHT40,SHT41,SHT43 und SHT45. SHT40 und SHT41 sind neben den guten Daten auch preislich interessant. Das DFN4 Gehäuse ist aber wirklich klein!
Auf dem TiNo2 sind Ladeflächen für SHTC3 oder SHT4x vorgesehen.
Der Atmega4808 hat einen fraktionalen Baudraten Generator. Damit sind bei niedriger Taktfrequenz wesentlich höhere Baudraten möglich als beim Atmega328P. Ich verwende einen Takt von 1 MHz und kommuniziere ohne Probleme mit 57600 Bd. Schneller gehts laut Datenblatt bei 1MHz nicht. Beim Atmega328P musste ich den Taktgenerator nachstimmen um mit 4800 Bd sicher kommunizieren zu können. Das ist ein großer Fortschritt, allerdings stehen Tests über Temperatur noch aus.
Die vom MegaCoreX bereitgestellten Optiboot Bootloader funktionieren soweit. Ich habe 3 verschiedene UPDI Programmer am TiNo2 ausprobiert, alle drei funktionieren gut.
- JTAG2UPDI: ein Arduino Pro Mini als Programmer. Der Sketch dazu stammt von einem "ElTangas". Im original Sketch verwendet er einen UNO mit 16MHz Takt. Am pro Mini musste ich den Takt auf 8MHz reduzieren und auch die Übertragungsrate auf 57600Bd reduzieren. Das ist etwas tricky, so dass ich diese Variante Anfängern nicht empfehle.
- SerialUPDI: Ein modifizierter handelsüblicher USB-Serial Adapter bei dem die RX Leitung über eine Schottky Diode mit der TX Leitung verbunden wird. Funktionierte auf Anhieb, auch mit hohen Baudraten. Ein sehr kostengünstiger Programmer (< 1 Euro!) der auch noch zuverlässig funktioniert und von der Arduino IDE unterstützt wird.
- Atmel ICE Programmer und Debugger. Der Programmer kostet gut 100 Euro, aber wer mit Microchip Studio arbeiten will und debuggen will, für den lohnt sich die Anschaffung. (Randnotitz: wenn man regelmäßig mit dem Debugger arbeitet, wird man denkfaul. Ich benutze den Debugger sehr sehr selten, nur wenn ich gar nicht mehr weiter komme.)
MegaCoreX installieren (link) Für den TiNo2: Boardsmanager -> MegaCoreX
Board: ATmega4808 Clock: internal 1MHz oder internal 4MHz BOD: Bod disabled nur für Bootloader Programmierung wichtig EEPROM: EEPROM retained nur für Bootloader Programmierung wichtig Pinout: 32 pin standard Reset pin: Reset nur für Bootloader Programmierung wichtig Bootloader: Optiboot (UART0 default pins) nur für Bootloader Programmierung wichtig
Fuses werden beim Programmieren des Bootloaders geschrieben.