Forum: Mikrocontroller und Digitale Elektronik Arduino Serial In Analog Out


von Sebastian G. (sgraw)


Lesenswert?

Hallo
ich würde gerne bei meinem Arduino über die Serielle Schnittstelle einen 
PWM Ausgang steuern.
Ich möchte eine Zahl zwischen 0 und 65536 über die Schnittstelle 
empfangen und am PWM 0 - 5V raus bekommen.
Mein Code ist wie folgt:
1
int val = 0;
2
void setup()
3
{
4
  Serial1.begin(9600);
5
6
 pinMode(13, OUTPUT);
7
}
8
9
void loop()
10
11
12
{
13
 
14
  if (Serial1.available()) {
15
16
    val = Serial1.read();
17
18
  val = map(val, 0, 65536, 0, 255);
19
       Serial.write(val);
20
      analogWrite(13, val);
21
}
22
}



Leider funktioniert das nicht.
Hoffe jemand kann mir helfen.

Freundliche Grüße
SGraw

von Karl H. (kbuchegg)


Lesenswert?

Serial1.read() liefert dir aber nur das nächste Byte, also einen Wert 
zwischen 0 und 255. Wenn du Zahlen zwischen 0 und 65535 übertragen 
willst, dann musst du dazu 2 Bytes empfangen und die dann auf der 
Empfängerseite wieder zu einem 2 Byte int zusammensetzen.
Womit du allerdings das nächste Problem hast. Denn: woher weiß denn 
jetzt der Arduino ob das gerade empfangene Byte das erste oder das 
zweite der 16 Bit Zahl war? Und schon läufst du in das Problem hinein, 
dass du ein Protokoll brauchst, welches im Stande ist, das alles zu 
regeln.

Allerdings: wozu das ganze, wenn du dann diese Zahl sowieso wieder auf 
den Bereich 0 bis 255 runtermappst?

von Sebastian G. (sgraw)


Lesenswert?

Auch wenn ich die Zeile:
  val = map(val, 0, 65536, 0, 255);

weglasse und eine zahl zwischen 0 und 255 eingebe funktioniert es nicht.

Die LED die ich an dem Ausgang habe geht an bei 255 aber wenn ich 0 
eingebe nicht wieder aus.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian Graw schrieb:
> Auch wenn ich die Zeile:
>   val = map(val, 0, 65536, 0, 255);
>
> weglasse und eine zahl zwischen 0 und 255 eingebe funktioniert es nicht.

Und wie sendest du weg?
Gibst du die Zahl per Hand ein?
Wird das dann binär weggeschickt oder doch eher als String. D.h. der 
Arduino kriegt nicht 1 Byte mit dem Zahlenwert 185 (wenn du 185 in 
deiner Eingabe tippst), sondern 3 Bytes mit den ASCII Codes für '1', '8' 
und '5'.



Ein Tipp:
Es ist manchmal sehr hilfreich, wenn man sich das über eine 
Schnittstelle empfangene gleich mal wo ausgeben lässt. Zb bei einer 
Seriellen indem man das dann zurückschickt - möglichst in einer Form so 
dass man auch verifizieren kann, was da eigentlich empfangen wurde.
Und nicht nur darauf schaut, ob die LED auch das macht was sie soll und 
anonsten stochert man dann eben im Nebel rum.
1
....
2
  if (Serial1.available()) {
3
4
    val = Serial1.read();
5
    Serial1.print( "Bytewert" );
6
    Serial1.print( val1 );
7
    Serial1.print( "(" );
8
    Serial1.print( (char)val1 );
9
    Serial1.println( ")" );
10
11
    ....

und schon hilft dir dein Arduino, in dem er dir zeigt, was er eigentlich 
über die Schnittstelle kriegt.

von Sebastian G. (sgraw)


Lesenswert?

Habs bislang immer als ASCII zeichen raus geschickt.
wenn ich es Binär schicke funktionierts!!
Dafür schonmal vielen Dank.
Ich würde aber gerne diese 0-5V in 16 bit auflösen also von 0 - 65536.
Wie kann ich das am besten machen?

von Karl H. (kbuchegg)


Lesenswert?

Sebastian Graw schrieb:

> Wie kann ich das am besten machen?

na zb so
1
  byte loByte = Wert % 256;
2
  byte HighByte = Wert / 256;

so wie man eben eine Zahl in seine Einzelteile zerlegt. Wenn du 85 in 8 
und 5 zerlegen musst, machst du ja auch nichts anderes. NUr das hier 
eben deine 'Ziffern' Werte von 0 bis 255 annehmen können und nicht nur 
von 0 bis 9.

Oder so
1
  byte loByte = Wert;
2
  byte hiByte = Wert >> 8;

die beiden Bytes einzeln übertragen und auf der Empfängerseite dann eben 
mit einer umgekehrten Operation wieder zusammensetzen.
Wie macht man aus 8 und 5 die Zahl 85? Na zb so: 8*10 + 5.
Die 10, weil es 10 Ziffern gibt.
Hier hast du nicht 10 Ziffern, sondern deren 256. Also
1
  Wert = hiByte * 256 + loByte;

oder so
1
  Wert = hiByte << 8 + loByte;

von PittyJ (Gast)


Lesenswert?

Man könnte auch atoi() oder sscanf() auf einem String verwenden.

von Karl H. (kbuchegg)


Lesenswert?

PittyJ schrieb:
> Man könnte auch atoi() oder sscanf() auf einem String verwenden.

Yep.
Damit kriegt man dann auch das Protokollproblem einfach in den Griff, 
wenn man ein Startzeichen und ein Endzeichen vereinbart.

von Sebastian G. (sgraw)


Lesenswert?

Danke für deine Hilfe!!!
Hab's verstanden :)

von amateur (Gast)


Lesenswert?

65536 ist eine 17 Bit Zahl, ein bisschen weniger wird's also wohl 
werden.
Sein nicht böse, wenn das Ausgangssignal nicht DVM-tauglich wird.

von Karl (Gast)


Lesenswert?

Schau mal in die Referenzen auf Arduino.cc unter Seriel. Da findest du 
u.A.

parseInt()

Das löst deine Probleme mit einer Zeile Code.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.