Author Topic: Arduino Dashboard  (Read 16234 times)

MathiasW

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 614
  • Karma: +13/-0
    • my Arduino page
Arduino Dashboard
« on: September 07, 2012, 04:25:44 PM »
Salut,

inspiriert von der Android App "Handbag" (welche leider nicht auf meinem Mobile installierbar ist), hatte ich die Idee, ein kleines Program zu schreiben, welches ein Sammlung an Controls anbietet die über das Arduino Sketch kontrolliert werden. Was dabei herausgekommen ist, kann man sich auf meiner Webpage anschauen : http://www.mathias-wilhelm.de/arduino/projects/arduino-dashboard/

Auf der gleichen Idee basiert auch eine Ansteuerung des Adafruit motor shields und der servos eines Roboterarms: http://www.mathias-wilhelm.de/arduino/projects/arduino-control/

Der Code ist lange noch nicht fertig aber mich würde Euer Feedback interessieren.

Ciao, Mathias

boxtec-support

  • Moderator
  • Hero Member
  • *****
  • Posts: 787
  • Karma: +15/-0
    • Boxtec Web
Re: Arduino Dashboard
« Reply #1 on: September 08, 2012, 04:41:22 PM »
Hallo Mathias,

Sehr interessant, ich bin grad an etwas ähnlichem zur Steuerung von zwei RGB Kanälen (z.B.) RGB LED Strips über seriell und Drehencoder mit Taster:



Dabei bedanke ich mich vor allem für den Hinweis auf serialEvent(), ich hab nicht gewusst, dass die neue Serial Library diesen Event schon registriert hat und standardmässig genannte Funktion aufruft. Absolut genial, danke für den Code, ich konnte mir da ein paar nette Tricks abschauen.

Viele Grüsse,
Christoph


MathiasW

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 614
  • Karma: +13/-0
    • my Arduino page
Re: Arduino Dashboard
« Reply #2 on: September 15, 2012, 09:31:18 AM »
Salut,

ich habe ein kleines Problem entdeckt: In meinem Sketch werden alle seriellen Daten über den Interrupt SerielEvent abgearbeitet. Im loop() geschiet eigentlich nichts. Nun habe ich im loop folgendes geschrieben:
Code: [Select]
if (readAnalog) {
  Serial.println(analogRead(A0));
}
Die boolsche Variable readAnalog wird im SerialEvent auf true oder false gesetzt, je nach Kommando, welches ich von aussen schicke.
Das Ganze funktioniert, aber es dauert bis zu 10 Sekunden, bis der Wechsel des Wertes von readAnalog in loop erkannt wird.

Hat jemand eine Idee?
Ciao, Mathias

MathiasW

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 614
  • Karma: +13/-0
    • my Arduino page
Re: Arduino Dashboard
« Reply #3 on: September 15, 2012, 03:31:14 PM »
Salut,

da ich mit Interrupts arbeite, dachte ich mir, dass ich die Ausleseaktion von loop() in eine subrountine verschiebe und diese über den timer ausführen lasse:
Code: [Select]
#include <MsTimer2.h>
....
void setup()
{
  Serial.begin(115200);
  for (int i=2;i<14;i++) {pinMode(i,OUTPUT);}
 
  MsTimer2::set(500, flash); // 500ms period
  MsTimer2::start();

}

void flash()

  int led_pin = 13;
  if (readPort) {
    digitalWrite(led_pin, !digitalRead(led_pin));
   if (dbOpen) {
      Serial.print("SLBV001.");
      Serial.print(analogRead(A0));
      Serial.println("E");
    }
  }
}

Mit diesem Konstrukt wird die Änderung in der variablen readPort sofort erkannt ...
Damit habe ich eine gute Lösung, aber ich würde das gerne verstehen ... Sobald ich ein Serial.println Statement in loop() einbaue, braucht es wieder bis zu 10 Sekunden, bis der Wechsel von readPort erkannt wird

