PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Arduino Motor Steuerung Code



Flexgate
05.08.2011, 11:36
Hi

hab mir mit meinem Uno und dem L6203 eine Steuerung zusammengebaut. Was für mich schon eine kleiner Erfolg ist ;)

Der Code sieht vor das per Eingabe über den Seriellen Monitor "+" und "-" die Drehrichtung vorgeben und "," den Motor stoppt. Funktioniert soweit auch ganz gut nur leider scheitere ich an der Eingabe für PWM :mad:

Das Problem scheint die Übergabe von der Konsole zum Pwm Signal zu sein, falscher Datentyp etc.?
Solange keine Zahl zwischen 0-255 eingegeben wird funktioniert das ganze auch, da das Pwm Signal im Ausgangszustand 255 beträgt.

Wäre schön wenn mir jemand helfen könnte.


/*
Eingaben in der Konsole:

+ dreht den Motor links
- dreht den Motor rechts
, stoppt den Motor
0-255 Pwm Signal

*/

char eingabe;
char pwmsignal=255;

void setup()
{
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
Serial.begin(9600);
}

void loop()
{
if (Serial.available() > 0)
{
eingabe = Serial.read();
if (eingabe >= '0' && eingabe <= '255')
{
pwmsignal = eingabe;
Serial.print(pwmsignal);
}
if (eingabe == '+')
{
analogWrite(11, pwmsignal); //
digitalWrite(10, LOW); //
digitalWrite(9, HIGH); //
Serial.println("links");
}
if (eingabe == '-')
{
analogWrite(11, pwmsignal); //
digitalWrite(10, HIGH); //
digitalWrite(9, LOW); //
Serial.println("rechts");
}
if (eingabe == ',')
{
analogWrite(11, 0); //
Serial.println("stop");
}

}
}

Gruß

Torrentula
05.08.2011, 18:19
char pwmsignal=255;

Du verwendest den falschen Datentypen. Die für PWM zuständige Funktion analogWrite(); benötigt einen integer. Also musst du die Variable pwmsignal als Integer und nicht als Character initialisieren. Einfach:


int pwmsignal = 255;

...

analogWrite(11, pwmsignal);


so sollte es funktionieren du kannst also den ganzen Code bis auf die Initialisierung von der pwmsignal-Variable beibehalten



if (eingabe == '-')
{
analogWrite(11, pwmsignal); //
digitalWrite(10, HIGH); //
digitalWrite(9, LOW); //
Serial.println("rechts");
}


Ich würde erst die Motordrehrichtung angeben bevor ich die Geschwindigkeit festlege... wäre nur mein Art es zu machen :)



if (eingabe == '-')
{
digitalWrite(10, HIGH); //
digitalWrite(9, LOW); //
analogWrite(11, pwmsignal); //
Serial.println("rechts");
}


MfG
Torrentula

Flexgate
05.08.2011, 19:08
Hi

hab mittlerweile den Fehler gefunden, die Konsole gibt Ascii Zeichen zurück was natürlich ein Problem ist.
Das mit dem Interger hatte ich auch schon mit meinen beschränkten VB & Arduino Kenntnissen in Verdacht, ist aber leider nicht der Schlüssel zum Erfolg.

Das mit dem Enable vor der Drehrichtung ändere ich.

Nach einem Code aus Google hab ich mir jetzt das zusammen gebastelt. Es muss allerdings 200+ oder 125- etc eingegeben werden.


long incomingByte;
char eingabe;
char Data[8];
int i;
unsigned long Tempo;


void setup()
{
Serial.begin(9600);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
}


void loop()
{
if (Serial.available())
{
eingabe = Serial.read();
}

do {
if (Serial.available())
{
Data[i] = Serial.read();
eingabe = Data[i];
i++;
}
if(i<1)Tempo = millis();
{
}

}
while (i<7&&(millis()-Tempo) < 500);
Data[i] = 0;
incomingByte = atof(Data);
i=0;
Serial.print(incomingByte);

if (eingabe == '+')
{
analogWrite(11, incomingByte); //
digitalWrite(10, LOW); //
digitalWrite(9, HIGH); //
Serial.println("LINKS");
}

if (eingabe == '-')
{
analogWrite(11, incomingByte); //
digitalWrite(10, HIGH); //
digitalWrite(9, LOW); //
Serial.println("RECHTS");
}
if (eingabe == ',')
{
analogWrite(11, 0); //
Serial.println("STOP");
}
}

Torrentula
05.08.2011, 21:53
Ich habe jetzt mal ein Programm geschrieben was das machen sollte was du möchtest :D

So funktionierts:

1) Der Arduino überprüft zuerst ob '+', '-' oder ',' gesendet wurde. --> Drehrichtung wird in die char-Variable "eingabe" geschrieben
2) Nun wartet der Arduino auf die Eingabe der Geschwindigkeit --> Geschwindigkeit wird in integer-Variable "speed" geschrieben
3) Der in "speed" gespeicherte Wert wird nun einfach in das PWM-Register des Timers geschrieben --> Motor wird auf die übergebene Geschwindigkeit eingestellt



char eingabe;
int speed;

void setup(){
Serial.begin(9600);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
}

void loop(){
if (Serial.available()){
eingabe = Serial.read();
}

if (eingabe == '+'){ // zuerst überprüfen, ob vorwärts oder rückwarts gefahren werden soll
if(Serial.available()){
speed = Serial.read(); // nochmals auf eine Eingabe der Geschwindigkeit warten
digitalWrite(10, LOW); //
digitalWrite(9, HIGH); //
analogWrite(11, speed); // Nun den eingegebenen Wert in das Timer PWM-Register schreiben = Geschwindigkeit regeln
Serial.println("LINKS");
}
}

if (eingabe == '-'){ // dasselbe für Rückwärtsfahrt
if(Serial.available()){
speed = Serial.read();
digitalWrite(10, HIGH); //
digitalWrite(9, LOW); //
analogWrite(11, speed); //
Serial.println("RECHTS");
}
}
if (eingabe == ','){
analogWrite(11, 0); //
speed = 0;
Serial.println("STOP");
eingabe = 's';
}
}


Hoffe so klappt es :D

MfG

Torrentula

Flexgate
05.08.2011, 22:16
Hi

klappt leider auch nicht, bekomme wieder nur ein fiepen weil der Pmw Wert durch den Ascii Code um die 50 liegt (denke ich)
Trotzdem Danke für deinen Versuch

Gruß

Torrentula
06.08.2011, 08:22
Also bei mir klappt es im Test mit einer LED einwandfrei und ich bekomme auch die Drehrichtung zurück.

Eingabeformat:
1) + oder - senden
2) Geschwindigkeit senden

wenn ich als Geschwindigkeit 200 angebe, leuchtet die LED deutlich.

Bevor du die Drehrichtung änderst, musst du immer ein Komma senden, damit der Motor angehalten wird. Dann kannst du wieder die Drehichtung und Geschwindigkeit festlegen.

Bei der Ansteuerung von Motoren verwendet man häufig Rampen zum kontrollierten Beschleunigen und Abbremsen der Motoren, um Stromspitzen zu vermeiden. Ich poste nochmal einen Code, der Rampen zum Beschleunigen und Abbremsen der Motoren verwendet.



char eingabe = 's';
int geschwindigkeit = 0;

void setup(){
Serial.begin(9600);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
}

void loop(){
if (Serial.available()){
eingabe = Serial.read();
}

if (eingabe == '+'){ // zuerst überprüfen, ob vorwärts oder rückwarts gefahren werden soll
if(Serial.available()){
geschwindigkeit = Serial.read(); // nochmals auf eine Eingabe der Geschwindigkeit warten
digitalWrite(10, LOW); //
digitalWrite(9, HIGH); //

for(int i = 0; i <= geschwindigkeit; i = i + 10){
analogWrite(11, i); // Nun den eingegebenen Wert in das Timer PWM-Register schreiben = Geschwindigkeit regeln
delay(20);
}

Serial.println("LINKS");
}
}

if (eingabe == '-'){ // dasselbe für Rückwärtsfahrt
if(Serial.available()){
geschwindigkeit = Serial.read();
digitalWrite(10, HIGH); //
digitalWrite(9, LOW); //

for(int i = 0; i <= geschwindigkeit; i = i + 10){
analogWrite(11, i); // Nun den eingegebenen Wert in das Timer PWM-Register schreiben = Geschwindigkeit regeln
delay(20);
}

Serial.println("RECHTS");
}
}
if (eingabe == ','){

for(int i = geschwindigkeit; i >= 0; i = i - 10){
analogWrite(11, i); // Nun den eingegebenen Wert in das Timer PWM-Register schreiben = Geschwindigkeit regeln
delay(20);
}
geschwindigkeit = 0;
Serial.println("STOP");
eingabe = 's';
}
}

Richard
06.08.2011, 08:28
Hi

klappt leider auch nicht, bekomme wieder nur ein fiepen weil der Pmw Wert durch den Ascii Code um die 50 liegt (denke ich)
Trotzdem Danke für deinen Versuch

Gruß

Gibt es denn bei C keinen Befehl mit den aus einem ASCII String eine integer Zahl gemacht werden kann?



$regfile = "m48def.dat" ' specify the used micro

