PICAXE Mikrocontroller programmieren mit dem Nano-Axe-Board                

Von Miguel Köhnlein und Michael Gaus                         

  
 
                      Elektronik-Labor  Bastelecke  Projekte  Mikrocontoller                        



Vorstellung des Nano-Axe-Boards

Um PICAXE Mikrocontroller komfortabel programmieren zu können bietet sich das Nano-Axe-Board an. Diese Platine ist als Set zusammen mit dem Sonderheft „Make PICAXE SPECIAL 2020“ sowie einem PICAXE-08M2 Chip im Onlineshop des Heise Verlags erhältlich:
https://shop.heise.de/make-picaxe-special-2020/Print

Im Sonderheft werden zuerst die Grundlagen der BASIC-Programmierung für die PICAXE-Chips erklärt, sodass dieses Set unserer Meinung nach auch sehr gut für Einsteiger geeignet ist, beispielsweise auch als Weihnachtsgeschenk für technikinteressierte Bastler. Ein „Cheat Sheet“ bietet eine kompakte Übersicht über wichtige Befehle und Funktionen. Die auf dem Nano-Axe-Board vorhandene Hardware sowie die Einrichtung der Programmierumgebung auf dem PC werden ebenfalls beschrieben. Anhand einfacher Beispiele wird gezeigt, wie auf die Peripherie des PICAXE zugegriffen werden kann, z.B. digitale I/Os, Analogeingänge, PWM-Ausgabe, Soundausgabe, Servoansteuerung, I2C-Bus usw. Im Projektteil des Hefts werden praktische Anwendungen mit den PICAXE-Mikrocontrollern vorgestellt. Nähere Infos zum Sonderheft sowie das Inhaltsverzeichnis findet man auf der Seite https://www.heise.de/news/Sonderheft-Make-PICAXE-Special-jetzt-im-heise-shop-erhaeltlich-4889649.html

Die erforderliche Programmierschaltung für die PICAXE Mikrocontroller ist bereits auf dem Board integriert. Dieser Teil der Platine kann optional auch abgetrennt und nur für die Programmierung über zwei 6-polige Stiftleisten mit dem PICAXE-Teil verbunden werden. Der Anschluss an den USB-Port des PCs erfolgt über eine Micro-USB-Buchse. Hierüber sind dann gleichzeitig auch eine Terminalausgabe sowie die Ausgabe von Debuginformationen möglich. Auf der Platine ist ein 20-poliger IC-Sockel vorhanden, in den 4 unterschiedliche PICAXE-Typen gesteckt werden können:
08M2 (im Lieferumfang vorhanden), 14M2, 20M2 sowie 20X2. Stellt man im Verlauf eines Projekts fest, dass man mehr Ressourcen benötigt, kann problemlos der nächst größere Typ bestückt werden.

Die I/O-Pins sowie die Versorgungsspannung sind auf zwei 15-poligen Stiftleisten herausgeführt. Dadurch kann die Platine auch problemlos in ein Breadboard gesteckt werden. Die Pinbelegung ist ähnlich wie beim Arduino Nano ausgelegt. Der 08M2 hat zwar wenige I/O-Pins, aber durch den sehr einfach zu nutzenden I2C-Bus kann dennoch eine Vielzahl günstig erhältlicher Sensor- und Anzeigemodule angeschlossen werden.
 
Foto 1: Die Nano-Axe-Platine mit einem PICAXE 08M2 im IC-Sockel

 



Projekt: Messung der Luftfeuchte und Temperatur mit Darstellung auf 7-Segment-Anzeige

Als praktische Anwendung möchten wir die relative Luftfeuchte sowie die Lufttemperatur mit dem Nano-Axe-Board messen und abwechselnd auf einer 7-Segment-Anzeige darstellen. So hat man die aktuellen Messwerte immer im Blick und kann im Winter beobachten, wie sich die trockene Heizungsluft im Raum auswirkt.

Feuchte- und Temperatursensor

