Forum: Mikrocontroller und Digitale Elektronik Roboter-Linienverfolgung mit P-Regler und Ausweichmodus


von Brocken Sei (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe nun mein Programm soweit, dass es prinzipiell funktionieren 
sollte, ich lann es aber leider nicht austesten, da einige der 
Hardwareteile noch nicht da sind.
Deswegen bitte ich euch das einmal anzusehen und eure Meinung zu sagen 
oder mir zu sagen ob es eventuell jetzt schon Bugs in meinem Programm zu 
erkennen sind, die ich übersehen habe.

Eins noch: Der Ausweichmodus wurde noch nicht programmiert. Es geht ums 
Prinzip und um eventuelle Fehler die jetzt schon drinnen sind.

Danke schon im Voraus.

Gruß Bro

von holger (Gast)


Lesenswert?

>Deswegen bitte ich euch das einmal anzusehen und eure Meinung zu sagen
>oder mir zu sagen ob es eventuell jetzt schon Bugs in meinem Programm zu
>erkennen sind, die ich übersehen habe.

Programmteile in eine Header Datei zu legen ist schon mal
grundsätzlich falsch.

von Karl H. (kbuchegg)


Lesenswert?

Zur Coding Technik

Welchen Sinn soll es haben, alle Unterprogramme in ein Header File zu 
quetschen. So ist das nicht gedacht!
In einem Header File stehen die Funktionsprototypen und was sonst noch 
so ein Verwender wissen muss. Der eigentliche Quellcode der Funktionen, 
solange er nicht geinlined werden soll, steht immer in *.c Files
http://www.mikrocontroller.net/articles/FAQ#Ich_hab_da_mehrere_.2A.c_und_.2A.h_Dateien._Was_mache_ich_damit.3F

1
//Starte Ultraschall:
2
extern inline void ultraschall_StarteMessungSRF05(volatile uint8_t *Port, volatile uint8_t TriggerPulse_PIN, volatile uint8_t delayTime_tillSTART_us)
3
{
4
  *Port |= (1<<TriggerPulse_PIN);
5
  _delay_us(delayTime_tillSTART_us);
6
  *Port &=~ (1<<TriggerPulse_PIN);
7
}
Das ist zwar jetzt wahrscheinlich nicht wirklich wichtig, aber das
  _delay_us(delayTime_tillSTART_us);
geht gar nicht.
Die _delay_xx Funktionen können nur mit konstanten Zahlenwerten benutzt 
werden. Ansonsten stimmen die Zeiten nicht.

1
//MesseLinie***************************************************
2
extern uint16_t messeSollwert()
3
{
4
  uint16_t sollwert;
5
    /*Sollwert messen:*/
6
        sollwert = GetADC_8bit(2);
7
  lcd_setcursor(0, 1);
8
  lcd_string("Sollwert = "); lcd_string(itoa(sollwert, buffer, 15)); //Zeige Messwert an
Du willst wirklich eine Zahlenausgabe im Zahlensystem zur Basis 15?
itoa macht dir das schon, nur ist es .... ungewöhnlich.


Weiter hab ich noch nicht geschaut

von Gregor (Gast)


Lesenswert?

P-Regler... ich stells mir grad schon vor wie das ding zittert...

So wie ich das seh hast du 3 Sensoren, die du alle per ADC abfragst, 
dann bildet du aber einen Mittelwert! Du hast also den verwertbaren 
Informationsgehalt tatsächlich gedrittelt!!!!

Bei sowas würd ich ein ganz anderen Ansatz verwenden:
Neuronales Netz: 3 Eingang-Nodes (deine 3 Sensoren) 2 Ausgangs-Nodes 
(Die Motoren) Keine Zwischenebene erforderlich! Jetzt kann man 
wunderschön die 6 Verbindungen gewichten und siehe da man hat ein 
wunderbaren Linienverfolger!

von Brocken Sei (Gast)


Lesenswert?

holger schrieb:
> Programmteile in eine Header Datei zu legen ist schon mal
> grundsätzlich falsch.

Wenn ich sie im Hauptprogramm anlege, dann wird das ganze 
unübersichtlich.
Und wenn ich sie am ende als *. inkludiere, da wurde mir gesagt dass man 
*.c Datein nicht inkludieren sollte.

Was habe ich denn sonst für alternativen?

von Karl H. (kbuchegg)


Lesenswert?

Brocken Sei schrieb:
> holger schrieb:
>> Programmteile in eine Header Datei zu legen ist schon mal
>> grundsätzlich falsch.
>
> Wenn ich sie im Hauptprogramm anlege, dann wird das ganze
> unübersichtlich.
> Und wenn ich sie am ende als *. inkludiere, da wurde mir gesagt dass man
> *.c Datein nicht inkludieren sollte.
>
> Was habe ich denn sonst für alternativen?



main.c
*******
1
#include "lcd.h"
2
3
int main()
4
{
5
  lcd_init();
6
7
  ....
8
}

lcd.h
*****
1
#ifndef LCD_H
2
#define LCD_H
3
4
void lcd_init( void );
5
6
#endif

lcd.c
*****
1
#include "lcd.h"
2
3
void lcd_init()
4
{
5
  hier die Imlpementierung von lcd_init
6
}


main.c und lcd.c werden im AVR-Studio unter Source Files hinzugefügt. 
lcd.h wird unter Header Files hinzugefügt.

Compilieren:
lcd.c wird compiliert
main.c wird compiliert

Linken:
lcd.o und main.o werden zum kompletten brennbaren Programm 
zusammengelinkt.

Um Compilieren bzw. Linken brauchst du dich nicht kümmern. Dadurch dass 
man die einzelnen Dateien im AVR-Studio zum Projekt hinzugefügt hat, 
weiß AVR-Studio schon, was es zu machen hat.

Bei Änderungen in main.c wird nur, und tatsächlich nur, main.c neu 
compiliert. Bei Änderungen in lcd.c wird nur, und tatsächlich nur, lcd.c 
neu compiliert und ein neues Programm gelinkt.


(Sinngenmäß natürlich für alle anderen Funktionen genauso. Aufgeteilt 
nach Themenkreisen, d.h. alle LCD Funktionen in 1 Header File bzw 1 
C-File. Für andere Themenkreise genauso. Und natürlich überall alle 
anderen includes die dort noch gebraucht werden. So wird lcd.c natürlich 
auch avr/io.h includieren.)

Aber speziell die LCD Routinen sind im Tutorial bereits nach Header File 
und Source Code File entsprechend aufgeteilt gewesen.

von Karl H. (kbuchegg)


Lesenswert?

y und differenz sind beides unsigned long und werden in main und der ISR 
verwendet.
Auf der Suche nach atomarer Absicherung beim Zugriff: Fehlanzeige

von Karl H. (kbuchegg)


Lesenswert?

Damit bin ich konzeptionell nicht einverstanden
1
      summe = (sensorL1 - sensorR0) + sollwert;  //sensorL1 - sensorR0 ergibt einen Bereich von -235 ... +235 und
2
                            //addiert mit 235 einen bereich von 0 ... 570 (für PID Algo)
3
                            //und Sollwert ist dann genau in der Mitte, da sensorM = sollwert
4
5
      if((summe > (sollwert - 5)) && (summe < (sollwert + 5)))  //Wenn Sollwert, dann Motoren beide voll
6
      {
7
        PWMleft = ON;
8
        PWMright = ON;
9
      }
10
      else if(summe < (sollwert - 5)) //ansonsten mehr links
11
      {
12
        differenz = (summe - sollwert) * (-1); //errechne Abweichung
13
        PWMright += y;   //PWM-Wert für Motor rechts
14
        PWMleft = OFF;  //MotorRechts = 0
15
      }
16
      else if (summe > (sollwert + 5)) //oder mehr rechts
17
      {
18
        differenz = summe - sollwert; //errechne Abweichung
19
        PWMleft += y;   //PWM-Wert für Motor links
20
        PWMright = OFF;  //MotorRechts = 0
21
      }



      summe = (sensorL1 - sensorR0) + sollwert;  //sensorL1 - sensorR0

wenn du das einfach signed rechnen würdest, würde isch deine Summe auch 
im signed Bereich bewegen. Kein Grund da mit offsets rumzumachen.



      if((summe > (sollwert - 5)) && (summe < (sollwert + 5)))  //Wenn 
Sollwert, dann Motoren beide voll

Ob du Gas geben kannst sagt dir der Regler und nicht die Sensoren


      else if(summe < (sollwert - 5)) //ansonsten mehr links
      ....
      else if (summe > (sollwert + 5)) //oder mehr rechts
      ....

Ob es links rum oder rechts rum geht, sagt dir der Regler mit seinem y 
und nicht die Sensorwerte.
Wenn du schon einen Regler hast, dann musst du den auch machen lassen! 
Entweder der Regler hat das Kommando oder er hat es nicht. WEnn er es 
aber hat, dann muss er es vollständig haben.

So in etwa
1
      if( y > -5 && y < 5 )
2
      {
3
         PWMleft = FullSpeed;
4
         PWMRight = FullSpeed;
5
      }
6
7
      else
8
      {
9
         PWMleft  = HalfSpeed + y;
10
         PWMRight = HalfSpeed - y;
11
      }

Aufgabe des PID Reglers ist es, dir ein y zu geben, so dass dein Wert 
Summe möglichst bei 0 (dem Sollwert) bleibt.
(Ob man jetzt y links oder rechts addiert musst du im einfachsten Fall 
einfach ausprobieren. Zahlenwerte ausgeben lassen und ansehen!)

(Und das FullSpeed würde ich fürs erste beiseite legen. Erst muss der 
Regler funktionieren)

von Brocken Sei (Gast)


Lesenswert?

Also entschuldige, dass ich gerade nicht mit euch mitkomme, aber das mit 
den 2 c Files hat gerade mein ganzes Projekt zerstört.
Hab jetzt über15 Fehlermeldungen (die ich auch analysiere) und8 
Warnings.

Ist ziemlich schwer das zurecht zu biegen.

da hilft nicht einmal das
http://www.mikrocontroller.net/articles/FAQ#Ich_hab_da_mehrere_.2A.c_und_.2A.h_Dateien._Was_mache_ich_damit.3F
Habs schon gelesen, aber ihr kennt doch Eclipse, die IDE will manchmal 
nicht^^.

Danke für die Geduld!

Gruß Bro

von Simon K. (simon) Benutzerseite


Lesenswert?

Du kannst das Projekt ja mal anhängen. Ansonsten benutze ich seit Jahren 
AVR-Eclipse und habe jetzt noch nicht festgestellt, dass die manchmal 
"nicht will".

von Brocken Sei (Gast)


Angehängte Dateien:

Lesenswert?

So!, hab das jetzt so gelassen wie es war. Denn die Deklarationen und 
Definitionen von mir waren nicht falsch und funktioniert wird es nach 
reichlicher Überlegung genau so gut.
Anstatt mich jetzt 2 Stunden mit Files erstellen, kopieren, includes 
einfüge, bleibe ich lieber beim Thema.

Gregor schrieb:
> So wie ich das seh hast du 3 Sensoren, die du alle per ADC abfragst,
> dann bildet du aber einen Mittelwert! Du hast also den verwertbaren
> Informationsgehalt tatsächlich gedrittelt!!!!

Also ich nutze schon den gesamten Bereich aus, wo bilde ich da einen 
Mittelwert`?

Karl heinz Buchegger schrieb:
> Die _delay_xx Funktionen können nur mit konstanten Zahlenwerten benutzt
> werden. Ansonsten stimmen die Zeiten nicht.

ok danke Karl, daswär sicher ne Fehlerquelle!

Karl heinz Buchegger schrieb:
> y und differenz sind beides unsigned long und werden in main und der ISR
> verwendet.

ja

Karl heinz Buchegger schrieb:
> Auf der Suche nach atomarer Absicherung beim Zugriff: Fehlanzeige
Sry, kann dir nicht folgen.

Karl heinz Buchegger schrieb:
> wenn du das einfach signed rechnen würdest, würde isch deine Summe auch
> im signed Bereich bewegen. Kein Grund da mit offsets rumzumachen.

du sagtest doch, dass ich einen Wertebereich von
kleiner Wertigkeit ... großer Wertigkeit brauche, deswegen die 
Rechnerei.

Karl heinz Buchegger schrieb:
> Ob du Gas geben kannst sagt dir der Regler und nicht die Sensoren

ok, da hast du nicht unrecht, da hab ich übertrieben.

@Karl: Die Idee mit Full und Halfspeed find ich klasse, da wär ich nicht 
draufkommen meinen Code so kurz und effizient zu schreiben wie du.
Irgendwie enttäuschend, aber was solls, ich lerne ja daraus.
Habs so übernommen wenns dich nicht stört.

Frage noch: Stört die negative Differenz beim D-Anteil dann nicht?
-->(Kd*((differenz-ealt)/Ta))

Aktuelles Programm im Anhang

Grus Bro

von Karl H. (kbuchegg)


Lesenswert?

Brocken Sei schrieb:

> So!, hab das jetzt so gelassen wie es war.

Das gibt Punkteabzüge. Und zwar massenhaft.
Wie willst du was lernen, wenn du alles gleich liegen lässt, sobald du 
dich verlaufen hast.

Du hast das Chaos angerichtet, also sortier es wieder auseinander.

> Anstatt mich jetzt 2 Stunden mit Files erstellen, kopieren,
> includes einfüge

Geh komm.
LCD und UART waren doch schon richtig aufgeteilt!
Die sind in 5 Minuten wieder auseinanderkopiert, in Files abgelegt und 
dem Eclipse klar gemacht, dass die auch zum Projekt gehören. Und wenn 
alle Stricke reißen, holst du dir halt noch mal die Originale und 
konfigurierst sie noch mal.

>> wenn du das einfach signed rechnen würdest, würde isch deine Summe auch
>> im signed Bereich bewegen. Kein Grund da mit offsets rumzumachen.
>
> du sagtest doch, dass ich einen Wertebereich von
> kleiner Wertigkeit ... großer Wertigkeit brauche, deswegen die
> Rechnerei.

Was spricht gegen -256 .. +256

Ist ein perfekter Wertebereich von ganz links bis ganz rechts :-)

> Frage noch: Stört die negative Differenz beim D-Anteil dann nicht?
> -->(Kd*((differenz-ealt)/Ta))

Das Kd hat ja auch noch ein Vorzeichen :-)

von Floh (Gast)


Lesenswert?

Wird sowieso nicht auf Anhieb laufen.

Kenn das von meinen Kiddies, da wird ein "riesiges" Programm komplett 
geschrieben, ohne ein einziges Mal zwischendrin am Roboter zu testen. 
Ergebnis:
Die Kinder wissen nicht, wo sie bei der Fehlersuche anfangen sollen, da 
sie noch nicht mal getestet haben, ob der Motor mit ner positiven 
Geschwindigkeit auch nach vorne fährt.

Daher testen, testen, ...
:-)

von Brocken Sei (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Das gibt Punkteabzüge. Und zwar massenhaft.
> Wie willst du was lernen, wenn du alles gleich liegen lässt, sobald du
> dich verlaufen hast.

Verdammte scheiße, ich wusste es doch das sowas kommt, ich weiß ich 
weiß. Aber kaum beschäftige ich mich mit dem geht der Thread schon unter 
und ich muss mir wieder einen neuen Thread überlegen, langsam gehn mir 
die Titeln aus.

Karl heinz Buchegger schrieb:
> Das Kd hat ja auch noch ein Vorzeichen

stimmt, das gleichsts aus, aber Kd lege doch ich fest, könnte ja 
trotzdem sein, dass es Probleme gibt.

Also ich werd dann meine Files studieren und richtig stellen^^

Gruß Bro

von Brocken Sei (Gast)


Lesenswert?

Floh schrieb:
> Wird sowieso nicht auf Anhieb laufen.

Das ist klar, damit wäre bei keinem grßeren Projekt zu rechnen.

Floh schrieb:
> da wird ein "riesiges" Programm komplett
> geschrieben, ohne ein einziges Mal zwischendrin am Roboter zu testen.
> Ergebnis:

Nein nein, ich teste zwischendurch Sensorik und zeige auf Display an obs 
passt.

Floh schrieb:
> ob der Motor mit ner positiven
> Geschwindigkeit auch nach vorne fährt.

Tja also mein Motor fährt schon ohne dass ich ihm den Befehl gebe, den 
Fehler da zu finden ist zwar möglich aber nicht notwendig da ich die 
Hardware nicht aufkriege ohne sie zu beschädigen.
Daher arbeite ich gerade an einer neueren zuverlässigeren und stabileren 
Hardware.

Gruß Bro

von Karl H. (kbuchegg)


Lesenswert?

Brocken Sei schrieb:
> Karl heinz Buchegger schrieb:
>> Das gibt Punkteabzüge. Und zwar massenhaft.
>> Wie willst du was lernen, wenn du alles gleich liegen lässt, sobald du
>> dich verlaufen hast.
>
> Verdammte scheiße, ich wusste es doch das sowas kommt, ich weiß ich
> weiß. Aber kaum beschäftige ich mich mit dem geht der Thread schon unter
> und ich muss mir wieder einen neuen Thread überlegen, langsam gehn mir
> die Titeln aus.

D a n n   m a c h   d i e   D i n g e   g l e i c h    r i c h t i g  !

Ist ja nicht so, dass die Einzelteile die du dir aus dem Web 
zusammengesucht hattest, nicht dafür vorbereitet gewesen wären. Das hat 
schon seinen Grund, dass man überall ein Header File UND ein C-File 
bekommt. Das C-File kommt zum Projekt dazu und wird compiliert. Das 
Header File wird in meinem eigenen Source-File #includiert und 
informiert den Compiler, wenn er meinen Source Code compiliert, was im 
anderen (dem downgeloadeten) Source Code File enthalten ist, welche 
Funktionen es dort gibt, wie sie heissen und welche Argumente die 
Funktionen nehmen.

von Brocken Sei (Gast)


Angehängte Dateien:

Lesenswert?

holger schrieb:
> Programmteile in eine Header Datei zu legen ist schon mal
> grundsätzlich falsch.

Ok, habe es jetzt richtig gemacht.

Danke bis dahin!

Habe ich sonst wo Fehlerhafte Quellen drinnen?
Mich würde der Teil mit dem Ultraschall interessieren.
Den habe ich mir heute neu überlegt.
Ob da vielleicht noch ein Bug drinnt ist?


Gruß Bro

von Brocken Sei (Gast)


Lesenswert?

Eine Warnung kriege ich noch:

inline function 'ultraschall_StarteMessungSRF05' declared but never 
defined  Unterprogramme.h

definiert ist sie aber in Unterprogramme.c

Diese Meldung wird in Unterprogramme.h angezeigt.

Kann mir wer helfen?

Gruß Bro

von Simon K. (simon) Benutzerseite


Lesenswert?

Häng das Projekt an, wir können doch nicht hellsehen!

von Brocken Sei (Gast)


Angehängte Dateien:

Lesenswert?

Simon K. schrieb:
> Häng das Projekt an, wir können doch nicht hellsehen!

Hab gedacht die Files reichen, sry.
Gemacht!

Gruß Bro

von Karl H. (kbuchegg)


Lesenswert?

nimm das inline raus.
Wie soll den der Compiler inlinen, wenn er den Code nicht zur Verfügung 
hat?

von Simon K. (simon) Benutzerseite


Lesenswert?

Nimm das "inline" weg. "extern inline" macht AFAIK eh keinen Sinn. 
Inline solltest du erst mal meiden.

Übrigens gibt es noch eine Warnung, weil du die Optimierungen 
ausgestellt hat.

von Brocken Sei (Gast)


Lesenswert?

Ok, recht habt ihr, sehe es auch gerade.

Simon K. schrieb:
> Übrigens gibt es noch eine Warnung, weil du die Optimierungen
> ausgestellt hat.

Bei mir nicht, habs es auch eingeschalten.

Ok, danke allen hier.

Geh jetzt mal schlafen.

Nacht, Bro

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