Hallo,
ich will die Motordrehzahl im seriellen Monitor eingeben, so dass wenn
ich z.B. 255 (PWM) eingebe der Motor sich mit maximaler Geschwindigkeit
dreht.
Ich habe folgenden Code geschrieben, der aber leider nicht funktioniert:
1
#define MOTOR_IN1 9
2
#define MOTOR_IN2 10
3
uint8_tdrehzahl;
4
intpwm;
5
voidsetup(){
6
Serial.begin(9600);
7
pinMode(MOTOR_IN1,OUTPUT);
8
pinMode(MOTOR_IN2,OUTPUT);
9
while(!Serial);// warten bis System bereit ist
10
Serial.println("Drehzahl eingeben: ");
11
}
12
13
voidloop(){
14
15
pwm=Serial.read();
16
delay(50);
17
while(pwm>=0&&pwm<=255){
18
19
digitalWrite(MOTOR_IN1,LOW);
20
analogWrite(MOTOR_IN2,pwm);
21
}
22
}
Man hört, dass sich da was tut aber der Motor bewegt sich nicht.
Ich vermute, dass es an der while-Schleife liegt.
KÖnnt Ihr mir da behilflich sein?
Danke.
Der Wert 255 besteht aus 3 Byte, die du empfangen musst.
Diese musst du dann in ein "int" erst konvertieren.
So empfängst du:
2
5
5
somit ist deine pwm Variable maximal 5.
Adam P. schrieb:> Der Wert 255 besteht aus 3 Byte, die du empfangen musst.> Diese musst du dann in ein "int" erst konvertieren.>> So empfängst du:> 2> 5> 5>> somit ist deine pwm Variable maximal 5.
Okey habe der Variable pwm den Typ uint8_t zugewiesen.
jedoch funktioniert mein Wunsch immernoch nicht. Sobald ich Spannung
draufgebe dreht der Motor voll auf. Das was ich im Seriellen Monitor
eingebe wird ignoriert.
Max U. schrieb:> Ich vermute, dass es an der while-Schleife liegt.
Es liegt so ziemlich an Allem.
Dir fehlen alle Grundlagen der Programmierung.
Ein read liest ein Byte, nicht eine Dezimalzahl in Ziffern.
Ein while welches den PWM Wert nicht ändert läuft ewig.
Eine Drehzahl regelt man nicht über das PWM Tastverhältnis, sondern
regeln heisst MESSEN und dann NACHSTEUERN.
Ein digitalWrite gefolgt von einem analogWrite ist Unsinn.
Wer in einer loop arbeitet, liest mehrfach von serial ein, muss also
auch jedesmal was eingeben.
Max U. schrieb:> Das was ich im Seriellen Monitor eingebe wird ignoriert.
Ist wohl noch ein Fehler im Programm.
> Okey habe der Variable pwm den Typ uint8_t zugewiesen.
Du bekommst über die serielle Schnitte 3 ASCII-Zeichen, von denen jedes
einzelne ein uint8_t ist. Du musst aus diesen drei ASCII-Zeichen den
eigentlichen pwm-Wert erst noch ausrechnen. Stichwort atoi() oder
ähnlich.
> Sobald ich Spannung draufgebe dreht der Motor voll auf. Das was ich im> Seriellen Monitor eingebe wird ignoriert.
Was passiert denn, wenn du da mal testweise feste Werte im Programm
vorgibst? Also drei Programme, mal mit pwm=10, und dann pwm=50, und dann
pwm=200?
Max U. schrieb:> so dass wenn ich z.B. 255 (PWM) eingebe der Motor sich mit maximaler> Geschwindigkeit dreht.
Wie ist denn "der Motor" an den Andruiden angeschlossen?
Wenn du von Hand in die serielle Konsole etwas eingibst dann werden
ASCII Zeichen übertragen.
Wie bereits geschrieben sendest du eine "2" "5" "5" also 0x32,0x35,0x35.
Diese DREI Werte musst du in EINE PWM-Variable umrechnen.
Max U. schrieb:> Okey habe der Variable pwm den Typ uint8_t zugewiesen.
Abgesehen davon dass du das ganz sicher nicht getan hast, löst das immer
noch nicht das Problem, das Adam angesprochen hat.
Guck dir mal die Serial.ReadString() an. Die könnte helfen. Und dann
atoi().
Michael B. schrieb:> Max U. schrieb:>> Ich vermute, dass es an der while-Schleife liegt.>> Eine Drehzahl regelt man nicht über das PWM Tastverhältnis, sondern> regeln heisst MESSEN und dann NACHSTEUERN.
Wer sagt denn dass ichhier was regeln will, wozu soll ich die Drehzahl
messen. Du weißt doch garnicht worum es geght. Ich will nix messen
brauche es auch nicht. Der Motor soll sich nur mit meiner vorgegebenen
Drehzahl durch die Software drehen da brauche ich nichts zu messen.
>> Ein digitalWrite gefolgt von einem analogWrite ist Unsinn.
Wieso ist das Unsinn
Max U. schrieb:>> Ein digitalWrite gefolgt von einem analogWrite ist Unsinn.> Wieso ist das Unsinn
Weil du den Pin ziemlich schnell zwischen ausgeschaltetem Ausgang und
PWM-Ausgang mit Timer im Hintergrund umschaltest.
"AnalogWrite" ist eine sehr irreführende Bezeichnung. Damit stellst du
das Tastverhältnis vom am Ausgang erzeugten PWM ein. Du musst nichts
ausschalten.
Ah. Vergiss es. Es sind unterschiedliche Pins. Das hat Michael
vermutlich auch übersehen.
Sebastian R. schrieb:> Max U. schrieb:>>> Ein digitalWrite gefolgt von einem analogWrite ist Unsinn.>> Wieso ist das Unsinn>> Weil du den Pin ziemlich schnell zwischen ausgeschaltetem Ausgang und> PWM-Ausgang mit Timer im Hintergrund umschaltest.>> "AnalogWrite" ist eine sehr irreführende Bezeichnung. Damit stellst du> das Tastverhältnis vom am Ausgang erzeugten PWM ein. Du musst nichts> ausschalten.
Ich sage doch nur, dass an einen Pin ein LOW-Signal geschrieben werden
soll und an den anderen der PWM-Wert, sodass der Motor in eine Richtung
dreht.
Max U. schrieb:> Michael B. schrieb:>> Max U. schrieb:>>> Ich vermute, dass es an der while-Schleife liegt.>>>>> Eine Drehzahl regelt man nicht über das PWM Tastverhältnis, sondern>> regeln heisst MESSEN und dann NACHSTEUERN.> Wer sagt denn dass ichhier was regeln will, wozu soll ich die Drehzahl> messen. Du weißt doch garnicht worum es geght. Ich will nix messen> brauche es auch nicht. Der Motor soll sich nur mit meiner vorgegebenen> Drehzahl durch die Software drehen da brauche ich nichts zu messen.>>>> Ein digitalWrite gefolgt von einem analogWrite ist Unsinn.> Wieso ist das Unsinn
Du schreibst du möchtest eine Drehzahl einstellen. Eine Drehzahl ist
unabhängig von der PWM. So könntest du eine PWM mit dem Wert 100
einstellen und den Motor festhalten. Dann ist deine Drehzahl 0. Also
müsste dein uC dann nachregeln um auf eine Drehzahl X zu kommen.
Was du möchtest ist keine Drehzahl einstellen sondern nur ein PWM
Tastverhältnis. Was der Motor im Endeffekt draus macht ist dir egal.
Wenn du sinnvolle Hilfe möchtest, beschreibe lieber mal deinen Code in
der Loop, das sieht alles sehr "spannend" aus. Beachte auch den Hinweis
mit dem ASCII Code. Die '2' '5' '5' sieht zwar aus wie ne Zahl ist aber
letztendlich mit einem Buchstaben zu vergleichen.
Der erste Schritt wäre somit die Daten zu empfangen z.B. in einem
String. Dann die einzelnen Elemente zu ihren Eigenwerten umzuwandeln,
bei Zahlen ist das immer -48, also z.B. fünf = (int)'5'-48; Dann musst
du noch die erste Stelle mit 10^2 und die 2. mit 10^1 multiplizieren.
Dann postet du dein Ergebnis und wir können weiter arbeiten.
Welcher Vollhonk hat eigentlich Michael B. (laberkopp) ein Minus
gegeben.
Er hat völlig recht und praktisch alle groben Fehler des TOs aufgezählt!
Ja die Wahrheit kann manchmal wehtun, aber vieleicht kann der
Minusbewerter ja das korrekte Programm tanzen.
@ Max U. (talha74)
Am besten du unterteilst dein Problem in Abschnitte,
dann wirst du dabei am meisten lernen.
1) Wie empfange ich mehrere Zeichen in einen String (char oder uint8_t
Array).
2) Wie prüfe ich die empfangenen Zeichen auf eine korrekte Zahl.
3) Wie konvertiere ich die empfangenen Zeichen in eine Ganzzahl
(Variable).
Und wenn das alles funktioniert, dann wird wohl auch deine PWM
funktionieren.
>> Wenn du sinnvolle Hilfe möchtest, beschreibe lieber mal deinen Code in> der Loop, das sieht alles sehr "spannend" aus. Beachte auch den Hinweis> mit dem ASCII Code. Die '2' '5' '5' sieht zwar aus wie ne Zahl ist aber> letztendlich mit einem Buchstaben zu vergleichen.> Der erste Schritt wäre somit die Daten zu empfangen z.B. in einem> String. Dann die einzelnen Elemente zu ihren Eigenwerten umzuwandeln,> bei Zahlen ist das immer -48, also z.B. fünf = (int)'5'-48; Dann musst> du noch die erste Stelle mit 10^2 und die 2. mit 10^1 multiplizieren.>> Dann postet du dein Ergebnis und wir können weiter arbeiten.
void zahl2string ( char zahl)
{
char hunderter, zehner, einer;
hunderter = zahl / 100;
zehner = ( zahl - 100 * hunderter) / 10;
einer = ( zahl - 100 hunderter - 10 zehner);
ADstring [0] = 0x30 + hunderter;
ADstring [1] = 0x30 + zehner;
ADstring [2] = 0x30 + einer;
return;
}
Habe diese Umrechnung vorgenommen. Hoffe sie ist richtig. Wie schreibe
ich nun den Wert an den Pin?
Max U. schrieb:> void zahl2string ( char zahl)> {> char hunderter, zehner, einer;> hunderter = zahl / 100;> zehner = ( zahl - 100 * hunderter) / 10;> einer = ( zahl - 100 hunderter - 10 zehner);> ADstring [0] = 0x30 + hunderter;> ADstring [1] = 0x30 + zehner;> ADstring [2] = 0x30 + einer;> return;> }>> Habe diese Umrechnung vorgenommen. Hoffe sie ist richtig. Wie schreibe> ich nun den Wert an den Pin?
void-Funktion und dann ein Return? Naja gut. Wird der Compiler nicht
mögen.
Aber: Du willst ja einen String in eine Zahl umwandeln. Deine Funktion
scheint genau die andere Richtung zu versuchen.
Ich nenne noch einmal atoi() als Recherche-Ausgangspunkt. Denn solche
Standard-Funktionen haben schon andere vor dir versucht. Und sogar so
gut gelöst, dass sie standardmäßig bei C(++) mit dabei ist :D
Max U. schrieb:>>>> Wenn du sinnvolle Hilfe möchtest, beschreibe lieber mal deinen Code in>> der Loop, das sieht alles sehr "spannend" aus. Beachte auch den Hinweis>> mit dem ASCII Code. Die '2' '5' '5' sieht zwar aus wie ne Zahl ist aber>> letztendlich mit einem Buchstaben zu vergleichen.>> Der erste Schritt wäre somit die Daten zu empfangen z.B. in einem>> String. Dann die einzelnen Elemente zu ihren Eigenwerten umzuwandeln,>> bei Zahlen ist das immer -48, also z.B. fünf = (int)'5'-48; Dann musst>> du noch die erste Stelle mit 10^2 und die 2. mit 10^1 multiplizieren.>>>> Dann postet du dein Ergebnis und wir können weiter arbeiten.>> void zahl2string ( char zahl)> {> char hunderter, zehner, einer;> hunderter = zahl / 100;> zehner = ( zahl - 100 * hunderter) / 10;> einer = ( zahl - 100 hunderter - 10 zehner);> ADstring [0] = 0x30 + hunderter;> ADstring [1] = 0x30 + zehner;> ADstring [2] = 0x30 + einer;> return;> }>> Habe diese Umrechnung vorgenommen. Hoffe sie ist richtig. Wie schreibe> ich nun den Wert an den Pin?
Ohje... warum einfach machen, wenn es kompliziert geht:
Nimm für die Umwandlung von...
... Integer in String: http://www.cplusplus.com/reference/cstdlib/itoa/
... String in Integer: http://www.cplusplus.com/reference/cstdlib/atoi/
Ist alles schon in C/C++ vorhanden
Wie die Funktion schon sagt zahl2string, was du brauchst ist
string2zahl.
Der Wertebereich char ist auch eher schlecht weil nur er nur bis 127
geht, du könntest unsigned char nutzen dann hast du 0 - 255.
Ist dir inzwischen bewusst, wie die Daten aussehen die du per serieller
Kommunikation erhälst? Übermittelt dir die Funktion einen string mit
allen gesendeten Bytes oder immer nur ein Byte?
Adam P. schrieb:> Und wenn das alles funktioniert, dann wird wohl auch deine PWM> funktionieren.
Und dann wissen wir immer noch nicht, ob der Motor mit der korrekten PWM
auch das tut, was sich der Max wünscht.
Max U. schrieb:> Du weißt doch garnicht worum es geght.
Dann ändere das. Ich hatte z.B. schonmal danach gefragt, WAS zur Hölle
denn da eigentlich angesteuert werden soll. Und dann habe ich auch noch
einen Tipp zur systematischen Fehlersuche gegeben (fixe PWM-Werte
vorgeben und schauen, ob sich da was ändert). Aber wenn du lieber
planlos herumwursteln willst, dann mach einfach weiter wie bisher.
Das folgende ist NICHT SCHÖN und wird so auch nicht programmiert,
da es sich um ein blockierendes Einlesen handelt.
Aber vllt. wird dir dadurch klar wie das mit dem Einlesen ablaufen
sollte.
Code ist nicht getestet! Soll dir lediglich die Funktionsweise zeigen.
Lothar M. schrieb:> Und dann wissen wir immer noch nicht, ob der Motor mit der korrekten PWM> auch das tut, was sich der Max wünscht.
Ich glaub er will einfach nur dass im Leerlauf ein Unterschied zwischen
0, 50, oder 255 zu erkennen ist...
Wenn das Einlesen mit Hilfe von Arrays schon solche Schwierigkeiten
bereitet - dann bezweifel ich, dass die Idee mit der "Regelstrecke" so
schlau war.
Adam P. schrieb:> /* Wert konvertieren */> pwm = atoi(input);
Weiterhin würde man an dieser Stelle noch eine Bereichsprüfung
durchführen, da du ja auch 380 eingeben könntest:
1
/**
2
* Mal davon ausgegangen, dass jmnd. ein Minuszeichen eingibt
3
* auch wenn dann nur noch 2 Zeichen für die Zahl bleiben.
unabhängig was schon alles geschriebn wurde, vielleicht hilft das auch
Zeichen einsammeln bis <ENTER> kommt per Serial.event (also im
Interrupt)
Max U. schrieb:> ich will
nanu, fehlt nur noch mit dem Fuß aufstampfen, haben wir nicht gelernt
"ich möchte" zu sagen?
nun gut, vieles wurde schon geschrieben, auch vieles richtige, vor allem
steht erst mal lernen an:
Serial.event ist z.B. eine gute Idee
1
#define MAXBUFFER 20
2
uint8_tchr_cnt=0;
3
4
charserial_in_command[MAXBUFFER];
5
charserial_in_buff[MAXBUFFER];
6
7
charserial_in_command[MAXBUFFER]={0};
8
charserial_in_buff[MAXBUFFER]={0};
9
10
setup();
11
{
12
//Serial.begin(9600); warum so langsam 19k2 ist auch gut!
13
Serial.begin(19200);
14
delay(200);// etwas warten bis alle Spannungen stehen war immer gut
Adam P. schrieb:> Lothar M. schrieb:>> Und dann wissen wir immer noch nicht, ob der Motor mit der korrekten PWM>> auch das tut, was sich der Max wünscht.> Ich glaub er will einfach nur dass im Leerlauf ein Unterschied zwischen> 0, 50, oder 255 zu erkennen ist...
Dann soll er naheliegenderweise doch mal genau das ausprobieren. Und
wenn das dann funktioniert, dann kann er die Sache mit der seriellen
Schnitte und der Interpretation der dort ankommenden Zeichen angehen.
> Ich glaub er will einfach nur
Und um ihm dabei zu helfen, wäre es m.E. nicht ganz umwichtig, die
verwendete Hardware zu kennen. Wenns dumm kommt, dann hat er nämlich
selber eine Brücke aus dem "Lehrbuch für Anfänger des Brückenbaus"
aufgebaut und die tut jetzt aufgrund ihrer schlichten Einfachheit
einfach nicht.
Hallo Max,
die loop-Schleife wird permanent ausgeführt, daher ist die
while-Schleife
in deinem Fall unnütz.
Um den Variablenbereich auf Gültigkeit zu prüfen sollte while durch if
ersetzt werden.
Serial.read() liest ein einziges 'int' ein und setzt die
Programmausführung fort.
Wenn der Serielle Puffer leer ist blockiert diese Funktion und wartet
auf einen 'int'. Das Programm ist blockiert.
Deshalb vorher nachschauen ob was zun einlesen da ist.
Da im Seriellen Monitor der Arduino IDE ASCII zeichen übergeben werden
könntest du es einmal mit der Eingabe eines Buchstaben versuchen:
Die Ziffer 0 entspricht dem wert 30 DEZ
Der Buchstabe A -> 41 Dez
Der Buchstabe a -> 61 Dez
Das Zeichen ~ -> 126 Dez
Wenn in der Arduino IDE zum abschicken des Zeichens ein Return
erforderlich ist, und dieses mitgesendet wird lesen wir es einfach mit
ein um den Puffer zu leeren. Sonst würde beim nächsten 'loop' der Return
als PWM wert eingelesen.
void loop() {
if (Serial.available() > 0) {
pwm = Serial.read();
Serial.read(); // Return einlesen
}
delay (50);
if (pwm >=0 && pwm <=255){
digitalWrite(MOTOR_IN1, LOW);
analogWrite (MOTOR_IN2, pwm);
}
}
Ich habe dies nicht getestet daher: Vorsicht gefährliches Halbwissen!
Gruß Stephan
Max U. schrieb:> Ich sage doch nur, dass an einen Pin ein LOW-Signal geschrieben werden> soll und an den anderen der PWM-Wert, sodass der Motor in eine Richtung> dreht.
Liest sich, als ob da ein Stepper-Controller dranhängt (wegen dem
Direction Pin). Dann wäre PWM allerdings völlig für den Allerwertesten.
guest schrieb:> Liest sich, als ob da ein Stepper-Controller dranhängt (wegen dem> Direction Pin). Dann wäre PWM allerdings völlig für den Allerwertesten.
Bei nem L293 oder so nicht unbedingt.