Als Sensor setzen wir das Modul GY-21 ein, auf dem sich ein HTU21D Feuchte- und Temperatursensor befindet, der per I2C-Bus ausgelesen werden kann. Wichtig dabei ist, dass auf der Unterseite des Moduls ein Spannungsregler vorhanden ist, der eine Versorgungsspannung von 3V für den HTU21D erzeugt, sowie ein I2C-Levelshifter, der die I2C-High-Pegel von 3V auf 5V umsetzt. Dadurch kann das Modul direkt mit den 5V des Nano-Axe-Board versorgt und direkt mit dem I2C-Bus des PICAXE verbunden werden. Es gibt auch ähnliche HTU21-Module ohne Spannungsregler, für die dann eine externe Zusatzbeschaltung notwendig wäre. Das hier vewendete Modul ist beispielsweise bei https://www.christians-shop.de/GY-21-HTU21-Sensor-fuer-Temperatur-und-Luftfeuchtigkeit-Modul-zum-messen-fuer-Arduino erhältlich. Ein Datenblatt des HTU21D gibt es z.B. hier: https://cdn-shop.adafruit.com/datasheets/1899_HTU21D.pdf

Foto 2: Ober- und Unterseite des GY-21 Sensormoduls

           

 
7-Segment-Anzeige

Für die 7-Segment-Anzeige verwenden wir ein Modul, das auf der Rückseite den Anzeigentreiber HT16K33 aufgelötet hat. Dieser wird ebenfalls per I2C-Interface angesteuert, sodass wir insgesamt zwei Teilnehmer am I2C-Bus haben. Ein Datenblatt des HT16K33 gibt es hier: https://www.holtek.com/documents/10179/116711/HT16K33v120.pdf
Solch ein 7-Segment-Modul mit 4 Digits ist bei Ebay erhältlich, beispielsweise hier:
https://www.ebay.de/itm/4-Digit-7-Segment-0-56-Inch-LED-Display-Module-HT16K33-I2C-for/202299129663

Foto 3: Auf der Rückseite des 7-Segment-Anzeigemoduls sitzt der Anzeigentreiber HT16K33

 


Schaltung und Verdrahtung

 

Die 5V Versorgungsspannung für das Sensor- sowie das Anzeigemodul werden direkt vom Nano-Axe-Board abgegriffen, das wiederum per USB mit 5V versorgt wird. Die im NANO AXE Schaltplansymbol innenliegenden Pins kennzeichnen die Portnummern des hier verwendeten PICAXE 08M2. Dieser verfügt über 6 I/O-Pins C0-C5. Die Bezeichnungen direkt an den Kontaktleisten PL4 und PL5 stimmen mit dem Aufdruck auf der Platine überein und kennzeichnen die Pins eines PICAXE 20M2. Beim PICAXE 08M2 ist die Datenleitung SDA des I2C-Interfaces am Pin C.2 (auf dem Nano-Axe-Board entspricht das der Beschriftung B1) und die Taktleitung SCL am Pin C.1 (auf dem Nano-Axe entspricht das der Beschriftung B0) herausgeführt. In der nachfolgenden Fritzing-Skizze sind die Pinbezeichnungen des 08M2 in schwarzer Schrift gekennzeichnet. Die erforderlichen Pullup-Widerstände an SDA und SCL sind jeweils auf dem GY-21 sowie auf dem 7-Segment-Anzeigemodul bereits vorhanden, sodass keine zusätzlichen externen Widerstände benötigt werden.

Die Fritzing-Skizze zeigt die Verdrahtung auf einem Steckbrett:

 


Foto 4: Der Schaltungsaufbau mit Steckbrett

 
 
Quellcode

Der Quellcode htu21_ht16k33.bas wurde mit dem PICAXE-Editor erstellt. Ganz oben werden einige Symbole für I2C-Adressen und Register definiert. Die 7-Bit I2C-Adresse des HTU21D ist 40 (hex), sodass sich im für den PICAXE benötigten 8-bit Format der Wert 80 (hex) ergibt (Symbol I2C_ADDR_HTU21D). Für den HT16K33 ergibt sich der Wert E0 (hex), da die externen Adresspins A0-A2 auf dem Anzeigemodul LOW sind.

Beim Programmstart wird einmalig durch Aufruf des Unterprogramms initDisplay die 7-Segment-Anzeige initialisiert und komplett gelöscht. In der Hauptschleife main_loop werden zunächst die Messwerte des I2C-Sensors HTU21D ermittelt.

