Steuerung des Arduino via Excel (VBA) möglich?

Es gibt ein ActiveX -> http://www.parallax.com/tabid/393/Default.aspx
Das ist zwar mehr zur Datenerfassung gedacht bietet aber auch einige Möglichkeiten der Rückmeldung.
Das habe ich für mein Projekt Pulsmonitor Ding des Monats 11/2012 – Biofeedback mit Arduino | DingFabrik Köln e.V. | Fritz-Voigt-Straße 1 | 50823 Köln benutzt.

So, hier habe ich jetzt mal das "einfache" Programm zur Steuerung des Arduino:

// Programm zur Steuerung von 3 Ventilen und 2 Kameras

int VENTIL1 = 2;     // Pin 2 = Ventil 1
int VENTIL2 = 3;     // Pin 3 = Ventil 2
int VENTIL3 = 4;     // Pin 4 = Ventil 3

int KAMERA1 = 8      // Pin 8 = Kamera 1 (Nikon D700)
int KAMERA2 = 9      // Pin 9 = Kamera 2 (Nikon D90)

int START = 13       // Pin 13 = Startknopf

void setup()
{
   pinMode(VENTIL1, OUTPUT);
   pinMode(VENTIL2, OUTPUT);
   pinMode(VENTIL3, OUTPUT);
   pinMode(KAMERA1, OUTPUT);
   pinMode(KAMERA2, OUTPUT);
   pinMode(START, INPUT);
}

void loop()
{
   // hier muß der “START-Befehl” erfolgen

   Delay3000;			// Pause für drei Sekunden

   // Steuerung Ventil 1
   digitalWrite(VENTIL1, HIGH);	// Ventil 1 öffnen
   delay 1000;			// Pause für eine Sekunde
   digitalWrite(VENTIL1; LOW);	// Ventil 1 schließen
   delay 1000;			// Pause für eine Sekunde

   // Steuerung Ventil 2
   digitalWrite(VENTIL2, HIGH);	// Ventil 2 öffnen
   delay 1000;			// Pause für eine Sekunde
   digitalWrite(VENTIL2; LOW);	// Ventil 2 schließen
   delay 1000;			// Pause für eine Sekunde

   // Steuerung Ventil 3
   digitalWrite(VENTIL3, HIGH);	// Ventil 3 öffnen
   delay 1000;			// Pause für eine Sekunde
   digitalWrite(VENTIL3; LOW);	// Ventil 3 schließen
   delay 1000;			// Pause für eine Sekunde


   // Steuerung Kamera 1+2
   digitalWrite(KAMERA1, HIGH);	// Kamera 1 auslösen
   digitalWrite(KAMERA2, HIGH);	// Kamera 2 auslösen
}

Da habe ich ein paar Fragen zu:

  1. Wie genau muss der "START"-Befehl aussehen, um das ganze durch Drücken des Buttons in Bewegung zu setzen?
  2. Werden so wie im Programm angegeben beide Kameras auch gleichzeitig ausgelöst?
  3. Was wenn die Kamera schon vor Öffnen des Ventil 3 auslösen soll? Den Abalauf dann komplett umzuschreiben währe sehr aufwendig.
    Kann man das irgendwie geschickter lösen, dass nicht "starr" Ventil 1 dann 2 dann 3 dann Kamera 1+2 im "Programmablauf" stehen
    sondern irgedwie mit Variablen o.ä. so das man einen "Zeitablauf" vorgeben kann?

erni-berni:
Das habe ich für mein Projekt Pulsmonitor Ding des Monats 11/2012 – Biofeedback mit Arduino | DingFabrik Köln e.V. | Fritz-Voigt-Straße 1 | 50823 Köln benutzt.

Hmm... soweit ich das sehen kann liest du aber nur die Werte vom Arduino aus - ich will ja genau den anderen Weg gehen... aber die "zündende" Idee ist mir noch nicht gekommen :blush:

obiwan:

  1. Wie genau muss der "START"-Befehl aussehen, um das ganze durch Drücken des Buttons in Bewegung zu setzen?

Schau dir mal die Beispiele "Button" und "Debounce" an. Da wird das beschrieben.

obiwan:
2. Werden so wie im Programm angegeben beide Kameras auch gleichzeitig ausgelöst?

ja. Mit wenigen µs Verzögerung.

obiwan:
Kann man das irgendwie geschickter lösen, dass nicht "starr" Ventil 1 dann 2 dann 3 dann Kamera 1+2 im "Programmablauf" stehen
sondern irgedwie mit Variablen o.ä. so das man einen "Zeitablauf" vorgeben kann?

Natürlich.
Schau' dir mal das Beispiel "BlinkWithoutDelay" an.
Da wird die Methode beschrieben.
Im Prinzip sollte das so gehen:
Bei Knopfdruck millis() merken.

startzeit = millis();

Dann für die einzelnen Aktionen abfragen:

if (startzeit + Ventil1zeit < millis()){
  digitalWrite(VENTIL1, HIGH);
}

Wie gesagt, im Beispiel BlinkWithoutDelay ist der Ansatz beschrieben.

Die Zeiten mußt du dir alle als Variable definieren.

unsigned long Ventil1ein = 5000;
unsigned long Ventil1aus = 6000;
unsigned long Ventil2ein = 5500;
unsigned long Ventil2aus = 6700;
etc

.
Die Zeiten am besten immer absolut von Start an gerechnet, muß aber nicht sein, dann musst du halt addieren.

Warum unsigned long und nicht "nur" long?

Währ das Proggi so jetzt "richtig" im Ansatz:?

// Programm zur Steuerung von 3 Ventilen und 2 Kameras

int VENTIL1 = 2;     // Pin 2 = Ventil 1
int VENTIL2 = 3;     // Pin 3 = Ventil 2
int VENTIL3 = 4;     // Pin 4 = Ventil 3

int KAMERA1 = 8    // Pin 8 = Kamera 1 (Nikon D700)
int KAMERA2 = 9    // Pin 9 = Kamera 2 (Nikon D90)

int START = 13       // Pin 13 = Startknopf

int VALUE = 0

unsigned long VENTIL1_EIN = 5500;
unsigned long VENTIL1_AUS = 6000;
unsigned long VENTIL2_EIN = 6500;
unsigned long VENTIL2_AUS = 7000;
unsigned long VENTIL3_EIN = 7500;
unsigned long VENTIL3_AUS = 8000;
unsigned long KAMERA1_EIN = 7500;
unsigned long KAMERA2_EIN = 7500;

void setup()
{
   pinMode(VENTIL1, OUTPUT);
   pinMode(VENTIL2, OUTPUT);
   pinMode(VENTIL3, OUTPUT);
   pinMode(KAMERA1, OUTPUT);
   pinMode(KAMERA2, OUTPUT);
   pinMode(START, INPUT);
}

