PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Erste Arrayversuche



Spongebob85
04.11.2007, 16:07
Moin!
Ich habe folgendes problem:
Ich habe einen Servo der immer hin und her dreht. Auf diesen servo ist ein GP2D12 montiert. Jetzt möchte ich, das für jede Position des Servos (das sind insgesamt 51), ein ADC-Wert gespeichert wird. Später soll mein Roboter jenachdem wo der kleinste Wert liegt, eine kette vor und eine zurück bewegen, um da hinzulenken, weil beim kleinsten Wert ja das weiteste Hinderniss liegt. Hier sind ein paar auszüge aus meinem Code, wo man sieht wie ich das versucht habe:



uint16_t IR_Wert[51]; //Array für Messwerte 0-50

So habe ich das Array erstmal Global deklariert



ISR(ADC_vect)
{
if (changechannel<=0)
{
changechannel++;
ADMUX |= (1<<MUX0); //Eingang ADC1 vorbereiten für den IR-Sensor
LDR = ADC;
}
else
{
changechannel=0;
ADMUX &= ~(1<<MUX0); //Eingang ADC0 vorbereiten für LDR-Messung
IR_Wert[posi]=ADC;
}
}

Hier ist meine Interrupt routine in der unter anderem die GP2D12-Werte eingespeichert werden sollen. (posi ist meine Variable, die die position des Servos enthält also 0 bis 50)