Das Unterprogramm i2cGetTemperature liefert die gemessene Temperatur in Grad Celsius über die Variable temperature. Die im Datenblatt des HTU21D angegebene Berechnungsformel lautet:
Temp = -46.85 + 175.72 * S_TEMP / 2^16
S_TEMP ist der gelieferte 16-bit Rohwert des Sensors. Da der PICAXE keine Befehle für Float-Berechnungen hat, wird hier ganzzahlig gerechnet mit den 100-fachen Werten, was bedeutet, dass im Ergebnis 2 Nachkommastellen enthalten sind.

Das Unterprogramm i2cGetHumidity liefert die gemessene relative Luftfeuchte in Prozent über die Variable humidity. Die Berechnungsformel lautet:
RH = -6 + 125 * S_RH / 2^16
S_RH ist der gelieferte Rohwert des Sensors. Das Ergebnis wird per Software auf einen Wertebereich von 0 bis 99 begrenzt.

Der Zugriff auf den I2C-Bus vom PICAXE aus ist ziemlich einfach. Mit dem hi2csetup Befehl werden zunächst die Busparameter inkl. der I2C-Adresse des anzusprechenden Teilnehmers eingestellt. Mit hi2cout kann schreibend und mit hi2cin lesend auf den Bus zugegriffen werden. Die notwendigen I2C-Start- und Stopbedingungen werden automatisch erzeugt.

Durch Aufruf der Unterprogramme printTemperature und printHumidity werden die Messwerte auf dem im PICAXE-Editor integrierten seriellen Terminal ausgegeben, mit dem über den virtuellen COM-Port des Nano-Axe-Boards kommuniziert wird. Jede Sekunde werden die Temperatur und die relative Luftfeuchte zeilenweise dargestellt. Da der sertxd Befehl verwendet wird, beträgt die Baudrate 4800 Bd bei einer PICAXE Taktfrequenz von 4 MHz. Beim Temperaturwert wird nur die erste Nachkommastelle angezeigt, was völlig ausreichend ist.

Um die Messwerte auf der 7-Segmentanzeige darzustellen werden die Unterprogramme displayTemperature und displayHumidity verwendet. Diese werden abhängig von der Variablen mode abwechselnd ca. jede Sekunde aufgerufen. Bei der Temperatur wird eine Nachkommstelle angezeigt, sofern der Platz auf der Anzeige abhängig von der Stellenanzahl des Werts ausreicht. Dies ist der Fall, sofern der Temperaturmesswert zwischen –9,9 und +99,9°C liegt. Mit dem Befehl bintoascii wird der Messwert in die einzelnen Dezimalstellen im ASCII-Format zerlegt. Die jeweils für die 7-Segment-Anzeige benötigten Stellen werden dann per Makro SET_DIGIT an die passende Position auf das Display geschrieben.

Das Makro SET_DIGIT(dig,val) kann benutzt werden, um die einzelnen Digits der Anzeige zu setzen. Hierbei muss für „dig“ einer der Werte REG_DIGIT0 (Digit ganz links) bis REG_DIGIT3 (Digit ganz rechts) angegeben werden. Bei „val“ sind Werte von 0 bis F (hex) zulässig, um die entsprechenden Dezimal- und Hexadezimal-Ziffern anzuzeigen, ebenso können die ASCII-Werte „0“ bis „9“ verwendet werden oder einer der mit „symbol“ definierten Werte DIGIT_xxx, beispielsweise DIGIT_DEGREE um das Gradsymbol anzuzeigen. Die entsprechenden Segmentkombinationen sind in der EEPROM-Tabelle EE_ADDR_DIGITS definiert. Ein Dezimalpunkt kann mit SET_DP(dig) eingeschaltet oder mit CLEAR_DP(dig) ausgeschaltet werden. Die Helligkeit der Anzeige kann mit SET_BRIGHTNESS (x) in 16 Stufen eingestellt werden.

Falls man Luftfeuchte und Temperatur gleichzeitig anzeigen möchte, kann man auch zwei Anzeigemodule verwenden und bei einem davon über die Lötbrücken auf der Rückseite eine andere I2C-Adresse einstellen. In der Software müsste man dann lediglich in einem der beiden Unterprogramme displayTemperature oder displayHumidity die entsprechende Adresse beim hi2csetup Befehl anpassen.
 
Terminalausgabe im PICAXE-Editor:
 


