PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit if-Bedingungen????????????????



Roboaktiv
16.06.2007, 14:42
Hallo!
Fogendes Programm habe ich für meinen Asuro geschrieben:

#include <asuro.h>

int main(void)
{
Init();
unsigned int data[2];
unsigned int dataalt[2];
FrontLED(ON);
LineData(dataalt);
LineData(data);
MotorDir(FWD,FWD);
MotorSpeed(230,230);
if(data[0]+data[1]!=dataalt[0]+dataalt[1])
{
MotorDir(RWD,FWD);
MotorSpeed(230,230);
break;
}
while(1);
return 0;
}

Compiliert
Geflasht
Programm auf einer einfarbigen Pappe gestartet
...
und dann
hat sich der Asuro gleich im Kreis gedreht, obwohl erdoch erst gradeaus fahren soll.

Und jetzt weiß ich nicht, ob ich spinne der Computer keine Ahnung hat oder der Asuro macht was er will.
Ich tippe auf die Eigensinnigkeit des Asuros oder dass der Keine noch nicht weiß, was eine If-Bedingung ist.
Was glaubt (wisst) ihr?

Roboaktiv

jeffreydj
16.06.2007, 15:56
Was möchtest du mit dem Programm eigentlich bezwecken? Dein Asuro soll solange die Summe der zwei mal eingelesenen Liniendaten gleich ist geradeaus fahren?

Die Liniendaten werden sich von Messung zu Messung so gut wie immer unterscheiden...durch minimal wechselnde Lichtverhältnisse, die ungenaue Messung, Spannungsunterschiede...daher dreht er sich die ganze zeit


PS: Und benutze in Zukunft bitte den Code-Button für den Programmcode, damit die Beiträge übersichtlicher sind.

Roboaktiv
16.06.2007, 16:52
Eigendlich soll der Asuro auf einem einfabigen Untergrund hrumfahren. Wenn er dann von dem Untergrund wegfährt, soll er sich drehen und wieder auf den Untergrund zurück fahren. Ich hab dafür so nen hell blaues Plakat genommen, was ich noch so in meinem Zimmer rumfliegen hatte. Aber ich könnte ja mal versuchen, ob der Spaß vielleicht im dunkeln geht. Wenn nicht, frag ich nochmal.

Danke
Roboaktiv

PS: Den Code Button hatte ich nicht gesehen.

Programmierst du den Asuro auch wie ich in C?
Wenn ja kannst du den Kleinen auch in Assembler programmieren?
Wenn nochmal ja welchen Editor benutzt du?
Ich wollte das nämlich auch mal versuchen. Mir fehlt aber noch der passende Editor.

damaltor
20.06.2007, 10:24
du hast die endlosschleife vergessen...

folgendes passiert:
die werte werden direkt hintereinander eingelesen, sind also gleich. dann fährt der asuro einige millisekunden vorwärts, bevor er die (gleichen) werte vergleicht und beginnt, sich zu drehen. und das macht er bis zum abschalten...

Pascal
20.06.2007, 10:31
Ich wollte das nämlich auch mal versuchen. Mir fehlt aber noch der passende Editor.

Nimm AVR Studio. Gibts gratis von Atmel und damit kann man prima asm programmieren. Mit WinAVR zusammen, kannst du sogar in AVR Studio in C programmieren.

damaltor
20.06.2007, 10:50
asm geht ganz gut in avr studio, und ansonsgten mit mehr oder weniger jedem editor der syntax-highlighting unterstützt. unter linux nehme ich meistens VI, oder mit grafischer oberfläche Kate. theoretisch eignet sich jeder beliebige texteditor, nur dann musst du recht stark auf die rechtschreibung achten.

Roboaktiv
20.06.2007, 12:00
Bei Atmel gibt es sehr viel Programme zu Downlaoden. Welches soll ich denn da am besten nehmen?
@ damaltor "du hast die endlosschleife vergessen..."
Muss statt der If-Bedingung da ne while-Schleife hin?

Roboaktiv

Pascal
20.06.2007, 12:14
Bei atmel gibts schon einige Programme zum downloaden, aber nicht sehr viele, die AVR Studio heißen.

Roboaktiv
20.06.2007, 12:20
Hab ich den Editor hab ich immer noch nicht gefunden! Bestimmt stel ich mich zu blöd an und versteh das Englisch nicht (Heute auf Zeugniss: Englisch: 2 :-))
Naja kann mir mal einer den genauen Link dazu aufschreiben? Am besten einer der das Englisch besser kann :-)
Danke!

Pascal
20.06.2007, 12:24
bitte schön: http://www.atmel.com/dyn/products/tools.asp?family_id=607#soft

Roboaktiv
20.06.2007, 12:30
Das ist aber beruhigend, dass zumindest enige Menschen auf diesem Planeten Englisch können!!!!!!!!!!!!!!

Danke schön!

Roboaktiv
22.06.2007, 09:35
du hast die endlosschleife vergessen...

folgendes passiert:
die werte werden direkt hintereinander eingelesen, sind also gleich. dann fährt der asuro einige millisekunden vorwärts, bevor er die (gleichen) werte vergleicht und beginnt, sich zu drehen. und das macht er bis zum abschalten...

Das hab ich grade nochmal durchgelesen und immer noch nicht verstanden!
Wenn die Werte ungleich sind, dann soll er sich doch solange drehen, wie die Werte immernoch ungleich sind.
Nachdenk........
AHHHHHHHHHHHH!!!!!!!!!
Meinst du das vielleicht so:

#include <asuro.h>

int main(void)
{
Init();
unsigned int data[2];
unsigned int dataalt[2];
FrontLED(ON);
LineData(dataalt);
while(1)
{
LineData(data);
MotorDir(FWD,FWD);
MotorSpeed(200,230);
while(data[0]+data[1]!=dataalt[0]+dataalt[1])
{
MotorDir(RWD,FWD);
MotorSpeed(200,230);
break;
}
}
while(1);
return 0;
}


Gruß Roboaktiv

@ jeffreydj: Dieser Codebutton geht bei mr irgendwie nicht!

damaltor
22.06.2007, 23:45
wenn der code button nocht geht, dann schreibe vor deinen code folgendes:




und dahonter



das ist schon besser, allerdings hättest du nur das erste if durch while ersetzen müssen. achte darauf, dass auch in jedem durchlauf der schleife neue werte gemessen werden!

Roboaktiv
23.06.2007, 14:34
Irgendwie find ich da kein (erstes) IF. Wo ist denn das so ungefähr? Im Momemt (so wie es da oben steht) wird doch immer ein neuer Wert gemessen oder?

Roboaktiv
25.06.2007, 09:53
Ah! Jetzt hab auch ich es verstanden!
Allerdings hab ich jetzt schon wieder nen neues Problem:



#include <asuro.h>

int main(void)
{
Init();
while(1)
{
MotorDir(FWD,FWD);
MotorSpeed(200,220);
while(PollSwitch()!=0)
{
MotorDir(RWD,RWD);
MotorSpeed(200,220);
Sleep(250);
Sleep(250);
MotorDir(RWD,FWD);
MotorSpeed(200,220);
Sleep(250);
Sleep(250);
Sleep(250);
break;
}
}
while(1);
return 0;
}


Der Asuro soll nun so rumfahren, bis er gegen einen Gegenstand fährt. Dann soll er nen Stück nach hinten fahren um genug Platz für die anschließende Drehung zu haben. Aber irgendwie funltioniert das nicht.

Was mach ich diesmal falsch?
Ist das vielleicht der gleiche Fehler wie oben?

Roboaktiv

radbruch
25.06.2007, 12:08
Hallo

PollSwitch() ist etwas zickig, bei Kollisionsabfragen verwende ich deshalb die direkte Abfrage des Tasteneingangs. Es werden dabei alle Tasten ausgewertet, aber nicht erkannt, welche gedrückt ist:

#define taste (!(PINC & (1<<PC4))) // Tastenabfrage
#define keine_taste (PINC & (1<<PC4))

Im Programm verwendet man das dann so:

if taste StatusLED(RED); else StatusLED(OFF);

oder

MotorSpeed(200,200);
while keine_taste;
MotorSpeed(0,0);

Selbstverständlich funktioniert das auch ohne #define:

if (!(PINC & (1<<PC4))) StatusLED(RED); else StatusLED(OFF);

ist aber nicht so schön zu lesen.

Warum fährst du eigentlich mit einer While-Schleife zurück? Mit einer if-Abfrage würde es auch funktionieren und käme dem Sinn näher: Fahre zurück, wenn eine Taste gedrückt wird. Beidesmal wird die Rückfahrbefehlsfolge einmal ausgeführt (der break ist unnötig!). Der Unterschied wäre, wenn die Wand mitfahren würde (oder ein Taster klemmt) und am Ende des Ausweichens eine Taste immer noch gedrückt ist. Dann würde mit while (aber ohne break!) der asuro sofort ein weiteres mal zurückweichen, bei if (oder while mit break) würde kurz vorwärts gesetzt und dann erst zurückgewichen. Allerdings so schnell, das mans nicht bemerkt.

Gruß

mic

Roboaktiv
26.06.2007, 09:31
Weiter oben hat damaltor am 22.06.2007 um 22:45 Was mit while anstatt If geschrieben und da dachte ich:"Dann machtes nochmal so!" Wahrscheinlich bezog sich das nur auf die Odometrie-Geschicht. Dieses #define dient nur zu erstellen einer Funktion oder?

Müsste das dann im ganzen Programm ungefähr so aussehen?


#include <asuro.h>
#define taste (!(PINC & (1<<PC4))) // Tastenabfrage
#define keine_taste (PINC & (1<<PC4))

int main(void)
{
Init();
while(1)
{
MotorDir(FWD,FWD);
MotorSpeed(200,220);
if(keine_Taste)
{
MotorDir(RWD,RWD);
MotorSpeed(200,220);
Sleep(250);
Sleep(250);
MotorDir(RWD,FWD);
MotorSpeed(200,220);
Sleep(250);
Sleep(250);
Sleep(250);
}
}
while(1);
return 0;
}

Oder doch irgendwie anders?
Roboaktiv

radbruch
26.06.2007, 15:43
Hallo

Nahe dran, aber noch nicht perfekt. O:)

Mit #define definierte Wörter werden im weiteren Programm durch den Text ersetzt, den man definiert hat. Ein