Ciao, Mathias

boxtec-support

  • Moderator
  • Hero Member
  • *****
  • Posts: 787
  • Karma: +15/-0
    • Boxtec Web
Re: Arduino Dashboard
« Reply #4 on: September 16, 2012, 04:06:30 PM »
Hallo Mathias,

Soweit ich den Code verstanden habe, wartest Du im serialEvent bis Du einen Charakter 13 kriegst, mit dem Du wohl die Kommandosequenz aus Deinem VB GUI terminierst. Ich kann mir daher vorstellen, dass der serialEvent die Ausführung des Codes in Loop blockiert, sprich der Loop wird tatsächlich erst nach 10s wieder durchlaufen weil solange immer der serialEvent blockt.
Ist aber ein wilder Schuss ins Blaue ohne den genauen Code gesehen zu haben.
Ev. kannst Du ein Stück Testcode zeigen, mit dem sich das Verhalten replizieren lässt.

Viele Grüsse & schönen Restsonntag,
Christoph

MathiasW

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 614
  • Karma: +13/-0
    • my Arduino page
Re: Arduino Dashboard
« Reply #5 on: September 17, 2012, 09:32:45 AM »
Salut,

da der Code nicht sonderlich lange ist, hier das vollständige Listing:
Code: [Select]
#include <MsTimer2.h>

int bufferCount;    // Anzahl der eingelesenen Zeichen
char buffer[80];    // Serial Input-Buffer
char temp[80];
char lastpin=2;
int blinkdelay;
boolean dbOpen = false;
static boolean readPort = false;
void setup()
{
  Serial.begin(115200);
  for (int i=2;i<14;i++) {pinMode(i,OUTPUT);}
 
  MsTimer2::set(500, flash); // 500ms period
  MsTimer2::start();

}

void loop()
{
  /*
  if (readPort) {
    digitalWrite(led_pin, !digitalRead(led_pin));
   if (dbOpen) {
      Serial.print("SLBV001.");
      Serial.print(analogRead(A0));
      Serial.println("E");
    }
  }
  */
}

void serialEvent(){
  char ch = Serial.read();
  buffer[bufferCount] = ch;
  bufferCount++;
  if(ch == 13){
    evalSerialData();
  }
}

void evalSerialData()
{
  int ptr;
  int val;
  strcpy(temp,"");
  if ((buffer[0]=='S')&&(buffer[bufferCount-2]=='E')) {
    strncat(temp, buffer, bufferCount-1);
    if (strcmp(temp,"SQVERSIONE")==0){
      strcpy(temp,"AC 1.0.0");
    }
    if (strcmp(temp,"SINITE")==0){
      // setup the Dashboard
      Serial.println("STTL1Dashboard DemoE");
      Serial.println("SBTN001.0020.0040.0080.0025.Click MeE");
      Serial.println("SCKB001.0105.0040.Led 5E");
      Serial.println("SSLD001.0020.0070.0002.0013.0001.Led SwiperE");
      Serial.println("SSLD011.0020.0150.0000.0250.0025.Led FaderE");
      Serial.println("SCBO001.0020.0240.0080.0025E");
      Serial.println("SCBA001.Port A0E");
      Serial.println("SCBA001.Port A1E");
      Serial.println("SCBA001.Port A2E");
      Serial.println("SCBA001.Port A3E");
      Serial.println("SCBA001.Port A4E");
      Serial.println("SCBA001.Port A5E");
      Serial.println("SCBS001.0002E");
      Serial.println("SLBL001.0250.0040.0080.0030.0.00E");
      Serial.println("SCKB011.0335.0040.Show Port DataE");
      dbOpen = true;
    }
    if (strcmp(temp,"SGoodByeE")==0){
      // stop the Dashboard
      dbOpen = false;
    }
    if ((buffer[1]=='C')&&(buffer[2]=='K')&&(buffer[3]=='B')){
      ptr = (buffer[4]-48)*10 + (buffer[5]-48);
      if (ptr==0) {digitalWrite(5,((buffer[6]-48)==1));}
      if (ptr==1) {readPort = (buffer[6]-48)==1;}
    }
    if ((buffer[1]=='B')&&(buffer[2]=='T')&&(buffer[3]=='N')){
      ptr = (buffer[4]-48)*10 + (buffer[5]-48);
        for (int i=2;i<14;i++) {digitalWrite(i,!(digitalRead(i)));}
    }
    if ((buffer[1]=='S')&&(buffer[2]=='L')&&(buffer[3]=='V')){
      ptr = (buffer[4]-48)*10 + (buffer[5]-48);
      val = (buffer[6]-48)*1000 + (buffer[7]-48)*100 + (buffer[8]-48)*10 + (buffer[9]-48);
      if (ptr==0) {
        digitalWrite(lastpin,LOW);
        lastpin=val;
        digitalWrite(lastpin,HIGH);
      }
      if (ptr==1) {
        analogWrite(10,val);
      }
    }
  } else {
    strcpy(temp,"BadCmd: ");
    strncat(temp, buffer, bufferCount);
    Serial.println(temp);
  }
  bufferCount=0;
}

