- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 2 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 11 bis 20 von 32

Thema: Odometrie Problem [Hirn Fatal ERROR]

  1. #11
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    12.02.2006
    Beiträge
    459
    Anzeige

    Praxistest und DIY Projekte
    Eigentlich will ich gar nicht "Haare spalten", aber weil's mir so ins Auge sticht:

    dies ist der grund damit ich proggen besser leren.
    der Lehrer könnte dem Schüler etwas lehren,
    der Schüler könnte viel mehr lernen

    und später ein Flasche leeren

  2. #12
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    29.07.2005
    Alter
    33
    Beiträge
    128
    @ robo.fr jop sry verschrieben hehe

    kann mir niemand helfen?

  3. #13
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo zusammen

    Zitat Zitat von Ceos
    an dem sleep erkennt man das er nicht die 2.7er asurolib benutzt also wird er das vermutlich nicht haben

    EDIT um diesem post noch einen sinn zu verleihen ... lad dir die asuro lib 2.71 installier sie und arbeite damit, da ist n haufen zeug bei was du brauchen kannst
    Ja, das ist gut, dass du noch einen Sinn dranhängst.
    Denn: Wenn du mal schaust, habe ich ja in meinem Post genau die benötigten Funktionen 'beigelegt'.

    @robo.fr
    Ich stimme für leeren.

    Zitat Zitat von listner
    iuch hoffe ihr könnt mir helfen.. und versteht was ich meinxD
    Zitat Zitat von listner
    kann mir niemand helfen?
    Klar können wir helfen. Siehe den Beitrag von Ceos.
    Aber ich für meinen Teil habe nicht verstanden wobei wir dir noch helfen sollen. Normalerweise gehen wir davon aus, dass du Hilfe zu deinem angegebene Programm willst. -> Hat Ceos vollbracht.
    Erkläre hier doch mal was du genau von uns möchtest.

    Hier mal Kleinigkeiten zu deinem Code, falls es das ist was du möchtest:
    Code:
            if((x == 1000) || (x > 1000))
                tausend= 1;
            else
                tausend= 0;
    kannst du besser so schreiben:
    Code:
            if(x >= 1000)
                tausend= 1;
            else
                tausend= 0;
    Oder hier würde ich umsortieren:
    Code:
            s[0]=huni+'0';
            s[1]=zehner+'0';
            s[2]=einer+'0';
            s[3]=tausend+'0';
    nach
    Code:
            s[0]=tausend+'0';
            s[1]=huni+'0';
            s[2]=zehner+'0';
            s[3]=einer+'0';
    Zumindest passen nun die Variablen-NAMEN zur Stelle. Oder du musst deine Rechnung in andere Variablen schreiben, so dass der Name zur Stelle passt. (Wäre zumindest für andere Leser wie mich dann sehr, sehr hilfreich.)
    Bei der Rechnung von Ceos kann man sich auf die Namen der Variablen verlassen.

    Gruß Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

  4. #14
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    29.07.2005
    Alter
    33
    Beiträge
    128
    hi leute, hab jetzt mein code bischen übersichtlicher gemacht (war ja ein schönes durcheinander oO)

    Code:
    #include "asuro.h" // Odometrie test
    unsigned int data[2];
    unsigned char s[5] = "thze\0";
    
    	void PrintCharR(unsigned int x)
    	   {
    		  unsigned char einer, zehner, huni, tausend;
    		  x = data[1];
    		  
    		  einer=x%10;
    		  zehner=(x-einer)/10;
    		  huni=(x-(zehner*10+einer))/100;  //nicht mit %, da "%" zu viel speicher brauch
    		  
    		  if(x >= 1000)
    				tausend= 1;
    		  else
    				tausend= 0;
    				
    		  s[0]=tausend+'0';
    		  s[1]=huni+'0';
    		  s[2]=zehner+'0';
    		  s[3]=einer+'0';
    		  
    		  
    		  SerWrite(s,5);
    	   }
    	   
    
    int main(void)
    {
    	Init();
    	
    	unsigned char a[5];
    	int i=0;
    	
    	while(1)
    	{ 								
    		OdometrieData(data); // aktuelle "Position der Odometrie einlesen
    		a[5] = s[5];
    		
    		SerWrite("Rechte Odometrie testen: ",24); //Wert der rechten Odometrie Senden
    		PrintCharR(a);
    		SerWrite("\r\n\n",3);
    		
    		for (i=0; i<2000; i++)		//5 Sekunden Pause 
    			{
    				Sleep(72);
    			}
    	}
    	return 0;
    	
    }
    dennoch funktioniert er immern och nicht, so wie er soll... er spukt über serwrite. "datenmüll" aus. hier mal ein auszug aus dem verlauft:

    Code:
    Rechte Odometrie testen:00M7                            
    
    Rechte Odometrie testen:00M5                            
    
    Rechte Odometrie testen:00M6                            
    
    Rechte Odometrie testen:00M7                            
    
    Rechte Odometrie testen:00M9                            
    
    Rechte Odometrie testen:00N2                            
    
    Rechte Odometrie testen:00N8                            
    
    Rechte Odometrie testen:00N7                            
    
    Rechte Odometrie testen:00N8                            
    
    Rechte Odometrie testen:00N8                            
    
    Rechte Odometrie testen:00N8                            
    
    Rechte Odometrie testen:00N9                            
    
    Rechte Odometrie testen:00N9                            
    
    Rechte Odometrie testen:00N9                            
    
    Rechte Odometrie testen:00O0                            
    
    Rechte Odometrie testen:00O0                            
    
    Rechte Odometrie testen:00O3                            
    
    Rechte Odometrie te                 
    
    Rechte Odometrie testen:00N7                            
    
    Rechte Odometrie testen:00N8                            
    
    Rechte Odometrie testen:00N8                            
    
    Rechte Odometrie testen:00N8                            
    
    Rechte Odometrie testen:00N8                            
    
    Rechte Odometrie testen:00O3
    
    Rechte Odometrie testen:00O1
    
    Rechte Odometrie testen:00O4
    
    Rechte Odometrie testen:00O2
    
    Rechte Odometrie testen:00O2
    
    Rechte Odometrie testen:00O2
    
    Rechte Odometrie testen:00O2
    
    Rechte Odometrie testen:00O2
    
    Rechte Odometrie testen:00O2
    
    Rechte Odometrie testen:00O2
    
    Rechte Odometrie testen:00O0
    kann mir jemand erklären, warum er an der stelle no den zehnern immer buchstaben schreibt, bzw, warum es einfach nicht so funktioniert, so wie ich mir das vorstelle ?

    danke im vorraus

  5. #15
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    a[5] = s[5];

    SerWrite("Rechte Odometrie testen: ",24); //Wert der rechten Odometrie Senden
    PrintCharR(a);
    SerWrite("\r\n\n",3);
    häh ??

    a[5] = s[5]; deine arrays sind nur 5 bytes groß der index geht nur von 0 bis 4!!! ausserdem ist das 5te byte sodenn es existieren würde nicht initialisiert, würde also einen zufälligen wert haben

    PrintCharR(a) aoll wohl heissen PrintCharR(Data[0 oder 1]) (...weis ncih ob rechts 0 oder 1 war :P)

    dein zehner ist x - 4 / 10 bei x = 1234 wäre das also 1234 - 4 / 10 = 123 also kein sinnvoller wert ... zumal ich dir schonmal gesagt habe das du dir das subtrahieren sparen kannst weilö du ganzzahlen verwendest und die nachkommastelle einfach abgeschnitten wird ... in der rechnung mit meinem x würde dein hunni übrigenns 9 ergeben also iss deine rechnung reichlich vermurkst XD ich grübel grad auch über ne bessere lösung als das modulo gedönns, ich meld mich wenn cih was habe

  6. #16
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    29.07.2005
    Alter
    33
    Beiträge
    128
    xD .. zuerst danke für die schnelle antwort^^

    2. zu lib 2.7.seht ihr was ich meine mit programmieren lernen?? :P aus diesem grund will ich erst mal mit der jetzigen lib klaar kommen. danach auf die 2.7 wechseln.. denn durch ausprobieren lern ich mehr

  7. #17
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    02.01.2008
    Alter
    32
    Beiträge
    239
    hallo zusammen

    ich habe vl eine idee wie man die einzellnen stellen einer zahl ermitteln kann:

    ich würde es versuchen mit den tauserndern anzufangen
    Code:
    int zahl;          //hier wird die zu untersuchende zahl abgespeichert
    int einer, zehner, huni, tausend;
    
    //zerlegen der zahl:
    tausend = zahl / 1000;                                   // dividieren durch 1000 ==> tausenderstelle
    
    huni = (zahl - 1000 * tausend) / 100;              //subdrahieren der tausender, finden der huni
    
    zehner = (zahl - 1000 * tausend - 100 * huni) / 10     //subdrahieren der tausender und huni, finden der einer
    
    einer = zahl - 1000 * tausend - 100 * huni - 10 * zehner;  //subdrahieren von tausender, huni, zehner ==> einerstelle
    ich hoffe es funktionier, und entspricht dem, was ihr gesucht habt

    mfg hai1991

  8. #18
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    die idee hatte ich auch schon ist aber auch recht rechenintensiv, ich grübel grad mit maskierungen und so rum, es soll ja möglichst effektiv sein, nur leider denk ich verquer und bleib immer stecken XD ...

  9. #19
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo listner, und natürlich auch ein Hallo an alle anderen die Bock haben das hier zu lesen,

    deine Buchstaben berechnest du dir selber, da du bei der zehner-Berechnung, wie Ceos ja schon schrieb, noch nicht Fehlerfrei bist.
    Prüfe daraufhin auch mal deine huni-Berechnung

    Hier mal als Beispiel einen anderen Wert als den von Ceos, damit du siehst wie du auf das 'M' kommst:
    Code:
    Zahl X=297			
    				
    einer    7  =X%10                        einer   + '0' = Zeichen '7'
    zehner  29  =(X-einer)/10                zehner  + '0' = Hier Zeichen '0' + 29
    huni     0  =(X-(zehner*10+einer))/100   huni    + '0' = Zeichen '0'
    tausend  0  =WENN(X>=1000;1;0)           tausend + '0' = Zeichen '0'
    Wie du selber nachrechen kannst, kommt bei den Zehnern hier die 29 raus. Die aber auf den ASCII-'0'-Wert von dezimal 48 addiert ergibt dann 77. Das ist dann der Buchstabe 'M'.
    Zum Nachrechnen in EXEL kannst du (bei einer deutschen Installation) den Befehl =REST(x;10) nutzen.

    Finde ich übrigens sehr gut, dass du nicht 'Fertigfutter' nutzt, sondern erst einmal selber versuchst dem Rätsel auf die Spur zu kommen. \/ (Die LIB allerdings solltest du aber nicht aus den Augen verlieren da sie von vielen hier benutzt wird. Fehlt sie dir, kannst du die Programme aus dem Forum nicht runterladen und bei dir probieren.)

    Um hier aber mal in die Pötte zu kommen, und damit du das auch (ganz bestimmt) komplett verstehst, hier mal ein Hergang, wie man es machen könnte.


    In deinem Kommentar hinter "huni=(x-(zehner*10+einer))/100;" schreibst du, dass du den %-Befehl nicht nutzen möchtest, da er zu viel Speicher brauchen würde.
    Du hast diesen Befehl aber schon bei der einer-Berechnung eingesetzt. Das bedeutet dann aber, dass der Programmspeicher für diesen Befehl schon benutzt/verbraucht wird. Dann macht es auch Sinn diese Funktion ruhig mehrfach zu benutzten.
    Fazit: Entweder nie, oder möglichst häufig eine Funktion benutzen.


    Und dann auch noch etwas zur Idee bei den Tausendern anzufangen:
    Als erstes eine Frage: Was wäre, wenn in der Zahl Zehntausender drin wären? Upps, das Programm muss dann geändert werden. Nicht schlimm, aber auch nicht schön.

    Also doch andersherrum:

    Deinen Fehler bei der zehner-Berechnung werden wir gleich ausnutzen!!! Also nicht korrigieren

    Wenn man sich das Ergebnis dieser fehlerhaften Berechnung anschaut, dann ist das ja die ursprüngliche Zahl ohne der letzten Stelle.
    Nun ja, auch das ist nur eine Zahl, die wir ja auch noch zerlegen wollen. Auch hier soll die letzte Stelle ermittelt werden um sie danach aber auch wieder abzuschneiden.
    Auch dann bleibt wieder nur irgendeine Zahl übrig, die wir schon wieder bearbeiten wollen.
    usw. usw. (Hört sich nach einer Aufgabe für eine Schleife an)
    Wann ist hier ein Ende in Sicht?
    Klar, wenn nach dem Abschneiden der letzten Stelle nichts mehr übrig bleibt.

    Kleine Zwischenüberlegung:
    Wie viel Platz benötigen wir maximal im Textspeicher? (Deine Variable "unsigned char s[5] = "thze\0";")
    Die Zahl x, die 'übersetzt' werden soll wird in deinem Programm in einer "unsigned int"-Variablen gespeichert.
    int sind IMMER 16 Bit. Somit 2 ^ 16 - 1 = 65535 als Maximum. Das sind nun 5 Speicherstellen PLUS dem String-Ende-Zeichen '\0' sind somit 6 Speicherstellen, die wir maximal benötigen.
    ---> unsigned char s[6] = "thze\0";
    Aus der Vorbelegung 'thze' machen wir '.....' (sollen 5 Leerzeichen sein), um alle Buchstaben aus der Variablen zu entfernen, da wir gleich in der Schleife nicht mehr alle Stellen bearbeiten werden.
    Nun also
    Code:
    unsigned char s[6] = "     \0";
    Hier ist aber schon ein kleiner Fehlerteufel in C vergraben.
    Wenn wir eine String-Variable mit einem in "" eingeschlossenem Text vorbelegen, dann kopieren wir hier eigentlich den Text zwischen den "" in die Variable. Der Text selber ist aber schon mit den doppelten "" eingeschlossen. Da es Text ist, wird automatisch ein '\n' angehängt.
    Somit haben wir nun 5 Leerzeichen, das \n und das automatische \n. Das sind nun 7 Zeichen.

    Also machen wir es nun richtig(er) mit:
    Code:
    unsigned char s[] = "     ";
    Wir lassen das \n weg und lassen auch die Größenangabe in der []-Klammer weg. Da kümmert sich der C-Compiler besser drum.

    Und nun können wir mit der Schleife anfangen. Sie soll so lange rechnen, solange noch eine Zahl vorhanden ist:
    Code:
    unsigned char s[] = "     ";
    
    while (x > 0)
    {
    }
    Oh, oh. Hier ist eine Stolperstelle.
    Was ist, wenn wir die Zahl 0 senden wollen? Dann ist x ja von Anfang an schon nicht mehr größer als 0.
    Kein Problem: Diesen Sonderfall initialisieren wir gleich in der String-Variablen mit einer 0 am Ende.

    Da wir in der Schleife die letzte Stelle unserer Zahl x irgendwie an die richtige Position im Textspeicher schreiben wollen, benötigen wir noch einen Merker an welcher Stelle im Textspeicher wir diese letzte Stelle eintragen müssen. Dieser Merker wird in der Schleife dann bearbeitet, und muss aber vorher natürlich initialisiert werden.
    Da wir hinten bei der Zahl x anfangen, muss dieser Merker 'am Ende' vom Textspeicher beginnen. ACHTUNG, nicht ganz am Ende, da das dort stehende '\n' natürlich nicht überschrieben werden darf.
    Code:
    unsigned char s[] = "    0";
    unsigned char Position;
    
    Position = sizeof (s) - 2;
    while (x > 0)
    {
       Position--;
    }
    Dieses sizeof() verbraucht im übrigen keinen Programmspeicher und keine Rechenzeit, da es schon beim compilieren 'ausrechnet' wie groß deine Variable s ist.
    Und warum werden 2 abgezogen?
    sizeof() liefert den Speicherbedarf der Variablen. Das sind also unsere 4 Leerstellen und die Initialisierungs-0 PLUS dem '\n' = 6.
    Wir wollen das '\n' ja nicht überschreiben: Also -1
    Und da der Speicher mit der Zahl in der []-Klammer immer bei 0 beginnt zu zählen und somit bei 0 die erste Speicherstelle meint, müssen wir diese Diskrepanz auch noch berücksichtigen. Und das sind unsere -2

    Nun ermitteln wir ohne den %-Befehl die letzte Stelle der Zahl x in einer Hilfsvariablen. Auch hier können wir Speicher sparen, und nehmen auch nur eine char-Variable:
    Code:
    unsigned char s[] = "    0";
    unsigned char Position;
    unsigned char LetzteStelle;
    
    Position = sizeof (s) - 2;
    while (x > 0)
    {
       Position--;
       LetzteStelle = x - ( (int)(x / 10) * 10 );
    }
    So weit so gut. Aber halt! Da ist ein Fehler! Position wird ja schon vor der Schleife auf den letzten sinnvollen Platz im Textspeicher gesetzt. Wenn wir also in der Schleife als erstes da noch einen abziehen, ist die Position ja schon verschoben. Also werden wir das gleich korrigieren!

    In diesem Schritt machen wir nun noch 3 Dinge. Zum einen nutzen wir nun deinen 'Fehler'. Dann speichern wir die letzte Stelle auch noch im Textspeicher. Und zu guter letzt 'pusten' wir das Ergebnis auf die Schnittstelle.
    Code:
    unsigned char s[] = "    0";
    unsigned char Position;
    unsigned char LetzteStelle;
    
    Position = sizeof (s) - 2;
    while (x > 0)
    {
       LetzteStelle = x - ( (int)(x / 10) * 10 );
       x = ( x - LetzteStelle ) / 10;             // Deinen Rechenfehler nutzen ;-)
       s [Position] = LetzteStelle + '0';
       Position--;
    }
    SerWrite (s, sizeof (s) - 1);
    Und das war es dann auch schon.


    Und nach der Pflicht natürlich noch die Kür.
    Warum funktioniert das Ausrechnen der letzten Stelle ist noch die große Frage?

    Da müsste doch eigentlich bei x = 297 dann mit 297 - ( 297 / 10) * 10 ) auch wieder 297 rauskommen.
    Der fiese C-Trick hier ist das kleine (int) in der Berechnung.
    Das schneidet nämlich alle Nachkommastellen einfach weg. Wir zwingen den Compiler, dass er den Rechenschritt (x / 10) auf alle Fälle nur mit einem Ganzzahlergebnis berechnet. (War auch schon von Ceos angedeutet an anderer Stelle.)
    Und dies ist auch das ganze Geheimnis der Funktion.


    Wenn du jetzt noch Puste hast, können wir noch die Variable LetzteStelle wegoptimieren.

    Was haben wir gerade für einen Trick mit dem (int) gesehen?
    Die Rechnung (int)(x / 10) hatte ja schon 'von ganz alleine' die letzte Stelle abgeschnitten. Genau dies benötigen wir aber nun nur noch in deiner 'falschen' Rechnung.

    Wenn wir also in der Zeile nur:
    x = ( x ) / 10; // Deinen Rechenfehler nutzen
    schreiben, dann schneidet auch diese Zeile die letzte Stelle weg, weil unsere Zielvariable x ja auch nur int-Zahlen speichern kann. Wir müssen uns die letzte Stelle hierfür somit nicht merken.

    Auch das Speichern der berechneten letzten Stelle können wir schon in der Rechenzeile selber machen. Hier benötigen wir also diese Variable auch nicht mehr.
    Und nun wirklich zu guter letzt, kann auch die Initialisierung der Variablen Position verschoben werden an die Stelle, wo wir die Variable 'erfinden'. Und das -- für die Position kann auch noch an anderer Stelle gemacht werden.

    Daraus ergibt sich nun:
    Code:
    unsigned char s[] = "    0";
    unsigned char Position = sizeof (s) - 2;
    
    while (x > 0)
    {
       s [Position--] = x - ((int)(x / 10) * 10) + '0';
       x /= 10;
    }
    SerWrite (s, sizeof (s) - 1);
    Ach du meine Güte, ist das eine Minifunktion geworden. Und die ist so auch nicht mehr leicht zu verstehen. Wichtig hier ist also eine gute Kommentierung vom Code. (Lassen wir hier jetzt aber weg.)
    Und du weißt nun wie man so etwas demnächst selber machen kann . Zumindest hoffe ich das du mir folgen konntest.
    Wenn nicht, dann frag natürlich und probiere auf alle Fälle weiterhin selber alles aus.

    Gruß Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

  10. #20
    Erfahrener Benutzer Roboter Genie Avatar von pinsel120866
    Registriert seit
    18.12.2007
    Ort
    Hohenems
    Alter
    57
    Beiträge
    847
    WOW Sternthaler,

    ich möchte nicht wissen wie lange du für diesen ausführlichen Post gebraucht hast. Gratulation - wie immer hochintelligent und humorvoll erklärt, noch dazu um diese Uhrzeit!

    [DENKBLASE] Ich wünschte mir würde auch mal einer beim meinem Problem mit der 2er IR-LED das so ausführlich erklären...

Seite 2 von 4 ErsteErste 1234 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad