Besonders zu Beginn eines neuen Projektes weiß man nicht immer, welchen Mikrocontroller man final verwenden wird. Reicht der Speicher aus, ist die Rechenleistung ausreichend, …? Das sind Fragen, die oft aufkommen. Natürlich startet man nicht blind in ein Projekt rein, sondern weiß wahrscheinlich schon ziemlich gut welche Hardware verwendet wird. Ändern sich die Anforderungen oder man benötigt mehr bzw. weniger Features, dann ist ein Umstieg meist nervig und mit viel Arbeit verbunden, denn die Software für den Mikrocontroller muss komplett angepasst werden.
In diesem Beitrag sprechen wir darüber wie man ein Projekt in PlatformIO so aufsetzten kann, dass mit mehreren Mikrocontrollern zugleich entwickelt werden kann. Es ist sogar möglich mit einer Hardware anzufangen und später beliebig viele hinzuzufügen, ohne dabei die “Altlasten” zu entfernen.
platformIO.ini #
Die zentrale Datei, in der das gesamte Hardware-Setup und deren dazugehörige Konfiguration definiert wird, ist platformio.ini. PlatformIO bietet hierbei die Möglichkeit mehrere “envs” (environments) oder aber auch Gemeinsamkeiten zu definieren.
Will man zum Beispiel eine spezielle Konfiguration für Arduino Uno erstellen, kann das wie folgt aussehen:
[platformio]
default_envs = uno
[env:uno]
platform = atmelavr
board = uno
framework = arduino
upload_port = COM5
monitor_speed = 9600
Dieser Code is schon vorbereitet, dass man ein weiteres “env” anlegen kann, man muss danach einfach nur in der platformIO Sektion die variable “default_envs” ändern und das gesamte Projekt wird für die neu definierte Hardware kompiliert.
Fügen wir beispielsweise zusätzlich nun noch einen Raspberry Pi Pico hinzu und wollen für beide Mikrocontroller kompilieren sieht es wie folgt aus:
[platformio]
default_envs = uno, rpi_pico
[env:uno]
platform = atmelavr
board = uno
framework = arduino
upload_port = COM5
monitor_speed = 9600
[env:rpi_pico]
platform = raspberrypi
board = pico
framework = arduino
board_build.mcu = rp2040
board_build.f_cpu = 133000000L
upload_port = COM4
monitor_speed = 9600
Man kann nun nach Belieben Mikrocontroller und Setups bzw. Konfigurationen hinzufügen und diese noch erweitern.
Definieren unterschiedlicher Libraries, Konstanten und Headerdateien #
Arbeitet man mit unterschiedlicher Hardware, will aber nur einen Code verwenden wird man schnell merken, dass man in Probleme laufen wird. Ein einfaches Beispiel wäre, dass die unterschiedlichen Mikrocontroller (auch wenn sie die gleiche Anzahl an Pins hat) eine ganz unterschiedliche Pinbelegung haben. Man kann das z.B. durch Hardwareabstrahierung lösen, oder man kann mithilfe der platformio.ini Konfigurationsdatei definieren welche Headerdateien spezifisch für den Mikrocontroller geladen werden sollen.
Bleiben wir bei dem Beispiel der unterschiedlichen IOs: Annahme ist, dass wir die verbaute LED blinken lassen wollen. Es ist mir bekannt, dass diese Konstante bereits existiert (LED_BUILTIN), es geht hierbei darum mit einfachen Beispielen auch sieht, dass es funktioniert. Im Falle des Arduino Uno wäre das der Pin 13 und beim Raspberry Pi Pico wäre das Pin 25. Als erstes müssen zwei Header Dateien angelegt werden, in denen wir diese Konstanten anlegen. Zu Demonstrations- und Testzwecken wird auch noch ein konstanter Text definiert, dieser dient später zur Datenübertragung über UART.
Wichtig: die Dateien müssen gleich heißen, befinden sich aber in unterschiedlichen Ordnern:
io_config.g wird jeweils in den rpipico und uno Ordner erstellt. Der Inhalt ist ähnlich, unterscheidet sich aber in IO_LED und TEXT2:
io_config.h: Arduino Uno
#ifndef IO_CONFIG_H_
#define IO_CONFIG_H_
#define IO_LED 13
#define TEXT2 "Arduino Uno"
#endif
io_config.h: Raspberry Pi Pico
#ifndef IO_CONFIG_H_
#define IO_CONFIG_H_
#define IO_LED 25
#define TEXT2 "Raspberry Pi Pico"
#endif
Es muss noch die platform.ini Datei angepasst werden und die io_config.h Headerdatei wird setupspezifisch geladen.
[platformio]
default_envs = uno, rpi_pico
build_flags =
-I/lib/common
[env:uno]
platform = atmelavr
board = uno
framework = arduino
upload_port = COM5
monitor_speed = 9600
build_flags =
-include lib/uno/io_config.h
[env:rpi_pico]
platform = raspberrypi
board = pico
framework = arduino
board_build.mcu = rp2040
board_build.f_cpu = 133000000L
upload_port = COM4
monitor_speed = 9600
build_flags =
-include lib/rpipico/io_config.h
In den einzelnen envs sind nun die spezifischen io_config.h Headerdateien als “biuld_flags” definiert und werden somit spezifisch geladen. Eine sehr mächtiger Mechanismus, der es ermöglicht unabhängig Konfigurationen zu laden.
Der Aufmerksame Leser sieht auch, dass in der paltformIO Sektion “build_flags= -I/lib/common” hinzugefügt wurde, diese Instruktion sagt, dass der common Ordner immer geladen/importiert werden soll, egal welches environment ausgewählt ist. In den common Ordner befindet sich lediglich eine Headerdatei: “const.h”, deren Inhalt definiert lediglich eine weitere Text Konstante:
#ifndef CONST_H_
#define CONST_H_
#define TEXT1 "used hardware is: "
#endif
Testen der Software #
Um zu zeigen, dass all das funktioniert, habe ich ein kleines Programm erstellt:
main.cpp:
#include <Arduino.h>
#include <const.h>
#include <io_config.h>
void setup() {
pinMode(IO_LED,OUTPUT);
digitalWrite(IO_LED,LOW);
Serial.begin(9600);
}
void loop() {
while(1){
digitalWrite(IO_LED,!digitalRead(IO_LED));
Serial.print(TEXT1);
Serial.println(TEXT2);
delay(1000);
}
}
Es werden alle nötigen Header geladen:
- Arduino.h: Arduino dient als grundliegendes Programmierframework
- const.h: Die gemeinsame Textkonstante für UART
- io_config.h: Die Mikrocontroller spezifische Headerdatei
In dem setup() wird der IO Pin der LED konfiguriert und auf low gesetzt und abschließend die Serielle Kommunikation (UART) konfiguriert. In der Programmschleife wird dann jede Sekunde die LED getoggelt und über die serielle Schnittstelle geschrieben um welchen Mikrocontroller es sich handelt.
Zur Erinnerung: ein Teil dieser Nachricht (TEXT1) ist in einer gemeinsamen Headerdatei definiert und TEXT2 in der hardwarespezifischen io_config.h.
Schließt man nun beide Mikrocontroller an den PC an (überprüfen, dass die COM Ports der platformio.ini korrekt sind) kann mit einem Klick die Software Kompiliert und Programmiert werden.
Verbindet man sich mit dem Serial Monitor zu den zwei Mikrocontrollern erhält man folgende Antwort:
COM4 signalisiert, dass es sich um den Raspberry Pi Pico handelt und COM5 meldet sich als Arduino Uno.
Man kann es leider nicht auf einem Bild festhalten, aber ich kann versichern, dass die LEDs auch korrekt blinken. Somit ist nun auch bewiesen, dass es nicht nur theoretisch, sondern auch praktisch funktioniert.
Denkt eventuell daran von Beginn eures Mikrocontroller Projektes dieses so aufzusetzen, dass es euch leichter fällt, später auf andere Hardware umsteigen zu können. Mir ist es oftmals schon passiert, dass ich nicht optimale Hardware verwendet habe und auch nicht umsteigen konnte ohne riesigen Softwareumbau, seid schlauer als ich und wendet die hier beschriebene Methode an.
Das Projekt steht hier zum download zur Verfügung.
Viel Spaß und Erfolg beim Programmieren eurer Mikrocontroller.