Hallo ihrsens. Ich hab schon ewig nichtmehr mit Logik u Schaltkreisen zu tun gehabt. Will mich aber wieder langsam reinfinden und hab mir ein kleines Projekt überlegt. Das Ziel ist klar nur der Weg dorthin ist mit etlichen Fragen gepflastert wie ich es am besten und effizientesten löse. Ich möchte gerne ca 15 LEDs ansteuern die zu je 5 hintereinander auf einem Rad sitzen, jedes 5er Paket um 120 Grad versetzt. Die LEDs sollen an einer bestimmten Position angehen und dann wieder aus wenn sie ungefähr 15 Grad weiter sind. Also die erste geht an, Rad dreht weiter 2te geht an während die erste noch leuchtet usw. Wenn die letzte LED aus dem Pack angeht leuchtet die erste immernoch, jedoch wenn sie einen Punkt überschreitet geht sie aus. Praktisch ein Winkel in dem die LEDs an sind. Die Frequenz des Rades ist recht gering so um die 1-4 Hz. Nun zu meinen Fragen. Wie entscheidet man ob eine recht analoge Schaltung unter Verwendung von Transistoren und Kondensatoren das hinbekommt, oder man sich doch lieber gleich einen Mikrocontroller oder andere logische Bauteile schnappt. Ich schätze mal man muss irgendwo diese "langsame" Umdrehung speichern. Da es mehrere LEDs werden sollen und sie alle ein seperates Signal brauchen da ihre Ein und Ausschalt Zeitpunkte unterschiedlich sein sollen schätze ich mal das sich LEDs mit Treibern dafür am besten eignen damit man keinen riesigen Kabelsalat bekommt oder? Der Hallsensor und die Steuerung ist an der Scheibe befestigt. So wie ich mir das vorstelle muss ich das Signal des Hallsensors erfassen und es erstmal mit 3 multiplizieren. Und dann muss dieses Signal an einem bestimmten Punkt anliegen den ich vorzugsweise zeitlich einstellen will mittels Poti + Kondensator? Die Einschaltdauer dieses Signals muss auch frequenzabhängig erfolgen damit die LEDs nur in dem vorgegebenen Winkelbereich an und ausgehen. Auch das lässt sich sicher leichter mit einem Mikrocontroller bewerkstelligen nehme ich mal an. Also analog oder digital? Und wenn Mikrocontroller, welchen würdet ihr mir da empfehlen? Ansonsten brauch ich nur einen groben Überblick oder den Namen einer Schaltung die soetwas hinbekommen würde. Den Rest werd ich mir dann selber anlernen. PS ein ähnliches Lauflicht hab ich schonmal gesehen, leider hatte da jede LED ein Kabel zum Baustein und zu GND. Diesen Kabelsalat möchte ich unbedingt vermeiden.
:
Bearbeitet durch User
Fam B. schrieb: > PS ein ähnliches Lauflicht hab ich schonmal gesehen, leider hatte da > jede LED ein Kabel zum Baustein und zu GND. Diesen Kabelsalat möchte ich > unbedingt vermeiden. Dann nimm WS2812. In dem Baustein befinden sich 3 LEDs (RGB) und ein Controller. Die Ansteuerung erfolgt mit einem seriellen Datenstrom, der von Baustein zu Baustein weiter gereicht wird. Dafür brauchst du dann nur 3 Leitungen (+5V, Gnd und Daten), die einmal rundrum laufen.
Das wird wohl die kabelloseste Lösung, wenn auch nicht unbedingt günstig. Schätze mal es gibt auch einfarbige LED Streifen mit diesem Treiber oder? Dann wirds sicher die LEDs auch lose geben. Mit Hall Sensoren kenn ich mich leider nicht so aus, aber theoretisch müsste diese Abfolge dann auch programmierbar sein oder? Da billige Controller wie der ATTiny wohl diese LEDs steuern kann mit entsprechender Bibliothek müsste ich dann Code schreiben um den Hall Sensor einzubinden und einen zweiten analogen Input um die Position feinzutunen schätze ich mal. Sicherlich kann ich nicht jeden x-beliebigen Controller nehmen, ich schätze mal ein Arduino Nano wäre eine gute Wahl? Oder würde ein Arduino Minni auch ausreichen? Eingäge brauche ich ja so gesehen nur 2 einen für Hall und einen für den Poti. Wobei ich nicht weiss ob es unterschiedliche Hall Sensoren gibt, die entweder ein Signal in Form von Strom oder Spannung oder gleich als 3.3 oder 5V Flanke ausgeben. Die ganze Steuerung soll ja relativ klein werden, dazu brauch ich noch ein paar Transistoren da diese Mikroontroller sicher nicht soviel Leistung schalten können richtig? Ich hoffe nur das ich mit meinen Überlegungen richtig liege, es ist wirklich schon ne ganze Weile her ;)
http://lifehacker.com/5920564/make-your-own-revolights-like-led-bike-lights http://www.instructables.com/id/Lightrider-DIY-Bike-Light/ Fam B. schrieb: > Wie entscheidet man ob eine recht analoge Schaltung unter Verwendung von > Transistoren und Kondensatoren das hinbekommt, oder man sich doch lieber > gleich einen Mikrocontroller oder andere logische Bauteile schnappt. Mit einem Microcontroller bist du flexibler und kannst mit jedem firmwareupdate das System korrigieren oder feintunen.
Hi Wie hell soll 'das Gelump' denn werden? 2mA pro LED kann der µC schon Wo wird's angebracht? Wie versorgt? Was darf's kosten? Wie lange muß Es halten? Wer baut's zusammen? ... und wieso überhaupt nimmt man nicht erst Mal einen µC, Den man bedienen kann und fängt an zu spielen? Oder, da der Arduino ja bereits genannt wurde, suchen, ob's nicht ein Hall-Shield und ein 5-LED-Shield gibt - stelle Es mir aber gerade spannend vor, das zusammen gestöpselte Zeug an einer drehenden Welle anzubämmseln - gerne mit Video :) MfG
Nunja, so was geht auch mit Gattern... Erstmal die Frequenz des Hallsensorsignals durch 2 teilen, damit Du 50:50 Tastverhältnis hast und dann per PLL vervielfachen. Der Knackpunkt dabei ist, dass die PLL bei allen Drehzahlen Deiner Scheibe einrasten muss. Das Aufleuchten bekommt man mit einem Schieberegister hin. Einfach hinten das invertierte Signal von dem, was vorne raus fällt, rein schieben. Und am besten das Schieberegister noch im richtigen Moment komplett löschen, damit ein Fehler sich nicht endlos auswirken kann. Der richtige Moment muss vermutlich ab einer Flanke vom Hallsensor an mit dem PLL-Takt gezählt werden. Das Schieberegister braucht natürlich 5 Stufen, die ihren Inhalt parallel an die Led's ausgeben. Insgesamt mehr Bauteile als ein Mikrokontroller, der die Drehzahl misst und rechnerisch in Teile zerlegt, zu denen er die Led's an und aus schaltet. Bleibt noch die Sache mit der Energieversorgung. Magst Du Batterien mit kreiseln lassen, oder die Versorgung über die Achse und einen Schleifkontakt auf die Scheibe geben ? Immerhin braucht so ein Hall-Sensor schon mal ca. 7 mA und eine Led 20 mA. Viele Kabel sehe ich da nicht. Die Scheibe macht man als Platine, so dass man alles per Leiterbahn verbinden kann.
An Patrik Soll schon einigermassen hell werden. Soll über Batterie laufen die ich dann dementsprechend dimensionieren muss zwecks AH. Villeicht wirds sogar ein LiPo mit etwas mehr Volt als ich benötige um dann mit nem kleinen Step down Modul Spannung und Strom zu begrenzen. Angebracht wird die Steuerung nahe der Welle, der Hall Sensor sitzt quasi neben dem Rad und nicht am Umfang. Als Magnet nehm ich dann Neodymium, damit müsste ich auch einen einigermassen grossen Spalt hinbekommen. Über die Kosten mach ich mir nicht so die Gedanken, ich bin mir ziemlich sicher das der teuerste Posten die WS2812B LEDs sein werden. Ich habe ja keinen Zeitdruck und sammle momentan nur meine Energie und mein Know How auf theoretischer Seite. Demzufolge werde ich meine Bauteile nach Effizienz und Kosten sortieren und kann mich nach Schnäppchen umkucken. Conrad und Reichelt haben echt strak nachgelassen, ebay ist da sehr viel flexibler, auch wenn das meiste von da wohl aus China kommt. Ich baus zusammen, ich hab Mechatroniker gelernt, nur in meinem Job kommt kaum Elektronik vor, da werden wenn nur mal paar Relais getauscht, oder gleich ganze Platinen gewechselt. EIgentlich schade, aber da gehts nur immer um schnell schnell ;) Als Gehäuse werd ich einen Zylinder mit loch nehmen, den mach ich zweiteilig und setz ihn um die Welle an, Die Platine werden wohl 2 oder 3 Teile die dann untereinander mit Flachkabel verbunden werden, und die Batterie kommt auchnoch rein, und ein wenig Polstermaterial :D Ein Hall shield gibt es wohl, aber wenigstens das ist bei Conrad gut sortiert, nur muss ich mich durch die Datenblätter wursteln. Wie fop angemerkt hat, sind Hall Sensoren nicht unbedingt stromsparend, dh da werd ich etwas suchen müssen. Bevor ich alles in Form giesse werd ich aber einen Versuchsaufbau machen mit statischem Hall Sensor und Magnet auf Scheibe der auf einem kleinen Elektromotor sitzt. So sollte ich mit geringem Aufwand die Programmierung testen können. Und fop, Schieberegister kam mir auch in den Sinn, nur will ich wirklich nicht soviele Kabel. die WS2812B brauchen halt nur 3 für je 5 LEDs, bei herkömmlicher Steuerung wären es 6 Kabel. Hört sich nicht nach einem grossen Unterschied an, aber ich wollte eh mal mit diesen "neuen" LEDs rumspielen. 10.000 mAh Powerbanks als 5 V gibt es schon als vernünftige Grössen, durch die Rotation leuchten ja auch immer maximal nur 5 LEDs. Bei maximaler Helligkeit nimmt eine LED 60 mA MC und Hall dazugerechnet denke ich mal das ich bei ca 350 mA lande was dann ca 25h Betrieb ausmacht wenn ich die Verluste des Step Down Konverters und thermische Verluste einbeziehe. Selbst 5000 mAH wären für den Anfang akzeptabel. Dieses Lichtspiel ist ja auch eher für dunklere Tageszeit gedacht und nur sporadisch, nicht im Dauerbetrieb. Fotos wirds wohl erstmal nicht geben, wie gesagt, alles erstmal in Planungs und Beschaffungsphase. Vielen Dank schonmal für euren Input.
Hi Statt Hall-Sensor einen Reed-Kontakt an einem riesigem PullUp? Hätte den Vorteil, nehezu beliebig wenig Strom zu nehmen - wenn der Magnet den Sensor aktiviert und nur Das, was in den µC-Pin rein geht, wenn nicht - erkauft mit dem Nachteil, daß ein mechanischer Kontakt prellt - also viele Male beim Ein/Ausschalten tastet. Wenn bekannt ist, wie lange es zum nächsten Signal dauert, kann man einfach bei der ersten Flanke reagieren und für x ms die Detektierung ignorieren/den Interrupt abschalten. Wenn die Scheibe mit 4Hz dreht, sind's 250ms, bis das nächste Signal erwartet wird - also dicke Zeit, Die man Einganssignale ignorieren kann ohne was zu verpassen. Wenn das Gadget als Blickfang/Effektbeleuchtung gedacht ist, wird vll. nicht so viel LED-Strom benötigt - heutige LEDs kommen mit erstaunlich wenigen mA aus, um ansehnlich viel Licht zu verbreiten. Dadurch könntest Du Dir ggf. Transistoren (... Treiber) sparen - hättest aber wieder n+1 Kabel an N LEDs. Wie WS2812 brauchen schon etwas Geschwindigkeit, die Pause zur Datenübernahme war ~50ns (sofern der Wert die Tage hier im Forum korrekt angegeben wurde) - das Datenblatt weiß dazu sicher Genaueres. Auch wird dort der Strombedarf der LED stehen - Das wird mehr als bei normalen LEDs. Noch ict mir nicht ganz klar, weshalb Du derzeit nahezu auf die WS2812 'bestehst' - ob das Flachbandkabel 3 oder 6 Drähte hat, macht den Kohl nicht fett (... hehe ... sorry). Wenn's nur um 'weil ich es kann/können will' geht, lasse ich Das aber auch gelten ;) Man will ja auch 'besser' werden ... irgend wann ... vll ... MfG
Ein Reed Schalter würde vielleicht auch funktionieren. Die Drehzahl ändert sich dynamisch dh sie bleibt nich konstant auf 4 Hz oder 1 Hz das ist eher 1-4 Hz. Aber ein guter Reed müsste das auch hinbekommen. Toll jetzt muss ich mir Datenblätter von Hall und Reeds ankucken um zu sehen was praktikabler ist :D Ja die Stromaufnahme von RGB Leds ist schon etwas hoch. Eine einstellbare Farbe ist dabei ein nettes Feature. Normale Treiberlose RGB Leds sind da im Gegenzug noch aufwändiger wenn man das mit Registern macht. Die Lichtstärke soll schon recht hoch sein. Die 3er Anordnung baut ja auf "Persistence of Vision" auf. Bedeutet das bei einer Drehzahl von ca 1.2 Hz es so aussehen soll das in dem Winkelbereich ständig Licht an ist. Da ist mehr Licht natürlich von Vorteil. Dazu möchte ich noch Diffusoren vor jede LED packen. Hat schon was mit besser werden zu tun, normale Register hab ich damals schon in der Berufschule aufgebaut, komplett aus 555 und dann nen Haufen AND und ORs. Der Lehrer hat uns gequält ;) Bin auch daran interessiert zu lernen wie man Sachen mit einem Controller ansteuert und die Programmierung solcher. In etwas weiterer Ferne möchte ich mir eine kleine CNC Fräse für zuhause bauen, da komm ich kaum um Mikrocontroller rum. Die WS LEDs sind auch ein notwendiges Übel, wenn es einfarbige LEDs gibt die einen seriellen Treiber haben wären die wohl am besten und stromsparend.
Fam B. schrieb: > Über die Kosten mach ich mir nicht so die Gedanken, ich bin mir ziemlich > sicher das der teuerste Posten die WS2812B LEDs sein werden. Das kommt ein bisschen auf deine mechanische Anordnung an und auf deine Begrifflichkeit von "teuer" an. http://www.ebay.com/itm/322058431958 http://www.ebay.com/itm/302209275097 Wenn du nicht ganz dogmatisch an deiner Zahl der LEDs hängst, gibt es auch fertige LED-Ringe - Verdrahtungsaufwand entfällt fast ganz. Beispiele: http://www.ebay.com/itm/172744977763 http://www.ebay.com/itm/182575471674 Patrick J. schrieb: > Noch ict mir nicht ganz klar, weshalb Du derzeit nahezu auf die WS2812 > 'bestehst' - ob das Flachbandkabel 3 oder 6 Drähte hat, macht den Kohl > nicht fett (... hehe ... sorry). Die Verdrahtung der LEDs fürs Charlyplexing musst du bei der Bewertung des Drahtverhaus auch mit rechnen - es geht nicht nur um die 6 Anschlussleitungen/Prozessorpins.
Ich sag mal so. Ein fertiger Streifen LEDs lässt sich leicht verwenden, und die sind auch preislich locker im Rahmen. Die Anzahl der LEDs wird eher vom gewünschten Effekt und dem Stromverbrauch reglementiert, es könnten mehr aber auch weniger werden, das muss ich erst noch testen. Sicher alles Faktoren für die anhängliche Steuerung. Übrigens ist mir vorhin grad eingefallen das ich keinen Hall oder Reed Kontakt brauche. Die Steuerung bewegt sich ja quasi mit und verändert ihre Position zu den LEDs nicht. So gesehen müsste dann auch ein Gyroskop/Accelerometer den Zweck erfüllen. Der kennt ja seine Ausrichtung. Dann müsste ich seine Position abfragen und der Steuerung sagen welche Led auf welcher Position zu leuchten hat bzw eine Position als Ausgangspunkt/Eingangsflanke für die Umdrehungsberechnung nehmen. Ich bin mir auch ziemlich sicher das diese Teile etwas weniger Stromaufnahme haben. Somit komme ich auf 3 Arten von Positionsbestimmung. Durch die Macht von Google hab ich eben gesehn das solche Gyros wohl eine recht teure Methode sind. Auch denke ich das ein Hall Sensor Preis/Leistungstechnisch bei weitem präziser wäre. Jedenfalls ne Menge die ich austesten muss.
Fam B. schrieb: > So gesehen müsste dann auch ein Gyroskop/Accelerometer den Zweck > erfüllen. Ein Gyroskop wird dir ohne zusätzliche Referenz überhaupt nichts nützen. Das driftet davon. Falls die Drehachse deiner Anordnung (näherungsweise) horizontal liegt, kannst du natürlich den Schwerevektor mit einem Beschleunigungssensor nutzen.
Ja da müsste ich kucken ob ein Gyro oder Accelerometer sich überhaupt dafür eignet. Die zentrifugale Beschleunigung wird wohl die Lagemessung zusätzlich beeinflussen. Übrigens hab ich schon ein Beispiel gefunden wo jmd mittels IR sensor die Umdrehung eines Lüfters ausliest. Der Code beinhaltet sogar einen Teiler mit dem im die Umdrehungsfrequenz auf 3 Interrupts per Umdrehung aufteilen kann. http://elimelecsarduinoprojects.blogspot.de/2013/06/measure-rpms-arduino.html Momentan finde ich mich in die Ansteuerung von Neopixels mit einem ATTiny ein über Autodesks Simulations Webseite. Sehr sehr hilfreich um zu verstehen wie alles funktioniert. Beinhaltet sogar einen Frequenzgenerator. Somit werde ich dann verschiedene Sensorenflanken simulieren können und schauen ob die Programmierung funktioniert. Die Datenbank der Bauteile ist etwas begrenzt, aber man hat sogar Zugriff auf einen virtuellen Arduino Uno. https://circuits.io/
Fam B. schrieb: > Ja da müsste ich kucken ob ein Gyro oder Accelerometer sich überhaupt > dafür eignet. Die zentrifugale Beschleunigung wird wohl die Lagemessung > zusätzlich beeinflussen. So sind die Spielregeln. Die Größe der zentrifugale Beschleunigung ist proportional zum Abstand der Drehachse, der Schwerevektor ist konstant. Du könntest das Sensorelement auf der Drehachse plazieren oder die Drehung bei der Auswertung rausrechnen.
Kleines Update. Anscheinend kommen die WS 2812B s langsam aus der Mode. Es gibt wohl mittlerweile einen Nachfolger der 2 Datenleitungen hat. Sieht so aus als wenn zB auf aliexpress viele Händler diese LEDs in allen Formen mit bis zu 30% Rabatt abstossen. Hab mir grade 50 Stück für 5€ bestellt. Normalerweise würde man dafür auf zB amazon und nem deutschen Händler locker das 4fache bezahlen. Und die kaufen auch in China ein. Zusammenfassung: WS2812B Hall sensor Arduino Style MC (muss kucken ob der Code in nem ATTiny läuft wenn ich mit meinen mikrigen C Kentnissen fertig bin) Als Batterien/Akkus werd ich wohl 18650er nehmen 2 Stück in Serie a ~4000mAh Step Down Konverter um die Spannung recht effizient auf 4.8-5V zu bringen. Die LEDs haben schon ihre eigenen Vorwiderstände, das spart mir nen Haufen Arbeit. Mein einziges Problem wird also nur die Programierung wozu ich mir erstmal ein echtes Bördchen besorgen muss da die Java Simulatoren doch recht langsam und begrenzt sind. Hab schon ne Menge Beispielprogramme gesehn wie Leute RPM Ansteuerung und Berechnung anstellen. Das dynamische Ergebnis müsste ich dann als Input für die Ansteuerung für die 3 "Strips" a 5 LEDs benutzen. Leider ist das Wochenende schonwieder zuende :D
:
Bearbeitet durch User
Hier schonmal mein virtueller Testaufbau den ich wohl bald durch einen realen ersetzen werde. https://circuits.io/circuits/5300408-wip-5-led-3-strip-ws2812b Im Setup ist erstmal ein kleiner Testdurchlauf damit man sieht ob nach dem Einschalten alle Verbindungen und der MC in Ordnung sind. Hall/Funktionsgenerator ist noch nicht integriert da die Webseite doch sehr langsam ist, zumindest kann ich so testen das ich keine Fehler bei der Verdrahtung mache. Code funktioniert soweit, für Vereinfachungen bin ich dankbar. Ich behandle die LEDs erstmal als 3 separate Strips da sie räumlich um 120 Grad versetzt sein sollen ist das glaube ich einfacher ein variables delay dazwischen zu realisieren. Die Ansteuerung beinhaltet nur eine Farbe, das an und ausgehen soll dann durch die rpm/Hall Sensor getimed werden.
1 | #include <Adafruit_NeoPixel.h> |
2 | #define NUMPIXELSA 5
|
3 | #define NUMPIXELSB 5
|
4 | #define NUMPIXELSC 5
|
5 | |
6 | Adafruit_NeoPixel strip_A = Adafruit_NeoPixel(NUMPIXELSA, 9, NEO_GRB + NEO_KHZ800); // 3 Strips designed to be offset by 120 degrees on a wheel |
7 | Adafruit_NeoPixel strip_B = Adafruit_NeoPixel(NUMPIXELSB, 10, NEO_GRB + NEO_KHZ800); |
8 | Adafruit_NeoPixel strip_C = Adafruit_NeoPixel(NUMPIXELSC, 11, NEO_GRB + NEO_KHZ800); |
9 | uint32_t whiteA = strip_A.Color(255, 255, 255); |
10 | uint32_t whiteB = strip_B.Color(255, 255, 255); |
11 | uint32_t whiteC = strip_C.Color(255, 255, 255); |
12 | |
13 | void setup() { |
14 | |
15 | strip_A.begin(); |
16 | strip_B.begin(); |
17 | strip_C.begin(); |
18 | strip_A.setBrightness(230); |
19 | strip_B.setBrightness(230); |
20 | strip_C.setBrightness(230); |
21 | for (int a = 0; a < NUMPIXELSA; a++) { // StripA Test |
22 | strip_A.setPixelColor(a, whiteA ); |
23 | strip_A.show(); |
24 | delay(1); |
25 | }
|
26 | for (int b = 0; b < NUMPIXELSB; b++) { // StripB Test |
27 | strip_B.setPixelColor(b, whiteB); |
28 | strip_B.show(); |
29 | delay(1); |
30 | }
|
31 | for (int c = 0; c < NUMPIXELSC; c++) { // StripC Test |
32 | strip_C.setPixelColor(c, whiteC); |
33 | strip_C.show(); |
34 | delay(1); |
35 | }
|
36 | }
|
37 | void loop() { |
38 | for (int a = 0; a < NUMPIXELSA; a++) { |
39 | strip_A.setPixelColor(a, strip_A.Color(0, 0, 0)); |
40 | strip_A.show(); |
41 | delay(1); |
42 | strip_A.setPixelColor(a, strip_A.Color(255, 0, 0)); |
43 | strip_A.show(); |
44 | delay(1); |
45 | }
|
46 | }
|
So mal nen kleines Update. circuits.io ist auf tinkercad umgezogen, hat etwas weniger unterstützte Komponenten die Vorschau scheint nichtmehr zu funktionieren wenn man nicht Eigentümer und im edit Modus its, aber hier mal trotzdem der Link falls es an mir liegt und bei euhc funktioniert. https://www.tinkercad.com/things/eIqIhgeNoYD LEDs sind im Simulator nun kreisförmig angeordnet. 5V Regulator anstelle eines Buck-Boost und ein normales Netzteil anstelle von 2x 18650 LiPolys Der Funktionsgenerator dient erstmal als Hall Sensor Ersatz um eine "Drehzahl" zu simulieren. Im Versuchsaufbau werde ich mir wohl oder übel einen Funktionsgenerator zusammenlöten müssen der meinen gewünschten Frequenzbereich mittels Poti abdeckt. Allerdings habe ich mit der Simulationssoftware schon ein komisches Verhalten meines Programms entdeckt. 1. Mein Interrupt scheint void (setup) schon zu überspringen wenn ich den benötigten Registerdaten gleich am Anfang ins Setup schreibe. Ich weiss das es interrupt() und noInterrupt() gibt aber ich weiss nochnicht genau ob das überhaupt mit einem ATTiny 85 funktioniert, die IDE und der Webseiten compiler meckern jedenfalls nicht rum wenn ich am Anfang des setups mit noInterrupts () anfange und am Ende des Setups mit interrupts() beende. Oder muss ich den auszuführenden Code in den jeweiligen Klammern einfügen? Mit einer for Schleife wird es doch dann genestet was mit C eigentlich nicht geht oder? Finde da zu kaum Beispiele. Google spuckt zumeist nur attachInterrupt() Zeug aus was ich beim ATTiny mit den Registern lösen muss und habe. Als Workaround habe ich sei() als letzte Zeile im Setup. Zur Info der Interrupt ist auf PB2 respektive INT0 und funktioniert soweit. Nur mit dem Timing komme ich nicht ganz klar. Ich lasse alle 3 Strips über for (int) laufen und habe dazwischen immer ein delay von (x) Im Programm heisst x rotDelay und ist erstmal als unsigned int als globale Variable definiert. Keine Ahnung ob das präzise genug ist, ich lasse den MC mit ausreichen grossen Ints rechnen so dass sich kaum ein merklicher Unterschied zu floats ergeben sollte. Hoffe ich zumindest ^^ Zu diesem Zweck habe ich ein wenig code geklaut die aus dem Interrupt erstmal rpm macht, dabei etwas gemittelt wobei ich aus einem 5er Array ein 3er gemacht habe um clk und Speicher zu sparen. Diesen rpm Wert der quasi volatile ist rechne ich dann in das rotDelay um über
1 | rotDelay = 360000 / (rpm * 15); |
Bei einer RPM von 60 bzw 1Hz vom Hall Sensor ergibt sich dann ein Wert von 400, was als Delay dann 400ms sind. So sollten bei 1 Hz die LEDs angehen weiter umlaufen und dann nach 400ms ausgehen. Und danach alle folgenden LEDs. Den Abstand der LEDs zueinander und den Abstand der Strips habe ich noch nicht programmiert denn es gibt ein kleines Problem was ich nicht lösen kann. Der Simulator ist entweder zu langsam oder ich übersehe etwas. Oder darf ich um das zu erreichen nur ein for (int) pro strip benutzen und jedes Pixel separat ansteuern mit einem kleineren Delay zwischen jedem? Hier ist der komplette Code. Einige Sachen sind wahrscheinlich überflüssig, die Refreshrate stammt teilweise noch vom Beispielcode dabei wurde auch der LCD Update gesteuert. Original war der auf 400ms gesetzt, aber es macht keinen Unterschied wenn ich ihn auf 10 ms setze.
1 | #include <Adafruit_NeoPixel.h> |
2 | #include <avr/io.h> |
3 | #include <avr/interrupt.h> |
4 | |
5 | #define NUMPIXELSA 5
|
6 | #define NUMPIXELSB 5
|
7 | #define NUMPIXELSC 5
|
8 | |
9 | Adafruit_NeoPixel strip_A = Adafruit_NeoPixel(NUMPIXELSA, 0, NEO_GRB + NEO_KHZ800); // 3 Strips designed to be offset by 120 degrees on a wheel |
10 | Adafruit_NeoPixel strip_B = Adafruit_NeoPixel(NUMPIXELSB, 1, NEO_GRB + NEO_KHZ800); |
11 | Adafruit_NeoPixel strip_C = Adafruit_NeoPixel(NUMPIXELSC, 3, NEO_GRB + NEO_KHZ800); |
12 | |
13 | //uint32_t whiteA = strip_A.Color(255, 255, 255); disabled for testing purposes
|
14 | //uint32_t whiteB = strip_B.Color(255, 255, 255);
|
15 | //uint32_t whiteC = strip_C.Color(255, 255, 255);
|
16 | |
17 | uint32_t offA = strip_A.Color(0, 0, 0); |
18 | uint32_t offB = strip_B.Color(0, 0, 0); |
19 | uint32_t offC = strip_C.Color(0, 0, 0); |
20 | |
21 | uint32_t whiteA = strip_A.Color(0, 0, 255); //Testcolor to better see it in the simulator ;) |
22 | uint32_t whiteB = strip_B.Color(0, 0, 255); |
23 | uint32_t whiteC = strip_C.Color(0, 0, 255); |
24 | |
25 | volatile unsigned long time = 0; |
26 | volatile unsigned long time_last = 0; |
27 | volatile unsigned int rpm_array[3] = {0, 0, 0}; // 3 samples averaged |
28 | unsigned long refreshInterval = 10; // in ms, for LCD refresh timing |
29 | unsigned long previousMillis = 0; |
30 | volatile unsigned int rpm = 0; |
31 | volatile unsigned int last_rpm = 0; |
32 | unsigned int rotDelay =0; // Calculated time based variable to control the duration and delay between LEDs switching on and off, integer instead of float to test and save processing time |
33 | |
34 | void setup() |
35 | {
|
36 | GIMSK = 0b01000000; // Enable INT0 External Interrupt |
37 | MCUCR = 0b00000011; // Rising-Edge Triggered INT0 |
38 | |
39 | DDRB &= ~(1<<PB5); //Set unused pins as input. |
40 | DDRB &= ~(1<<PB4); |
41 | PORTB |= (1 << PB5); // Enable pullup resistor |
42 | PORTB |= (1 << PB4); |
43 | |
44 | strip_A.begin(); // Initialize Neopixel Strips |
45 | strip_B.begin(); |
46 | strip_C.begin(); |
47 | strip_A.setBrightness(230); // Set Strips to approx 90% Brightness |
48 | strip_B.setBrightness(230); |
49 | strip_C.setBrightness(230); |
50 | strip_A.show(); // Send empty data to strips to reset floating output turning all Neopixels off |
51 | strip_B.show(); |
52 | strip_C.show(); |
53 | |
54 | for (int a = 0; a < NUMPIXELSA; a++) { // Strip Test |
55 | strip_A.setPixelColor(a, whiteA ); |
56 | strip_A.show(); // Send data |
57 | delay(100); // Delay to test each strip |
58 | }
|
59 | for (int a = 0; a < NUMPIXELSA; a++) { |
60 | strip_A.setPixelColor(a, offA ); |
61 | strip_A.show(); |
62 | }
|
63 | for (int b = 0; b < NUMPIXELSB; b++) { |
64 | strip_B.setPixelColor(b, whiteB); |
65 | strip_B.show(); |
66 | delay(100); |
67 | }
|
68 | for (int b = 0; b < NUMPIXELSA; b++) { |
69 | strip_B.setPixelColor(b, offB ); |
70 | strip_B.show(); |
71 | }
|
72 | for (int c = 0; c < NUMPIXELSC; c++) { |
73 | strip_C.setPixelColor(c, whiteC); |
74 | strip_C.show(); |
75 | delay(100); |
76 | }
|
77 | for (int c = 0; c < NUMPIXELSA; c++) { |
78 | strip_C.setPixelColor(c, offC ); |
79 | strip_C.show(); |
80 | }
|
81 | sei(); // Enable Interrupts |
82 | }
|
83 | void update_rpm() { |
84 | //Update The RPM
|
85 | //5 sample moving average on rpm readings
|
86 | rpm_array[0] = rpm_array[1]; |
87 | rpm_array[1] = rpm_array[2]; |
88 | rpm_array[2] = 60 * (1000000 / (time * 1)); // todo: handle case that there is full stop // *1 for one interrupt per revolution (Hall Sensor) |
89 | // formula is explained here: http://www.pyroelectro.com/tutorials/tachometer_rpm_arduino/theory2.html
|
90 | rpm = (rpm_array[0] + rpm_array[1] + rpm_array[2]) / 3; //Last 3 Average RPM Counts Equals.... |
91 | rotDelay = (360000 / (rpm * 15))/ 360; // Smoothed rpm into frequency divided by angle of full circle to get radial increment in milliseconds 1 Hz = 400 ms in this formula |
92 | }
|
93 | |
94 | void loop() { |
95 | update_rpm(); // sensor ISR will look for time period |
96 | if (last_rpm - rpm != 0 ) { // update LCD only if there is a change of rpm |
97 | last_rpm = rpm; |
98 | // need to check the case that there is 0 rpm (full stop)
|
99 | unsigned long currentMillis = millis(); |
100 | if (currentMillis - previousMillis > refreshInterval) { // at a decent refresh rate |
101 | previousMillis = currentMillis; |
102 | }
|
103 | }
|
104 | for (int a = 0; a < NUMPIXELSA; a++) { |
105 | strip_A.setPixelColor(a, whiteA ); |
106 | strip_A.show(); |
107 | delay(rotDelay); |
108 | }
|
109 | for (int a = 0; a < NUMPIXELSA; a++) { |
110 | strip_A.setPixelColor(a, offA ); |
111 | strip_A.show(); |
112 | delay(rotDelay); |
113 | }
|
114 | for (int b = 0; b < NUMPIXELSB; b++) { |
115 | strip_B.setPixelColor(b, whiteB ); |
116 | strip_B.show(); |
117 | delay(rotDelay); |
118 | }
|
119 | for (int b = 0; b < NUMPIXELSB; b++) { |
120 | strip_B.setPixelColor(b, offB ); |
121 | strip_B.show(); |
122 | delay(rotDelay); |
123 | }
|
124 | for (int c = 0; c < NUMPIXELSC; c++) { |
125 | strip_C.setPixelColor(c, whiteC ); |
126 | strip_C.show(); |
127 | delay(rotDelay); |
128 | }
|
129 | for (int c = 0; c < NUMPIXELSC; c++) { |
130 | strip_C.setPixelColor(c, offC ); |
131 | strip_C.show(); |
132 | delay(rotDelay); |
133 | }
|
134 | }
|
135 | |
136 | ISR(PCINT0_vect) //Capture Hall via Interrupt |
137 | {
|
138 | time = (micros() - time_last); |
139 | time_last = micros(); |
140 | }
|
Kommentare hab ich auf englisch gelassen und eingefügt. Für Hilfestellung und Verbesserungsvorschläge bin ich offen. Auch schon überlegt statt Interrupt den Timer zu benutzen, weiss halt noch viel zuwenig über C und stückel mir das grad mehr oder weniger zusammen. Es funktioniert ja auch fast. Aber nur fast ;) PS. Über die Arduino IDE die ich parallel benutze checke ich ob das Program in einen ATTiny 85 reinpasst. Momentan werden 3778 Bytes verwendet, also sind noch ca 2000 Byte übrig neben dem Bootloader soweit ich es verstanden haben. Globale Variablen sind bei 127/512 Bytes. Noch jede Menge Platz um das Program zu verbessern.
Es hat sich ein kleiner Fehler eingeschlichen. Wohl beim hin und her kopieren aus IDE und Webseiten Compiler passiert. So funktioniert es nicht, der Interrupt ist ja kein Pin Change.
1 | ISR(PCINT0_vect) //Capture Hall via Interrupt |
2 | {
|
3 | time = (micros() - time_last); |
4 | time_last = micros(); |
5 | }
|
muss
1 | ISR(INT0_vect) //Capture Hall via Interrupt |
2 | {
|
3 | time = (micros() - time_last); |
4 | time_last = micros(); |
5 | }
|
sein, sonst wird die RPM standardmässig auf 65K /3 gesetzt und ist kein bisschen dynamisch.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.