Arduino - Bluetooth - Android - LEDs

Hallo liebe Arduino-Gemeinde,

ich würde gerne digitale LEDs (WS281x) mit einem (Android-)Smartphone steuern.
Um die Kosten im Rahmen zu halten, möchte ich das über mein Arduino UNO und einem Bluetooth Modul (genauer HC-05) realisieren.

Mittels FastSPI lassen sich die LEDs simpel über das Arduino ansteuern.
Eine Verbindung von Smartphone zum Bluetooth-Modul ist auch schon geglückt und es ist mir gelungen mittels Bluetooth-Terminal die LEDs anzusteuern.

Für mich, als Neuling auf ganzer Linie, ist das schon ein großer Erfolg.

Dennoch würde ich gerne die Bediehnung kompfortabler gestallten und hoffe hier auf Unterstützung - gerne auch durch Zusammenarbeit falls jemand interessiert ist.

Das Ganze soll dann in etwa wie in diesem Video aussehen: Link

Mein Ziel ist es eine Android App zu schreiben, mit der man über einen "Farbkreis" und einer Schiebe-Leiste statische Farben (HSV) und Sättigung einstellen kann oder die LEDs in einem bestimmten Modus (im Arduino gespeichert) zu betreiben.
(z.B. fade durch alle Farben).

Mein Problem ist, dass ich starke Probleme habe eine solche (erste) App zu programmieren, da das Thema Bluetooth nicht so ganz tirivial für mich ist und auch noch nicht so richtig weiß, wie ich die Daten übergeben soll.

Über das Terminal habe ich zum Beispiel einzelne Zahlen an das Arduinoboard geschickt, dass dann diese Zahl in eine HSV Farbe umgewandelt hat und die LEDs zum leuchten gebracht hat.

Für meinen Zweck bräuchte ich aber wahrscheinlich mehrere Parameter etc. und müsste das dann irgendwie an das Arduino schicken.
Auch ist es mir nicht gelungen eine App zu schreiben, die eine funktionierende Bluetooth-Verbindung zum Arduino aufbaut.

Vielleicht gibt es hier ja jemanden der Interesse hätte und mir helfen möchte.
Das Ergebnis und auch die Entwicklung soll hier festgehalten werden, damit die "Nachwelt" etwas davon hat und ich mir bei meinen Ideen immer einbilde, dass auch andere Interesse an so etwas haben könnten :slight_smile:
Ich danke euch!

Du hattest mir dein vorhaben ja bereits als PM erläutert. Also das Streamen selber wird über Bluetooth wenig Sinn machen, da zwischen Senden und Empfangen eine kurze Zeit vergeht und somit keine schnellen Fades möglich sein werden. Jedoch kann man Fades gut im Arduino abspeichern und dann ensprechende Parameter übergeben (Geschwindkeit, Farbeton, Sättigung und ggf. auch die max. Helligkeit).

Ich warte noch auf mein Bluetooth Module ehe ich testen kann. So wie im Video gezeigt wurde, ist es noch relativ unkompliziert von der Kommunikation. Kenne mich mit der Android SDK nicht aus. Jedoch würde ich empfehlen zu Anfang mit 2-3 1D Skalen zu arbeiten. So zumindest werde ich das zu Beginn versuchen

Modus:
{Eingabe einer Zahl von ... bis ...)

Farbton:
(Skalen als Slider, eventuell mit der Grafik hinterlegt. ! FastSPI Lib nutzt für die Auflösung der HSV (0...36o°) nur 0...255)
|....|....|....|....|
0        128       255

Sättigung
|....|....|....|....|
0        128       255

Helligkeit
|....|....|....|....|
0        128       255

Dauer
|....|....|....|....|
0        128       255

Nun könnte man wie folgt weiterarbeiten, bitte nur als PseudoCode sehen.

sendCommand = hue;
sendCommand = (sendCommand * 1000) + sat;
sendCommand = (sendCommand * 1000) + brightness;
sendCommand = (sendCommand * 1000) + duration;

Nun würde man bei rot(Farbton 0 und Sättigung 255), 75% Helligkeit (138) und Dauer des des Fades(100(könnte 10s bedeuten)) folgendes Commando rauskommen:

sendCommand = 100138255000

Nun müsste das Commando in Arduino wieder auseinander genommen werden. Eventuel in der App selber nur mit einem Senden Button die Werte schicken oder aber auf dem Arduino den Wert überprüfen, ob dieser sich geändert hat.

Natürlich kann man dieses auch noch andersweitig abfangen, das ist mir klar, in dem man die Werte hinterander sendet, aber hier geht es mehr oder weniger nur erst einmal um meinen Ansatz.

Gruß Stefan