#define Lampe_rot StatusLED(RED)

ersetzt alle Stellen im Programm die Lampe_rot heisen mit dem Text StatusLED(RED) (bisschen banal vielleicht) Das verwendet man um sich Tipparbeit zu ersparen und/oder um ein Programm verständlicher/unverständlicher zu gestalten.

Zum deinem aktuellen Programm:

keine_Taste muss natürlich keine_taste heisen, weil es so auch im #define steht. Alles in c ist case-sensitiv, das bedeutet, Groß- und kleinschreibung wird unterschieden. Ausserdem möchtest du doch prüfen, ob eine Taste gedrückt ist. Also sollte die Abfrage if taste... heisen. Die Klammern könntest du weglassen, denn die sind im #define schon dabei.

Die Zeiten der Sleep()s sind zu kurz! Sleep(36) entspricht ca. 1 Millisekunde (soweit ich weis und nur, wenn du eine der neueren asuro.c verwendest.) Also würden 3 Sleep(250) ungefähr 750/36 ms verzögern. Das sind quasi 0,02 unmerkliche Sekunden.

for (zeit=0; zeit<1000; zeit++) { Sleep(36); }

würde dann eine Sekunde verzögern. Alternativ kennen die neueren Libaries auch die Msleep()-Funktion. Hier kann die Zeit direkt in Millisek. angegeben werden:

Msleep(1000);

wartet dann auch eine Sekunde lang.

Ob if oder while, viele Wege führen zum Ziel.

Gruß

mic

Roboaktiv
26.06.2007, 19:28
Müsste dann die if-Schleife so aussehen?


if(keine_taste) //Wenn keine Taste gedrückt ist, dann...
{
MotorDir(RWD,RWD);
MotorSpeed(200,220);
for(zeit=0;zeit<1000;zeit++) //zeit wird oben natürlich definiert
{
Sleep(36);
}
MotorDir(RWD,FWD);
MotorSpeed(200,220);
for(zeit=0;zeit<1000;zeit++)
{
Sleep(36);
}
}

zu #define: Wären denn die KLammern falsch?
zu Msleep (bzw. Sleep): Den Asuro hab ich zu Weihnachten 2006 bekommen.

Danke,
Roboaktiv

radbruch
26.06.2007, 20:04
Hallo

Es wird immer besser. O:)

zeit (mir fiel kein blöderer Name ein) sollte natürlich als int definiert sein. Die Schleifen müsten so funktionierten. c ist recht flexibel in der Gestaltung des Quelltextes.

if taste wird ersetzt durch if (!(PINC & (1<<PC4)))
if (taste) wird ersetzt durch if ((!(PINC & (1<<PC4))))

Das ist eigentlich nicht falsch und wird vom Compiler erkannt und wegrationalisiert. Das erzeugte .hex sollte bei beiden Varianten gleich sein.

Die Dateien auf der asuro-CD sind schon recht alt, neuere Libaries gibt es hier (http://sourceforge.net/project/showfiles.php?group_id=155217&package_id=172835), Infos zu V2.7 findest du hier (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=26594). Allerdings ist die brandneue Version 2.7 recht kompliziert, für Einsteiger würde ich ältere Versionen empfehlen. (Msleep() und PrintInt() gibt es seit ca. V2.1?) Für ein Update brauchst du lediglich die Dateien asuro.h und asuro.c jeweils durch die neueren Versionen ersetzen.

Gruß

mic

Roboaktiv
27.06.2007, 08:48
Ich bin grade dabei das Buch "Mehr Spaß für ASURO" durchzulesen und zu verstehen. Ist ja eigendlich recht einfach. Aber nur eigendlich. Das mit den Registern hab ich noch nicht verstanden. Woher weiß man, welches Register für welchen Pin zuständig ist? Ich vermute, wenn ich mit den Registern gut klar komme wird der Rest auch nicht so schwer. Und vielleicht verstehe ich dann auch V2.7. Welche Libaries würdest du mir denn empfelen?

Was meinst du eigentlich mit
"iif taste wird ersetzt durch if (!(PINC & (1<<PC4)))
if (taste) wird ersetzt durch if ((!(PINC & (1<<PC4))))"

Roboaktiv

Roboaktiv
27.06.2007, 09:33
Das Programm hab ich jetzt einfach mal auf den ASURO geflasht und mal ausprobiert! Und es geht!!! :-)Jetzt hab ich es noch nen bisschen verschönert(Mir den vielen LEDs)und es sieht schon sehr gut aus(Lob und Dank an dich) Hier nochmal das Programm für die, die das Gleicheproblem haben, die sich diese "Unterhaltung" durchgelesen haben und jetzt auch das Endprodukt anschauen möchten:


#include <asuro.h>
#define taste (!(PINC & (1<<PC4)))// Tastenabfrage
#define keine_taste (PINC & (1<<PC4))

int main(void)
{
int zeit;
Init();
while(1)
{
BackLED(OFF,OFF); //BackLED beide aus und
StatusLED(GREEN); //StatusLED grün also alles Okay
MotorDir(FWD,FWD);//Also kann man auch schön gradeaus fahren
MotorSpeed(200,220);
if(taste)
{
BackLED(ON,ON);//BackLED beide an und
StatusLED(RED);//StatusLED ROT also Kollision
MotorDir(RWD,RWD);//also erst ein Stück zurück
MotorSpeed(200,220);
for(zeit=0;zeit<500;zeit++)//(0,5 Sekunde zurück)
{
Sleep(36);
}
StatusLED(YELLOW);//StatusLED orange
BackLED(ON,ON);//BachLED ROT also Besserung in Sicht
MotorDir(RWD,FWD);//Drehung
MotorSpeed(200,220);
for(zeit=0;zeit<1000;zeit++)//(1 Sekunden warten)
{
Sleep(36);
}
}
}
while(1);
return 0;
}


Bestimmt sind in diesem Programm auch noch so kleine Fehlerchen, die man mal verbessern könnte. Tut euch keinen Zwang an. Aber mich würds auch Intressieren, was ihr noch so verandert habt.
@Radbruch Vielleicht hast du ja auch noch Ideen zur Verbesserung

Danke nochmal
Roboaktiv

radbruch
27.06.2007, 11:50
Hallo


Lob und Dank an dichQuatsch, DICH muss man loben. So macht mir das Spass, viele andere hier sind doof, faul, unhöflich oder beratungsresistent. Natürlich ist es ein eher kleines Programm, aber als Einstieg echt klasse. Die LEDs hast du prima eingesetzt, auch deine Kommentare sind vorbildlich. Allerdings vermeide ich Umlaute in den Kommentaren, denn ich hatte mal ein Problem beim Compilieren das von den Umlauten verursacht wurde.


Was meinst du eigentlich mit
if taste wird ersetzt durch if (!(PINC & (1<<PC4)))
if (taste) wird ersetzt durch if ((!(PINC & (1<<PC4))))
Beide Zeilen funktionieren gleich und erzeugen auch den selben Code, aber zähl mal die Klammern.

Das Buch besitze ich nicht, es scheint mir aber ein guter Einstieg zu sein, soweit ich bisher darüber gelesen habe. Die 2.7er-Lib ist eigentlich recht genial und ist auch gut dokumentiert. Die an ihrer Erstellung beteiligten RN-Forum-User helfen auch jedem, der bei der Installation und Anpassung an seinen asuro Probleme hat. Allerdings ist bei ihrer Anwendung die eigentliche Hardware des asuros nicht mehr erkennbar.

Ich programmiere aber lieber hardwarenah, deshalb verwende ich nur einige Funktionen einer älteren Version (mit IR-Erweiterung von waste (https://www.roboternetz.de/phpBB2/viewtopic.php?t=11114)). Mein Ziel ist der Einsatz der hvwdefines.h (http://www.arexx.com/forum/download.php?id=34)(aktuell ist Version 1.09. (http://www.arexx.com/forum/viewtopic.php?p=1325#1325)) von asuro-henk (http://home.planet.nl/~winko001/Asuro/Software/AsuSfwPagFrm.htm). Damit programmiert man direkt die Register des ATMega8 und kann herrlich schlanke Programme erzeugen. Allerdings bedeutet das auch viel Tipparbeit und man muss sich alle Funktionen selbst erarbeiten.

Infos zu den AVRs und deren Programmierung gibt es bei wikipedia (http://de.wikipedia.org/wiki/Atmel_AVR), bei mikrocontroller.net (http://www.mikrocontroller.net), im RN-Wissen (https://www.roboternetz.de/wissen/index.php/AVR-Einstieg_leicht_gemacht), im asuro-wiki (http://www.asurowiki.de/pmwiki/pmwiki.php) und natürlich im Datenblatt des ATMega8L (http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf).

Gruß

mic

Roboaktiv
28.06.2007, 08:59
Danke für das Rücklob!
Das mit dem if(taste) hab ich mir so angewöhnt. Im meinem C-Buch steht nach den "Schleifen-Einleitewort" (oder wie das heißt) auch immer diese Klammer.
Ich glaube, es ist jetzt erstmal besser wenn ich bei meiner Libary bleibe und erstmal in Ruhe mit den Registern programmiere. Sonst werde ich da bestimmt vollkommen durcheinander kommen.

Ansonsten hab ich JETZT keine weiteren Fragen mehr. Du kannst ja mal zwischendurch hier vorbeischauen, ob wieder nen Problem aufgetreten ist.

Deine Hilfe war echt hilfreich!!

Danke nochmal!

Roboaktiv

Roboaktiv
29.06.2007, 09:14
Ich hab mal versucht, mit dem Englisch im ATMega8-Datenblatt klar zu kommen. Bin ich auch. Allerdings kam mir das sehr kompliziert vor. Hab mir jetzt überlegt, das ich jetzt erstmal weiter so rumprogrammiere. Wenn mir das dann u langweilig wird, versuch ich es mal mit einer anderen Libary.



Ideen zur Verbesserung

Jo ich hab selber eine:
Man könnte doch mal versuchen, dass der Asuro sich im Verhältniss zur Länge der Strecke davor dreht. Meine ersten Überlegungenansetzte sind, das man nach der If-Schleife noch ne Else-Schleife anhängt, inder dann zu einem Wert immer etwas dazu addiert, der dann mit ins Verhältnis der Dauer der Drehung gesetzt wird. Das sieht dann ungefähr so aus:


while(1)
{
Sleep(36);
zeit=zeit+100;
if(zeit>=Laenge)
{
break;
}
}
}
else
{
Laenge=Laenge+100;
}

(Alles was davor und danach nicht da steht, bleibt gleich.)
Das hab ich auch schon ausprobert. Im Grunde funktioniert alles. Nur die Werte (von Laenge und zeit) sind bei jedem größen Verhältniss anders. Also wenn man den Asuro auf relativ kleinem Raum(1-2qm) fahren lässt, müssen die Werte weiter auseinader liegen als bei einem größeren Raum.

Gruß
Roboaktiv

radbruch
29.06.2007, 11:33
Hallo

Die whiles gefallen dir wohl sehr. Wenn ich richtig verstehe, willst du messen, wie lange der asuro frei geradeaus fährt um dann, bei einer Kollision, die Dauer der Drehung abhängig von dieser Messung zu machen.

Dazu sehe ich eigentlich zwei Ansätze:

1.: Man misst die Zeit (z.B. über die Anzahl der Schleifendurchgänge oder mit Gettime(); )
2.: Man misst die Wegstrecke (und auch die Drehung) mit der Odometrie

Wobei die Zeitmessung "ungenauer" sein wird.

Zeitmessung mit Schleifenzähler: Du verwendet eine Zählvariable. Diese wird zu Beginn des Programms und jeweils nach dem Drehen auf 0 gesetzt. Bei Geradeausfahrt wird der Zähler dann hochgezählt und beim Drehen ausgewertet. Das Problem dabei ist der schnelle ATMega8, der Zähler wird rasend schnell riesige Werte annehmen. Deshalb verzögere ich den Ablauf etwas (um je eine 1/1000stel Sekunde, deshalb Geradeauszeit ungefähr gleich Drehzeit). Man könnte auch eine größere Zählvariable verwenden (int long) und später den Wert runterteilen:



#include <asuro.h>

#define taste (!(PINC & (1<<PC4)))// Tastenabfrage
#define keine_taste (PINC & (1<<PC4))

unsigned int zaehler; //Schleifenzaehler

int main(void)
{
int zeit;
Init();
zaehler=0; //Schleifenzaehler zuruecksetzen
while(1)
{
BackLED(OFF,OFF); //BackLED beide aus und
StatusLED(GREEN); //StatusLED grün also alles Okay
MotorDir(FWD,FWD);//Also kann man auch schön gradeaus fahren
MotorSpeed(200,220);
Sleep(36); // Ablauf etwas verzoegern, weil ATMega8 so schnell ist
if (zaehler < 5000) zaehler++; //Schleifenzaehler hochzaehlen mit Begrenzung!
if(taste)
{
BackLED(ON,ON);//BackLED beide an und
StatusLED(RED);//StatusLED ROT also Kollision
MotorDir(RWD,RWD);//also erst ein Stück zurück
MotorSpeed(200,220);
for(zeit=0;zeit<500;zeit++)//(0,5 Sekunde zurück)
{
Sleep(36);
}
StatusLED(YELLOW);//StatusLED orange
BackLED(ON,ON);//BachLED ROT also Besserung in Sicht
MotorDir(RWD,FWD);//Drehung
MotorSpeed(200,220);
for(zeit=0;zeit<zaehler;zeit++) //abhaengig von gerader Fahrt drehen
{
Sleep(36);
}
zaehler=0; //Ende der Drehung, Schleifenzaehler zuruecksetzen
}
}
while(1);
return 0;
}

Die Drehung kann man dann noch z.B. mit
for(zeit=0;zeit<(zaehler/2);zeit++)
beeinflussen.

Mit Gettime() würde es so ähnlich funktionieren. Anstatt den Zähler zurückzusetzen müsste man sich die aktuelle Zeit merken und beim Drehen den aktuellen Zeitunterschied auswerten. Das alles ist aber sehr ungenau und hat auch eigentlich keinen Sinn. Außer eben, dass man übt.

Ich würde dir aber raten, das über die Odometrie zu lösen. Dann bist auch erstmal beschäftigt, denn die Odometrie hat einige Tücken und ist nicht einfach zu beherrschen. Zusätzlich zur optimierten Mechanik (axiales Spiel der Codescheiben, Abdeckung der Sensoren) must du auch die Min-/Maxwerte kennen(mit PrintInt(); zum Terminal schicken) um eine vernünftige Funktion programmieren zu können. Es gibt noch viel zu tun und zu entdecken.

Aus dem Datenblatt kann man gut die Beispielcodes verwenden, z.B. das Schreiben und Lesen des EEProms. Ich mische aber im Moment auch die Libary mit einigen direkten Portzugriffen (z.B. Tastenabfrage). Die Libary ist eben bequem, weil man sich um nichts kümmern muss und schnell zu einem Ergebniss kommt. Je nach Interesse kann man sich eben mehr Richtung KI oder Richtung Hardware orientieren.

Bitte verstehe das jetzt nicht falsch. Ich habe nicht die Zeit und auch keine Lust dich bei jedem Schritt zu unterstützen. Du hast jetzt den Einstieg geschafft, alles weitere kommt von alleine, es braucht eben etwas Zeit und Mühe. Vieles wurde hier schon besprochen und erklärt. Da solltest du einfach mal etwas im Forum stöbern. Wenn's dann mal wirklich wieder klemmt, helfe ich dir natürlich weiter, wenn ich kann. Auch meine Möglichkeiten und Kenntnisse sind begrenzt. Aber es gibt ja auch noch andere asuro-Besitzer die sich gut auskennen und dir helfen können.

Gruß

mic

Roboaktiv
29.06.2007, 16:57
Ja ich seh es auch ein. Solangsam fallen mir auch keine Fragen mehr ein.:-) Mit der Odometrie hab ich heute morgen auch schon angefangen. Besonders weit bin ich zwar noch nicht gekommen aber ich probier mal fleißig weiter. Wenn es zu einer Stelle kommt, wo ich nicht mehr weiter weiß berichte ich dir hier davon. Wenn ich zu einem MEGAerfolg gekommen bin auch. Vielleicht kuckt ein anderer Forum-User hin und wieder auch mal hier vorbei. Deshalb sind nicht alle meine Einträge hier direkt an dich adressiert. Wenn du Zeit und Lust hast kannst du ja auch noch deine Ideen, Empfelungen usw. dazugeben.

Gruß
Roboaktiv

damaltor
30.06.2007, 16:45
Ich hab mal versucht, mit dem Englisch im ATMega8-Datenblatt klar zu kommen. Bin ich auch. Allerdings kam mir das sehr kompliziert vor.

da könnte ich helfen... was genau meinst du denn bzw. welches thema interessiert dich besonders?

Roboaktiv
30.06.2007, 16:57
Eigendlich wollt ich nur wissen, welcher Pin zu welchem Register gehört. Am besten wäre es wenn du das gleich mit den Asuro erklärst.

Gruß Roboaktiv

damaltor
30.06.2007, 17:19
hmm... ok. schnapp dir mal den schaltplan. dann such nach dem teil, das du ansprechen willst. nehmen wir mal die frontled. die hängt glaube ich an PORTD, PIN 6.

dann machst du folgendes: zuerst stellst du diese port als ausgang ein.

DDRD =DDRD | (1<<6);

das bedeutet:
DDRD ist das register in dem definiert wird, ob ein pin ein eingang (0) oder ausgang (1) ist.
(1<<6) bedeutet das gleiche wie 01000000. eine eins, um 6 stellen nach links geschoben.
durch das | wird der rest des registers nicht beeinflusst.

dann sagst du dem prozessor, ob der pin high(an, 1) oder low (0) sein soll:
-ein:
PORTD = PORTD | (1<<6);
-aus:
PORTD = PORTD & ~(1<<6);

das | sowie das & ~ sorgen wieder dafür, dass der rest des registers nicht beeinflusst werden.

radbruch
30.06.2007, 21:29
Hallo

Kurz und knapp. Das versteht jeder, der logische Verknüpfungen und Programmieren mit der Muttermilch verabreicht bekam. Didaktisch (http://de.wikipedia.org/wiki/Didaktisch) zwar völlig wertlos, aber für mich ein Ansporn, endlich in die Low-Level-Programmierung einzusteigen. So ein "blöder" RISC-Prozessor kann doch nicht soooo kompliziert sein, dass ich ihn nicht beherschen kann.

Bitte nicht falsch verstehen. Ich bin immer noch auf der Suche nach meinem "Weg", ob Mechanik oder Software, ich weis einfach nicht, was mich mehr begeistert. Auf jeden Fall war der asuro für mich ein "Glücksgriff", genauso wie dieses Forum hier. Und bevor ich hier noch mehr ins offtopic abdrifte, beende ich besser mein sentimentales Gesülze. Schönes We noch.

Gruß

mic

damaltor
01.07.2007, 10:36
Didaktisch wertlos, da hast du wohl recht... machs besser -.- sprüche klopfen kann ja jeder...

radbruch
01.07.2007, 13:52
Hallo


machs besser
Würde ich ja gerne, wenn ich's könnte. Da ich aber AVR und c Neuling bin, verwirrt mich dieses Bitgeschiebe etwas. Ich würde das ganz traditionell durch binäre Schreibweise ersetzen, dann würde auch der Zusammenhang zwischen Bitnummer und Port erkennbar sein. Du machst das ja auch so in deinem ersten Beispiel:

DDRD =DDRD | (1<<6);

würde ich dann so schreiben:

DDRD =DDRD | 0b01000000;

was als Einstieg aber immer noch viel zu kompliziert ist.

Erstmal muss man wissen, dass DDRD für das Datenrichtungsregister des Port D steht und irgendwo (in der io.h?) per #define definiert wurde. Nach dem Reset sind alle Ports auf Eingang gesetzt (offenbar sind sie es nicht, siehe unten) und müssen, je nach Bedarf, als Ausgang geschaltet werden. Um den 7. Pin als Ausgang zu definieren, genügt ein

DDRD=0b01000000; // binaere Schreibweise

wobei man beachten muss, dass die Zählung der Bits bei 0 beginnt. Allerdings werden mit diesem Befehl auch die anderen Richtungsbits beeinflust, dies ist aber meist nicht gewünscht. Um gezielt ein bestimmtes Bit zu setzen (ein 1 reinschreiben), muss man eine oder-Verküpfung anwenden, die nur das gewünschte Bit verändert und den Rest unbeeinflusst läst:

DDRD=DDRD | 0b01000000;

Das Setzen eines Ausgangs funktioniert dann nach dem selben Schema, nur das man dabei auf das Datenregister zugreift, das als PORTD definiert wurde. Wiederum mit einer oder-Verknüpfung, um die anderen Ports nicht zu beeinflussen, sieht das Setzen die 7. Ports (Portbit6!) dann so aus:

PORTD=PORTD | 0b01000000;

Das Rücksetzen des Ausgangs funktioniert nun ähnlich, mit dem Unterschied, dass wir eine und-Verknüpfung anwenden müssen, um die anderen Portbits nicht zu beeinflussen. Das würde dann so aussehen:

PORTD=PORTD & 0b10111111;

und läst sich mit dem ~-Operator noch wunderbar vereinfachen, weil dieser einen Wert bitweise negiert, also aus einer 0 eine 1 macht und aus einer 1 eine 0. Man kann also einfach auch

PORTD=PORTD & ~0b01000000;

schreiben. So wird beim Lesen gleich klar, welches Bit eigentlich gemeint ist, dem AVR ist es aber egal, er setzt beidesmal das Portbit auf 0.

Na wunderbar, scheinbar habe wenigstens ich es jetzt kapiert. Hier mein allererstes selbstgeschriebenes Programm, das OHNE die asuro-Lib direkt auf die Ports zugreift. Weil meine umgebaute FrontLED unsichtbares IR-Licht aussendet, setze ich völlig unspektakulär die StatusLED auf rot:



#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
DDRB=0; // nicht benoetigte Ports auf Eingang setzen
DDRC=0;
DDRD=0b00000100; //rote StatusLED haengt an PD2(= Port D, Bit2)
PORTD=0b00000100; // Ausgang setzen
while(1);
return(0);
}

Mit #include <avr/io.h> werden, je nach Compilerdirektive, die #defines für den entsprechenden Mikrokontroller eingebunden. In unserem Fall eben die Definitionen für den ATMega8.
Mit #include <avr/interrupt.h> werden noch die Default-Interruptroutinen eingebunden, ohne verabschiedet sich der Prozessor nach dem Programmstarts ins Nirwana.

Da ich mir das nun selbst erarbeitet habe, bin ich ziemlich stolz auf das Ergebniss. Natürlich werden die AVR-Profis unter euch darüber schmunzeln, aber jeder fängt eben mal klein an. Die "Bitschiebereien" habe ich natürlich kapiert, aber für den Einstieg finde ich es so verständlicher.

Gruß

mic

[Edit]
Abschließend noch zum Thema Tastenabfrage:


#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
DDRB=0; // nicht benoetigte Ports auf Eingang setzen
DDRC=0;
DDRD=0b00000100; //rote StatusLED haengt an PD2(= Port D, Bit2)
while(1)
{
/*
Die Tasten haengen an PortC Bit4. Wenn keine Taste gedrueckt ist,
wird ueber R23 VCC an diesen Pin gelegt. Das ergibt eine 1 beim Einlesen.

Wenn man dann eine Taste drueckt, ergibt sich ein Spannungsteiler,
bei dem der Pin dann deutlich, bei K6 1000K zu 68K, nach 0V gezogen wird.
Das ergibt eine 0 am Eingang.

Den C7 kann man ignorieren, R24 ebenfalls, weil PD3 als Eingang (ohne Pullup?)
geschaltet ist.
*/

if (PINC & 0b00010000) // PortC Bit4 ist der Tasteneingang
{
PORTD=0b00000100; // StatusLED rot setzen
}
else
{
PORTD=0b00000000; // StatusLED ausschalten
}

/*
Spätestens jetzt wird auch mir klar, dass die Bitschieberei effektiver ist:

PORTD=((PINC & (1<<PC4)) >> 2);

*/
}
return(0);
}

Wenn man eine Taste drückt, geht die StatusLED aus. O:)

damaltor
01.07.2007, 18:05
find ich gut, das problem ist dass der avr-gcc (zumindest bei mir) keine binärzahlen erkennt. da kommt nur expected ; before string constant oder sowas. er denkt also das ist ein string.

an sich ist das programm sonst das gleiche.. alternative: für jedes linksschieben kann man auch mit 2 multiplizieren.

1<<4 ist dann 1*2*2*2*2.

funktioniert gut, ist allerdings prozessortechnisch eine absolute katastrophe, weil man eine verschiebung manuell in eine multiplikation umschreibt, die dann im prozessor wieder in eine schiebung umgewandelt wird. das erzeugt relativ viel unnützen code, weil der prozessor für jede 2 zwei register reserviert (integer brauchen 2), dann verschiebungen über beide register mit ständigen carry-check macht usw.

funktioniert bei euch 0b00100000 im quelltext?

Roboaktiv
01.07.2007, 18:08
Im Buch vom Asuro steht es so, wie damaltor es geschrieben hat. Das hat mich bisher auch überzeugt und ich habs verstanden.

@radbuch Du hast geschrieben das du dich nicht entscheiden kannst. Nehm doch Michatronik! Das ist ne Mischung aus Mechanik und Informatik.

@damaltor: Das was du da oben geschrieben hast hab ich verstanden. Aber woher weiß ich jetzt welches Register zu welchem Pin gehört.

Auch nicht verstanden hab ich die Geschichte vom Motor. Da gibt es ja so ne Pulsweitende-Funktion oder so ähnlich. Außerdem gibt es da ja 3 Pins pro Motor (z.B. für den linken Motor: PD4(XCK/T0) PD5(T1) PB1(OC1A)). Und was soll das jetzt??

Gruß Roboaktiv

Roboaktiv
05.07.2007, 18:04
Hallo Radbuch,
ich hab's heute endlich geschaft, dass der ASURO z.B. 4 Umdrehungen vorfährt!!! Hier das Programm:


/*Asuro fährt geradeaus und misst die Helligkeit der Readsensoren*/
#include <asuro.h>
#include <string.h>
int main(void)
{
unsigned int umdrehung=0; //Ist wichtig zu zaehlen der Umdrehungen
unsigned int zaehler=0; //Ist wichtig zu zaehlen der verschiedenen Felder
unsigned int zeit; //Ist wichtig fuer die Pausen
unsigned int data[2],data_min[2],data_max[2],data_mit[2];
char AusgabeTxt[80], Text[80], Textaa[80]; //Ist wichtig für die SerWrite ausgaben
Init();
data_max[0] = 0;
data_max[1] = 0;
data_min[0] = 65000;
data_min[1] = 65000;

MotorDir(FWD,FWD); //Asuro fäht sehr langsam fuer genaue Messungen
MotorSpeed(150,160);

OdometrieData(data); //Das aktuelle Feld wird erfasst
if (data[0] < data_min[0]) //Hier werden die Daten vom OdometrieData ausgewertet und der höchste
{
data_min[0] = data[0]; //und niedrigste Wert beider Seiten wird gespeichert
}
if (data[1] < data_min[1])
{
data_min[1] = data[1];
}
if (data[0] > data_max[0])
{
data_max[0] = data[0];
}
if (data[1] > data_max[1])
{
data_max[1] = data[1];
}

sprintf (AusgabeTxt, "Min 1: %d Min 2: %d Max 1: %d Max 2: %d \n\r",
data_min[0],data_min[1],data_max[0],data_max[1]); //Die gespeicherten Werte werden hier über einen Striing ausgegeben
SerWrite(AusgabeTxt,80);
data_mit[0]=((data_max[0]-data_min[0])/2)+data_min[0]; //Hier wird der Mittelwert vom linkenm Rad berechnet
sprintf (Text,"Mittelwert links: %d \n\r",data_mit[0]); //Dieser wird dann ausgegeben
SerWrite(Text,80);
data_mit[1]=((data_max[1]-data_min[1])/2)+data_min[1]; //Das ganze mit der anderen Seite
sprintf (Textaa,"Mittelwert rechts: %d \n\r",data_mit[1]);
SerWrite(Textaa,80); //Bishierhin wurde nur kaliebriert und erfasst
while(1) //Folgendes wird immer wiederholt und ist das eigendliche Programm
{
OdometrieData(data); //Das aktuelle Feld wird erfasst
if(data[1]>data_mit[1]) //und mit dem Mittelwert verglichen
{ //wenn es dunkeler war wird das zu der Anzahl der dunkelen Felder addiert
zaehler++;
SerWrite("zeahler++\n\r",11); //Dieses TOPEREIGNISS wird natürlich weitererzählt
}
if(zaehler>=6) //Wenn 6 dunkle Felder erfasst wurden
{
umdrehung++; //Haben sich die Räder einmal gedreht
SerWrite("Umdrehung++\n\r",14); //Auch dieses TOPEREIGNISS wird natürlich weitererzählt
zaehler = 0;
}
if(umdrehung>=4) //wenn sie sich denn 4 mal gedreht haben
{
MotorSpeed(0,0);
for(zeit=0;zeit<4000;zeit++) //Vier Sekunden stillstand
{
Sleep(36);
}
umdrehung = 0;
SerWrite ("Das waren 4 Umdrehungen!\n\r",26);
}
}
while(1)
return 0;
}


Und was sagst du dazu.
Natürlich will ich besteh ich nicht darauf, dass du was dazu schreibst. Programmieren und CO soll ja Spaß machen. Aber ich würde mich schon mal über ne kurze Stellungsnahme von dir freuen. :-) Allerdings ist es jetzt kein MEGAerfolg. Aber dennoch ein Erfolg.

Gruß Roboaktiv

radbruch
05.07.2007, 20:24
Hallo Roboaktiv

Na, dann wollen wir mal:

Zuerst eine Anmerkung zu den Zeilennummern: Ich habe dein Programm mit einem Klick auf https://www.roboternetz.de/phpBB2/templates/fisubsilversh/images/nav_select_all.gif markiert, dann kopiert und dann in meinen Editor eingefügt. Möglicherweise stimmen deshalb die von mir angegebenen Zeilennummern nicht mit deinen überein. Ursache dafür wären dann Leerzeilen oder ein Zeilenvorschub(=Enter) zwischen dem code-Tag und der ersten Progammzeile in deinem Posting.

Zeile 15/16: Ein integer ist beim ATMega8 zwar maximal 65535 groß, aber die Odometrie verwendet nur 10 Bits, also ist der Maxwert 1023.
Zeile 20: Hier sollte vielleicht eine Pause sein, damit der Motor hochdrehen kann.
Zeile 22-37: Das solltest du in einer Schleife mehrmals tun damit die Ritzel Zeit haben sich zu bewegen! So liest du genau einmal einen Wert ein! Und if kleiner else if größer wäre eleganter
Zeile 41/44: Den Mittelwert bildet man mit dieser Formel: (max+min)/2

Zeile 50-54:Bei jedem Schleifendurchgang mit data[1] > datamit[1] wird der Zähler hochgezählt, auch wenn das Rad stehen würde! Deshalb prüft man auf die helle Kante, merkt sich, dass zuletzt hell war, prüft dann auf die dunkle Kante, merkt sich, dass zuletzt dunkel war usw,usw...

Ab Zeile 50: Ich vermute, du willst das mal anschauen und zählst deshalb die Umdrehungen und die Impulse pro Umdrehung. Und hast auch deshalb die SerWrite()s drin. Im echten Leben würde das nicht funktionieren. 4 Umdrehungen mit der 6er Codescheibe sind 24 Segmente. Also fährt man auch auf 24 (besser auf 22, der Bremsweg zählt ja weiter), und sendet dann den Wert, denn während SerWrite() kann der asuro nichts anderes tun und würde vielleicht Impulse übersehen.

Möglichweise ist das noch nicht alles. Ich konnte dein Programm aber leider nicht compilieren und testen, weil ich einen "implicit declaration of function `sprintf' "-Fehler gemeldet bekomme. Und da ich string.h bei meinen Programmen nicht anwende, war ich zu faul die Ursache dafür zu suchen.

Ich mache das so:
Ich teile den Bereich zwischen max und min in drei Teile, oberes Drittel ist high, unteres Drittel ist low und prüfe dann, in welchem Drittel der eingelesene Wert liegt und merke mir das als Bit. Wenn das bit nicht gesetzt ist, prüfe ich auf high, wenn erkannt setzte ich das bit und prüfe auf low und lösche, wenn erkannt das bit wieder usw,usw..

Jeder Bitwechsel wird gezählt und dabei die StatusLED umgeschaltet. Die 6er Scheibe hat dann 12 Impulse pro Umdrehung und ein Stoppen auf den Kante zählt keinen Unsinn:



void Count(){
OdometrieData(data);
if (!odo_bit_l & (data[0] > odo_high_l)) {
odo_bit_l=1; count_l ++; StatusLED(YELLOW);
}
if (odo_bit_l & (data[0] < odo_low_l)) {
odo_bit_l=0; count_l ++; StatusLED(OFF);
}
if (!odo_bit_r & (data[1] > odo_high_r)) {
odo_bit_r=1; count_r ++; StatusLED(RED);
}
if (odo_bit_r & (data[1] < odo_low_r)) {
odo_bit_r=0; count_r ++; StatusLED(OFF);
}
}

Übrigens heißen meine Variablen hinten alle _l bzw. _r. Ich teste dann nur den Code für eine Seite, kopiere den Code und suche&ersetze dann in der Kopie das _l durch ein _r.

Ich würde string.h nicht einbinden und alle Ausgaben mit SerWrite()/PrintInt() erledigen. Jedes #include bläht möglicherweise den Code auf. Aber das ist in erster Linie Geschmackssache.

Ich hoffe, dass hilft dir etwas auf die Sprünge.

Gruß

mic

Falls es jemanden interessieren sollte:
Das ist das Programm, aus dem der Zählcode stammt. Das waren meine c-Anfänge, mit Datum vom 8.1.07, da hatte ich den asuro grad 2 Wochen. Und das sieht man auch, es stecken noch einige Fehler drin. 8-[ Die Funktion: Der asuro wird auf dem Boden stehend eingeschaltet. Er fährt dann ein Stüch vorwärts und misst die Min-/Maxwerte, wenn er fertig ist, blickt er. Man muss ihn dann hochheben und wieder auf den Boden setzen. Wieder auf dem Boden beschleunigt er auf eine vorgegebene Geschwindigkeit, verzögert wieder auf 0 und sendet die Zählerstände. Dann das selbe rückwärts. Endlos bis der Akku leer ist:


#include <asuro.h>

unsigned char sw_data, i, tmp_char, step, speed_min, speed_max, rampe_v, rampe_r;
unsigned int data[2], j, tmp_int;
unsigned long loop_count, rampe_delay;
unsigned char odo_bit_l, odo_bit_r;
unsigned int odo_min_l, odo_max_l, odo_low_l, odo_high_l;
unsigned int odo_min_r, odo_max_r, odo_low_r, odo_high_r;
unsigned int count_l, count_r, count_soll_l, count_soll_r;
unsigned int speed_l, speed_r, speed_max_l, speed_max_r, speed_soll_l, speed_soll_r;

void hochheben() { // blinken: gelb=hochheben green=hinsetzen dauergreen=los
LineData(data); tmp_char=data[0]+data[1]+20; // Schwelle für aufheben vom Boden
do {
LineData(data); StatusLED(OFF);Msleep(300); StatusLED(YELLOW); Msleep(150);
} while ((data[0]+data[1]) < tmp_char);
do {
LineData(data); StatusLED(OFF);Msleep(300); StatusLED(GREEN); Msleep(150);
} while ((data[0]+data[1]) > tmp_char);
StatusLED(GREEN); Msleep(2000);
}

int init_odo() {

StatusLED(YELLOW); MotorDir(RWD,FWD);
odo_min_l=odo_max_l=odo_low_l=odo_high_l=count_l=0 ;
odo_min_r=odo_max_r=odo_low_r=odo_high_r=count_r=0 ;

MotorSpeed(150,150);
for (j==0; j<5000; j++) {
OdometrieData(data);
if (data[0] < odo_min_l) odo_min_l=data[0];
if (data[0] > odo_max_l) odo_max_l=data[0];
if (data[1] < odo_min_r) odo_min_r=data[1];
if (data[1] > odo_max_r) odo_max_r=data[1];
for (i=0; i<200; i++);
}
MotorSpeed(0,0);Msleep(100);
OdometrieData(data);

odo_low_l=((odo_min_l + odo_max_l)/3); // je ein drittel high-nix-low
odo_high_l=((odo_min_l + odo_max_l)/3)*2;
if (data[0] >= ((odo_min_l + odo_max_l)/2)) odo_bit_l=1; else odo_bit_l=0;

odo_low_r=((odo_min_r + odo_max_r)/3); // je ein drittel high-nix-low
odo_high_r=((odo_min_r + odo_max_r)/3)*2;
if (data[1] >= ((odo_min_r + odo_max_r)/2)) odo_bit_r=1; else odo_bit_r=0;
MotorDir(BREAK,BREAK);
}

void Count(){
OdometrieData(data);
if (!odo_bit_l & (data[0] > odo_high_l)) {
odo_bit_l=1; count_l ++; StatusLED(YELLOW);
}
if (odo_bit_l & (data[0] < odo_low_l)) {
odo_bit_l=0; count_l ++; StatusLED(OFF);
}
if (!odo_bit_r & (data[1] > odo_high_r)) {
odo_bit_r=1; count_r ++; StatusLED(RED);
}
if (odo_bit_r & (data[1] < odo_low_r)) {
odo_bit_r=0; count_r ++; StatusLED(OFF);
}
}

int MotorRampe(unsigned char sp_l, unsigned char sp_r, unsigned int r) {

if (loop_count > rampe_delay) {
if (sp_l != speed_l) {
if (sp_l > speed_l) speed_l ++;
if (sp_l < speed_l) speed_l --;
rampe_delay=loop_count+r;
}
if (sp_r != speed_r) {
if (sp_r > speed_r) speed_r ++;
if (sp_r < speed_r) speed_r --;
rampe_delay=loop_count+r;
}
MotorSpeed(speed_l,speed_r);
}
return ((sp_l == speed_l) && (sp_r == speed_r));
}

void run(void) {
}

int main(void) {
Init();
SerWrite("\nHallo\nBatterie: ",17);
PrintInt(Batterie());

init_odo();// hochheben();
step=loop_count=rampe_delay=speed_l=speed_r=count_ l=count_r=0;
speed_min=0; speed_max=250; rampe_v=15; rampe_r=15;

do {
loop_count ++;
switch (step) {
case (0): MotorDir(FWD,FWD); FrontLED(ON); BackLED(OFF,OFF);
count_l=count_r=0; step++; break;
case (1): if (MotorRampe(speed_max,speed_max,rampe_v)) step++; break;
case (2): if (MotorRampe(speed_min,speed_min,rampe_r)) step++; break;
case (3): MotorDir(RWD,RWD); FrontLED(OFF); BackLED(ON,ON);
SerWrite("\n",1);PrintInt(count_l); SerWrite("\n",1); PrintInt(count_r);
step++; break;
case (4): if (MotorRampe(speed_max,speed_max,rampe_v)) step++; break;
case (5): if (MotorRampe(speed_min,speed_min,rampe_r)) step=0; break;
case (98): MotorDir(BREAK,BREAK); step++; break;
case (99): FrontLED(OFF); BackLED(OFF,OFF); step=99; break;
}
Count();
} while (1);
return 0;
}

Roboaktiv
06.07.2007, 14:15
Hi Mic,
erstmal danke für deine Meinung und deine Tipps!

Da ich die Geschichte mit der Bitprogrammierung und den Registern hab ich noch nicht richtig verstanden. Dehalb probiere ich jetzt erstmal mit den vorprogrammierten Libaries rum. Außerdem wollte ich dieses Programm als Übergangsprogramm für diese Tastergeschichte nehmen.

Der Integerwert (65000) wird doch sowieso bei dem erstendurchlauf der Schleife runtergesetzt.

Das mit der Hochdrehpause ist doch dann so ne Sleep-Geschichte oder?

Eigendlich könnte man diese sprintf- und SerWritefunktionen auch weglassen.

Im Grunde hab ich doch das ganze Programm zu kompliziert gemacht. Es reicht doch, wenn man es so schreibt:


/*Asuro fährt geradeaus und misst die Helligkeit der Readsensoren*/
#include <asuro.h>
int main(void)
{
unsigned int durchlauf;
unsigned int umdrehung=0; //Ist wichtig zu zaehlen der Umdrehungen
unsigned int zaehler=0; //Ist wichtig zu zaehlen der verschiedenen Felder
unsigned int zeit; //Ist wichtig fuer die Pausen
unsigned int data[2],data_neu[2];
Init();
while(1)
{
MotorDir(FWD,FWD); //Asuro fäht sehr langsam fuer genaue Messungen
MotorSpeed(150,160);
OdometrieData(data); //Das aktuelle Feld wird erfasst
for(durchlauf=0;durchlauf>=1000;durchlauf++)
{
sleep(36);
}
OdometrieData(data_neu); //Das aktuellere Feld wird erfasst
if(data[1]!=data_neu[1]) //und mit dem aktuellem Feld verglichen
{ //wenn es anders war wird das zu der Anzahl der veränderten Felder addiert
zaehler++;
SerWrite("zeahler++\n\r",11); //Dieses TOPEREIGNISS wird natürlich weitererzählt
}
if(zaehler>=24) //Wenn 24 Änderungen erfasst wurden
{
umdrehung++; //Haben sich die Räder einmal gedreht
SerWrite("Umdrehung++\n\r",14); //Auch dieses TOPEREIGNISS wird natürlich weitererzählt
zaehler = 0; }
if(umdrehung>=4) //wenn sie sich denn 4 mal gedreht haben
{
MotorSpeed(0,0);
for(zeit=0;zeit<4000;zeit++) //Vier Sekunden stillstand
{
Sleep(36);
}
umdrehung = 0;
SerWrite ("Das waren 4 Umdrehungen!\n\r",26);
}
}
while(1)
return 0;
}

Eigendlich funktioniert da jetzt auch gut.
Falls du Verbesserungvorschläge, Zeit und auch noch Lust hast bitte ich dich mir von diese zu berichten.

Roboaktiv
07.07.2007, 09:41
Ich hab grade ma die länge der zurückgelegten Strecke gemessen und mir ist aufgefallen, dass diese viel zu lang ist. Und auch, wenn ich die Räder festhalt hält der trotzdem irgendwann an. Liegt das vielleicht auch daran, das die Fototransistoren zu genau messen? Wie kann man die Messungen ungenauer machen? Diese Fragen müssen nicht unbedingt von Radbruch beantwortet werden, sondern auch von Usern, die auch davon Ahnung haben und hier mal vorbei surfen.

Gruß Roboaktiv

radbruch
07.07.2007, 10:37
Hallo

Das liegt schlicht daran, dass dein Programm nicht funktioniert. Du solltest einfach auch lesen, was man dir schreibt. Das auch im Stillstand gezählt wird, habe ich dir oben schon geschrieben. Wenn du durch Einrückungen deinen Code etwas struckturierst wird dir vielleicht auch klar, dass du nur eine einzige Schleife hast:



/*Asuro fährt geradeaus und misst die Helligkeit der Readsensoren*/
//#include <asuro.h>
int main(void)
{
unsigned int durchlauf;
unsigned int umdrehung=0; //Ist wichtig zu zaehlen der Umdrehungen
unsigned int zaehler=0; //Ist wichtig zu zaehlen der verschiedenen Felder
unsigned int zeit; //Ist wichtig fuer die Pausen
unsigned int data[2],data_neu[2];
Init();
while(1)
{
MotorDir(FWD,FWD); //Asuro fäht sehr langsam fuer genaue Messungen
MotorSpeed(150,160);
OdometrieData(data); //Das aktuelle Feld wird erfasst
for(durchlauf=0;durchlauf>=1000;durchlauf++)
{
sleep(36);
}
OdometrieData(data_neu); //Das aktuellere Feld wird erfasst
if(data[1]!=data_neu[1]) //und mit dem aktuellem Feld verglichen
{ //wenn es anders war wird das zu der Anzahl der veränderten Felder addiert
zaehler++;
SerWrite("zeahler++\n\r",11); //Dieses TOPEREIGNISS wird natürlich weitererzählt
}
if(zaehler>=24) //Wenn 24 Änderungen erfasst wurden
{
umdrehung++; //Haben sich die Räder einmal gedreht
SerWrite("Umdrehung++\n\r",14); //Auch dieses TOPEREIGNISS wird natürlich weitererzählt
zaehler = 0; }
if(umdrehung>=4) //wenn sie sich denn 4 mal gedreht haben
{
MotorSpeed(0,0);
for(zeit=0;zeit<4000;zeit++) //Vier Sekunden stillstand
{
Sleep(36);
}
umdrehung = 0;
SerWrite ("Das waren 4 Umdrehungen!\n\r",26);
}
}
while(1)
return 0;
}

Nur ein paar Fehler:

-Zwischen dem Einlesen der alten und neuen Werte funktioniert die Zeitschleife nicht, weil du auf "durchlauf>=1000" prüfst. Wenn die Verzögerung funktionieren sollte, was sollte sie bewirken? Alter Wert einlesen-eine Sekunde warten während das Rad lustig weiterdreht-Überprüfen, ob sich der Wert geändert hat? Wenn er sich nicht geändert hätte, würde mich das sehr wundern!

-Du sendest immer noch während der Fahrt.

-Du kümmerst dich nicht um Hell oder Dunkel, du zählst einfach nur die Unterschiede.

Das sind auf den ersten Blick die gröbsten Dinge. Lies dir mal diesen Codescheiben-Thread (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=27081) durch und führe das Messprogramm (den Datenlogger (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=247898#247898)) aus, dass in diesem Thread angeboten wird. Dann bekommst du vielleicht ein Gefühl für die Odometrie und ihre Tücken.

Gruß

mic

Roboaktiv
07.07.2007, 14:54
Wenn du durch Einrückungen deinen Code etwas struckturierst wird dir vielleicht auch klar, dass du nur eine einzige Schleife hast:


Struktoriert hab ich das eigendlich. Es ist halt nur das Problem, dass ich diese Struckturen nicht in das Forum kopieren kann. was ist eigendlich so schlimm an nur ener Schleife?


Nur ein paar Fehler:

-Zwischen dem Einlesen der alten und neuen Werte funktioniert die Zeitschleife nicht, weil du auf "durchlauf>=1000" prüfst. Wenn die Verzögerung funktionieren sollte, was sollte sie bewirken? Alter Wert einlesen-eine Sekunde warten während das Rad lustig weiterdreht-Überprüfen, ob sich der Wert geändert hat? Wenn er sich nicht geändert hätte, würde mich das sehr wundern!

Ich hab mr gedacht, wenn die Werte direkt hintereinander kommen sind sie vielleicht nochidentisch und deshalb soll da noch nen bisschen Pause sein.


-Du sendest immer noch während der Fahrt.
[quote="radbruch"]
Sorry, das hab ich oben einfach überlesen.
[quote=radbruch]
-Du kümmerst dich nicht um Hell oder Dunkel, du zählst einfach nur die Unterschiede.

Reicht das nicht?


Das sind auf den ersten Blick die gröbsten Dinge. Lies dir mal diesen Codescheiben-Thread (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=27081) durch und führe das Messprogramm (den Datenlogger (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=247898#247898)) aus, dass in diesem Thread angeboten wird. Dann bekommst du vielleicht ein Gefühl für die Odometrie und ihre Tücken.

Hab ich und es war sehr informativ alledings konnt ich irgendwie die Anhänge nicht öffnen.

Ich hab aus deinem letzten Berricht irgendwie entschlüsselt, dass ich dich einwenig nerve. Wenn ich damit recht hab tut mir das Leid. Vielleicht stell ich mich auch einfach zu blöd an.
Du sollst dich auch nicht verpflchtet fühlen mir zu antworten auch wenn ich dich drumm bitte!

Gruß Roboaktiv

Roboaktiv
21.07.2007, 00:23
Hallo Damaltor,
ich habe bemerkt, dass du so ab dem 3.7 nicht mehr online warst. In letzter Zeit hatte ich ich auch keine Zeit dazu. Jetzt hab ich bemerkt, dass du wieder öffter da bist. Es sind alllerdings die obengestellten Fragen noch offen.

Hier sind sie nochmal:
Das was du da oben geschrieben hast hab ich verstanden. Aber woher weiß ich jetzt welches Register zu welchem Pin gehört.

Auch nicht verstanden hab ich die Geschichte vom Motor. Da gibt es ja so ne Pulsweitende-Funktion oder so ähnlich. Außerdem gibt es da ja 3 Pins pro Motor (z.B. für den linken Motor: PD4(XCK/T0) PD5(T1) PB1(OC1A)). Und was soll das jetzt??

Allerdings hab ich auch gelesen, dass du z.Z. nurnoch an der FH online gehen kannst. Wenn dir da irgendwie die Zeit fehlt, dich mit mir zu "unterhalten" hab ich dafür auch Verständnis.

Gruß

Roboativ

damaltor
21.07.2007, 10:47
hmm ok.
ich werde es versucchen.

(fast) immer 8 prozessorpins sind zu einem port zusammengefasst. jeder port hat einen großbuchstaben.
PD4 bedeutet vierter pin vom port D.

für jeden port gibt es drei register, in denen jeweils 8 bit gespeichert werden. sinnvollerweise steht immer das nullte bit für den nullten pin, das erste bit für den ersten usw. bis zum siebten bit für den siebten pin. es gibt (zumindest rein auf informatischer ebene =) weder ein achtes bit noch einen achten port =)

als beispiel nehme ich port D, für alle anderen ports muss nur jeweils der großbuchstabe geändert werden.
die drei register heissen
DDRA,DDRB,DDRC,DDRD für die RICHTUNG
-für jedes bit gilt, 1=ausgang,0=eingang
PORTA,PORTB,PORTC,PORTD für den ausgangspegel oder die pullups(später)
1=strom an, 0 = aus ODER 1=pullup an, 0=aus
PINA,PINB,PINC,PIND für das eingangssignal.
1 gelesen = strom von aussen ist an, 0=aus

wenn ich also PD2 zum beispiel einschalten möchte, dass 5v spannung ausgegeben werden, muss ich
zuerst in das richtungsregister an die entsprechende stelle eine 1 schreiben. damit die anderen bits nicht verändert werden, wird das ganze mit einer ODER-bedingung verknüpft.
damit man nicht immer alle bitwerte in hex-zahlen umrechnen muss (was aber durchaus möglich ist) wird einfach nur eine 1 verschoben, wie recht weit obern geschrieben mit dem << - operator.
für pd2:
DDRD |= (1<<2);

also im register DDRD wird das zweite bit gesetzt. der pin ist jetzt ein ausgang.

jetzt wllen wir strom anlegen, dafür ist das register PORTD da. hier muss eine 1 gesetzt werden zum einschalten oder eine null zum ausschalten. aber um eine null zu setzen, muss man umdenken: man verschiebt eine 1 an die entsorechende stelle, (00000100) invertiert das ganze mit dem ~ operator (11111011) und verknüpft das ganze mit dem und-operator.
PORTD |= (1<<2); //eingeschaltet
PORTD &= ~(1<<2); //ausgeschaltet.

damit kannst du zb schon leds anschalten usw, du kannst ja einfach im schaltplan rausfinden an welchem pin die jeweilige led angeschlossen ist.

um einen pin als eingang zu nutzen, zb um einen taster auszulesen, muss der taster gegen masse an den pin angeschlossen werden.
also GND --- taster --- atmega
dann schaltest du dein pin auf eingang:
DDRD &= ~(1<<2);
und den pullup-widerstand ein. das ist nötig um festzuegen dass der pin solange high ist bis der taster gedrückt wird.
PORTD |= (1<<2); //das gleiche register wie für den ausgangpegel, aber hier für den pullupverwenndet
wenn du jetzt wissen willst ob der taster gedrückt wurde, mach folgendes

unsigned char test;
test = PIND & (1<<2);

wenn test >0 ist, dann wurde die taste NICHT gedrückt, wenn test gleich null ist, wurde die taste gedrückt.

für die pwm hab ich grade keine zeit, evtl später mal.

frag wenn du was nicht verstanden hast =)

Roboaktiv
22.07.2007, 19:03
Hallo
erstmal danke, dass du dir Zeit für mich genommen hast!
Jetzt die Fragen:
Im 4. Absatz von oben hast du die Geschichte mit DDRD(Hier hast du mal Großbuchstaben verwendet!!!!:-)) und co erklärt. Warum nimmt man da das? Und das mit der Richtung hab ich auch nicht verstanden.

Im 5. Absatz von unten hast du geschrieben:"muss der Taster gegen masse (meinst du da masse oder maße?) an den pin angeschlossen werden" außerdem habe ich das mit dem pullup-widerstand nicht verstanden.

Den Rest hab ich ohne Probleme verstanden. Danke schön.

Gruß Roboaktiv

PS: Lass dich nicht von mr stressen! Im Grunde bin ich eigendlich sehr geduldig:-).

damaltor
22.07.2007, 19:29
allgemeine erklärungen zu abkürzungen:
VCC = BEtriebsspannung = plus 5V = Pluspol der batterie = logisch 1 = HIGH
GND = Masse = 0V = Minuspol der batterie = logisch 0 = LOW

also die ganzen abkürzungen (DDRxPORTx,PINx usw) sind die namen der register, in die man schreiben will.

DDRx ist das richtungsreigister. wenn hier eine 1 an z.B. die 2te stelle geschrieben wird, ist der 2. Pin vom Port x (zu ersetzen durch A,B,C oder D) ein ausgang. man kann dann mithilfe von PORTx entweder VCC oder GND, also 5V oder 0V, an diesem pin ausgeben. damit leuchtet zB eine LED wenn 5V angegeben sind, und eben nicht, wenn 0V angegeben sind.

wird in DDRD eine null geschrieben, dann ist der entsprechende pin ein Eingang. man kann also mithilfe des registers PINx herausfinden, ob von aussen strom an den pin geleitet wird, oder ob der pin von aussen mit der masse verbunden wurde.
Wenn jedoch der pin WEDER mit etwa 5v, NOCH mit der masse verbunden ist, ist er in einem sogenannten undefinierten zusatnd. dieser fall sollte eigentlich nach möglichkeit vermieden werden, da es dann absoluter zufall ist, ob der prozessor nun denkt ob 5V oder Masse(GND, 0V) anliegen.

nun stell dir mal vor, du würdest den taster einfach so an den pin anschliessen, und den anderen pol des tasters an die Masse (!). solange der taster nicht gedrückt ist, wäre der pin in einem undefinierten zustand (er ist ja weder mit masse noch mit VCC verbunden). man könnte alo nicht rausfinden, ob er gedrückt ist oder nicht - das ergebnis wäre zufällig, wenn er nicht gedrückt wäre, und null, wenn man ihn drückt. das hilft im allgemeinen nicht besonders bei der programmentwicklung, da man sich auf das ergebnis nicht verlassen kann.
jetzt stell dir mal die folgende konstruktion vor:

Masse --- Taster --- Prozessorport --- Widerstand --- VCC

wobei eben sowohl eine seite des tasters als auch der widerstand mit dem prozessor verbunden sind.

ist der taster nicht gedrückt, wird strom über den widerstand an den prozessorport gegeben. der prozessor meldet also bei einer entsprechenden abfrage ganz sicher eine 1 - schliesslich liegt ja strom an.
wird der taster gedrückt, fliesst der ganze strom richtung masse ab, der prozessor meldet also eine null für taster wurde gedrückt, da kaum strom bei ihm ankommt.

(einen solchen widerstand nennt man pullup-widerstand, da er den prozessorpin bei nicht gedrücktem schalter auf VCC "zieht".
im gegensatz dazu gibt es übrigens auch pulldown-widerstände, diese sind mit masse verbunden und ziehen den pin immer auf GND. der atmega8 hat jedoch solche nicht, und deshalb ist das nur eine nebenbei-info die nix mit dem eigentlichen thema zu tun hat. =) )

damit man jedoch nicht für jeden taster, oder ähnliches, den man verwenden will, einen eigenen widerstand auf die platine löten muss, hat der atmega eingebaute pullup-widerstände. diese lassen sich aktivieren oder deaktivieren.

wenn das richtungsregister DDRx (heisst übrigens "Data Direction Register") auf Eingang geschaltet ist, kann man mithilfe des dateneingangsregisters PINx ja den wert null oder eins auslesen, wie oben beschrieben. der datenausgangsregister PORTx wird also nicht benötigt, da er ja nur dafür da ist den spannungspegel zu definieren, der am entsprechenden pin ausgegeben werden soll - und der pin ist ja jetzt ein eingang. also wird der (oder das) register "missbraucht": schreibt man eine eins an die entsprechende stelle, werden intern pullup-widerstände aktiviert - man liest also mit PINx immer eine eins, bis der pin manuell, zum beispiel mithilfe eines tasters, auf GND gezogen wurde. dadurch wird also vermieden, dass der pin in einem undefinierten zustand ist.

Mr.Roboto
23.07.2007, 11:21
Also ich hab gestern auch diese tolle Erfahrung mit der IF-Anweisung gemacht, scheibar hat der Asuro Probleme berechnungn in der Klammer (Wahrheitsprüfung) zu machen, deswegen das Ergebnis der Berechnung vorher in eine seperate Variable speichern und diese dann in der If-Anweisung prüfen.

damaltor
23.07.2007, 11:30
nein, rechner kann der asuro sehr exakt. aber wenn du deinen programmcode herzeigst, können wir ja mal nach fehlern suchen...

oder wenn du die taster meinst, diese haben einen anderen grund für ihre ehleranfälligkeit. die sind nämlich nicht einzeln am prozessor, sondern hängen alle an einem pin, und benutzen verschiedene (qualitativ schlechte) widerstände.

Roboaktiv
23.07.2007, 12:30
Mit dem letzten Absatz ob hast du mich einwenig verwirrt.

Ich dachte immer, dass man erstmal mit dem DDR x und der |=(1<<x)-Geschichte definiert, dass ein Pin ein Eingang ist.
Mit dem Port x und der gleichen Geschichte wird z.B. eine LED eingeschaltet.
Und diese jetzt wieder aus zu schalten nimmt man die Portx &= ~(1<<x) Geschichte.

Das ganze als Ausgang:
abfrage=Portx &= ~ (1<<x)
if(abfrage=0)//dann ist der z.B. Taster nicht gedrückt

Stimmt das so?

Und wozu benötigt man jetzt die Pinx-Geschichte?

Gruß Roboaktiv

PS: Ich glaub das heißt DAS Register

damaltor
23.07.2007, 13:26
fast richtig.

mit PORTx werden werte ausgegeben, oder die pullups werden eingestellt.
mit PINx wird der aktuelle status des tasters gelesen.

nehmen wir an, du hast folgende schaltung(eigentlich brauchen leds einen vorwiderstand, den lasse ich jetzt hier weg):

Prozessor --- LED --- GND am PD2, also port d, pin 2

zuerst schalten wir den pin auf ausgangsrichtung:
DDRD |= (1<<2);
dan schalten wir den pin auf HIGH, um die led einzuschalten:
PORTD |= (1<<2);
Die led leuchtet jetzt. wir wollen sie wieder ausschalten:
PORTD &= ~(1<<2);
jetzt ist sie wieder aus.

nun benutzen wir folgende schaltung am gleichen pin:
Prozessor --- Taster --- GND

zuerst schalten wir den pin auf eingang:
DDRD &= ~(1<<2);

Dann schalten wir den Pullup-widerstand ein:
PORTD |= (1<<2);
damit wurde das PORTx-register verwendet, welches normalerweise zum ausgeben eines pegels verwendet wurde.

jetzt wollen wir den status des tasters einlesen:
abfrage = PIND & (1<<2);

zuer erklärung: zuerst wird PIND eingelesen, es wird je nach den angelegten spannungen zB 01001101 sein. dann wird dieser wert mit & mit dem wert 00000100 verknüpft, also werden alle bits ausser dem an stelle 2 auf null gesetzt, weil ja nur dieser eine interessant ist.

wenn der taster nicht gedrückt wurde, ist der pin auf HIGH-pegel, da er ja über den pullup-widerstand mit VCC verbunden ist. folglich hat die abfrage jetzt den wert 00000100, also 4. alle werte ungleich null gelten als "WAHR"

wenn der taster gedrückt ist, dann ist der pegel am pin LOW. die variable abfrage hat jetzt den wert 00000000, also 0. der wert null gilt als "FALSCH".

folgendes programm wäre möglich, wenn du einen taster zur hand hast und den entsprechend anschliesst:

unsigned char abfrage;
DDRD &= ~(1<<2); //als eingang wählen
PORTD |= (1<<2); //pullups aktivieren
while(1){ //endlosschleife
abfrage = PIND & (1<<2); //abfrage durchführen
if(abfrage){ //wenn abfrage nicht null, also WAHR ist
SerWrite("Taster nicht gedrückt\n\r",23); //dann text ausgeben
} //ende if
else{ //wenn abfrage =0 also FALSCH
SerWrite("Taster gedrückt\n\r",17); //dann text ausgebeb
} //ende else
} //ende while

zusammenfassung:
DDRx : bestimmt, ob ein pin eingang (1) oder ausgang(0) ist
PORTx : bestimmt bei ausgängen, ob HIGH (1)oder LOW (0) ausgegeben wird, und bei eingängen pb die pullup-widerstände verwendet werden sollen(1) oder nicht(0).
PINx : enthält den aktuellen wert des von aussen angelegten spannung, (1) für 5V, (0) für GND

Roboaktiv
23.07.2007, 16:39
Ah! Jetzt hab ich es verstanden und fühle mch schon viel schlauer! Danke schön!

Beim ASURO kann man diese Art der pullup-Geschichte doch nur für die Taster verwenden oder?

Bei der Status LED(PD2(zweiter Pin im Port D),PB0(erster Pin im Port B)) muss man doch nur jenach Farbe einen von den beiden Pins ansteuern und wenn man diesen Orange Ton haben will beide.
Bei der Verbindung zu PD2 steht an der LED "rd" ist das Rot?
Und bei der Verbindung zu PB0 steht an der LED "gn" scheint Grün zu sein oder?

Also für Grün:

DDRB |= (1<<1); //als Ausgang wählen
PORTB |=(1<<1); //einschalten
PORTB &=~(1<<1);//ausschalten

Für Rot die ganze mit DDRD und PORTD
und für dieses Orange mit beiden.

War das so jetzt richtig?

Im meinem ASUROBUCH steht, dass man für die PWM-Geschichte(Geschichte ist vermutlich mein neues Lieblingswort gewöhn dich schonmal daran) nen Register namens TCCR1A, TCCR1B benötigt aber welchen dieser 3 Pins pro Motor soll man jetzt ansteuern?

Die PWM-Geschichte :-) brauchst du mir nur erklären, wenn ich die LED-Geschichte richtig aufgeschrieben habe.

Gruß Roboaktiv

PS: Die PWM-Geschichte scheint relativ kompliziert zu sein wenn du dazu keine Zeit hast kannst du sie mir auch dann erklären, wenn du Zeit hast.

damaltor
23.07.2007, 16:58
der pin PB0 ist nicht der erste, sondern der nullte pin. deshalb musst du sozusagen die 1 um null stellen verschieben: (1<<0).

übrigens, wenn du die verschieberei sparen willst, geht auch folgendes:

(1<<0) = 1
(1<<1) = 2
(1<<2) = 4
(1<<3) = 8
(1<<4) = 16
(1<<5) = 32
(1<<6) = 64
(1<<7) = 128

du kannst also zum wählen von PD2 als ausgang folgendes schreiben:
DDRD |= 4;

in deinem programm musst du für die led PB0 nehmen, NICHT PB1!!

rd und gn hast du richtig bemerkt.

pwms sind schwieriger, das mache ich in 2 wochen wenn ich selbst wieder internet zuhause habe.

damaltor
23.07.2007, 17:13
pullupwiderstände kann man übrigens nutzen, wie man will - sind sie aktiviert, ist der pin über einen widerstand mit VCC verbunden.

Roboaktiv
24.07.2007, 09:16
pwms sind schwieriger, das mache ich in 2 wochen wenn ich selbst wieder internet zuhause habe.
OK. Dann melde dich dann solange versuche ich mal die Programmierung mit den Registern soweit das möglich ist. Wie funktioniert das eigendelich mit den Lichtsensoren? Ist das auch so kompliziert? Kann man da auch nur kuchen, ob das Licht an oder aus ist? Aber ich glaube, dass das noch kompliezierter ist als PWM.

Wie schon gesagt:
Lass dich von mir nicht stressen

Gruß
Roboaktiv

damaltor
24.07.2007, 18:13
die sind etwas anders. über einige einstellungen kann man wählen, dass der spannungspegel der ankommt umgerechnet wird. je nach helligkeit ist der widerstand der sensoren größer oder kleiner, und es kommt mehr oder weniger spannung am prozessor an. diesen spannungswert kann man in einen wert von 0 (masse) bis 1023 (+5V) umrechnen. aber dafür müssen auch einige register konfiguriert werden, muss mal nachsehen welche... =)

Roboaktiv
27.07.2007, 10:55
Ich würde vorschlagen, dass wir erst die Liniensensoren nehmen, denn weiter oben hab ich mich schon mit den Radsensoren schwergetan. :-)
Also der Pin für den Linken Fototransistor: PC3 Dritter Pin im Register C
" " " " Rechten " : PC1 Erster " " " "
Im Asuro-Buch steht, dass man für die A/D-Wandlung ADCSRA, ADMUX, ADCL und ADCH benötigt.
Geht das vielleicht dann so?:

//Die Geschicht ist jetzt für den Linken Fototransistor:
unsigned int abfrageL, abfrageR;
DDRC &=~(1<<3);
abfrageL=ADCH&(1<<3);
//Die Geschicht ist jetzt für den Rechten Fototransistor:
DDRC &=~(1<<1);
abfrageR=ADCH&(1<<1);
if(abfrageL>abfrageR)
...

Aber wofür sind dann die anderen Regster da?

Gruß Roboaktiv

damaltor
29.07.2007, 20:01
hrhr... nein leider nicht ganz so einfach. das kan ich dir aber erst nächste woche erklären, denn ich warte noch immer auf mein internet.

mithilfe der vier register die du genannt hast, wird ausgewählt welcher der analog-digitalkonverter verwendet wird, und es wird die umwandlung gesteuert. das ist eben nicht ganz so einfach.

Roboaktiv
31.07.2007, 12:39
Schade mit dem Programm!

Ansonsten melde dich dann wenn du ein funktionsfähiges Internet hast.

Gruß Roboaktiv

Roboaktiv
30.08.2007, 20:35
Oh!!!!

Ich habe gerade vernommen, dass dein Internet wieder nicht geht. Das tut mir irgendwie leid!!!

Ich weiß nicht, ob es in Jena so was gibt, aber ich hab mal irgendwo gelesen, dass es einen DSL-Anschluss ohne Telekom-Anschluss gibt. Vielleicht wäre das eine Alternative.

Aber genaueres weiß ich darüber auch nicht. Das war halt nur aufzeigen der Optionen und Stressmache an Telekom. Ansonsten halt ich mich lieber aus so verträglichen Angelegenheiten raus.

Ansonsten wünsche ich dir immer noch viel Erfolg!

damaltor
31.08.2007, 12:52
die idee hatte ich auch schon- aber bei mir sind die leitungen gerade neu verlegt, und die telekom will erstmal selbst kunden abfassen - also verkauft sie keine leitungen an die fremdanbieter.

Roboaktiv
15.09.2007, 17:18
Hallo!
Ich habe aus dem Telekom-Läster-Bereich irgendwo entnommen, dass die Internet jetzt wieder läuft.
Stimmt das?
Wenn ja: Wie geht das jetzt mit der PWM?
Wenn nein: Ich hoffe das beste für dich und dein Internet. Lass dich durch mich nicht aus der Ruhe bringen.

damaltor
16.09.2007, 16:55
mein internet funktioniert wieder, aber ich bin grade nicht heim.

ich melde mich aber die woche wieder. =)

Roboaktiv
01.11.2007, 11:21
Hallo (mal wieder),
leider hatte ich in den letzten Monaten sehr viel zu tun (Schule und so), und deshalb war ich nur sehr selten hier. Jetzt hab ich ein langes Wochenende :-) und wollt meinem Asuro nach langer Zeit mal wieder Leben einhauchen.

Da mein nächster Punkt jetzt diese PWM ist, möchte ich dich bitten mir das mal zu erklären. Sofern du auch dazu Zeit und Lust hast.

damaltor
02.11.2007, 02:13
hm ich hoffe dass ich dazu am wochenende zeit finde, muss mich selbst mal wieder reinlesen.

das prinzip PWM hast du verstanden? oder soll ich das auch erklären, also was eine PWM ist, wie sie funktioneirt usw?

Roboaktiv
02.11.2007, 17:52
Wenn du diese Diagramme meinst mit dem An/Aus-Kurven, die unterschiedlich oft an bzw. aus sind, ja.

Ich hab mir überlegt, dass das vielleicht mit dem Quarz zusammenhängen könnte. Das man irgendwie den Takt abfragt und daraus dann den Motor ansteuert.

Die Pins für den Quarz sind PB6 (XTAL1) und PB(XTAL2).

Wenn du keine Zeit findest ist auch nicht schlimm.

Danke schonmal!

damaltor
02.11.2007, 18:24
ok. mal ein kurzes allgemeines bild: H=high, L=low. eine taktperiode sind 10 zeichen. bei gleicher frequenz also:

LLLLLLLLLHLLLLLLLLLHLLLLLLLLLH -> 10 prozent der leistung, 1/10 der periodendauer ist der port HIGH.
LLLLHHHHHHLLLLHHHHHHLLLLHHHHHH -> 60% leistung, 60% der zeit ist der pin high.

dabei bleibt wie gesagt die frequenz gleich.

die ganze arbeit dahinter, also aus dem prozessortakt einen takt für die pwm zu errechnen, und die passende zeit high und low zu schalten, kann der prozessor schon in hardware, also muss nicht zwingend viel programmiert werden.
ich warte ja auf sternthaler, dass er wieder eine große und gute erklärung schreibt, weil ich kaum zeit hab. ;) aber ich versuche es... kann nur noch etwas dauern... =)

Roboaktiv
03.11.2007, 13:39
Das mit den Zeitproblemen kenn ich.



Wie schon gesagt:
Lass dich von mir nicht stressen


Das gilt immer noch.

Die guten Erklärungen von Sterntaler kenn ich auch. Die sind echt gut! =D>

Aber das mit der PWM allgemein hab ich verstanden.

damaltor
03.11.2007, 23:45
stäääääääärnthaler... *ruf* :)