$crystal = 8000000 ' used crystal frequency

$baud = 19200 ' use baud rate

$hwstack = 32 ' default use 32 for the hardware stack

$swstack = 10 ' default use 10 for the SW stack

$framesize = 40 ' default use 40 for the frame space



Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0



Dim A As Byte , S As String * 10

S = "123"

A = Val(s) 'convert string

Print A ' 123

End



Gruß Richard

Torrentula
06.08.2011, 09:46
Gibt es denn bei C keinen Befehl mit den aus einem ASCII String eine integer Zahl gemacht werden kann?

Doch schon: atoi();



char string[20] = "123";
int Integer;

Integer = atoi(string);
Serial.println(Integer);


Aber im Falle des Arduino passiert das automatisch, wenn man die Konsoleneingabe in einen Integer einliest. Und wenn man die Konsoleneingabe in ein char einliest, dann wird diese als ASCII-Zeichen gespeichert. Wenn man die Eingabe in einen String einliest, dann wird diese al String gespeichert.

Deswegen ist es auch einfacher mit der Arduino IDE zu programmieren. Man muss sich nicht ständig um Datentyp-Konvertierungen gedanken machen, wenn man Daten einliest bzw. Daten ausgibt.

Die Arduino IDE nimmt einem ein ganzes Stück arbeit ab. Wenn sie dies nicht tun würde, müsste man sich in dem Code oben auch noch um die PWM-Erzeugung, die includes und und und kümmern.

Richard
06.08.2011, 10:34
Doch schon: atoi();



char string[20] = "123";
int Integer;

Integer = atoi(string);
Serial.println(Integer);


Aber im Falle des Arduino passiert das automatisch, wenn man die Konsoleneingabe in einen Integer einliest. Und wenn man die Konsoleneingabe in ein char einliest, dann wird diese als ASCII-Zeichen gespeichert. Wenn man die Eingabe in einen String einliest, dann wird diese al String gespeichert.

Deswegen ist es auch einfacher mit der Arduino IDE zu programmieren. Man muss sich nicht ständig um Datentyp-Konvertierungen gedanken machen, wenn man Daten einliest bzw. Daten ausgibt.

Die Arduino IDE nimmt einem ein ganzes Stück arbeit ab. Wenn sie dies nicht tun würde, müsste man sich in dem Code oben auch noch um die PWM-Erzeugung, die includes und und und kümmern.


Dann verstehe ich das Problem nicht richtig, Der PWM Wert ist hier ja nicht z.b. int 128 sondern der ASCII wert 49 DEZ 1. Also nur die 1. Stelle von 128. Man muss also einen String "128" empfangen und dann in eine Zahl wandeln, dann sollte auch der richtige Wert im PWM Register landen?

Irgendwann muss ich mich doch noch einmal um C kümmern. :-( Wenn bloß die Tastaturbelegung mit den ganzen () {} [] nicht wäre.

Gruß Richard

Flexgate
06.08.2011, 11:04
Hi

erst mal danke für eure Antworten.

Hab beide Codes von Torrentula kopiert und ausgeführt.
Beim ersten kommt nur ein Fiepen, beim 2ten passiert leider gar nix. Führe ich meinen zweiten Code aus können mit 200+ \ 180- \ 255+ die Motoren gesteuert werden. Also an der Schaltung liegt es nicht.

Ich kann mich leider erst Morgen damit weiter beschäftigen weil ich gleich auf Tour bin.

Gruß

Torrentula
06.08.2011, 11:52
Irgendwie ist die Konvertierung von ASCII zu integer komisch.... deswegen auch die Lösung mit separaten Eingaben... allerdings zickt mein Programm auch ein wenig rum, manchmal übernimmt es keine Werte :(

Zum Verzweifeln

Torrentula

Flexgate
09.08.2011, 17:05
Hi

das ganze funktioniert auch ganz gut mit Firmata, hier downloaden:

http://firmata.org/wiki/Main_Page

in der Arduino IDE 0022 mit dem Uno folgenden Sketch öffnen und auf das Board hochladen: (mit dem Uno erscheinen nur mit diesem Sketch Buttons in Firmata)

File -> Examples -> Firmata -> StandardFirmata_2_2_forUNO_0_3

Danach die Firmata.exe als Admin ausführen und den richtigen Com Port auswählen.
Anschließend kann in der Software per Mausklick High \ Low \ PMW eingestellt werden.

siehe:
http://firmata.org/wiki/File:Firmata_test_screenshot.png

Gruß

Greg Deveel
20.03.2014, 12:24
Moin

ich müsste einen servo dazu bringen, das die bewegungsgeschwindichkeit mit einem poti einstellbar ist.kann mir da jemand helfen. Please