Über den Beitrag
Der ATmega328PB ist eine Weiterentwicklung des guten alten ATmega328P, den ihr von diversen Boards, wie dem Arduino UNO R3, dem klassischen Arduino Nano V3 oder dem Arduino Pro Mini her kennt. Im Vergleich zum ATmega328P ist der ATmega328PB sicherlich keine Revolution, gleichwohl hat er einige sinnvolle Erweiterungen.
Mittlerweile gibt es eine ganze Reihe an Boards, die mit dem ATmega328PB bestückt sind. Als Vertreter für Boards im Nano-Stil habe ich mir den ARD-NanoV4-MC von Joy-IT näher angeschaut, als Vertreter des Pro-Mini-Stils den A-Star 328PB Micro von Pololu und den Wattuino Pro Mini PB von Watterott electronic.
Im Beitrag werdet ihr sehen, dass die von den Herstellern empfohlenen Boardpakete die Vorteile des ATmega328PB in unterschiedlichem Maße und auf unterschiedliche Weise implementiert haben. Ich möchte dabei nicht von besser oder schlechter sprechen, denn es kommt auf eure Vorlieben an und auf das, was ihr damit vorhabt. Und niemand zwingt euch, das empfohlene Boardpaket zu verwenden.
Das erwartet euch:
- ATmega328PB vs. ATmega328P – Überblick
- „Nano-Stil“ Board am Beispiel ARD-NanoV4-MC
- „Pro Mini Stil“ Board am Beispiel Pololu A-Star 328PB Micro
- Wattuino Pro Mini PB
- Das Boardpaket wechseln
ATmega328PB vs. ATmega328P – Überblick
Der ATmega328PB ist abwärtskompatibel zum ATmega328P. Das heißt Sketche, die ihr für den ATmega328P und darauf basierende Boards geschrieben habt, funktionieren auch auf dem ATmega328PB. Ein Datenblatt zum ATmega328PB findet ihr hier bei Microchip.
Das sind die aus meiner Sicht wichtigsten Änderungen:
- Jeweils eine zusätzliche USART (Serial), TWI (I2C) und SPI Schnittstelle.
- Zwei zusätzliche 16-Bit Timer/Counter (Timer/Counter 3, Timer/Counter 4).
- Vier zusätzliche I/O Pins (PE0, PE1, PE2, PE3).
- Für PE0 und PE1 wurden ein GND und ein VCC geopfert.
- Die Pins für ADC6 und ADC7 haben jetzt auch I/O-Pin Funktion (PE2 und PE3).
- Output Compare Modulator: kombiniert die Ausgänge von Timer/Counter 3 und Timer/Counter 4 an PD2.
- Analog Comparator Ausgang an PE0.
- PTC: Peripheral Touch Controller. Der PTC ermöglicht es euch, kapazitive Berührungssensoren an den I/O-Pins auszuwerten. Allerdings muss man dafür den Atmel Start QTouch® Configurator verwenden. Ich gehe nicht darauf ein.
Eine vollständige Zusammenfassung der Unterschiede gibt es in der Application Note AN42559 von Microchip.
„Nano-Stil“ Board am Beispiel ARD-NanoV4-MC
Ich werde am ARD-NanoV4-MC zeigen, wie ihr die zusätzlichen Funktionen, die der ATmega328PB bietet, nutzt. Ihr findet das Board zum Teil auch unter der Bezeichnung „ARD NANO V4 (MINICORE)“. Ich nenne es kurz „NanoV4-MC“.
Auf der Joy-IT Website findet ihr die vorbildliche Dokumentation des NanoV4-MC mit Datenblatt und Anleitung in verschiedenen Sprachen.
An dieser Stelle noch eine Anmerkung: ich werde weder von Joy-IT, noch von Pololu oder Watterott in irgendeiner Weise für die Vorstellung ihrer Produkte entlohnt.
Installation des empfohlenen Boardpaketes
Joy-IT hat für den NanoV4-MC das Boardpaket MiniCore von MCUdude vorgesehen, das ihr hier auf GitHub findet.
Auf das Installieren von Boardpaketen in der Arduino IDE gehe ich nicht im Detail ein. Bei Bedarf schaut in die Anleitung von Joy-IT. Hier die Kurzversion:
- Geht in der Arduino IDE auf Datei → Einstellungen.
- Klickt auf das Icon neben „Zusätzliche Boardverwalter-URLs“.
- Ergänzt die Zeile: „https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json“ (ohne Anführungsstriche), dann 2x das „OK“ bestätigen.
- Klickt am linken Rand der IDE auf das Icon für die Bordverwaltung und gebt „MiniCore“ als Suchbegriff ein.
- Installiert MiniCore von MCUdude.
Um das richtige Board einzustellen, wählt ihr unter „Werkzeuge → Boards“ den Eintrag „MiniCore → ATmega328“. Als Variante müsst ihr noch „328PB“ festlegen und als „Clock“ die Einstellung „External 16 MHz“ vornehmen.
Pinout
Hier das Pinout (mit freundlicher Genehmigung von Joy-IT):
Auf den ersten Blick sieht das gute Stück wie ein Arduino Nano aus. Die wesentlichen Unterschiede sind:
- Die zusätzlichen Pins D23 und D24.
- An D23 und D24 ist die zweite I2C Schnittstelle (Wire1) ausgeführt.
- A6 und A7 sind als GPIOs nutzbar (D20/D21).
- Die zweite SPI-Schnittstelle ist an den Pins A0, A1 und A7 ausgeführt.
- Serial1 ist an den Pins D11 und D12 ausgeführt.
Serial1 nutzen
Da der Programmupload auf den Arduino Boards per USART (Serial) vorgenommen wird, ist die Verwendung von Serial für andere Zwecke manchmal problematisch. Deswegen setzen die meisten in solchen Fällen SoftwareSerial ein, was aber mehr Ressourcen kostet als HardwareSerial.
An einem einfachen Anwendungsbeispiel möchte ich zeigen, wie ihr Serial1 verwendet. Dazu verbindet ihr zwei NanoV4-MC Boards wie folgt:
Dann ladet ihr den folgenden Sketch auf beide NanoV4-MC Boards (am besten mit unterschiedlichen Namen, damit ihr zwei serielle Monitore öffnen könnt) :
void setup() { Serial.begin(9600); Serial1.begin(9600); } void loop() { if (Serial1.available()) { Serial.write(Serial1.read()); } if (Serial.available()) { Serial1.write(Serial.read()); } }
Jetzt könnt ihr Nachrichten über den seriellen Monitor austauschen. Wenn ihr nur einen NanoV4-MC habt, dann könnt ihr auf der anderen Seite auch ein anderes Board verwenden und dort SoftwareSerial einsetzen. Wichtig ist, dass auf beiden Seiten dieselbe Baudrate eingestellt ist. Falls ihr auf der anderen Seite ein 3.3 Volt basiertes Board verwendet, müsst ihr noch Spannungsteiler oder einen Levelshifter dazwischen setzen. Mehr zu Serial und SoftwareSerial findet ihr hier.
Wire1 nutzen
Viele externe Bauteile werden per I2C (Wire) angesteuert. Problematisch wird es, wenn ihr mehrere Bauteile mit derselben I2C-Adresse habt. Sofern es nur zwei Bauteile mit derselben Adresse sind, könnt ihr das eine per Wire und das andere per Wire1 ansteuern. Voraussetzung ist dabei, dass bei Verwendung von Bibliotheken diese die Übergabe von Wire-Objekten erlauben. Wie ihr Wire und Wire1 gleichzeitig einsetzt, zeige ich exemplarisch am ADS1115.
Hier die Schaltung:
Und hier der zugehörige Sketch:
#include<ADS1115_WE.h> #include<Wire.h> #include<Wire1.h> #define I2C_ADDRESS 0x48 ADS1115_WE adc_0 = ADS1115_WE(&Wire, I2C_ADDRESS); ADS1115_WE adc_1 = ADS1115_WE(&Wire1, I2C_ADDRESS); void setup() { Wire.begin(); Wire1.begin(); Serial.begin(9600); if(!adc_0.init()){ Serial.println("ADS1115 0 not connected!"); } else{ Serial.println("ADS1115 0 successfully connected!"); } if(!adc_1.init()){ Serial.println("ADS1115 1 not connected!"); } else{ Serial.println("ADS1115 1 successfully connected!"); } } void loop() {}
Erwartungsgemäß lautet die Ausgabe:
SPI1 nutzen
Prinzipiell könnt ihr SPI1 zwar nutzen, aber die Übergabe an Objekte funktioniert nicht ohne Weiteres wie bei Wire1. Das Hauptproblem ist, dass SPI1 in der MiniCore Bibliothek als Objekt der Klasse „SPI1Class“ definiert worden ist und die meisten Bauteil-Bibliotheken „SPI1Class“ nicht kennen.
Eine direkte Verwendung von SPI1, also per SPI1.transfer()
und Co ist hingegen kein Problem. Falls ihr nur SPI1 verwenden wollt, weil ihr die Standard-SPI Pins für andere Zwecke benötigt, dann könntet ihr das Pololu Boardpaket nutzen. Dazu kommen wir später.
Zusätzliche Timer / PWM
Der ATmega328PB besitzt die zusätzlichen Timer/Counter 3 und 4. Die Systematik der zugehörigen Register entspricht der des Timer/Counter 1, den ich hier im Detail beschrieben habe. Die Ausgänge OC3A und OC4A befinden sich an PD0 (RX/D0) und PD1 (TX/D1). Hier ein einfaches Beispiel für ein PWM Signal an OCRA:
void setup(){ noInterrupts(); // prescaler: 8, top = ICR3, clear at OCR3A, set at top, output at OC3A TCCR3A = (1 << COM3A1) | (1 << WGM31); TCCR3B = (1 << WGM33) | (1 << WGM32) | (1 << CS31); DDRD = (1 << DDD0); // PD0 to OUTPUT OCR3A = 9999; ICR3 = 39999; // pwm frequency 50 Hz, duty cycle 25% interrupts(); } void loop() {}
Und wie immer bei diesem Thema empfehle ich das großartige Tool Arduino Web Timers von David Buezas. Damit könnt ihr eure Einstellungen mittels Tick-Boxen vornehmen und müsst die Registereinstellungen nicht mühsam aus dem Datenblatt heraussuchen.
Output Compare Modulator
OC3B und OC4B teilen sich den Pin PD2 (D2) und bilden den Output Compare Modulator, mit dem ihr die beiden PWM Signale kombinieren könnt. Dabei gibt es zwei Einstellungen:
- PD2 ist auf HIGH eingestellt:
- PD2 Level = SignalOC3B | SignalOC4B
- D. h. die Signale sind über ein logisches ODER verknüpft.
- PD2 ist auf LOW eingestellt:
- PD2 Level = SignalOC3B & SignalOC4B
- D. h. die Signale sind über ein logisches UND verknüpft.
Als Beispiel nehmen wir zwei PWM Signale mit einem Duty Cycle von 25 %. Die PWM-Frequenz von OC4B soll das Zwanzigfache der PWM Frequenz von OC3B betragen.
Hier der Sketch dazu:
void setup(){ noInterrupts(); // OC3B settings: TCCR3A = (1 << COM3B1) | (1 << WGM31); TCCR3B = (1 << WGM33) | (1 << WGM32) | (1 << CS31); OCR3B = 9999; ICR3 = 39999; // OC4B settings: TCCR4A = (1 << COM4B1) | (1 << WGM41); TCCR4B = (1 << WGM43) | (1 << WGM42) | (1 << CS41); OCR4B = 399; ICR4 = 1999; // PD2 settings DDRD = (1 << DDD2); // PORTD |= (1<<PD2); interrupts(); } void loop() {}
Das Signal an PD2 hängt davon ab, ob ihr Zeile 17 auskommentiert lasst oder entkommentiert. Um die Einzelsignale OC3B und OC4B zu erhalten, müsst ihr Zeile 17 entkommentieren und jeweils die Zeilen 4 bis 7 bzw. 10 bis 13 auskommentieren.
Mit einem Logic Analyzer habe ich folgende Ausgaben erhalten:
Analog Comparator Output
Der Analog Comparator vergleicht zwei Spannungen und zeigt an, welche der Spannungen größer ist. Beim ATmega328P hat man dazu das ACO Bit (Analog Comparator Output) abgefragt oder einen Interrupt eingerichtet. Der ATmega328PB besitzt hingegen zusätzlich einen ACO Pin (PE0 / D23).
Hier ein kleines Beispiel, in dem wir an AIN0 (PD6 / D6) die halbe Versorgungsspannung einstellen und an AIN1 (PD7 / D7) mit einem Poti eine variable Spannungsquelle hängen. Eine LED am ACO Pin zeigt an, welche Spannung größer ist.
Hier der erstaunlich kurze Sketch dazu:
void setup() { ACSR = 0x00; ADCSRB = 0x00; ACSRB = (1 << ACOE); // Analog Comparator Output Enable } void loop() {}
Wenn die Spannung an D7 höher ist als an D6, dann ist die LED aus. Ist die Spannung an D7 kleiner, dann ist die LED an. Die Eingänge für den Analog Comparator lassen sich auf alle analogen Pins multiplexen. Aber das würde hier jetzt etwas zu weit führen.
„Pro Mini Stil“ Board am Beispiel Pololu A-Star 328PB Micro
Wenn ihr ein ATmega328PB basiertes Board im Pro Mini Stil bevorzugt, könntet ihr zum Pololu A-Star 328PB Micro greifen. Es gibt ihn in vier Varianten:
- 5 Volt – 20 MHz
- 5 Volt – 16 MHz
- 3.3 Volt – 12 MHz
- 3.3 Volt – 8 MHz
Pololu weist darauf hin, dass das 20 MHz Modell außerhalb der Spezifikation (max. 16 MHz) betrieben wird. Ich habe die 20 MHz Variante für einige Stunden in Betrieb gehabt und es funktionierte fehlerfrei – was natürlich auch keine Garantie ist!
Auch der A-Star 328PB ist auf den Pololu Seiten vorbildlich mit Anleitungen, Spezifikationen und Grafiken dokumentiert. Außerdem gibt es ein Pololu-Forum, an das ihr euch bei Problemen wenden könnt.
Installation des empfohlenen Boardpaketes
Die Installation in der Arduino IDE ist hier auf den Pololu Seiten ausführlich beschrieben. Die Ultrakurzversion lautet:
- Ergänzt die folgende Boardverwalter-URL: „https://files.pololu.com/arduino/package_pololu_index.json“.
- Installiert das Boardpaket: „Pololu A-Star Boards“.
- Wählt als Board: „Pololu A-Star Boards“ → „Pololu A-Star 328PB“.
- Stellt die richtige Variante hinsichtlich Spannung und Takt ein.
Pinout
Obwohl der A-Star 328PB Micro dieselben Abmessungen wie ein Arduino Pro Mini Board hat, sind auf ihm die beiden zusätzlichen GPIOs PE0 (D22) und PE1 (D23) und AREF ausgeführt. Hinzu kommen ein verpolungsgeschützer Batterieeingang (BAT+), ein zusätzlicher VCC Pin und ein ISP Header. Letzteres ist sehr praktisch für den Upload per Programmer.
Hier das Pinout Diagramm (mit freundlicher Genehmigung von Pololu):
Sketch Upload / Bootloader brennen
Per Serial mit USB-zu-TTL Adapter
Für den Upload per Serial benötigt ihr einen USB-zu-TTL Adapter (auch als FTDI Adapter bezeichnet). Zu beachten ist, dass RX an TX und TX an RX gehört. Außerdem muss die Betriebsspannung des Adapters mit der des A-Star 328PB Micro übereinstimmen.
Falls der Upload per Adapter mal nicht funktioniert und mit einer Fehlermeldung „Zugriff verweigert“ abbricht, dann könnte es daran liegen, dass der serielle Monitor noch geöffnet ist. Schließt ihn und dann sollte es funktionieren.
Upload per ISP / Bootloader brennen
Wenn ihr den Upload per ISP bevorzugt, dann benötigt ihr einen Programmer. Der Vorteil dieser Methode ist, dass ihr euch den Bootloader (= 512 Byte Flash) spart. Der Nachteil ist, dass ihr keine Verbindung zum seriellen Monitor habt.
Beim Upload per ISP wird der Bootloader gelöscht. Falls ihr auf den Upload per Serial zurückwechseln wollt, dann müsst ihr vorher den Bootloader brennen.
Preiswerte Programmer findet unter dem Suchbegriff USBASP oder USBtinyISP. Ich habe diese und verschiedene andere getestet und mit allen ging es problemlos.
Das Kombi-Gerät: Pololu USB AVR Programmer v2.1
Für den A-Star 328BP Micro ist der Pololu USB AVR Programmer v2.1 eine ideale Ergänzung. Er ist USB-zu-TTL Adapter und ISP Programmer in Einem. Für den Programmupload per Serial könnt ihr ihn direkt aufstecken, für die Programmierung per ISP verbindet ihr die ISP Header.
Solltet ihr zu diesem Modell greifen, dann empfehle ich, die Anleitung zu lesen. Einige Einstellungen dieses Programmers, wie z. B. die Betriebsspannung, nehmt ihr über eine Benutzeroberfläche vor.
Serial1 nutzen
Serial1 zu nutzen ist genauso einfach, wie das beim NanoV4-MC der Fall war. Zum Testen könntet ihr zwei A-Star 328 PB Micro „miteinander sprechen“ sprechen lassen. Dazu verbindet ihr TXD1 mit RXD1, RXD1 mit TXD1 und GND mit GND.
Als Sketch nehmt ihr nanov4_mc_serial_serial1.ino von weiter oben.
Wire1 und SPI1 nutzen
Bei Wire1 und SPI1 geht das Pololu Boardpaket einen anderen Weg als das MiniCore Paket. Eine parallele Nutzung von Wire („Wire0“ / „TWI0“) und Wire1 bzw. von SPI („SPI0“) und SPI1 ist nicht vorgesehen. Stattdessen stellt ihr in der Arduino IDE ein, welche der Schnittstellen ihr nutzen wollt:
Ihr könnt hin- und herwechseln, aber nicht innerhalb eines Sketches. Als Beispiel zeige ich die Ansteuerung von ADXL345 Modulen per SPI. Dazu habe ich ein Modul an SPI0 und das andere SPI1 angeschlossen:
Der Sketch ist für beide Module bzw. SPI Schnittstellen derselbe:
#include<ADXL345_WE.h> #include<SPI.h> #define CS_PIN 10 // Chip Select Pin bool use_spi = true; // specific for ADXL345_WE ADXL345_WE myAcc = ADXL345_WE(&SPI, CS_PIN, use_spi); void setup(){ Serial.begin(9600); Serial.println("ADXL345 SPI-Test"); if(!myAcc.init()){ Serial.println("ADXL345 not connected!"); } else { Serial.println("ADXL345 successfully connected!"); } } void loop() {}
Falls euch das Verhalten von Wire und SPI bei Verwendung des Pololu-Paketes nicht gefällt, dann könntet ihr zum MiniCore Paket wechseln.
Analog Comparator Output, Timer und Output Compare Modulator
Da meine Beispielsketche für den NanoV4-MC die Register des ATmega328PB direkt ansprechen, funktionieren sie genauso für den A-Star 328PB Micro.
Wattuino Pro Mini PB
Diesen Abschnitt halte ich kurz, da sich die Dinge wiederholen. Ihr bekommt den Wattuino Pro Mini PB in zwei Versionen:
- 5 Volt / 16 MHz
- 3.3 Volt / 8 MHz
Eine – im Vergleich weniger ausführliche – Dokumentation findet ihr hier.
Watterott hat für den Wattuino Pro Mini PB das Boardpaket ATmega328PB-Testing vorgesehen. Auch das könnt ihr direkt oder über den Boardmanager der Arduino IDE installieren. Die Boardmanager-URL lautet:
„https://github.com/watterott/ATmega328PB-Testing/raw/master/package_m328pb_index.json“
Das Pinout Design ist fast identisch mit dem des Arduino Pro Mini. Es sind lediglich die Pins für PE0 (SDA1 / 22) und PE1 (SCL1 / 23) hinzugekommen. AREF ist wie beim originalen Pro Mini nicht ausgeführt. Den Schaltplan des Boards findet ihr hier.
Serial1 funktioniert wie bei den anderen Boards. Wire1 und SPI1 haben wieder das Problem, dass sie Objekte der Klassen TwoWire1 bzw. SPI1Class sind. Deshalb ist auch hier die Verwendung von Bibliotheken, die Wire oder SPI nutzen, nur mit Einschränkungen üblich, obwohl anscheinend an dem Problem gearbeitet wurde. Ich persönlich würde eher Boardpakete von Pololu oder MCUdude empfehlen.
Wechsel des Boardpaketes
Wie ihr gesehen habt, werden die Eigenschaften der hier betrachteten Boards in hohem Maße durch das verwendete Boardpaket bestimmt. Ihr seid frei in der Wahl des Boardpaketes, solange es für den ATmega328PB geschrieben ist. Bei manchen Übergängen, z. B. vom Pololu Paket zu MiniCore, müsst ihr zunächst den Bootloader brennen. Zu beachten ist auch, dass ggf. die Arduino Pin Nummern für die PE0 und PE1 unterschiedlich sind.
Danksagung
Vielen Dank an Pololu, Joy-IT und Watterott für die freundliche Unterstützung!
Vielen Dank für die klare Erklärung , ich habe eine Frage:Welche ist die maximale SCK-Frequenz für die SPI-Schnittstelle des ATmega328P: fosc/4 oder fosc/2 (doppelte Frequenz)?
Es wird die SPI-Schnittstelle des ATmega328P verwendet. Um die maximal mögliche SCK-Frequenz (SCK-Übertragungstakt) einzustellen, müssen die entsprechenden Register konfiguriert werden. Der Ruhezustand der Taktleitung soll auf Low-Pegel gesetzt werden, und die Daten sollen mit der steigenden Flanke übernommen werden. Stellen Sie die Register wie folgt ein, um diese Konfiguration zu erreichen
Hi, die maximale SPI-Frequenz ist fosc/2. Das gilt sowohl für den ATmega328P als auch für den ATmega328PB. Wie die Einstellun per Arduino Code erfolgt, findest du hier:
https://www.arduino.cc/reference/en/language/functions/communication/spi/spisettings/
Mit welcher Flanke die Daten übernommen werden, stellst du über den Modus (0 bis 3) ein. Dazu findest du Informationen hier:
https://docs.arduino.cc/learn/communication/spi/
Hoffe, das hilft!
VG, Wolfgang
Hallo Wolle,
danke für den umfassenden Beitrag.
Bei Ali gibt es Nano V3 Boards, die mit dem 328BP bestückt, sind für ~2,5€.
Durch Hochbiegen von Pin 3 und 6 und einlöten einer längeren Stiftleiste kann man die relativ leicht zu einem vollwertigen 328BP Board umbauen.
Allerdings habe ich noch nicht getestet, inwieweit es sich um voll funktionierende 328BP Chips handelt oder ob es fake Clones sind.
Hallo Peter,
ich habe einen UNO mit Atmega328PB. Es ist ganz interessant, dass der ATmega328PB AVRDUDE vorgaukeln kann, er sei ein ATmega328P. Hochladen per Programmer geht nicht, da erkennt AVRDUDE, dass die Signatur nicht stimmt. Mit dem Minicore Boardpaket und der Einstellung für 328PB geht es dann. Dann ist allerdings der Bootloader weg. Man kann dann den Minicore Bootloader oder den von Pololu brennen, aber mehr nicht den für den UNO (jedenfalls nicht über die Arduino IDE). Ich schätze mal, dass deine Boards auch vollwertige ATmega328PBs sind. Allerdings ist das Hochbiegen von Pins vielleicht nicht jedermanns Sache.
VG, Wolfgang
Nette Erweiterung, aber wie schon angedeutet, nicht der große Wurf. Mehr RAM und mehr Flash als die knappen 32MB wären cool gewesen. Und etwas höher takten gefiele mir auch.
Trotzdem ist der Controller für mich immer noch erste Wahl, wenn man mit 5 Volt Pegeln arbeitet.
…schön wäre auch der volle Takt bei niedrigerer Spannung. Wie es geht, zeigt der LGT8F328P. Aber immerhin.
Hallo Thomas,
in dem Datenblatt auf der Seite von Reichelt habe ich gesehen das der
Controller nur 32KB RAM hat und keine 32MB RAM hat, es sei denn das Datenblatt
ist Fehlerhaft
Grüße
32 MB wären schön! Das war ein Versehen, um mal für Thomas zu sprechen.