Foto 5: Anzeige der Temperatur in Grad Celsius

 

Foto 6: Anzeige der relativen Luftfeuchte (rH) in Prozent



Quelkltext-Download: htu21_ht16k33.zip
symbol I2C_ADDR_HTU21D = 0x80
; HTU21D commands
symbol HTU21D_REQ_TEMP = 0xF3
symbol HTU21D_REQ_HUM = 0xF5

;*****************************************************************

symbol I2C_ADDR_HT16K33 = 0xE0
; HT16K33 register addresses
symbol REG_DIGIT0 = 0
symbol REG_DIGIT1 = 2
symbol REG_DIGIT2 = 6
symbol REG_DIGIT3 = 8
symbol REG_COLON = 4
; definitions for EEPROM table EE_ADDR_DIGITS
symbol DIGIT_OFF = 0x10
symbol DIGIT_DEGREE = 0x11
symbol DIGIT_R = 0x12
symbol DIGIT_H = 0x13
symbol DIGIT_MINUS = 0x14

symbol EE_ADDR_DIGITS = 0

; 7segment digit values for 0-9, A-F, OFF, degree, r, H, -
EEPROM EE_ADDR_DIGITS, (0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, _
0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, _
0x00, 0x63, 0x50, 0x76, 0x40)


#macro SET_BRIGHTNESS(x) ; x=0..F
param = x and 0xF or 0xE0
hi2cout (param)
#endmacro

; set 7segment digit
#macro SET_DIGIT(dig, val) ; dig=REG_DIGIT0..REG_DIGIT3, val=0..F or DIGIT_xxx
param = Val
reg_addr = dig
GoSub setDigit
#endmacro

; set decimal point of a 7segment digit
#macro SET_DP(dig) ; dig=REG_DIGIT0..REG_DIGIT3
reg_addr = dig
GoSub setDp
#endmacro

; clear decimal point of a 7segment digit
#macro CLEAR_DP(dig) ; dig=REG_DIGIT0..REG_DIGIT3
reg_addr = dig
GoSub clearDp
#endmacro

; activate colon of 7segment display
#macro SET_COLON_ON
hi2cout (REG_COLON, 0xFF)
#endmacro

; deactivate colon of 7segment display
#macro SET_COLON_OFF
hi2cout (REG_COLON, 0x00)
#endmacro
;*****************************************************************

symbol Value = w0
symbol value_lsb = b0
symbol value_msb = b1
symbol temperature = w1
symbol humidity = w2
symbol crc = b6
symbol value_nk = b7
symbol mode = b8
symbol reg_addr = b9
symbol param = b10
symbol read_value = b11
symbol negativeValue = b12
symbol dec3 = b13
symbol dec2 = b14
symbol dec1 = b15
symbol nk1 = b16
symbol nk2 = b17


GoSub initDisplay
main_loop:
GoSub i2cGetTemperature
GoSub i2cGetHumidity

GoSub printTemperature
GoSub printHumidity
sertxd(cr,lf)

If mode = 0 Then
GoSub displayTemperature
ElseIf mode = 1 Then
GoSub displayHumidity
End If
inc mode
If mode = 2 Then
mode = 0
End If

pause 1000
GoTo main_loop


i2cGetTemperature:
hi2csetup i2cmaster, I2C_ADDR_HTU21D, i2cslow, i2cbyte ; setup I2C
hi2cout (HTU21D_REQ_TEMP)
pause 60 ; wait until measurement complete
hi2cin (value_msb, value_lsb, crc)
value = value & 0xFFFC ; discard bit0 and bit1
; Temp = -46.85 + 175.72 * S_TEMP / 2^16
temperature = 17572 ** value - 4685
Return


i2cGetHumidity:
hi2csetup i2cmaster, I2C_ADDR_HTU21D, i2cslow, i2cbyte ; setup I2C
hi2cout (HTU21D_REQ_HUM)
pause 60 ; wait until measurement complete
hi2cin (value_msb, value_lsb, crc)
value = value & 0xFFFC ; discard bit0 and bit1
; RH = -6 + 125 * S_RH / 2^16
humidity = 125 ** value - 6
if humidity >= 0x8000 then
humidity = 0 ; negative result => limit to 0%
ElseIf humidity > 99 Then
humidity = 99 ; limit to 99%
End If
Return


