Table of ContentsChipKit Boards (PIC32 chips von Microchip)Allgemeines zu ChipKitWenn man sich die Produktpalette von Microchip anschaut, wird man als erstes von der Vielfalt der über 800 Typen erschlagen. Dabei war es beim Arduino so überschaubar:
Bei den PIC Prozessoren von Microchip hat man eine ähnliche Vorauswahl gemacht und das Ganze unter dem Projekt chipKIT ins Leben gerufen. Dabei hat man sich beim IDE direkt beim Arduino bedient und das zu chipKIT passende IDE heißt MPIDE. Die Software gibt es auf der [http://chipkit.org|Projektseite]] als Download. Um mit dem chipKIT vertraut zu werden, möchte ich erst einmal mit dem einfachen Selbstbau beginnen. Der dabei verwendete Chip ist der PIC32MX250F128B, der das gleiche 28-pin Gehäuse hat wie der ATmega328. Seine Parameter sind:
Die Pinbelegung ist hier wiedergegeben: Durch die eingebaute Unterstützung von USB 2.0 ist mit wenigen Bauteilen eine lauffähige Breadboardversion erstellt. Man benötigt
Der Chip hat einen internen Quarz, so dass der externe Quarz nicht unbedingt nötig ist. Er wird aber in allen Beschreibungen empfohlen. Für die beiden Kondensatoren am Quarz habe ich Werte von 22, 33, 36 pF gefunden. Ein Aufbau mit 33 pF läuft problemlos. Der Chip kann bei BoxTec gekauft werden und ist ab Werk mit dem chipKit Bootloader geflasht. Im MPIDE verwende ich als Board das Digilent chipKIT DP32 welches diesen Chip einsetzt. Der Aufbau ist überschaubar und hier abgebildet: Eine detaillierte Aufbauanleitung findet man hier. Statt dem dort angegebenen Fubarino Board wie gesagt das DP32 board auswählen, da der Fubarino einen anderen Chip verwendet. Hier noch der Schaltplan: Mir hat der Aufbau viel Spass bereitet und mir gefällt die Einfachheit des Boards. Es liegt also nahe, dass man ein eigenes Board analog zum Helvetino aufbaut. Der HelvePic32Das BoxTec ChipKit BoardDie Designvorgaben für das Board sind folgende:
Die finale Version V1.0 der Umsetzung dieser Vorgaben sieht dann so aus:
Das Bild gibt die Belegung der einzelnen GPIO Pins wieder und die entsprechende Pinnummer des DP32 bootloaders. Tests und AnwendungsbeispieleSketch UploadDer HelvePic32 schaltet nicht automatisch in den Bootloader Modus, sondern vor einem Upload eines Sketches muss dieser durch Drücken der Program- und Reset-Taste in den Bootloadermodus schalten. Dabei ist es wichtig, dass erst die Program-Taste gedrückt wird und dann Reset. Man erkennt den Bootloader daran, dass ein serieller Port erscheint, der dann vom IDE verwendet werden kann. PinMapFür den HelvePic32 wird die Boardeinstellung ChipKitDP32 verwendet, da dieses Board von Digilent den gleichen Chip verwendet. Leider sind die Pins auf unserem HelvePic32 etwas anders angeordnet, so dass wir ein Array verwenden, das die Pinnummer umsetzt. Dieses Array besteht aus zwei Vektoren, welche die jeweils linke (Index 0) oder die rechte (Index 1) Seite widerspiegeln: const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; // pins of version 1.0 using DP32 board definitions Die Definition der ersten beiden Konstanten ist optional, macht den Code aber lesbarer. Die LED ist auf der rechten Seite an Pin 2 angeschlossen, kann also über nP[RIGHT][2] angesprochen werden. Man sieht in der Liste der Pins, dass der Pin 17 auf beiden Seiten angegeben ist. Das hängt damit zusammen, dass der Pin 17 der Programmierpin ist. Da auf beiden Seiten 8 Pins, zusammen also 16 Pins zur Verfügung stehen, der Chip aber nur 15 nutzbare Pins bietet, lag es nahe, den Programmierpin auf beiden Seiten an der gleichen Stelle anzubieten. Über den zusätzlich verfügbaren Reset-Pin kann so das Board von einem Wing sowohl resettet als auch in Bootloadermodus verbracht werden. Außer den beiden Pinleisten gibt es noch weitere Pins, die hier dargestellt sind:
BlinkIn guter Tradition ist der erste Test eines Boards der, die User-LED zum blinken zu bringen. Beim HelvePic32 gibt es da zwei Möglichkeiten: 1) Traditionell digitalWrite()const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; // pins of version 1.0 using DP32 board definitions void setup() { pinMode(nP[RIGHT][2],OUTPUT); } void loop() { digitalWrite(nP[RIGHT][2], HIGH); delay(250); digitalWrite(nP[RIGHT][2], LOW); delay(250); } 2) Register ManipulationHier bedienen wir uns eines Tricks, den wir uns in der UTFT Library abgeschaut haben. Statt das Register und die zugehörige Bitmask selbst zusammen zu suchen, kann man eine entsprechende Routine aufrufen, die einem das Portregister als auch die passende Bitmask zu einem Pin ausrechnet. Das funktioniert übrigens auch beim Arduino… Zusätzlich zum Pin-Array definieren wir ein Pointerarray pP, welches auf die Portregister zeigt und ein Bitmaskarray bP, welches die Bitmask speichert. Der nachfolgende Code verwendet dann zwei Pre-Prozessor Macros um das jeweilige Bit zu setzen (sbi) oder zu löschen (cbi). Der Code prüft auch die Architektur, so dass der Code auch auf einem Arduino laufen kann. #define cbi(reg, bitmask) *reg &= ~bitmask #define sbi(reg, bitmask) *reg |= bitmask const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; // pins of version 1.0 using DP32 board definitions #if defined(__AVR__) volatile uint8_t *pP[2][8]; uint8_t bP[2][8]; #elif defined(__PIC32MX__) volatile uint32_t *pP[2][8]; uint32_t bP[2][8]; #endif void _IO_Init() { for (uint8_t i=0; i<2; i++){ for (uint8_t j=0; j<8; j++){ pP[i][j] = portOutputRegister(digitalPinToPort(nP[i][j])); bP[i][j] = digitalPinToBitMask(nP[i][j]); } } } void setup() { _IO_Init(); for (uint8_t i=0; i<8; i++){ pinMode(nP[RIGHT][i],OUTPUT); } } void loop() { sbi(pP[RIGHT][2], bP[RIGHT][2]); delay(500); cbi(pP[RIGHT][2], bP[RIGHT][2]); delay(100); } (zur Unterscheidung sind die Delays unterschiedlich gewählt) Was ist der Unterschied?Das nachfolgende Bild zeigt erst das Setzen des Pins auf HIGH mit digitalWrite gefolgt von einem Aufruf zu digitalWrite, um den Pin auf LOW zu setzen. Danach die gleiche Aktion mit sbi und cbi: Man sieht, dass mit digitalWrite der kürzeste Puls 1.2 μs lang ist, mit sbi/cbi nur 140 nS, also um einen Faktor 8-10 schneller. Serielle SchnittstelleAls nächstes testen wir die serielle Schnittstelle. Deren hat es drei:
Der Code ist entsprechend einfach: void setup() { Serial.begin(9600); Serial0.begin(9600); Serial1.begin(9600); } void loop() { Serial.println("Hello World 1"); Serial0.println("Hello World 2 UART1"); Serial1.println("Hello World 3 UART2"); delay(1000); } Mit diesem Code sieht man in drei Terminalfenstern die unterschiedlichen Ausgaben. Die hier verwendete Baudrate von 9600 kann natürlich gegen höhere Baudraten ausgetauscht werden. Als Verbindung habe ich zwei FOCA Breakout verwendet. Man beachte, dass RX des FOCA an TX des Boards geht sowie TX des FOCA an RX des Boards. Mit diesem Setup ist es möglich, eine serielle Kommunikation unabhängig vom USB Anschluss aufzubauen, z.B mit einem Bluetooth Adapter. ServoSpätestens jetzt ist es an der Zeit etwas Bewegung an das Board zu bringen: Der Anschluss eines Servos. Dazu bietet es sich an, gleich die SoftPWMServo Bibliothek zu verwenden. Damit ist es möglich, jeden IO Pin zur Steuerung des Servos zu verwenden. Der zugehörige Code ist entsprechend einfach: const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{0,17, 9,10,11,12,13,14 },{18,17, 1, 2, 3, 6, 7, 8 }}; // pins of version 1.0 using DP32 board definitions #include <SoftPWMServo.h> int pos = 0; // variable to store the servo position, in microseconds const int pin = nP[RIGHT][3]; // Choose _any_ pin number on your board, i.e. pin 3, right side void setup() { } void loop() { for(pos = 1000; pos < 2000; pos += 10) // goes from 1ms to 2ms { // in steps of 10us SoftPWMServoServoWrite(pin, pos); // tell servo to go to position in variable 'pos' delay(25); // waits 25ms for the servo to reach the position } } Auffällig ist, wie glatt und fließend der Servo sich bewegt. 16 x 2 LCD AnzeigeAls nächstes wollen wir eine Anzeige an den HelvePic32 anschließen. Wie beim Arduino bietet sich hier eine zweizeilige LCD-Anzeige an. Da ChipKit das Ziel hat, den Code weitestgehend gleich zum Arduino zu halten, gibt es auch hier die Bibliothek LiquidCrystal und der Code ist identisch zum Arudino Code, hier “Hello World”. Der Anschluss ist dementsprechend sehr ähnlich: Und der Code bedarf nur der Pin-Definition von oben. Die #define Anweisungen dienen nur der Lesbarkeit: /* Code based on: LiquidCrystal Library - Hello World Library originally added 18 Apr 2008 by David A. Mellis library modified 5 Jul 2009 by Limor Fried (http://www.ladyada.net) example added 9 Jul 2009 by Tom Igoe modified 22 Nov 2010 by Tom Igoe modified for HelvePic32 30 Dec 2014 by Mathias Wilhelm This example code is in the public domain. */ const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; // pins of version 1.0 using DP32 bootloader #define RS nP[RIGHT][0] #define EN nP[RIGHT][1] #define D4 nP[RIGHT][2] #define D5 nP[RIGHT][3] #define D6 nP[RIGHT][4] #define D7 nP[RIGHT][5] #include <LiquidCrystal.h> LiquidCrystal lcd(RS, EN, D4, D5, D6, D7); void setup() { lcd.begin(16, 2); lcd.print("hello, world!"); } void loop() { lcd.setCursor(0, 1); lcd.print(millis()/1000); } Noch ein Tipp: Der Poti, der über V0 den Kontrast einstellt muss bei 3.3V fast ganz aufgedreht werden. Als Poti habe ich 10kOhm verwendet. Bei einem 5kOhm Poti blieb das LCD dunkel, was mich einige Stunden der Fehlersuche gekostet hat. Die LCD Hintergrundbeleuchtung auf den LCD-pins 15 und 16 ist nicht angeschlossen, da für das Beispiel unwichtig. Analog InputDer PIC32MX250F128B hat 9 analoge Input Pins, welche als A0 … A8 vordefiniert sind. Der Einfachheit des Codes zu Liebe bleiben wir bei der Notation mit dem oben eingeführten Pin-Arrays. Dazu schliessen wir ein Potentiometer (10 kOhm) an GND und 3.3V an. Den Mittenabgriff geben wir auf der linken Seite auf den Pin 2, den ersten analogen Input dieser Seite (siehe Diagramm oben).Das Auslesen des analogen Inputs geht wie beim Arduino: /* Code based on Analog Input Created by David Cuartielles Modified 4 Sep 2010 by Tom Igoe modified 31 Dec 2014 by Mathias Wilhelm This example code is in the public domain. http://arduino.cc/en/Tutorial/AnalogInput */ const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; // pins of version 1.0 using DP32 bootloader int sensorPin = nP[LEFT][2]; // select the input pin for the potentiometer int ledPin = nP[RIGHT][2]; // select the pin for the LED int sensorValue = 0; // variable to store the value coming from the sensor void setup() { pinMode(ledPin, OUTPUT); } void loop() { sensorValue = analogRead(sensorPin); digitalWrite(ledPin, HIGH); delay(sensorValue); digitalWrite(ledPin, LOW); delay(sensorValue); } Es bietet sich natürlich an, diesen Sketch mit dem Servo Sketch zu verbinden und den Servo über den Poti zu steuern: /* Control a Servo via a poti Created 31 Dec 2014 by Mathias Wilhelm */ const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; // pins of version 1.0 using DP32 bootloader #include <SoftPWMServo.h> int pos = 0; // variable to store the servo position, in microseconds const int pin = nP[RIGHT][4]; // Choose _any_ pin number on your board int sensorPin = nP[LEFT][2]; // select the input pin for the potentiometer int ledPin = nP[RIGHT][2]; // select the pin for the LED int sensorValue = 0; // variable to store the value coming from the sensor void setup() { pinMode(ledPin, OUTPUT); } void loop() { sensorValue = analogRead(sensorPin); pos = map(sensorValue,0, 1023, 1000, 2000); SoftPWMServoServoWrite(pin, pos); delay(25); } Step MotorStatt eines Servos kann man auch einen Schrittmotor anschließen. Für den Test verwenden wir den weit verbreiteten 28BYJ-48 in der 5V Ausführung und den günstigen ULN2003 Treiber: Da die Anschlusskabel oft variieren, ist die Motorbeschaltung auch gezeichnet. Der Code kann ohne Veränderung vom Arduino übernommen werden: /* Based on Stepper exemple V1.01 11/30/2013 by terry@yourduino.com */ #define LEFT 0 #define RIGHT 1 uint8_t nP[2][8] = {{0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; // pins of version 1.0 using DP32 bootloader #include <AccelStepper.h> #define FULLSTEP 4 #define HALFSTEP 8 // motor pins #define motorPin1 nP[RIGHT][3] // Blue - 28BYJ48 pin 1 #define motorPin2 nP[RIGHT][2] // Pink - 28BYJ48 pin 2 #define motorPin3 nP[RIGHT][1] // Yellow - 28BYJ48 pin 3 #define motorPin4 nP[RIGHT][0] // Orange - 28BYJ48 pin 4 // Red - 28BYJ48 pin 5 (VCC) // NOTE: The sequence 1-3-2-4 is required for proper sequencing of 28BYJ48 AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4); void setup() { stepper1.setMaxSpeed(1000.0); stepper1.setAcceleration(50.0); stepper1.setSpeed(200); stepper1.moveTo(2048); // 1 revolution } void loop() { //Change direction at the limits if (stepper1.distanceToGo() == 0) stepper1.moveTo(-stepper1.currentPosition()); stepper1.run(); } Warnung: Ein Schrittmotor zieht recht viel Strom, so dass die USB Versorgung gegebenenfalls durch eine stärkere Stromversorgung ersetzt werden muss. Der ULN2003 kann auch 12V schalten. Servo DetailsteuerungWenn man sich die PWM Signale der normalen Servo Bibliothek anschaut, sieht man, dass die Puls-weite zwischen ca. 500 μs und 2300 μs variiert. Das bedeutet, dass man mit Hilfe der SoftPWMServo Bibliothek die Position eines Servos in Zehntel-Grad ansteuern kann. Da die Bibliothek aber in der Voreinstellung die Puls-weite auf 2 ms begrenzt, muss man diese Werte anpassen. Der zugehörige Code sieht so aus: const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{ 0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; const int Smax=1800; const int Smin=500; #include <SoftPWMServo.h> int pos = 0; const int pin = nP[RIGHT][7]; // Choose _any_ pin number on your board void setup() { SoftPWMServoInit(); SoftPWMServoSetFrameTime(100000); // 2500 us are 100000 tics for 40 MHz CPU! SoftPWMServoSetServoFrames(8); // 8 frames make 20 ms wavelength } void loop() { for (pos=0; pos <= 1800; pos+=2) // use deci-degree in 0.2 degree steps { SetServoPos_decidegree(pos); delay(5); } for (pos=0; pos <= 1800; pos+=2) // use deci-degree in 0.2 degree steps { SetServoPos_decidegree(1800-pos); delay(5); } for (pos=0; pos <= 180; pos++) // use degree in 1 degree steps { SetServoPos_degree(pos); delay(25); } for (pos=0; pos <= 180; pos++) // use degree in 1 degree steps { SetServoPos_degree(180-pos); delay(25); } SetServoPos_degree(90); delay(1000); SetServoPos_degree(180); delay(1000); SetServoPos_degree(0); delay(1000); } void SetServoPos_degree(int degree) { SoftPWMServoServoWrite(pin, 10*degree+Smin); } void SetServoPos_decidegree(int decidegree) { SoftPWMServoServoWrite(pin, decidegree+Smin); } Der Code fährt einmal den Servo von 0 bis 180 Grad in 0.2 Grad Schritten und dann wieder zurück, danach die gleiche Aktion aber in Gradschritten. Zum Schluss werden die Positionen 90°, 180° und 0° für je eine Sekunde angefahren. Grafik LCD mit SPI (320x240 Pixel TFT)Richtig interessant wird es für mich, wenn ich mit dem Mikrocontroller ein farbiges LCD ansteuern kann. Hier gibt es eine Reihe von günstigen TFT und hier sei das 2.2” TFT mit 320×240 Pixeln Auflösung beschrieben, welches über SPI angesprochen wird: Um das TFT anzusteueren brauchen wir die UTFT Bibliothek von Henning Karlsen. Diese Bibliothek ist sowohl für Arduino als auch für ChipKit geschrieben. Leider hat Henning keinen PIC32MX250F128B Prozessor zum testen gehabt, wesshalb der Code im Original nicht funktioniert. Mit einigen leichten Änderungen läuft dieser aber problemlos mit unserem HelvePic32. Die modifizierte Bibliothek kann man hier herunterladen. Als Test kann man das UTFT Beispiel für UTFT_Demo_320x240_Serial mit folgender Pindefinitionen verwenden: const uint8_t LEFT=0; const uint8_t RIGHT=1; uint8_t nP[2][8] = {{ 0,17, 9,10,11,12,13,14},{18,17, 1, 2, 3, 6, 7, 8}}; const uint8_t TFT_CS = nP[RIGHT][7]; const uint8_t TFT_RST = nP[RIGHT][6]; const uint8_t TFT_RS = nP[RIGHT][5]; const uint8_t TFT_SDA = nP[RIGHT][4]; const uint8_t TFT_SCL = nP[RIGHT][3]; #include <UTFT.h> // Declare which fonts we will be using extern uint8_t SmallFont[]; // Usage: myGLCD(<model code>, SDA, SCL, CS, RST[, RS]); // Serial 2.2" TFT 320x240 UTFT myGLCD(TFT22SHLD, TFT_SDA, TFT_SCL, TFT_CS, TFT_RST, TFT_RS); NeopixelBei den Anwendungsbeispielen darf natürlich nicht die Anbindung der beliebten NeoPixel fehlen. Die beim Arduino verwendete Bibliothek kann dabei nicht benutzt werden, da diese auf den Atmel-Chip ausgelegt ist und Maschinencode dieses Prozessors verwendet. Andererseits gibt es eine Bibliothek, welche für chipKit geschrieben wurde und mit den Standard-Boards funktioniert. Da der HelvePic32 aber mit einer anderen Taktfrequenz arbeitet, musst der Code leicht angepasst werden. DIe Neopixel Strips können an jeden Pin angeschlossen werden. Es gelten die gleichen Regeln bezüglich der Stromversorgung. 30 Pixel liefen problemlos mit der Stromversorgung des Boards. Die Bibliothek wurde so angepasst, dass die Funktionsaufrufe der Adafruit Bibliothek verwendbar sind. Es muss also nur die Einbindung der Bibliothek und der Generierung des Objekts geändert werden: #include <ChipKitPixel.h> ChipKitPixel strip1(30, nP[RIGHT][6], GRB); ChipKitPixel strip2(8, nP[RIGHT][7], GRB); Bei beiden Strip bitte beachten, dass die Datenleitung an DIN angeschlossen ist (Daher ist der Stick von der Rückseite her gezeigt) LED WingsBeim HelvePic32 gibt es nicht primär Shields sondern Winds, welche zur Seite hin angeschlossen werden. Shields sind derzeit in der Entwicklung. Aufgrund dieser Wings sind die Stiftleisten an der Seite rotations-symmetrisch, so dass ein Wing an beide Seiten angeschlossen werden kann. ALs ersten Wing bietet es sich an, jeden Pin mit einer LED gegen GND mit Widerstand zu versorgen: Im Betrieb werden dabei vier LED auffallen:
Es hat sich gezeigt, dass ein Wing auf der linken Seite sehr hilfreich ist, wenn die Pins nicht gebraucht werden. Der LED-Wing kann im Betrieb abgezogen und aufgesteckt werden. I2C BusÜber den I2C Bus kann man sehr elegant Module anbauen. Um dies zu veranschaulichen, sind in diesem Beispiel drei I2C Module angeschlossen:
Beim I2C ist die Adresse des Moduls am wichtigsten. Um zu sehen, ob man das Modul richtig angweschlossen hat, kann man den Code i2cscanner verwenden (identisch zum Arduino code bis auf den Aufruf der wire Unterroutine twi_writeTo) /** * I2CScanner.pde -- I2C bus scanner for Arduino * based on the work of 2009, Tod E. Kurt, http://todbot.com/blog/ */ #include "Wire.h" extern "C" { #include "utility/twi.h" // from Wire library, so we can do bus scanning } int devfnd=0; void scanI2CBus(byte from_addr, byte to_addr, void(*callback)(byte address, byte result) ) { byte rc; byte data = 0; // not used, just an address to feed to twi_writeTo() for( byte addr = from_addr; addr <= to_addr; addr++ ) { // rc = twi_writeTo(addr, &data, 0, 1, true); // last argument: send stop at the end rc = twi_writeTo(addr, &data, 0, 1); // last argument: send stop at the end callback( addr, rc ); } } void scanFunc( byte addr, byte result ) { char str[40]; sprintf(str,"addr: %3d 0x%02x",addr,addr); Serial.print(str); Serial.print( (result==0) ? " DEV!":" "); Serial.print( (addr%5) ? "\t":"\n\r"); if (!result) devfnd++; } byte start_address = 16; byte end_address = 123; // standard Arduino setup() void setup() { Wire.begin(); pinMode(1,OUTPUT); Serial.begin(9600); delay(2000); Serial.println("\nI2CScanner ready!"); } // standard Arduino loop() void loop() { Serial.print("starting scanning of I2C bus from "); Serial.print(start_address,DEC); Serial.print(" to "); Serial.print(end_address,DEC); Serial.println("..."); devfnd=0; // start the scan, will call "scanFunc()" on result from each address scanI2CBus( start_address, end_address, scanFunc ); Serial.println("\ndone"); Serial.print("I2C devices found: "); Serial.println(devfnd); for (int i=0;i<devfnd; i++){ digitalWrite(1,HIGH); delay(250); digitalWrite(1,LOW); delay(250); } delay(5000); } Im Serial Monitor zeigen sich die Module an den erhofften Adressen: starting scanning of I2C bus from 16 to 123... addr: 16 0x10 addr: 17 0x11 addr: 18 0x12 addr: 19 0x13 addr: 20 0x14 addr: 21 0x15 addr: 22 0x16 addr: 23 0x17 addr: 24 0x18 addr: 25 0x19 addr: 26 0x1a addr: 27 0x1b addr: 28 0x1c addr: 29 0x1d addr: 30 0x1e addr: 31 0x1f addr: 32 0x20 addr: 33 0x21 addr: 34 0x22 addr: 35 0x23 addr: 36 0x24 addr: 37 0x25 addr: 38 0x26 addr: 39 0x27 addr: 40 0x28 addr: 41 0x29 addr: 42 0x2a addr: 43 0x2b addr: 44 0x2c addr: 45 0x2d addr: 46 0x2e addr: 47 0x2f addr: 48 0x30 addr: 49 0x31 addr: 50 0x32 addr: 51 0x33 addr: 52 0x34 addr: 53 0x35 addr: 54 0x36 addr: 55 0x37 addr: 56 0x38 addr: 57 0x39 addr: 58 0x3a addr: 59 0x3b addr: 60 0x3c DEV! addr: 61 0x3d addr: 62 0x3e addr: 63 0x3f addr: 64 0x40 addr: 65 0x41 addr: 66 0x42 addr: 67 0x43 addr: 68 0x44 addr: 69 0x45 addr: 70 0x46 addr: 71 0x47 addr: 72 0x48 addr: 73 0x49 addr: 74 0x4a addr: 75 0x4b addr: 76 0x4c addr: 77 0x4d addr: 78 0x4e addr: 79 0x4f addr: 80 0x50 addr: 81 0x51 addr: 82 0x52 addr: 83 0x53 addr: 84 0x54 addr: 85 0x55 addr: 86 0x56 addr: 87 0x57 addr: 88 0x58 addr: 89 0x59 addr: 90 0x5a addr: 91 0x5b addr: 92 0x5c addr: 93 0x5d addr: 94 0x5e addr: 95 0x5f addr: 96 0x60 addr: 97 0x61 addr: 98 0x62 addr: 99 0x63 addr: 100 0x64 addr: 101 0x65 addr: 102 0x66 addr: 103 0x67 addr: 104 0x68 addr: 105 0x69 addr: 106 0x6a addr: 107 0x6b addr: 108 0x6c addr: 109 0x6d addr: 110 0x6e addr: 111 0x6f addr: 112 0x70 DEV! addr: 113 0x71 addr: 114 0x72 DEV! addr: 115 0x73 addr: 116 0x74 addr: 117 0x75 addr: 118 0x76 addr: 119 0x77 addr: 120 0x78 addr: 121 0x79 addr: 122 0x7a addr: 123 0x7b done I2C devices found: 3 Zur Ansteuerung der Module können die Adafruit Bibliotheken fast unverändert verwendet werden. Lediglich beim Code für das 14-Segment Modul musste der Aufruf von pgm_read_word entfernt werden, da PIC32 kein PROGMEM kennt. AusblickBau von “Wings”, welche an die Seite angesteckt werden:
Eagle Dateien… wird fortgesetzt … |
|
Letzte Aktualisierung: © boxtec internet appliances · the better security products |