void flash()

  int led_pin = 13;
  if (readPort) {
    digitalWrite(led_pin, !digitalRead(led_pin));
   if (dbOpen) {
      Serial.print("SLBV001.");
      Serial.print(analogRead(A0));
      Serial.println("E");
    }
  }
}

Ich dachte auch, dass der SerialEvent den Prozessor blockt, aber dann müsste er das auch für die getimte Routine machen. Ausserdem schcike ich in der Zeit nichts sondern lese eldiglich auf der PC Seite die geschickten Werte und stelle sie in einem Graph dar.

Das Ganze dient übrigens als Plotroutine, so dass ich im Dashboard mit nur einem Kommando ein Graph-Control anfordern kann und dann Daten vom Arduino geplottet werden. Das habe ich immer vermisst, wenn ich z.B. den Input an A0-A5 betrachten will
Inzwischen ist das Dashboard mit den Controls Button, CheckBox, Combobox, Label und Slider fertig

Ciao, Mathias

boxtec-support

  • Moderator
  • Hero Member
  • *****
  • Posts: 787
  • Karma: +15/-0
    • Boxtec Web
Re: Arduino Dashboard
« Reply #6 on: September 17, 2012, 11:18:31 AM »
Guten Morgen Matthias,

Nur eine kurze und vrmtl. dumme Frage: Warum deklarierst Du readPort als static im globalen Kontext ? Soweit ich mich da errinnere erreichst Du damit, dass die Variable auf file scope reduziert wird. Ob das das Problem beseitigt weiss ich nicht, aber es scheint mir einen Versuch wert, die Variable ohne static zu deklarieren.

Grüsse,
Christoph

MathiasW

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 614
  • Karma: +13/-0
    • my Arduino page
Re: Arduino Dashboard
« Reply #7 on: September 17, 2012, 12:03:47 PM »
Salut Christoph,

ich hatte die variable ursprünglich ohne static deklariert und dachte, dass es funktioniert, wenn ich sie static deklariere - kein Effekt

Mich wundert das Verhalten, da ich erwarte, dass die variable eine Speicherstelle belegt und in der Interruptroutine verändert wird. SObald dies im Memory geschrieben ist, sollte dies doch in der loop() routine sichtbar sein...
Da ich nach dem Befehle, die Variable auf false zu setzen auch nichts mehr über die Serielle Schnittstelle schicke, sollte auch keine Blockade durch das Handling der Seriellen Schnittstelle da sein, zumal 10 Sekunden sehr lange sind...

Ciao, Mathias
« Last Edit: September 21, 2012, 02:45:13 PM by MathiasW »