void loop()
{
   VALUE = digitalRead(START)

   if (VALUE = 1)
   {
      Delay3000;
      STARTZEIT = millis();
         if (STARTZEIT + VENTIL1_AN == millis())
         {
         digitalWrite(VENTIL1, HIGH);
         }
         if (STARTZEIT + VENTIL1_AUS == millis())
         {
         digitalWrite(VENTIL1, LOW);
         }
         if (STARTZEIT + VENTIL2_AN == millis())
         {
         digitalWrite(VENTIL2, HIGH);
         }
         if (STARTZEIT + VENTIL2_AUS == millis())
         {
         digitalWrite(VENTIL2, LOW);
         }
…
…

Schon besser. Aber funktioniert hat es nicht, oder? :slight_smile:

Die Abfrage kannst du nicht auf "==" machen, denn diese Bedingung ist nur genau 1ms wahr.
Besser ist "<".
Und dann solltest du, ähnlich wie im Beispiel "BlinkWithoutDelay" auch eine Statusvariable für deine Ausgänge einführen, damit du nur einmal schaltest.

Mach dir doch ein Steckbrett, auf dem anstelle der Optokoppler jeweils eine LED mit Vorwiderstand am Ausgang hängt. Dann kannst du einfach ausprobieren, ob dein Sketch läuft.

Immer weiter probieren!
Versuch macht kluch! :wink:

guntherb:
eine LED mit Vorwiderstand

warum mit Vorwiderstand und wie groß sollte der sein? 100??

guntherb:
Die Abfrage kannst du nicht auf "==" machen, denn diese Bedingung ist nur genau 1ms wahr. Besser ist "<".

Aber dann würde das Ventil doch sofort öffnen wenn kleiner millis gesagt wird - oder??? Das versteh ich nicht so ganz.

Ich möchte doch das nach dem drücke des Buttons erst einmal 3 Sekunden gewartet wird bis der Prozess startet und dann soll nach 5,5 Sekunden (also eigentlich nach 3 Sekunden + 5,5 Sekunden = 8,5 Sekunden) das erste Ventil für 0,5 Sekunden öffnen (wobei ich mir die 3 Sekunden am Anfang auch sparen kann - sollte nur eine "Sicherheitsreserve sein, dass auch alles richtig "übertragen" wurde).

obiwan:

guntherb:
Die Abfrage kannst du nicht auf "==" machen, denn diese Bedingung ist nur genau 1ms wahr. Besser ist "<".

Aber dann würde das Ventil doch sofort öffnen wenn kleiner millis gesagt wird - oder??? Das versteh ich nicht so ganz.

Warum?
Du drückst den Knopf beim Stand der internen Systemuhr = 10000 und damit setzt Startzeit = 10000;
in der nächsten if Anweisung fragst du ab 10000 + 5500 < 10001? falsch, also keine Ausführung des Befehls.
das macht der Arduino solange bis irgendwannn, 5,5sek später:
if (10000 + 5500 < 15501) jetzt true, also wird der Pin gesetzt.

obiwan:

guntherb:
eine LED mit Vorwiderstand

warum mit Vorwiderstand und wie groß sollte der sein? 100??

besser 200? bis 500?.
Eine LED (die normalen bunten Signal LED, nicht die HighPower Leucht-LEDs) braucht etwa 10mA um vernünftig zu leuchten, bei >35mA gehen die meisten kaputt. Also gilt es den Strom zubegrenzen mit einem Vorwiderstand:
(5V (Arduino-Ausgang) - 1,5V (LED Spannung) ) / 10mA = 350?.
(die LEDs auf dem Arduino-Board laufen mit 1k Vorwiderstand)

Zum Schalter abfragen würde ich (für den Anfang) sowas reinsetzen:

while (digitalRead(Startknopf) == HIGH  && Start == false) {    // Für Schalter nach Masse.  Für Schalter nach 5V auf LOW prüfen
  STARTZEIT = millis();
}
Start = true;
delay(100);  // zum Entprellen des Tasters

Die while-Schleife wird solange durchlaufen (er "hängt in der Whileschleife fest") bis der Taster gedrückt wurde.
Variable boolean Start sorgt dafür, dass er erst wieder in die whileschleife eintritt, wenn der nächste Start freigegeben ist.
Das würde ich jetzt wieder über eine Abfrage machen:

if (STARTZEIT + AllesFertig == millis()){
Start = false;
}

später kannst du das auch über den PC wieder freischalten.

AllesFertig sollte eine Zeit sein, die länger als alle anderen ist.

Puh... da hoff ich mal, daß am Wochenende schlechtes Wetter ist, damit ich das mit meinem Steckbrett mal testen kann.

Bis hierhinn erstmal vielen Dank! Sobald der Code "steht" und meine LEDs so blinken wie später die Ventile öfnen sollen, meld ich mich wieder
(oder wenns Probleme beim Code gibt :blush:).

hi,

ich hab' jetzt mal eine kleine anbindung von excel an arduino gemacht.
dazu verwende ich XMComm von dieser seite.
http://home.comcast.net/~hardandsoftware/xmcomm.htm
das ist ein in VBA-kreisen bekannter ersatz für die kostenpflichtige MSComm.
den ino-sketch hochladen und im excel drei werte einstellen.
ich habe keine ahnung, ob die portierung auf einen anderen rechner so funktioniert.
aber wer will, kann's probieren.

gruß stefan

test2_funkt.ino (441 Bytes)

Serial.xls (36.5 KB)

Währ schön, wenn das jemand testen könnte. Ich bin nun ja erst einmal damit beschäftigt die Hardware zusammenzulöten...

hi,

mußt nix groß testen. xmComm drauf, arduino anstecken, los...

gruß stefan

PS.: achja, com-port einstellen im VBA-code nicht vergessen.

Eisebaer:
mußt nix groß testen. xmComm drauf, arduino anstecken, los...

Ich bekomme die Excel-Datei nicht runtergeladen. Da kommt immer nur ein unvollständiger Download an: Serial.xls.xb5k7ku.partial

seltsam, ich kann sie downloaden.
ich probier's als zip...

gruß stefan

EDIT: zip ist kaputt, aber das excel sollte funktionieren...

Serial.zip (15 KB)

Ich bekomme schon wieder einen Fehler

fehler.jpg

Die ZIP datei kann ich auch nicht öffnen.
Die Excel hingegen schon.

die zip wurde wirklich beim hochladen beschädigt. auch als rar das gleiche ergebnis.
aber das excel geht, keine ahnung, wieso bei obiwan nicht.
ich kann's Dir's, obiwan, per mail schicken. PN genügt...

gruß stefan