Forum: Mikrocontroller und Digitale Elektronik LED Lauflicht Drehzahlabhängig / Hall Sensor


von Fam B. (fambaa)


Angehängte Dateien:

Lesenswert?

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
von Wolfgang (Gast)


Lesenswert?

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.

von Fam B. (fambaa)


Lesenswert?

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 ;)

von Frank G. (frank_g53)


Lesenswert?

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.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

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

von fop (Gast)


Lesenswert?

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.

von Fam B. (fambaa)


Lesenswert?

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.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

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

von Fam B. (fambaa)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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.

von Fam B. (fambaa)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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.

von Fam B. (fambaa)


Lesenswert?

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/

von Wolfgang (Gast)


Lesenswert?

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.

von Fam B. (fambaa)


Lesenswert?

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
von Fam B. (fambaa)


Lesenswert?

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
}

von Fam B. (fambaa)


Lesenswert?

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.

von Fam B. (fambaa)


Lesenswert?

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
Noch kein Account? Hier anmelden.