jenkie / Arduino-Pedelec-Controller

Software for the Pedelec/E-Bike controller based on Arduino hardware, see www.pedelecforum.de "ForumsController"
http://www.pedelecforum.de/forum/showthread.php?14653-ForumsController
81 stars 44 forks source link

SW SPI speed #22

Closed pillepalle127 closed 12 years ago

pillepalle127 commented 12 years ago

Hallo, ich bin durch Probleme mit meiner SW Filterung auf ein deutliches Optimierungspotential gestossen. Hintergrund: Ich verwende die HW-SPI fuer den LTC6803 BMS Chip und habe keine Leitung mehr zum Lenker frei, um das CS am LCD zu bedienen. Daher laeuft das LCD SPI (wie bei dir) nach-wie-vor auf SW SPI. Detail: Die SW SPI verwendet die Arduino interne shiftOut library. Diese setzt digitalWrite() ein, um die Pins zu setzen. digitalWrite ist fuer seinen Overhead beruechtigt. Auswirkung: Ich benoetige 44,8ms(!) um dem Bildschirminhalt zu aktualisieren; 306ms fuer den kompletten Neuaufbau (eure Zeiten koennen variieren; ich habe den Code zu 90% auf Fixpoint umgestellt und muss fuer die Darstellung auf dem LCD daher umskalieren). Loesung: Anstatt shiftOut() verwende ich eine neue Funktion shiftOutFast() (Anregung und teilweise uebernahme aus http://arduino.cc/forum/index.php/topic,37304.0.html. Ich benoetige nur noch 13,8ms um den Bildschirminhalt zu aktualisieren (Faktor 3 reduziert) und 225ms fuer den kompletten Neuaufbau. Komischerweise spare ich, trotz der int umskalierung bei der Aktualisierung viel mehr als beim kompletten Neuaufbau. Ich kann mir das noch nicht so ganz erklaeren.

Trotzdem macht es viel aus.

Hier die Funktion (nur fuer 4bit Nokia): //--- shiftOutFast - Shiftout method done in a faster way .. needed for tighter timer process void shiftOutFast(unsigned char myDataPin, unsigned char myClockPin, unsigned char myDataOut) { //=== This function shifts 8 bits out MSB first much faster than the normal shiftOut function by writing directly to the memory address for port //--- clear data pin bitClear(PORTC,myDataPin);

//Send each bit of the myDataOut byte MSBFIRST for (int i=7; i>=0; i--) { bitClear(PORTC,myClockPin); //--- Turn data on or off based on value of bit if ( bitRead(myDataOut,i) == 1) { bitSet(PORTC,myDataPin); } else { bitClear(PORTC,myDataPin); } //register shifts bits on upstroke of clock pin bitSet(PORTC,myClockPin); //zero the data pin after shift to prevent bleed through bitClear(PORTC,myDataPin); } //stop shifting bitClear(PORTC,myClockPin); }

pillepalle127 commented 12 years ago

P.s. Ich habe noch ein weiteres digitalWrite ersetzt; in PCD8544::send() durch: if (type) bitSet(PORTC,this->pin_dc - 14); else bitClear(PORTC,this->pin_dc -14);

Die Komplette Funktion: void PCD8544::send(unsigned char type, unsigned char data) { if (type) bitSet(PORTC,this->pin_dc - 14); else bitClear(PORTC,this->pin_dc -14); //digitalWrite(this->pin_sce, LOW); // shiftOut(this->pin_sdin, this->pin_sclk, MSBFIRST, data); shiftOutFast(this->pin_sdin - 14, this->pin_sclk - 14, data); //digitalWrite(this->pin_sce, HIGH); }

jenkie commented 12 years ago

Das hört sich super an. Ich glaube der aktuelle Code benötigt bei mir auch so um die 45 ms. Das ist also immernoch SW-SPI, nur mit modifizierten Befehlen? Ich schaus mir mal genauer an damit ich das auch verstehe, aber ich denke das sollten wir einbauen - Zeit ist Geld :D

pillepalle127 commented 12 years ago

Ja, allerdings ist der Code quick&dirty. Der Port ist fest gecodet (PORTC, also Analogpins) und auch der Offset (14) ist auf den PORTC zugeschnitten. Fuer Pin 10-13, wie bei euch, benoetigst du (ohne Gewaehr) PORTB und einen Offset von 8. Das ist ein bisschen bloed. Liegt an den Pin Defines und am Pin-out des Arduino....

p.s. Pin 2-9 wiederum ist glaube ich PORTD und hat wieder einen anderen Offset. Das kommt hat von den (zugegebenermaßen manchmal sehr praktischen) Arduino Makro feel-good Wolke. Ich bin immernoch gespalten, was das AVR Programmieren mittels Arduino angeht (miese IDE, sehr grosser Overhead und kein JPEG Interface im 328P AAArghh), aber auf Eclipse gehts dann doch irgendwie und zum rumspielen reicht es....

Aufgrund der Timinggeschichte verzichte ich komplett auf den Bildschirm Neuaufbau. Die Aktualisierung passt jetzt gerade so zwischen zwei Reads meines LTC6803. Hatte ich mir einfacher vorgestellt das ganze.

jenkie commented 12 years ago

Habs eingebaut, funktionert tatsächlich mit PortB -8 :) Gemessene 13ms statt 41 für den Standard-Code. Vielen Dank nochmal! Siehe https://github.com/jenkie/Arduino-Pedelec-Controller/commit/d37cd1907acb54f1205468918c3044daeb7a283e