Vom Prinzip her ist das ja identisch.
Die Modi sollen ja auf dem Arduino abgelegt sein und dann ggf. aktiviert werden (mit eventuell nötigen Parametern).
Die Modi könnte man auf einer 2. Seite auswählbar machen und nach dem Einstellen der Parameter in der App auf "senden" klicken.
Insofern ist das schonmal bei uns beiden von der Überlegung gleich.

Bei den statischen Farbwerten ist es vom menschlichen Gedankengang her schwer eine gewünschte Farbe mittels 4 Slider hinzubekommen.
Es ist von dort aus auch nur noch ein kleiner Schritt zu einem Farbkreis und dann eben noch nen Slider für die Sättigung (ggf. mehr Parameter, wenn man es braucht).
Die Verschiebung um jeweils 3 Stellen hatte ich auch schon so im Kopf.
Wenn man z.B. das erste Tripple für die Einstellung des Modus macht und die anderen mit weiteren Parametern füttert könnte man sich zumindest einen Workaround basteln.
So ergäben sich dann 999 Modi - also mehr als ausreichend.

Allerdings ist das relativ unelegant, da man wirklich sehr festgelegt ist auf eine Berücksichtigung aller Fälle zu Beginn und es ist leider auch sehr ungenau.

Gedankenbeispiel:
Der Benutzer stellt Modus 100 ein für ein zufälliges Blinken der LEDs und gibt anschließend die Farb-, Sättigungs-, und Helligkeitswerte an.
Hier wäre es aber noch gut, wenn man eine max. und min. Helligkeit einstellen könnte und auch die Geschwindigkeit des Blinkens einstellen könnte - und zwar sowohl für den Fall, dass man im Bereich von 0-1 Sekunde was einstellen möchte, als auch im Bereich von >1 Sek. Vielleicht sogar als Zufallswert zwischen zwei Zahlen...
Da wir aber nur drei Stellen zur Verfügung haben wird es unmöglich sein alle Einstellungen zuzulassen.

Klar das Beispiel ist ein Spezialfall, aber es demonstriert dennoch gut, dass die Methode der Kommunikation etwas unflexibel ist.

Soweit ich weiß kann man nicht nur Zahlen, sondern auch Strings mit Bluetooth senden.
Es wäre also meiner Meinung nach besser das Ganze direkt als String zu senden und die einzelnen Parameter mittels Operatoren zu trennen und Start und Ende zu begrenzen.

Das Arduino kann den String dann wieder zerlegen und man ist so zumindest etwas flexibler.
Leider weiß ich nicht inwiefern das zulasten der Performance geht.

Dein Beispiel-Kommando würde dann so aussehen können:

sendCommand = |100,138,255,000|

Trennoperator = ,
Start/Ende Operator = |

Wenn ich allerdings schon bei diesem "Problem" wäre, dann wäre ich schon sehr zufrieden :slight_smile:

Momentan schaffe ich es nicht eine App zu programmieren, die eine BT-Verbindung aufbaut...

Die Skala 0...255 meinte ich in etwa so. Einen Farbkreis sowie eine zusätzliche Skala für die Helligkeit wirste aber benötigen.

Kann ja ggf. so geregelt werden, dass du auf der ersten Seite den Modus wählst, dann auf der nächsten Seite die Eingabe mit Parameter,Auswahl Farbkreis etc machst. Mit 3 stellen war lediglich ein Beispiel, sehe gerade, da komme ich eh über die mögliche Länge eines uint32_t.

Erst einmal reine Ideen, wenn meine Teile da sind, kann ich es besser testen.

Ich hatte da an sowas hier gedacht:

das ich hier gefunden hab.

Leider reicht meine Java und Android-Kenntnisse nicht aus um das einzubauen.
Bin es nun schon 2 Tage am versuchen.
Ich warte und hoffe, dass du evtl. mehr erreichen kannst.

Ich glaube er hat gemeint, das zum Anfang erst mal einfach zu halten. Mit simplen Slidern. Gerade wenn du dich nicht auskennst, muss man nicht überall gleich komplizierte Baustellen einbauen die große Fehlerquellen sind.

Wenn das dann mal mit Slidern läuft, kann man die Bedien-Elemente komplizierter machen und mehr Parameter übertragen. Du musst lediglich deinen Code so schreiben, dass er einfach erweiterbar ist.

Ja genau :wink:

Es würde auch gehen, wenn diese erst einmal alle manuell eingetragen werden. Was bringt das aufwendige programmieren, wenn kurz vor Schluss aufällt, dass es so nicht realisierbar ist.

