PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Arduino Uno] - Multitasking und Serielle Befehle



neo3000
14.04.2011, 02:05
Hallo,
Kurz eine Beschreibung meines Projektes:

Ich möchte eigene Steuerbefehle per COM an den Arduino senden welche dieser auswertet und weiter verarbeitet, was soweit auch schon ganz gut funktioniert.
zb: Befehl 1003 senden
Adruino Empfang >> Pin9 auf HIGH setzen

Einen PWM wert sende ich indem ich zb.: 3235 sende und am Arduino 3235 - 3000 rechne das.
So erhalte ich den Wert 235 für dem PWM1 Ausgang.
PWM2 = 4000 usw.
Wenn ich die Befehle auch schön nach einander Sende werden diese auch ohne Problem verarbeiten.
Sende ich nun (timer abhänging) zb.: alle 2 sec dass der PWM1 auf 180 und dann wieder auf 0 gehen soll und will gleichzeitig noch mehere LEDs steuern und Daten vom Arduino an den PC senden bekomme ich immer wieder verschide aussetzer zb.: vom Servo an PWM1.

Kurz geasgt ich benötige Multitaskting am Arduino.!!

Mein derzeitiger Code (CODE WURDE DURCH HINWEISE VON BENUTZER "lokirobotics (https://www.roboternetz.de/community/member.php?11422-lokirobotics)" ANGEPASST, thx.)


const int pwmPin = 9;
const int ledPin = 8;
byte pwmWert;
int incomingData;
char data[4];
int i;

//Setup-Routine
void setup(){
Serial.begin(9600);
pinMode(ledPin,OUTPUT);
pinMode(pwmPin,OUTPUT);
}

//Hauptprogramm-Routine
void loop(){
//Abwarten bis data[] vier Stellen hat
do{
if (Serial.available()){data[i++] = Serial.read();}
}
while(i<4);
incomingData = atoi(data); // "data[]" in Integer umwandeln und in "incomingData" speichern

Daten_auswerten(); //Interger "incomingData" auswerten
PWM_setzen(); //PWM Wert auf Pin 9 ausgeben
Eingaenge_abrufen(); //Alle Ausgänge und Eingänge abrufen

i = 0;
}

void PWM_setzen(){analogWrite(pwmPin, pwmWert);}

void Daten_auswerten(){
if (incomingData == 1002){digitalWrite(ledPin, HIGH);} //Befehl "1002" um LED einzuschalten
if (incomingData == 1003){digitalWrite(ledPin, LOW);} //Befehl "1003" um LED einzuschalten
if (incomingData >= 3000){pwmWert = byte(incomingData - 3000);} //Befehl "3000" um PWM zu senden (bsp: 3245 - 3000 = 245) 3000 ist nur zur Unterscheidung
}

void Eingaenge_abrufen(){
//Daten aller Analogeingänge abrufen
for(int i = 0;i < 6;i++){
Serial.print(analogRead(i));
Serial.print(",");
}
//Daten der Digitaleingänge 0 - 8 abrufen
for(int i = 0;i < 14;i++){
if (i == 9){Serial.print(analogRead(i));}
else{Serial.print(digitalRead(i));}
if(i<13){Serial.print(",");}
}
Serial.print("&H");
Serial.flush();
//331,250,206,173,149,137,1,0,0,0,0,0,0,0,0,158(PWM) ,0,0,0,0&H
}
Wie kann ich nun die verschiedene Subroutinen so programmieren dass ich "zeitgleich" zb.: Daten (ständig) abrufen, PWM setzen, und LEDs über den PC steuern kann.

Zum Schluss möchte ich es so weit möglich machen dass ich ständig alle daten des Arduino einlesen, und zb.: Motorgeschwindigkeit und Servos gleichzeitig über den PC steuren kann.

Vielen Danke
Markus

lokirobotics
14.04.2011, 07:40
Hallo,