MathiasW

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 614
  • Karma: +13/-0
    • my Arduino page
Re: Arduino Dashboard
« Reply #8 on: September 24, 2012, 01:01:18 PM »
Salut Christoph,

welches IDE verwendest Du für den Ambientino? Ich bin am überlegen, das Arduino Dashboard auch auf Linux zu protieren

Ciao, Mathias

boxtec-support

  • Moderator
  • Hero Member
  • *****
  • Posts: 787
  • Karma: +15/-0
    • Boxtec Web
Re: Arduino Dashboard
« Reply #9 on: September 27, 2012, 01:15:13 PM »
Guten Tag Mathias,

Entschuldige meinen späten Follow-Up. Ich wollte auch nochmal in Dein Serial Problem reinsehen da es mich selber sehr interessiert hab aber einfach die Zeit noch nicht gefunden.

Ich verwende unter Linux mit grosser Vorliebe PythonCard welches einen sehr einfachen Wrapper um wxPython bietet und somit auch auf Windows läuft wenn wx.Python vorhanden ist oder es mit einem Packer zu einer exe gepackt wurde welche alle Libraries enthält.

Sobald man etwas wildere UIs bauen will kommt man um den direkten Zugriff via wxPython nicht rum, aber für schnelle und einfache Hacks ist PythonCard mein absoluter Liebling. So gut wie die gesamte innere Logistik und Lagerverwaltung bei Boxtec wird mit einer mittlerweile recht umfangreichen PythonCard Applikation gehandelt. Ich finde sogar mit dem pySerial Modul gibt es nichts trivialeres um Daten von einem Arduino seriell auszuwerten. Hier nur zum Appetit anregen die nötigen Zeilen um den Befehl "P1" seriell zu senden:

Code: [Select]
#!/usr/bin/python
import serial
serial_obj = serial.Serial('/dev/ttyACM0', 9600)
serial_obj.write("P1")
print "das wars auch schon"
# 2 bytes lesen und ausgeben
print serial.read(2)
# der saubere Handwerker schliesst der Port, passiert aber am Ende des Script eh:
serial_obj.close()

</Python-Lobpreisung> ;-)

Viele Grüsse,
Christoph

MathiasW

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 614
  • Karma: +13/-0
    • my Arduino page
Re: Arduino Dashboard
« Reply #10 on: September 27, 2012, 05:35:36 PM »
Salut Christoph,

klingt interessant und ich werde mir das mal anschauen. Was ich auf der Hompage gesehen habe, ist recht vielversprechend.
Zwischenzeitlich habe ich die erste Version des Arduino Dashboards fertig gestellt:

Der Democode liest den in der Combobox angewählten anlog Port aus und stellt ihn im Histogram dar, im zweiten Tab werden alle 6 analog Ports dargestellt. Die beiden Zeitpanels schicken entweder die aktuelle PC-Zeit oder eine frei wählbar Zeit als Ticket an den arduino (der Sketch ist noch in Arbeit)

Ciao, Mathias

MathiasW

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 614
  • Karma: +13/-0
    • my Arduino page
Re: Arduino Dashboard
« Reply #11 on: October 09, 2012, 11:45:58 PM »
 Salut,

das Problem mit der verzögerten Antwort für eine logische Variable, welche in der Handlingroutine des SerialEvents() gesetzt wird, habe ich gelöst:
Die Variable muss als "Volatile" deklariert werden (siehe attachInterrupt() Dokumentation)

Spannend wird es, wenn man versucht, Encodermotoren über die serielle Schnittstelle zu steuern. Da man für die Auslese der Encoder externe Interrupts verwendet, stört das die SerialEvent Routine (wie auch dort in der Dokumentation beschrieben). Es sieht aber so aus, als könne man das mit etwas mehr Protokollaufwand abfangen.

Ciao, Mathias
« Last Edit: October 09, 2012, 11:47:40 PM by MathiasW »