Kleine Nebenfrage: Warum sollen denn die vergleichsweise teuren WS281x verwendet werden. Deren Vorteil ist doch, dass man jede LED einzeln ansteuern kann. Das geht jedoch aus deinem Bedienungskonzept nicht hervor, auch der Kollege im Video hat nur einfache RGB-Stripes. Oder hab ich was überlesen (was mich auch nicht wundern würde)? :wink:

On a similar note, I have almost completed a new Android app that allows me to control my deck/landscape LED's. Have you looked into MIT's (was Google) App Inventor for programming the app you are describing? Its a great way for us Android noobs to program Android apps.

Danke schonmal für eure zahlreichen Antworten!

Also zu den Slidern: Da habt ihr natürlich recht: Einfacher ist einfacher.
Ich wollte damit aber schonmal abfragen ob jemand vielleicht diesen komplizierten Slider (Color Picker) schonmal programmiert hat und ich auf etwas Fertiges zurück greifen kann.

Mein Problem ist, dass ich momentan viele Fragen hab und ich erleichtert bin, wenn zumindest ein Teil nicht mehr ungeklärt ist ^^

@sth77:
Die WS281x sollen verwendet werden, damit man schöne Modi benutzen kann.
Ziel ist es eine App zu haben, mit der man unterschiedliche Effekte starten und steuern kann.
Auf Seite 1 der App sollen statische Farben gewählt werden können.

Auf Seite 2 gibt es dann Modi in denen man z.B. ein Lauflicht, Meteor und vieles mehr wählen kann.
Die digitalen LEDs haben das Potential alle Effekte darzustellen.

Außerdem ist es für einen Anfänger hier einfacher das Arduino zu flashen, als eine App zu schreiben.
Wenn jemand also einen tollen Sketch programmiert hat, der die LEDs nach seinen Wünschen zum Leuchten bringt, reicht es Prinzipiell aus, meine App zu nehmen und einen Modus von mir mit seinem Sketch zu überschreiben.
Man ist mit den digitalen LEDs also flexibler und das Projekt kann theoretisch von allen - unabhängig vom Können - benutzt und erweitert werden.

Und zur Info: Ich habe 5m WS2812B LED Streifen mit IP65 (also mit Silikonüberzug und damit wasserdicht) für gerade mal 42€ inkl. Versand gekauft. Ich glaube nicht, das die schlechteren wesentlich günstiger sind.

@deejayspinz: Yeah I already looket MITs app inventor up but for time reasons I did not really close .
I was thinking of use an existing app and edit it like I found here: instructables.com
But decided to make "a real" app (with eclipse) where I surely will not come to any restrictions of the program. But maybe I will take a closer look at it.

Für die Kommunikation werde ich ziemlich sicher Strings benutzen.
Ich habe die Übermittlung von Strings an das Arduino eben gerade erfolgreich getestet.
Somit kann man schön ziwschen den Modi wählen und viele Parameter mitschicken.
Nach meinen Tests ist ab 63 Zeichen schluss - also genug um einiges an Daten mitzuschicken.

Sonderzeichen funktionieren auch wie man sieht:

Liebe Grüße!

Sorry ich kann dir zwar nicht helfen, aber wo hast du den Stripe so günstig bekommen?

Wäre vielleicht dass was für dich? http://www.myledlamp.net/
Wie wärs damit? http://www.ebay.de/itm/300978424310?ssPageName=STRK:MEWAX:IT&_trksid=p3984.m1438.l2648

Hallo,
damit das hier nicht ausufert, bitte ich solche Offtopic-Fragen demnächst direkt (PM) zu stellen.
Die Stripes habe ich aus China über aliexpress.

Ok - ich verstehe nicht wo das Problem ist und hoffe jemand von euch weiß Rat.

Ich möchte aus einem String einen (dynamischen) array von Strings machen und diesen dann am besten noch zählen.
Versucht habe ich folgendes:

String text = "das,ist,ein,beispiel,string";   
String[] stringArray = text .Split(",");     //Fehler: expected unqualified-id before '[' token
int AnzahlParameter = stringArray.length;  //Fehler: 'stringArray' was not declared in this scope

Rauskommen soll:
stringArray[0]: das
stringArray[1]: ist
stringArray[2]: ein
stringArray[3]: beispiel
stringArray[4]: string

Ich schätze ich bringe da was durcheinander.
Es wäre lieb, wenn mir jemand weiterhelfen könnte.

Bezüglich der App hab ich immerhin schonmal die Slider hinbekommen.
Sie ändern momentan die Hintergrundfarbe über RGB Slider und geben die dazugehörige Hexadecimal Farbe in einem Feld aus.
Später möchte ich dann die Hex-Farbe über Bluetooth schicken (sind weniger zeichen als RGB oder HSV).

Kleiner Appetithappen:

Da ist ein Leerzeichen zwischen "text." und "split". Ist das nur beim Kopieren entstanden?

Außerdem solltest du beachten, dass Methoden in Java anders als in C# klein geschrieben werden. Weiß aber nicht wieso der Compiler da schon vorher meckert. Sollte eigentlich funktionieren.

Nee das ist leider nicht beim kopieren entstanden, sondern beim aus dem kopf tippen.
Komisch ist, dass es dennoch nicht funktioniert.
Sieht irgendwie so aus, als ob das Arduino irgendwas mit strings und arrays generell nicht unterstützt.
Ist das denn komplett implementiert oder gibt es da aus speichergründen irgendwelche restriktionen?

Ist das jetzt C++ oder Java? Ich dachte Java, so wie du das Array deklariert hast.

In C geht das so:

char text[] = "das,ist,ein,beispiel,string";      //die Array Klammern sind hier *nach* der Variable
const int arraySize = 10;
char* stringArray[arraySize];          //Pointer für 10 Strings. Bei Bedarf größer machen
int i = 0;

char* pch = strtok(text, ",");

while(pch != NULL)
{
    stringArray[i++] = pch;
    pch = strtok(NULL, ",");
}

stringArray enthält nur Pointer auf bestimmte Teil-Strings im ursprünglichen Array "text". Deshalb wird nur Speicher für die Pointer benötigt, aber der Text wird nicht dupliziert. Mann kann natürlich auch ein richtiges String-Array anlegen (zwei-dimensionales Array auf char) und dann die Strings mit strcpy kopieren. Das kostet aber mehr Speicher und bringt nicht wirklich was.

Wenn du mit dem Index sicher gehen willst, frage in der while-Schleife noch ab ob "i" innerhalb des Arrays liegt:
while(pch != NULL && i < arraySize)

strtok:

http://www.cplusplus.com/reference/cstring/strtok/

Es gibt in C++ auch eine richtige String Klasse wie in anderen Sprachen, aber die ist auf dem AVR nicht implementiert (die String Klasse die du verwendet hast ist Arduino-spezifisch). Deshalb werden i.d.R. klassische C-Strings verwendet und die alte string.h Lib (welche automatisch inkludiert ist).

Aha!
Auch wenn ich deine Lösung noch nicht ganz verstanden hab, ist es zumindest schonmal ein Ansatz, wo mein Fehler liegt.
Das Thema “Pointer“ ist komplett neu für mich.
Dazu habe ich schon den ein oder anderen Cide-Schnipsel gesehen und werde es mir wohl mal genauer angucken.
Kurz gesagt sind Pointer speicherschonender oder?

Und bezüglich der eckigen Klammern:
Ich hatte es sowohl als auch probiert.
Da ist eine gewisse Verwirrung, wenn man von php über java auf c kommt...
Ich bin gerade unterwegs. Werde mich aber morgen nochmal dran setzen und es mit deiner Lösung probieren.
Vielen Dank!

In Java ist es wahrscheinlich "int[] var", weil Arrays da eigene komplexe Datentypen sind. Also "int[]" ist was ganz anderes als "int". In C/C++ sind Arrays lediglich ein reservierter Speicherbereich und die Variable ist ein Pointer auf das erste Element.

strtok (string tokenizer) ist auf dem ersten Link eigentlich gut erklärt. Man initialisiert die Funktion einmal und ruft sie danach mit NULL als Parameter auf. Das ist das einzig verwirrende. Danach geht strtok durch den String und sucht alle Zeichen die im zweiten Paramter als Delimiter angegeben sind. Diese werden durch NULL ersetzt, wodurch die Teil-Strings Null-terminiert werden und damit woanders verwendet werden können. Die Funktion liefert dann jedesmal einen Pointer auf den Teil-String. Und NULL wenn sie fertig ist, d.h. wenn sie den Terminator des Gesamt-Strings gefunden hat.

Also ich hab das mir den Pointer nun verstanden.

Momentan ist mein String max. 63 Zeichen lang, d.h. der array ist maximal 32 Felder groß (erstes und letztes Zeichen sind nie “,“ ).

Du hast den array mit einer konstanten Größe initialisiert. Mir ist klar, dass ich die Größe entsprechend im Code verändern kann.
Ich hatte allerdings versucht den array “dynamisch“ zu erstellen.

Wenn z.b. der string so aussieht:char text[] = “1,8“;
Dann würde eigentlich ein array der größe 2 (anstatt 32) reichen.
Die benötigte array größe könnte man vorher mit der summe aller vorkommenden Kommata + 1 bestimmen.
Kann man ein array in c bzw. im arduino überhaupt in Abhängigkeit einer Variablen initialisieren?