da stellt sich mir ersteinmal die Frage: Was für eine Aktualisierungsrate brauchst du?
Ein Ansatz ist, mit einem Timer z.B. alle 10ms einen Interrupt zu erzeugen. Die ISR ruft dann nacheinander alle benötigten Funktionen auf. Stichwort dazu: Kooperatives Multitasking (http://de.wikipedia.org/wiki/Multitasking#Kooperatives_Multitasking)

Dann gibt es noch "leistungsfähigere", kompliziertere Ansätze. Steht ebenfalls in dem Wiki-Artikel.

Ein paar Fragen hätt ich noch:
1. Wo ist deine Main-Funktion?
2. Wo kommt dein "incomingByte" her?
3. Wie kannst du einen Bytewert auf >255 setzen?

Und ein paar Anmerkungen zur leserlichkeit des Codes:
Die Lesbarkeit des Codes erhöht sich deutlich, wenn du einheitliche Notationen verwendest.
Beispiel: Variablennamen beginnen immer mit einem Kleinbuchstaben, Methoden immer mit einem Großbuchstaben. Globale Variablen werden zudem mit einem führenden Unterstrich gekennzeichnet.

Das ist alles Geschmackssache, jeder macht das, was ihm am besten gefällt. ABER man sollte sich durchgängig an seine Notation halten. Noch ein Stichwort: Ungarische Notation (http://de.wikipedia.org/wiki/Ungarische_Notation). Bin ich zwar auch kein riesen Fan von, ist aber durchaus sinnvoll.

MfG

neo3000
14.04.2011, 12:32
Hallo,
Danke schonmal für die Tipps zum Code schreiben. Habe den neuen Code nochmal oben eingefügt. Diesmal ohne Servo. PWM ist erstmal nur für eine LED.
Wie gesagt meine Befehle werden im Arduino zu Integer umgewandelt und mit IF abgefragt.
PWM: Ich sende für PWM1 3150. Arduino empfängt diesen Wert und rechnet: 3150 - 3000(für PWM Pin9) = 150
Ich sende für PWM2 4050. Arduino empfängt diesen Wert und rechnet: 4050 -4000(für PWM Pin11) = 50

Mein problem ist so wie auch schon oben beschriebeen dass ich die Befehle nur hintereinander ausführen kann.
Sende ich nun über mein VB.net Programm durch einen "timer" abwechselnd alle 2sec den befehl für LED ein bzw aus schalten und über stelle
zeitgleich den PWM1 wert mit einer Trackbar ein so setzt immer wieder eines von den beiden aus oder bleibt hängen.
Suche nun eine Möglichkeit für Multitasking ab Arduino. Ein Beispielcode wäre ganz toll.

Besten Dank im voraus.

Hubert.G
14.04.2011, 13:06
Das Problem beim Arduino ist, das ähnlich wie in BASCOM ein Großteil der Routinen in Librarys gefasst ist.
Hier Änderungen vorzunehmen ist schwierig. Wenn du C kannst ist es einfacher den ganzen Code selbst neu zu schreiben.

neo3000
14.04.2011, 13:21
Was genau meinst du, das ich dafür neu schreiben muss ?!?

Hubert.G
14.04.2011, 13:41
Weist du wie der UART im Uno arbeitet? Ist er mit ISR oder ohne?
Weist du wie die einzelnen Funktionen die du aufrufst arbeiten?
Es ist das gleiche Problem wie im BASCOM, solange die einzelnen Funktionen sich nicht gegenseitig beeinflussen und stören, eine tolle Sache da man mit wenigen Zeilen ein komfortables Programm hat.
In dem Moment in dem sich die Funktionen gegenseitig stören, hat man zwei Möglichkeiten, man klaubt die Funktionen auseinander und sieht nach wo es hakt, oder schreibt sich die Funktionen selbst neu.
Also in die Arduino Materie vertiefen oder selbst neu schreiben.

neo3000
14.04.2011, 13:54
OK, werde ich machen. Danke.

Richard
14.04.2011, 15:47
OK, werde ich machen. Danke. Man kann auch versuchen alle x ms alle möglichen Werte in einmem Rutsch zu holen und in ein Arry ab zu legen und diese dann in der Main "in Ruhe" auszuwerten.

Gruß Richard

PICture
17.04.2011, 10:04
Hallo!

Als "Lektüre" wurde ich noch ännliches Thread empfehlen, der nicht in "Ähnliche Themen" aufgelistet ist: https://www.roboternetz.de/community/showthread.php?51033 . :)