Hi!
Versuch das mal mit strcpy und strcat oder mit sprintf
Das sind die C-standard-Funktionen für sowas.
Ich weis aber nicht, ob das der AVR-GCC unterstützt...
VLG Tobi
Hi,
es geht darum, einige Werte ber UART auszugeben. Zur Ausgabe habe ich folgende Methoden:
Ich muss also z.B. einen String wie "<Variable>: <Wert>" ausgeben können, dazu muss ich ja nen String bauen, in den der Wert eingearbeitet ist. Nur wie mache ich das? Oder gibts ne besserer Methode das auszugeben?Code:void uart_out(char c) { loop_until_bit_is_set(UCSRA, UDRE); UDR = c; } void uart_puts(char *s) { int len = strlen(s); while(len--) { loop_until_bit_is_set(UCSRA, UDRE); UDR = *s; s++; } }
mfg
jagdfalke
Hi!
Versuch das mal mit strcpy und strcat oder mit sprintf
Das sind die C-standard-Funktionen für sowas.
Ich weis aber nicht, ob das der AVR-GCC unterstützt...
VLG Tobi
http://www.tobias-schlegel.de
"An AVR can solve (almost) every problem" - ts
Hi, ich habe jetzt mal das hier geschrieben:
Es gibt schon einigermaßen das richtige aus, aber irgendwann siehts so aus:Code:char *s_pre = "Shoulder: "; char *str = " "; sprintf(str, "%d", shoulder_pos); str = strcat(s_pre, strcat(str, "\n\r")); uart_puts(str);
Die Methode, die das macht wird per timer interrupt ausgeführt. Ich habe aber am Anfang der Methode cli() und am Ende ein sei() stehn.Shoulder: 128
Shoulder: 128
130Shoulder: 128
130131Shoulder: 128
130131131Shoulder: 128
13013113.131Shoulder: 128
13013113.131131Shoulder: 128
13013113.131131131Shoulder: 128
13013113.131131131131Shoulder: 128
13013113.131131131131131Shoulder: 128
13013113.131131131131131131Shoulder: 128
13013113.131131131131131131131Shoulder: 128
13013113.131131131131131131131131Shoulder: 128
13013113.131131131131131131131131131Shoulder: 128
hier mal die komplette methode:
mfgCode:void keep_moving() { cli(); //NEUE POSITIONEN AUSRECHNEN UND RUNDEN shoulder_pos = (uint8_t)(shoulder_pos + shoulder_step); elbow_pos = (uint8_t)(elbow_pos + elbow_step); //POSITIONEN ÄNDERN //move(1, shoulder_pos); //move(2, shoulder_pos); //move(3, elbow_pos); char *s_pre = "Shoulder: "; char *str = " "; sprintf(str, "%d", shoulder_pos); str = strcat(s_pre, strcat(str, "\n\r")); uart_puts(str); //WENN DIE POSITIONEN GERUNDET ÜBEREINSTIMMEN //NEUBERECHNUNG DER STEPS ERLAUBEN UND NEUES ZIEL FÜR ELBOW SETZEN if(shoulder_pos == shoulder_dest && elbow_pos == elbow_dest) { recalc_flag = 1; } else { recalc_flag = 0; } servo_flag = 0; sei(); }
jagdfalke
Versuch mal so was.
und mach dir den Unterschied klar zwischenCode:char s_pre[] = "Shoulder: "; char str[10]; sprintf (str, "%d", shoulder_pos); uart_puts(s_pre); uart_puts(str); uart_puts("\n\r");
char *s = "foo";
char s[] = "foo";
anstatt sprintf ist effizienter itoa
und guckst du
https://www.roboternetz.de/phpBB2/ze...=130591#130591
Disclaimer: none. Sue me.
kann du mir erklären was der unterschied ist?
Was mache ich wenn shoulder_pos ein float ?
mfg
jagdfalke
wenn schoulder_pos ein float ist kannst es z.B. so schreiben:
sprintf (str, "%f", shoulder_pos);
dass habe ich schon probiert, es kommt aber
Ich bin mir aber sich, dass shoulder_pos float ist. Wenn ich schreibewarning: format '%f' expects type 'double', but argument 3 has type 'float'
bleibt shoulder_pos ja float und wird nocht zum uint8_t oder?Code:uint8_t shoulder_to_go = (uint8_t)shoulder_pos; uint8_t elbow_to_go = (uint8_t)elbow_pos;
hier mal das, was evtl. wichtig ist:
mfgCode:volatile uint8_t servo_flag = 0; volatile uint8_t recalc_flag = 1; volatile float shoulder_pos = 127.0; volatile uint8_t shoulder_dest = 255; volatile float shoulder_step = 0; volatile float elbow_pos = 127.0; volatile uint8_t elbow_dest = 1; volatile float elbow_step = 0; int main (void) { /* UART AN UND TIMEREINSTELLEN ... */ sei(); while(1) { if(recalc_flag == 1) { calc_steps(); } if(servo_flag == 1) { keep_moving(); } } return 0; } void keep_moving() { cli(); //NEUE POSITIONEN AUSRECHNE shoulder_pos = shoulder_pos + shoulder_step; elbow_pos = elbow_pos + elbow_step; uint8_t shoulder_to_go = (uint8_t)shoulder_pos; uint8_t elbow_to_go = (uint8_t)elbow_pos; //AUSGABE char s_pre[] = "Shoulder: "; char str[10]; sprintf (str, "%f", shoulder_pos); uart_puts(s_pre); uart_puts(str); uart_puts("\n\r"); //WENN DIE POSITIONEN GERUNDET ÜBEREINSTIMMEN //NEUBERECHNUNG DER STEPS ERLAUBEN UND NEUES ZIEL FÜR ELBOW SETZEN if(shoulder_pos == shoulder_dest && elbow_pos == elbow_dest) { recalc_flag = 1; uart_puts("ERREICHT!!!!!!!!!!!"); } else { recalc_flag = 0; } servo_flag = 0; sei(); } void calc_steps(void) { //BERECHNEN WIE VIEL SICH DIE Servos BEWEGEN MÜSSEN* uint16_t shoulder_to_go = shoulder_dest - shoulder_pos; uint16_t elbow_to_go = elbow_dest - elbow_pos; //HIER ALS ABSOLUTE WERTE int16_t shoulder_abs = abs(shoulder_to_go); int16_t elbow_abs = abs(elbow_to_go); //STEP ERSTMAL AUF +/- 1 SETZEN, JE NACH RICHTUNG elbow_step = signum(elbow_to_go); shoulder_step = signum(shoulder_to_go); if(elbow_abs < shoulder_abs) { elbow_step = 1 * signum(elbow_to_go); shoulder_step = (shoulder_abs / elbow_abs) * signum(shoulder_to_go); } if(elbow_abs > shoulder_abs) { shoulder_step = 1 * signum(shoulder_to_go); elbow_step = elbow_abs / shoulder_abs * signum(shoulder_to_go); } } SIGNAL (SIG_OVERFLOW0){ servo_flag = 1; }
jagdfalke
Den Unterschied sieht man am besten am erzeugten Code:
foo1 enthält nur die Adresse des Strings "Text1"Code:char *foo1 = "Text1"; char foo2[] = "Text2"; void bar (char*); void inc() { foo1[1] = 11; bar (foo1); foo2[1] = 22; bar (foo2); } ------------------------------------------------------- .size foo2, 6 foo2: .string "Text2" .LC0: .string "Text1" .size foo1, 2 foo1: .word .LC0 inc: ;; foo1[1] = 11; lds r30,foo1 lds r31,(foo1)+1 ldi r24,lo8(11) std Z+1,r24 ;; bar (foo1); lds r24,foo1 lds r25,(foo1)+1 rcall bar ;; foo2[1] = 22; ldi r24,lo8(22) sts foo2+1,r24 ;; bar (foo2); ldi r24,lo8(foo2) ldi r25,hi8(foo2) rcall bar ret
foo2 iat der Anfang des Speicherbereichs, der mit "Text2" initialisiert wird.
Dementsprechend sehen Zugriff und Adressbildung auch anders aus.
Beide sind vom Typ char*, aber während foo1++ ok ist, gibt foo2++ einen Fehler.
Disclaimer: none. Sue me.
Ja shoulder_pos bleibt floatbleibt shoulder_pos ja float und wird nocht zum uint8_t oder?
aber wegen dem Problem format '%f' expects type 'double'...
ich habe bis jetzt bei printf mit floats immer %f verwendet (allerdings nur am PC und nicht am µC!!!)
probier vielleicht einmal statt %f, %g oder %e
zur Not könntest du es auch so schreiben:
es gibt aber bestimmt noch eine elegantere Methode ...Code:sprintf (str,"%f",(double)shoulder_pos);
Lesezeichen