void Motorsteuerung(int Hinderniss_info)
{
OCR0=60;
OCR2=60;

if(Hinderniss_info<=20)
{
PORTC |= (1<<Motor_Links_Rueck); //Roboter soll nach Links drehen
}
else
{
PORTC &= ~(1<<Motor_Links_Rueck); //Roboter soll aufhören nach links
//zu drehen
}

hier soll der Roboter anweisung bekommen sich nach lins zu drehen, wenn links frei ist.



int GP2D12(void)
{
uint8_t i, memoposi=0;
uint16_t memo=65535; //zum merken des kleinsten Wertes;
//65535=maxwert bei 16-Bit

for (i=0; i<=50; i++)
{
if (IR_Wert[i]<memo)
{
memoposi = i; //Zum merken der Servoposition, bei der der kleinste
//wert liegt
}
}
return (memoposi);
}

hier soll die funktion GP2D12 die Position des kleinsten wertes zurückgeben



int main(void)
{
Initial_ADC();
Initial_IR_Servo();
Initial_Motoren();
sei(); //Globales Interrupt gesetzt

while(1)
{
ADCSRA |= (1<<ADSC); //ADC-Messung soll immer wenn möglich aktiv sein

if (count)
{
count=0;
IR_Servo = IR_Servoposition();
Motorsteuerung(GP2D12());
helligkeitsmessung();
}
}
return 0; //wird nie erreicht
}

Meine Main Function. Der GP2D12 wert soll der Funktion Motorsteuerung übergeben werden, wo dann ja geregelt wird wo der Roboter hinfährt.

Hoffe ich hab nichts vergessen

Ach ja! Das Problem was ich habe ist, das die linke Kette dauerhaft rückwärts dreht. Ich hab keine Ahnung was schiefgelaufen sein kann. Is auch das erste mal wo ich mit Arrays arbeite.
Hoffe mir kann jemand helfen.

MfG Jan

robocat
04.11.2007, 20:07
in der for-schleife musst du memo einen neuen wert zuweisen:

if (IR_Wert[i]<memo)
{
memoposi = i; //Zum merken der Servoposition, bei der der kleinste
//wert liegt

memo=IR_Wert[i]; <------ fehlt

}

gruesse

Hubert.G
04.11.2007, 20:12
Wenn man den Fehler anhand der Code-Schnipsel erkennen könnte, hättest du ihn selbst wahrscheinlich als erster gefunden, da du den Zusammenhang kennst.

Spongebob85
04.11.2007, 21:15
@robocat:
Das stimmt natürlich. Hab das eben erstmal geändert.

Das mit dem schalten, fürs rückwärtsdrehen klappt jetzt.
Aber, wer hätte das gedacht, ich hab natürlich gleich noch ein Problem.
Die Motoren brummen nur und quälen sich voll rum, seitdem ich das Array programmiert hab. Hab das setzen vom ADSC-Bit auch vorher nicht in der Main-Funktion gehabt. Selbst wenn ich OCR0 und OCR2 den wert 150 gebe ändert sich nichts.
Ohne das Array laufen die Motoren ganz normal.
Hier is mein ganzer Code:


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

#ifndef F_CPU
#define F_CPU 16000000
#endif

#define Scheinwerfer PD0
#define Rueckleuchten PD1
#define PWM_ServoPort PD5
#define IR_Servo OCR1A
#define Motor_Links PB3
#define Motor_Rechts PD7
#define Motor_Links_Rueck PC0
#define Motor_Rechts_Rueck PC1

/*************************************Prototypes*** *************************************/
void helligkeitsmessung(void);
int IR_Servoposition(void);
void Motorsteuerung(int);
int GP2D12(void);
/************************************************** *************************************/

/**********************************Globale Variablen************************************/
uint8_t count=0, reward_time=0;
int8_t posi=25, a=1, changechannel=0;
uint16_t LDR;
uint16_t IR_Wert[51]; //Array für Messwerte 0-50
/************************************************** *************************************/

/**********************************Interruptroutine n************************************/

//--------------------------------------Timer1COMB--------------------------------------
ISR(TIMER1_COMPB_vect)
{
count++;
}

//-----------------------------------------ADC------------------------------------------
ISR(ADC_vect)
{
if (changechannel<=0)
{
changechannel++;
ADMUX |= (1<<MUX0); //Eingang ADC1 vorbereiten für den IR-Sensor
LDR = ADC;
}
else
{
changechannel=0;
ADMUX &= ~(1<<MUX0); //Eingang ADC0 vorbereiten für LDR-Messung
IR_Wert[posi]=ADC;
}
}
/************************************************** **************************************/

/***************************************Routinen*** **************************************/

//---------------------------------Helligkeitsmessung---------------------------------
void helligkeitsmessung(void)
{
if (LDR<=150)
{
PORTD |= (1<<Scheinwerfer);
PORTD |= (1<<Rueckleuchten);
}
if (LDR>=190)
{
PORTD &= ~(1<<Scheinwerfer);
PORTD &= ~(1<<Rueckleuchten);
}
}

//-------------------------------------IR_Servosteuerung---------------------------------------
int IR_Servoposition(void)
{
if (a>=1)
{
posi++;
if (posi>=50)
{
a=0;
}
}
if (a<=0)
{
posi--;
if (posi<=0)
{
a=1;
}
}
return ((posi)+440); //440=min, 490=max
}

//--------------------------------------Motorsteuerung-----------------------------------------
void Motorsteuerung(int Hinderniss_info)
{
OCR0=100; //Maximal 255
OCR2=100; //Maximal 255

if(Hinderniss_info<=15)
{
PORTC |= (1<<Motor_Rechts_Rueck); //Roboter soll sich nach Rechts drehen
}
else
{
PORTC &= ~(1<<Motor_Rechts_Rueck); //Roboter soll aufhören nach Rechts zu drehen
}

if(Hinderniss_info>=35)
{
PORTC |= (1<<Motor_Links_Rueck); //Roboter soll sich nach Links drehen
}
else
{
PORTC &= ~(1<<Motor_Links_Rueck); //Roboter soll aufhören nach Lins zu drehen
}
}

//------------------------------------------GP2D12---------------------------------------------
int GP2D12(void)
{
uint8_t i, memoposi=0;
uint16_t memo=0xffff; //zum merken des kleinsten Wertes; 0xffff=maxwert bei 16-Bit

for (i=0; i<=50; i++)
{
if (IR_Wert[i]<memo)
{
memo = IR_Wert[i];
memoposi = i; //Zum merken der Servoposition, bei der der kleinste wert liegt
}
}
return (memoposi);
}
/************************************************** ********************************************/

/**************************************initialisier ungen***************************************/
void Initial_ADC(void)
{
ADMUX |= 0x00; //AREF, resultat rechtsbündig, ADC-Eingang ADC0
ADCSRA |= ((1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)); //ADC eingeschaltet, Teilungsfaktor..
ADCSRA |= (1<<ADIE);
DDRD |= ((1<<Scheinwerfer) | (1<<Rueckleuchten));
}

void Initial_IR_Servo(void)
{
TCCR1A |= ((1<<WGM11)|(1<<COM1A1)|(1<<COM1A0)); //9-Bit PWM, Inverted Mode OC1A
TCCR1A |= ((1<<COM1B1)|(1<<COM1B0)); //Inverted Mode OC1B
TCCR1B |= (1<<CS12); //Prescaler 256
TIMSK |= (1<<OCIE1B);
DDRD |= (1<<PWM_ServoPort);
PORTD |= (1<<PWM_ServoPort);
OCR1B=500; //beliebige zeit (irgendwas unter ner ms)
}

void Initial_Motoren(void)
{
//Ausgang Initialisieren (OC0)
DDRB |= (1<<Motor_Links); //Setzen als Ausgang
PORTB |= (1<<Motor_Links); //Pull-Up

//Ausgang Initialisieren (OC2)
DDRD |= (1<<Motor_Rechts); //Setzen als Ausgang
PORTD |= (1<<Motor_Rechts); //Pull-Up

//Initialisierung der Ausgänge für Rückwärtsfahren
DDRC |= ((1<<Motor_Links_Rueck)|(1<<Motor_Rechts_Rueck));

//Initialisierung PWM für OC0
TCCR0 |= ((1<<WGM01)|(1<<WGM00)); //Fast PWM
TCCR0 |= (1<<COM01); //Clear Output on Compare, Set on Top
TCCR0 |= ((1<<CS02)|(1<<CS00)); //CLK/1024 (15,625kHz, 64µs/periode)
//Compare Register ist OCR0

//Initialisierung PWM für OC2
TCCR2 |= ((1<<WGM21)|(1<<WGM20)); //Fast PWM
TCCR2 |= (1<<COM21); //Clear Output on Compare, Set on Top
TCCR2 |= ((1<<CS22)|(1<<CS21)|(1<<CS20)); //CLK/1024 (15,625kHz, 64µs/periode)
//Compare Register ist OCR2
}
/************************************************** ************************************/

/**************************************Hauptprogram m***********************************/
int main(void)
{
Initial_ADC();
Initial_IR_Servo();
Initial_Motoren();
sei(); //Globales Interrupt gesetzt

while(1)
{
ADCSRA |= (1<<ADSC); //ADC-Messung immer wieder gestartet werden, wenn möglich

if (count)
{
count=0;
IR_Servo = IR_Servoposition();
Motorsteuerung(GP2D12());
helligkeitsmessung();
}
}
return 0; //wird nie erreicht
}
/************************************************** **************************************/


Hoffe da findet jemand was. Ich finde die sache mit dem Array eigentlich echt gut und will das am liebsten beibehalten.
Kann auch sein das ich mit den Zeiten wieder irgendwas falsch gemacht habe. Ich finde aber leider nichts.

MfG Jan

McJenso
05.11.2007, 21:14
Hallo,

schau dir mal diesen Thread (https://www.roboternetz.de/phpBB2/viewtopic.php?t=35340) an. könnte dir helfen.

Gruß

Jens

Spongebob85
17.11.2007, 23:42
Moin!

Sorry das ich mich jetzt erst melde. Hab meine komplette Steuerplatine neu gebaut. Jetzt läuft alles wieder. Hab heut noch ein bisschen gerätselt, weil ich meine Quarz zwar angelötet, aber nicht mit dem uC verbunden hatte. Plötzlich ging gar nichts...Naja, bin ja froh das ich das selber gefunden hab. sonst hätt ich mich hier erstmal richtig zum Affen gemacht :lol:
Ich hab den Tip von Jens jetzt mal mit "eingebaut" und vor alle Variablen die in Interrupts verändert werden "volatile" gesetzt. Leider macht der trotzdem nichts. Der reagirt überhaupt nicht auf Hindernisse. Ohne Array macht der das. Echt komisch. Naja, vielleicht hat noch jemand einen Tipp.
Falls ich selbst was finde melde ich mich auch.

MfG Jan

robocat
18.11.2007, 08:41
bin noch etwas schläfrig...
dass du hier in der 2ten zeile der funktion TCCR1B meinst, kann es nicht sein, oder?


void Initial_IR_Servo(void)
{
TCCR1A |= ((1<<WGM11)|(1<<COM1A1)|(1<<COM1A0)); //9-Bit PWM, Inverted Mode OC1A
TCCR1A |= ((1<<COM1B1)|(1<<COM1B0)); //Inverted Mode OC1B <-- HIER
TCCR1B |= (1<<CS12); //Prescaler 256

ansonsten finde ich grad nix -.-

gruesse

Spongebob85
26.11.2007, 21:26
Ich komm einfach nicht weiter.
Mein Prog sieht jetzt so aus:



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

#ifndef F_CPU
#define F_CPU 16000000
#endif

#define Scheinwerfer PD0
#define Rueckleuchten PD1
//#define Impulsgeber PD4
#define PWM_ServoPort PD5
#define IR_Servo OCR1A
#define Motor_Links PB3
#define Motor_Rechts PD7
#define Motor_Links_Rueck PC0
#define Motor_Rechts_Rueck PC1

//---------------------------------Globale Variablen----------------------------------
uint8_t count=0;
int8_t posi=25, a=1, ADC_Switch=1;
uint16_t LDR, memo=2000;
uint16_t IR_Messung[51];

//---------------------------------Interruptroutinen----------------------------------
ISR(TIMER1_COMPB_vect)
{
count++;
}

ISR(ADC_vect)
{
if (ADC_Switch)
{
ADC_Switch=0;
LDR = ADC;
ADMUX = 0x01; //Auf ADC1 umschalten
ADCSRA |= (1<<ADSC); //Nach aufzeichnen Ergebniss in LDR, neue Messung starten
}
else
{
ADC_Switch=1;
IR_Messung[posi] = ADC;
ADMUX = 0x00; //Auf ADC0 umschalten
ADCSRA |= (1<<ADSC); //Nach aufzeichnen Ergebniss in IR_Messung, neue Messung starten
}
}

//---------------------------------Helligkeitsmessung---------------------------------
void helligkeitsmessung(void)
{
if (LDR<=140)
{
PORTD |= (1<<Scheinwerfer);
PORTD |= (1<<Rueckleuchten);
}
if (LDR>=190)
{
PORTD &= ~(1<<Scheinwerfer);
PORTD &= ~(1<<Rueckleuchten);
}
}

//-------------------------------------IR_Servosteuerung---------------------------------------
int IR_Servoposition(void)
{
if (a>=1)
{
posi++;
if (posi>=50)
{
a=0;
}
}
else
{
posi--;
if (posi<=0)
{
a=1;
}
}
return ((posi)+440); //440=min, 490=max
}

//--------------------------------------Motorsteuerung-----------------------------------------
void Motorsteuerung(void)
{
uint8_t i, farest=0;

OCR0=100; //255=Max (Links)
OCR2=100; //255=Max (Rechts)

//if (IR_Messung > 150)
if (posi<=0)
{
for (i=0; i<=51; i++)
{
if (IR_Messung[i] < memo)
{
memo=IR_Messung[i];
farest=i;
}
}
}
if (farest<=15)
{
PORTC |= (1<<Motor_Rechts_Rueck);
}
else if (farest>=35)
{
PORTC |= (1<<Motor_Links_Rueck);
}
else
{
PORTC &= ~((1<<Motor_Links_Rueck)|(1<<Motor_Rechts_Rueck));
}
}

//-------------------------------------initialisierungen---------------------------------------
void Initial_ADC(void)
{
ADMUX |= 0x00; //AREF, resultat rechtsbündig, ADC-Eingang ADC0
ADCSRA |= ((1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)); //ADC eingeschaltet, Teilungsfaktor..
ADCSRA |= (1<<ADIE);
DDRD |= ((1<<Scheinwerfer) | (1<<Rueckleuchten));
}

void Initial_IR_Servo(void)
{
TCCR1A |= ((1<<WGM11)|(1<<COM1A1)|(1<<COM1A0)); //9-Bit PWM, Inverted Mode OC1A
//TCCR1A |= ((1<<COM1B1)|(1<<COM1B0)); //Inverted Mode OC1B
TCCR1B |= (1<<CS12); //Prescaler 256
TIMSK |= (1<<OCIE1B);
DDRD |= (1<<PWM_ServoPort);
PORTD |= (1<<PWM_ServoPort);
//DDRD |= (1<<Impulsgeber);
//PORTD |= (1<<Impulsgeber);
//OCR1B=500; //beliebige zeit (irgendwas unter ner ms)
}

void Initial_Motoren(void)
{
//Ausgang Initialisieren (OC0)
DDRB |= (1<<Motor_Links); //Setzen als Ausgang
PORTB |= (1<<Motor_Links); //Pull-Up

//Ausgang Initialisieren (OC2)
DDRD |= (1<<Motor_Rechts); //Setzen als Ausgang
PORTD |= (1<<Motor_Rechts); //Pull-Up

//Initialisierung der Ausgänge für Rückwärtsfahren
DDRC |= ((1<<Motor_Links_Rueck)|(1<<Motor_Rechts_Rueck));

//Initialisierung PWM für OC0
TCCR0 |= ((1<<WGM01)|(1<<WGM00)); //Fast PWM
TCCR0 |= (1<<COM01); //Clear Output on Compare, Set on Top
TCCR0 |= ((1<<CS02)|(1<<CS00)); //CLK/1024 (15,625kHz, 64µs/periode)
//Compare Register ist OCR0

//Initialisierung PWM für OC2
TCCR2 |= ((1<<WGM21)|(1<<WGM20)); //Fast PWM
TCCR2 |= (1<<COM21); //Clear Output on Compare, Set on Top
TCCR2 |= ((1<<CS22)|(1<<CS21)|(1<<CS20)); //CLK/1024 (15,625kHz, 64µs/periode)
//Compare Register ist OCR2
}

//---------------------------------------Hauptprogramm---------------------------------
int main(void)
{
Initial_ADC();
Initial_IR_Servo();
Initial_Motoren();
ADCSRA |= (1<<ADSC); //Erste Messung starten

sei(); //Globales Interrupt gesetzt

while(1)
{
if (count)
{
count=0;
helligkeitsmessung();
IR_Servo = IR_Servoposition();
Motorsteuerung();
}
}
return 0; //wird nie erreicht
}



Warum geht das bloß nicht???
Eine Kette dreht vorwärts und die andere rückwärts.
Es ändert sich auch nichts und der Sensor reagiert auch auf nichts.
Hoffe das kuckt sich noch jemand an.

@robocat:
Das war schon richtig so. Hab im datenblatt noch mal nachgesehen.
Aber jetzt benutz ich das ja gar nicht mehr.

MfG Jan

Hubert.G
27.11.2007, 15:58
Wenn du in der Motorsteuerung farest=20; eingibst dann lauffen beide Motore in die selbe Richtung.
Du bist mit der Doku etwas sparsam, so ist es etwas mühsam nachzuvollziehen was du dir gedacht hast.

McJenso
27.11.2007, 18:02
Hallo,

probier den Fehler durch vorgabe von Daten einzukreisen. Wie Hubert schon schrieb farest fest vorgeben. Wenn das Ergebnis wie erwartet ist, geht es weiter mit dem Array. Füll es in der Motorsteuerung über eine Schleife mit Werten. Einen Wert überschreibst du mit einem Kleinsten Wert. Was passiert? Alles ok? Dann geht es weiter, das Array im ADC interrupt füllen wie in der Motorsteuerung. usw, usw. Irgendwann wird was unerwartetets passieren. Das gilt es dann zu ergründen.

Gruß

Jens

Spongebob85
30.11.2007, 00:04
Ich hab das jetzt alles nochmal durchgedacht und bisschen rumgespielt.
Bin ja jetzt mit Schule durch und hab zeit :-)
Auf jeden fall hab ich gemerkt, das das array mit werten gefüllt wird, aber sobald ich eine for-Schleife verwende, reagiert der roboter auf gar nichts mehr...
Is ziemlich nervig. aber ich hab das jetzt erstmal anders gemacht. Ich vergleiche jetzt einfach zwei felder (eins links und eins rechts) mit einem wert und lasse die jeweilige Kette rückwärts drehen. Damit könnte ich mir das array zwar schennken, aber es läuft erstmal...ehr schlecht aber immerhin...
Vielleicht steige ich irgendwann mal dahinter.

MfG Jan

sast
30.11.2007, 10:00
Hi Jan,

bin nur mal kurz über deinen Code geflogen und dabei ist mir aufgefallen, dass du memo nur einmal mit einem großen Wert belegst. Ich weiß zwar nicht was du dir da gedacht hast, aber wenn du die while(1) ein paar mal durchlaufen hast, geht es nicht mehr weiter runter. Wenn du bei jedem Durchlauf wieder von oben anfangen willst, solltest du memo in der main() auch immer wieder auf 2000 (oder was auch immer) setzen.

Hoffe das hilft dir.

sast

Spongebob85
02.12.2007, 10:06
@sast:
danke für den Tip!
Hab memo dann unter "if (posi <=0)" geschrieben, so das memo immerwieder neu auf 2000 gesetzt wird, wenn der servo ganz links ist und bevor die schleife wieder das Array durchsuchen soll hat leider auch nichts gebracht :-(

MfG Jan