printTemperature:
sertxd ("T [dC]: ")
Value = temperature
if value >= 0x8000 then
value = -value; negative temperature
sertxd ("-")
End If
value_nk = value % 100 / 10
Value = Value / 100
sertxd(#value, ",", #value_nk, cr, lf)
Return


printHumidity:
sertxd ("rH [%]: ")
sertxd(#humidity, cr, lf)
Return


initDisplay:
hi2csetup i2cmaster,I2C_ADDR_HT16K33,i2cslow,i2cbyte ; setup I2C
hi2cout(0x21) ; Normal operation mode
hi2cout(0x81) ; Display On
SET_BRIGHTNESS(0xF) ; max. brightness
GoSub clearDisplay
Return


clearDisplay:
hi2csetup i2cmaster,I2C_ADDR_HT16K33,i2cslow,i2cbyte ; setup I2C
For reg_addr = 0 To 15
hi2cout (reg_addr, 0) ; clear all segments
Next reg_addr
Return


setDigit:
If param >= "0" And param <= "9" Then
param = param - "0"
End If
param = param + EE_ADDR_DIGITS

read param, param ; get 7segment digit value from onchip EEPROM
hi2cin reg_addr, (read_value) ; read old value from HT16K33
param = read_value and 0x80 or param ; keep decimal point (bit 7) and change digit value
hi2cout(reg_addr, param) ; write new value value to HT16K33
Return


setDp:
hi2cin reg_addr,(read_value) ; read old value from HT16K33
param = read_value or 0x80 ; set decimal point (bit 7) and keep digit value
hi2cout(reg_addr, param) ; write new value value to HT16K33
Return


clearDp:
hi2cin reg_addr,(read_value) ; read old value from HT16K33
param = read_value and 0x7F ; clear decimal point (bit 7) and keep digit value
hi2cout(reg_addr, param) ; write new value value to HT16K33
Return


displayTemperature: ; temperature xxx.xx (multipled with 100 because of 2 decimal places)
hi2csetup i2cmaster,I2C_ADDR_HT16K33,i2cslow,i2cbyte ; setup I2C
GoSub clearDisplay
Value = temperature
if value >= 0x8000 then
negativeValue = 1
value = -value; negative temperature
SET_DIGIT(REG_DIGIT0, DIGIT_MINUS)
Else
negativeValue = 0
End If
bintoascii Value, dec3, dec2, dec1, nk1, nk2
SET_DIGIT(REG_DIGIT3, DIGIT_DEGREE)

Value = Value / 100
If Value < 10 Then
SET_DIGIT(REG_DIGIT1, dec1)
SET_DP(REG_DIGIT1)
SET_DIGIT(REG_DIGIT2, nk1)
ElseIf Value < 100 Then
If negativeValue = 1 Then
SET_DIGIT(REG_DIGIT1, dec2)
SET_DIGIT(REG_DIGIT2, dec1)
Else
SET_DIGIT(REG_DIGIT0, dec2)
SET_DIGIT(REG_DIGIT1, dec1)
SET_DP(REG_DIGIT1)
SET_DIGIT(REG_DIGIT2, nk1)
End If
Else
If negativeValue = 1 Then
SET_DIGIT(REG_DIGIT1, dec3)
SET_DIGIT(REG_DIGIT2, dec2)
SET_DIGIT(REG_DIGIT3, dec1)
Else
SET_DIGIT(REG_DIGIT0, dec3)
SET_DIGIT(REG_DIGIT1, dec2)
SET_DIGIT(REG_DIGIT2, dec1)
End If
End If
Return


displayHumidity: ; humdity xx (0..99)
hi2csetup i2cmaster,I2C_ADDR_HT16K33,i2cslow,i2cbyte ; setup I2C
GoSub clearDisplay
Value = humidity
bintoascii Value, dec3, dec2, dec1
If Value >= 10 Then
SET_DIGIT(REG_DIGIT0, dec2)
End If
SET_DIGIT(REG_DIGIT1, dec1)
SET_DIGIT(REG_DIGIT2, DIGIT_R)
SET_DIGIT(REG_DIGIT3, DIGIT_H)
Return



Elektronik-Labor  Bastelecke  Projekte  Mikrocontoller