zurück zum Artikel

Keine bittere Pille - die Blue Pill mit ARM Cortex M3

Der Pragmatische Architekt

Im Arduino-Universum existieren von einigen Herstellern Arduino-kompatible Boards, die mit anderen Prozessoren als denen aus der ATMEL-Microprozessorfamilie aufwarten. Teensy, ESP8266 und ESP32 haben wir bereits kennengelernt. Von STMicroelectronics gibt es das Board STM32F103C8T6, das seine Anhänger Blue Pill nennen – ein Board mit ausgezeichnetem Preis-/Leistungsverhältnis.

Welcome, on Board

Warum die Blue Pill so heißt wie sie heißt, lässt sich dem folgenden Profilbild entnehmen:

Der Microcontroller STM32F103C8T6, oft nur unter seinem Kosenamen Blue Pill bekannt, liefert hohe Leistung für wenig Geld
Der Microcontroller STM32F103C8T6, oft nur unter seinem Kosenamen Blue Pill bekannt, liefert hohe Leistung für wenig Geld (Bild: http://wiki.stm32duino.com)

Mit einer 32Bit ARM-Cortex-M3-Architektur und einer Taktfrequenz von 72 MHz steckt die Blue Pill einen Arduino auf Basis des 8-Bit Prozessors ATMega328P mit 16 MHz Taktfrequenz performanzmäßig locker in die Tasche. 64 KB (manchmal auch 128 KB) Flashspeicher und dazu 20 KB RAM bieten genügend Reserven für viele Aufgabenstellungen. Zudem beinhaltet das Board eine mit einem separaten Quarz auf 32 MHz getaktete Echtzeituhr (RTC). Im Normalbetrieb unterstützt der Mikrocontroller ein Logiklevel von 3.3V. Es sind zwar auch 5V möglich, wobei einige, aber nicht alle Pins 5V vertragen.

Für eine Blue Pill ist beim Dealer ein Obolus zwischen 2 und 5 Euro zu entrichten. Beschaffungskriminalität lohnt sich also nicht. Wie immer gilt: Je kleiner der Preis, desto näher liegt der Händler bei China.

Das Board verfügt über mehrere serielle Ports, und über mehrere SPI- und I2C-Busanschlüsse (siehe nachfolgende Abbildung des Pin-Layouts). Ein ADC mit 12-Bit-Auflösung lässt die genauere Messwerterfassung von Sensoren zu.

Und natürlich darf eine essenzielle Information nicht fehlen: die eingebaute LED der Blue Pill liegt am Pin PC13.

Die Pinbelegung zeigt, dass die Blue Pill einige nützliche Features besitzt, unter anderem mehrere serielle Ports, CAN- SPI- und I2C-Anschlüsse
Die Pinbelegung zeigt, dass die Blue Pill einige nützliche Features besitzt, unter anderem mehrere serielle Ports, CAN- SPI- und I2C-Anschlüsse

Mehr Details erfährt der Entwickler in einem von STMicroelectronics bereitgestellten Dokument [1].

Hinweis

Beim Performanzvergleich zwischen Cortex-M3 und ATMega328P lauern Fallstricke. Ein Beispiel gefällig: In der Arduino IDE gibt es zwar double und float als Datentypen. Beide sind auf Arduino-Boards aber identisch und umfassen jeweils 32 Bit. Auf einem Cortex-M3-Board wie der Blue Pill sind Werte des Typs double aber 64-Bit breit, haben also doppelte Größe. Beim Benchmarking ist daher wichtig, nicht Äpfel mit Birnen zu vergleichen.

Entwicklungshilfen

In dieser Folge konzentriere ich mich darauf, wie sich das Board mit Hilfe der Arduino IDE programmieren lässt. Allerdings ist das nur eine der Möglichkeiten. Die meisten anderen Möglichkeiten für den Entwickler sind teilweise besser geeignet – zumindest für Pros. Leider habe ich an dieser Stelle nicht die Möglichkeit, diese anzusprechen. Wenigstens sollen einige dieser Optionen zur Sprache kommen:

Generell zu empfehlen ist auch die Blog-Seite [6], die über mehrere dieser Programmieroptionen schreibt.

Integration in die Arduino IDE

Zum Glück gibt es eine große Community namens STM32duino, die sich um das Integrieren von STM32-Boards in das Arduino-Ökosystem kümmert. Viele Informationen, Tipps und Tricks sind auf deren Website [7] zu finden. Ein Besuch dieser Webseiten ist daher sehr zu empfehlen.

Doch nun in medias res. Um Unterstützung für die Blue Pill in die Arduino IDE zu integrieren, bedarf es mehrere Schritte. Dazu nötig ist mangels ST-Link-Programmer eine serielle Verbindung zu einem FTDI-Board oder einem anderen UART-USB-to-TTL-Adapter.

Schritt 1: Blue Pill mit UART-USB-to-TTL-Adapter verbinden

Zunächst sind die notwendigen Verbindungen zwischen Blue Pill und dem verwendeten UART-USB-to-TTL-Adapter zu etablieren (siehe Abbildung). Nach dem Anschluss des Ganzen per USB an den Computer blinkt normalerweise die LED an PC13, weil der Blink-Sketch bei der Produktion zu Testzwecken aufgespielt wurde.

Was genau zu tun ist:

Verbindung von Blue Pill und UART-USB-to-TTL-Adapter
Verbindung von Blue Pill und UART-USB-to-TTL-Adapter

Schritt 2: Board-Manager für Arduino SAM Boards laden

Im nächsten Schritt gehen Sie über Tools > Boards > Boards Manager, suchen nach Arduino SAM Boards (ARM Cortex-M3) und installieren den entsprechenden Board-Manager.

Im zweiten Schritt ist die Installation des Boardmanagers für ARM Cortex M3 Boards notwendig
Im zweiten Schritt ist die Installation des Boardmanagers für ARM Cortex M3 Boards notwendig

Schritt 3: STM32duino Core installieren

Roger Clark ist Master des Githubs für STM32-basierte Arduino Cores. Laden Sie sich über dessen Github-Seite [8] das gesamte Paket als ZIP-Archiv herunter. Damit lassen sich Blue Pills in der Arduino IDE wie native Arduino Boards programmieren.

Auf der Github-Seite von STM32DUINO ist das Zip-Archiv verfügbar
Auf der Github-Seite von STM32DUINO ist das Zip-Archiv verfügbar

Das Archiv gilt es zu entpacken und das daraus resultierende Verzeichnis Arduino_STM32 in das Sketchbook-Verzeichnis der Arduino IDE zu kopieren, zum Beispiel

Sollte das Hardware-Verzeichnis noch nicht existieren, muss es angelegt werden. Danach verlassen Sie die Arduino IDE und starten die IDE erneut. Jetzt können Sie nicht nur Blue Pill, sondern auch andere Boards von STM unter der Arduino IDE nutzen.

Schritt 4: Blue Pill Einstellungen setzen

Gehen Sie in der Arduino IDE unter Tools und konfigurieren Sie das entsprechende Board (siehe links oben in der Abbildung)..

Für die Blue Pill ist das die Generic STM32F103C8 series die richtige Wahl als Board
Für die Blue Pill ist das die Generic STM32F103C8 series die richtige Wahl als Board

Unter Menüpunkt Variant sollten Sie einstellen: STM32F103C8 (20k RAM. 64k Flash).

Danach als Upload method: "Serial" (es sei denn, Sie verwenden eine andere Variante des Programmers wie etwa ST-LINK).

Unter Port spezifizieren Sie den von dem UART-USB-to-TTL Adapter verwendeten seriellen Port. Nutzen Sie etwas anderes als einen FTDI-basierten Adapter, ist zuvor eventuell das zusätzliche Installieren eines für Ihren Adapter bestimmten USB-Treibers notwendig.

Schritt 5: Testsketch programmieren

Im Menüpfad File > Examples > A_STM32-Examples > Digital können Sie als Testprogramm beispielsweise Blink wählen. Port PB1 ändern Sie dabei in PC13. Oder Sie schreiben einfach einen eigenen Testsketch. Mein simpler Sketch für das LED-Blinken sieht wie folgt aus:

void setup() {
pinMode(PC13, OUTPUT); // OnBoard-LED liegt an PC13
Serial.begin(9600); // Ausgabe am seriellen Monitor
}

void loop() {
digitalWrite(PC13, !digitalRead(PC13)); // LED invertieren
Serial.println(digitalRead(PC13) ? "low" : "high"); // -> ser. Monitor
delay(1000); // Pause einlegen
}

Bevor sich der Sketch auf die Blue Pill laden lässt, ist das Setzen des Blue Pill in den Programmiermodus wichtig. Zu diesem Zweck bewegen Sie den oberen gelben Jumper (BOOT0) von Position 0 auf 1 (im nachfolgenden Bild von links nach rechts), und drücken anschließend die RESET-Taste. Der untere Jumper BOOT1 bleibt dabei stets unverändert.

Den BOOT1-Jumper können Sie übrigens für eigene Anwendungen nutzen. Er hat sonst keine andere Funktion.

Um einen Sketch hochlasden zu können, muss der BOOT0-Jumper (oben) auf 1 gestellt, und anschließend ein Reset durchgeführt werden.
Um einen Sketch hochladen zu können, muss der BOOT0-Jumper (oben) auf 1 gestellt, und anschließend ein Reset durchgeführt werden.

Nun kann die Arduino IDE den kompilierten Sketch auf die Blue Pill laden. Hat das geklappt, passiert folgendes: Die Onboard-LED blinkt. Im seriellen Monitor sehen Sie zeilenweise eine Folge von "low" und "high"-Nachrichten.

Soll der Sketch nach einer Änderung neu auf das Board geladen werden und ist der BOOT0-Jumper immer noch auf Stellung 1 positioniert, genügt ein Reset vor dem Sketch-Upload. Wollen Sie hingegen ein Überschreiben des Sketches verhindern, setzen Sie diesen Jumper auf Position 0 zurück.

Port Mapping

Um die in der Arduino IDE verwendbaren Port-Namen zu kennen, genügt ein Blick auf die Implementierung des STM32duino Core, genauer gesagt auf die Headerdatei board.h:

...Header board.h ....

#define BOARD_NR_USARTS 3
#define BOARD_USART1_TX_PIN PA9
#define BOARD_USART1_RX_PIN PA10
#define BOARD_USART2_TX_PIN PA2
#define BOARD_USART2_RX_PIN PA3
#define BOARD_USART3_TX_PIN PB10
#define BOARD_USART3_RX_PIN PB11

#define BOARD_NR_SPI 2
#define BOARD_SPI1_NSS_PIN PA4
#define BOARD_SPI1_MOSI_PIN PA7
#define BOARD_SPI1_MISO_PIN PA6
#define BOARD_SPI1_SCK_PIN PA5

#define BOARD_SPI2_NSS_PIN PB12
#define BOARD_SPI2_MOSI_PIN PB15
#define BOARD_SPI2_MISO_PIN PB14
#define BOARD_SPI2_SCK_PIN PB13

#define BOARD_NR_GPIO_PINS 35
#define BOARD_NR_PWM_PINS 12
#define BOARD_NR_ADC_PINS 9
#define BOARD_NR_USED_PINS 4


#define BOARD_JTMS_SWDIO_PIN 22
#define BOARD_JTCK_SWCLK_PIN 21
#define BOARD_JTDI_PIN 20
#define BOARD_JTDO_PIN 19
#define BOARD_NJTRST_PIN 18

#define BOARD_USB_DISC_DEV GPIOB
#define BOARD_USB_DISC_BIT 10

// Note this needs to match with the PIN_MAP array in board.cpp
enum {
PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13,PA14,PA15,
PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13,PB14,PB15,
PC13, PC14,PC15
};

...

Beim Entwickeln in der Arduino IDE können Programmierer die obigen Bezeichner nutzen.

Demobeispiel

Jetzt soll ein etwas komplexerer Sketch demonstrieren, dass sich durchaus für die Blue Pill Bibliotheken in der Arduino IDE so nutzen lassen als hätten wir ein natives Arduino-Board vor uns. Im Beispiel ist ein Temperatursensor des Typs Dallas DS18B20 angeschlossen. Zu dessen Nutzung hat Maxim (der heutige Name des Herstellers) den OneWire-Bus eingeführt. Den OneWire-Bus und den Sensor hatte ich bereits in einem früheren Beitrag [9] illustriert. Zwischen Dateneingang und Versorgungseingang des Sensors ist ein 4.7 KΩ notwendig.

Das Schaltbild erweitert sich wie folgt:

Blue Pill und DS18B20 gehen gemeinsame Wege
Blue Pill und DS18B20 gehen gemeinsame Wege

Der Sensor (links oben in der Schaltung) ist über Pin PA2 angeschlossen.

Der Sketch ist eher einfach gestrickt. Er soll einfach in jedem Zyklus den Sensorwert des DS18B20 erfassen und am seriellen Monitor ausgeben:

//************************************************
// Blue Pill plus DS18B20 Dallas Temperatursensor
// Demonstration zur Verwendung der Bibliotheken
// fuer Blue Pill in der Arduino IDE
//************************************************


// Zutaten: 1-Wire Protokoll und Sensor-Bibliothek
#include <OneWire.h>
#include <DallasTemperature.h>


// Der Bus haengt an Port PA2 des STM32F103CT6 Boards
#define ONE_WIRE_BUS PA2

// 1-Wire-Protokoll initialisieren
OneWire oneWire(ONE_WIRE_BUS);

// ... und Referenz übergeben
DallasTemperature sensors(&oneWire);

// Generelles Setup von seriellem Monitor und der
// Sensor-Bibliothek


void setup(void)
{
Serial.begin(9600); // seriellen Monitor starten
Serial.println("Demo des DS18B20 Sensors an der Blue Pill");

// Bibliothek initialisieren
sensors.begin();
}

// Unser Thermometer dreht sich im Kreis

void loop(void) {
// Alle anwesenden Sensoren um Temperatur bitten
sensors.requestTemperatures();

// Wir nehmen den erstbesten
Serial.println(sensors.getTempCByIndex(0));

delay(1000); // und goennen uns eine Sekunde Pause
}

Wir lernen: Einige Arduino-Bibliotheken funktionieren auch für STM32-Boards. Aber: Speziell Bibliotheken mit direktem Hardwarezugriff oder Einsatz von AVR Inline-Assembler-Code können auf der Blue Pill nicht laufen. Zum Glück arbeitet die STM32duino-Welt kontinuierlich an der Integration von Bibliotheken.

Kommunikation mit der Aussenwelt

Von Natur aus, ist eine Blue Pill ist sehr schweigsam und besitzt keinen IC für WiFi oder Bluetooth. Abhilfe schaffen können Maker zum Beispiel mit dem ESP-01 aus der ESP8266-Familie. Eine Implementierung für den Zugriff auf ein ESP8266-Board im AT-Kommandomodus liefert Steve Strong (siehe hier [10]). Steve hat einen minimalistischen Webserver implementiert, um LEDs über einen Browser zu schalten oder deren Zustand abzufragen (Anm.: In einem vergangenen Beitrag [11] hatte ich das Zusammenspiel von Arduino mit ESP-01 im AT_Kommandomodus beschrieben).

Eine Integration von Websockets [12] stammt vom gleichen Autor.

Problem Child?

Leider haben die meisten Chargen der Blue Pill einen kleinen Fehler eingebaut. An D+ (siehe Abbildung) wäre ein 1.5 KΩ Pull-up-Widerstand notwendig. Stattdessen findet sich dort ein Widerstand mit 4.7 KΩ oder 10 KΩ. Hat der Widerstand die Aufschrift 103, so handelt es sich um einen Widerstand mit 10 KΩ, bei Code 472 indessen um einen 4.7 KΩ Widerstand. Der korrekte Code lautet aber 153 (= 1.5 * 103).

Das bleibt meistens ohne Folgen, oder es macht sich durch sporadische Probleme beim Sketch-Upload bemerkbar. Auf meinem iMac muss ich bei einigen Blue Pills öfters den Upload durchführen bis es klappt.

Wollen Maker das Problem lösen, müssen sie Hand anlegen. Entweder sie entfernen den fehlerhaften SMD-Widerstand und ersetzen ihn durch einen neuen. Oder sie verwenden die ästhetisch nicht ganz astreine Lösung aus folgender Abbildung:

http://amitesh-singh.github.io/stm32/2017/05/27/Overcoming-wrong-pullup-in-blue-pill.html
Um den Fehler auszumerzen, löten Sie den falschen Widerstand in einer Reflow-Station aus und bringen einen geeigneten Widerstand an. Alternativ können Sie das Problem auch so lösen wie in der Abbildung (Bild: http://amitesh-singh.github.io/stm32/2017/05/27/Overcoming-wrong-pullup-in-blue-pill.html)

Als reine Softwarelösung schlägt Amitesh Singh (von ihm stammt auch die obige Abbildung) vor [13], folgende Codesequenz am Anfang eines Programms einzubauen:

// Notwendig bei inkorrektem Pull-up-Widerstand an D+
// Ein Muss für chinesische Boards des Typs stm32f103c8t6, auch bekannt als "Blue Pill"
rcc_periph_clock_enable(RCC_GPIOA);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
gpio_clear(GPIOA, GPIO12);
msleep(5); // Pause

Das klingt zwar etwas nach Dieselabgas-Affäre, funktioniert aber tatsächlich.

Fazit

Eine Blue Pill bietet zu einem günstigen Preis sehr gute Leistung. Dank der Aktivitäten der STM32duino-Community lässt sie sich in der gewohnten Arduino IDE programmieren, wobei einige Bibliotheken funktionieren, aber nicht alle. Die Blue Pill ist nur eine Vertreterin der unterstützten STM32-Boards. Es gibt viele weitere, auf die der Beitrag aus Platzgründen nicht eingehen kann. Diese kommen in zukünftigen Postings zur Sprache, etwa das Maple-Board, das wie die Blue Pill aus der STM32F103-Familie stammt. Beim Entwickeln mit Blue Pills verlassen Programmierer ein wenig ihre Komfortzone, weil die Unterstützung für Arduino-Boards noch viel umfangreicher ist. Auf der anderen Seite bieten sich im STM32-Universum viele unterschiedliche Werkzeugketten an, die Debugging gut unterstützen, sich ebenfalls für Pros eignen, oder sogar die Generierung von Projekten erlauben wie STM32Cube.

Ein Eintauchen in die Welt der Blue Pill und ihrer Verwandten macht jedenfalls Spaß und erweitert den Horizont.


URL dieses Artikels:
http://www.heise.de/-4009580

Links in diesem Artikel:
[1] http://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf
[2] http://www.st.com/en/development-tools/flasher-stm32.html
[3] http://www.st.com/en/ecosystems/stm32cube.html?querycriteria=productId=SC2004
[4] http://www.openstm32.org/HomePage
[5] https://github.com/trebisky/stm32f103
[6] https://satoshinm.github.io/blog/171212_stm32_blue_pill_arm_development_board_first_look_bare_metal_programming.html
[7] http://www.stm32duino.com
[8] https://github.com/rogerclarkmelbourne/Arduino_STM32
[9] https://www.heise.de/developer/artikel/Lauschen-mit-Sensoren-3217195.html
[10] https://github.com/stevstrong/STM32_ESP01_WebServer
[11] https://www.heise.de/developer/artikel/Ueberraschungsei-fuer-Wetterfroesche-dank-BME680-ESP8266-Arduino-ThingSpeak-3979158.html
[12] http://www.stm32duino.com/viewtopic.php?f=19&t=3281
[13] http://amitesh-singh.github.io/stm32/2017/05/27/Overcoming-wrong-pullup-in-blue-pill.html