PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Timer Atmega16 NiboBee



PinQin
14.04.2014, 17:53
Hallo,

ich hab ein Problem mit folgenden Code:


#include <C:/Program Files (x86)/NIBObeeLib/include/nibobee/iodefs.h>
#include <C:/Program Files (x86)/NIBObeeLib/include/nibobee/led.h>
#include <C:/Program Files (x86)/NIBObeeLib/include/nibobee/delay.h>
#include <C:/Program Files (x86)/NIBObeeLib/include/nibobee/motpwm.h>
#include <C:/Program Files (x86)/NIBObeeLib/include/nibobee/i2cmaster.h>
#include <C:/Program Files (x86)/NIBObeeLib/include/nibobee/sens.h>

#include <C:/Users/Max/Documents/Atmel Studio/6.1/Beschleunigungssensor/Beschleunigungssensor/BMA020.h>
#include <C:/Users/Max/Documents/Atmel Studio/6.1/Beschleunigungssensor/Beschleunigungssensor/i2c_communicate.c>

#include <avr/io.h>

//Prototyping
void fahren(int16_t, int16_t);
void yAchse(void);
long abstand (long);
void stop(void);

//Variablendeklaration
int16_t speed_l, speed_r;
int8_t sensor_l, sensor_r;
long mess_abs;
long counter=0;
long old=0;

int16_t main()
{
//Pause vor Start
delay(3000);

//Initialisierung
led_init();
void i2c_init(void);
motpwm_init();
sens_init();

enable_interrupts();

//Timerinitialisierung
TCCR2 = (1<<CS01);
TIMSK |= (1<<CS01);
sei();


//PortC Bit 3 als Ausgang setzen
DDRC = 0b00001000;

//PORTC = (1<<PC3);

//Endlosschleife
while(1==1)
{
PORTC |= (1<<PC3);

#ifndef TIMER2_OVF_vect
#endif

//Reset
led_set(LED_L_RD, 0);
led_set(LED_R_RD, 0);
led_set(LED_R_YE, 0);

//Sensoren abfragen
sensor_l = sens_getLeft();
sensor_r = sens_getRight();

//Abstand
if (mess_abs>0)
{
led_set(LED_R_YE, 1);
stop();
counter=0;
}

//Beschleunigungssensor

//Beschleunigungssensor abfragen
yAchse();

//Abstand messen
abstand(counter);

//langsam
if (BMA_Y>0 && speed_l != 80 && sensor_l == 0 && sensor_r == 0)
{
speed_l = 80;
speed_r = 80;
led_set(LED_L_YE, 1);
}

//schnnell
if (BMA_Y<10 && speed_l!=400 && sensor_l == 0 && sensor_r == 0)
{
speed_l = 500;
speed_r = 500;
led_set(LED_L_YE, 0);
}


//Kolission
//Kolission detektieren Sensor links
if (sensor_l != 0)
{
led_set(LED_L_RD, 1);
}

//Kolission detektieren Sensor rechts
if (sensor_r != 0)
{
led_set(LED_R_RD, 1);
}

fahren(speed_l, speed_r);
}
return 0;
}

//Funktionendeklaration
void fahren(int16_t wert_l, int16_t wert_r)
{
if (sensor_l || sensor_r != 0 )
{
motpwm_setLeft(-400);
motpwm_setRight(-400);

delay(2000);

motpwm_setLeft(-400);
motpwm_setRight(400);

delay(500);
}

motpwm_setLeft(wert_l);
motpwm_setRight(wert_r);

}

void yAchse(void)
{
BMA_sleep(0);
BMA_init(RANGE_2g | BANDWIDTH_25hz);
BMA_acc_y();
}

long abstand (long counter)
{
PORTC &= ~(1<<PC3);
delay(1);
PORTC |= (1<<PC3);
delay(1);
PORTC &= ~(1<<PC3);

old = counter;

while(PINC & (1<<PINC2))
{

}

mess_abs = counter - old;
mess_abs *= 136.53 /1000/10;

return mess_abs;
}

void stop(void)
{
motpwm_setLeft(-400);
motpwm_setRight(-400);

delay(2000);

motpwm_setLeft(-400);
motpwm_setRight(400);

motpwm_setLeft(-400);
motpwm_setRight(400);

delay(500);

//counter =0;
}

#ifndef TIMER2_OVF_vect
#endif
ISR (TIMER2_OVF_vect)
{
counter = counter + 1;
}




Das Programm läuft im Grunde so wie es soll, lediglich der Timer funktioniert nicht. Genauer mess_abs wird nie größer als 0, kann mir jemand einen Denkanstoss geben? Es geht also um die Funktion abstand und den Timer ...

Besserwessi
14.04.2014, 18:25
Das passende Schlüsselwort sollte VOLATILE sein. Damit sollte man alle Variablem kennzeichnen, die in der ISR und im Hauptprogramm genutzt werden.

PinQin
14.04.2014, 18:31
Nur bei der Variablendeklaration? Oder auch um ISR und dem Prototyping?

Searcher
14.04.2014, 18:51
//Timerinitialisierung
TCCR2 = (1<<CS01);
TIMSK |= (1<<CS01);

Hier verwendest Du Bits vom Timer0 für Timer2. Kommt mir spanisch vor ;)

Gruß
Searcher

PinQin
15.04.2014, 18:22
Ich habe den Code mal zerlegt, ist vielleicht übersichtlicher...




void main (void)
{
//Timerinitialisierung
TCCR2 = 0b001;
TIMSK |= (1<<TOIE2);
sei();

while(1)
{}

}

ISR (TIMER2_OVF_vect)
{
counter = counter + 1;
}


Dieser Timer sollte bei 15MHz Takt alle 17µs die ISR aufrufen, stimmt das?

Searcher
16.04.2014, 08:30
Dieser Timer sollte bei 15MHz Takt alle 17µs die ISR aufrufen, stimmt das?
Würd ich rein nach Datenblatt auch so sehen. Allerdings kenne ich mich mit C und den Nibobee Funktionen nicht aus. Nicht, daß da irgendeine Funktion den Timer2 auch noch nutzt.

Kommt auf eine Interruptfrequenz von ca. 58,5kHz und damit ist der µC schon gut beschäftigt und man könnte mal überprüfen, ob das in Zusammenarbeit mit übrigem Programm und Interrupts nicht zuviel ist?

TCCR2 = 0b001; find ich nicht so gut. Binärzahl entsprechend der Registerbreite angeben, also 0b00000001 oder gleich übersichtlich mit TCCR2 |= (1<<CS20); (wenn andere Bits nicht beeinflußt werden sollen)

PS: 15MHz ist eine unübliche Taktfrequenz?

Gruß
Searcher

Besserwessi
16.04.2014, 16:10
Da die ISR recht kurz ist, sollte es auch mit einer so hohen Frequenz noch funktionieren. Einfach nur in der ISR Zählen ist aber ggf. auch unnötig - das kann der Timer auch in Hardware. Also einfach den Vorteiler um den Faktor 256 höher setzen und dann das Timer register auslesen statt der Variabele Counter. Besser wäre es da aber den 16 Bit timer(1) zu nutzen - dann hätte man auch da 16 Bit Auflösung. Oft reicht das. Der Timer direkt hätte auch noch gleich den Vorteil, das da Hardware für den ungestörten Zugriff auch 16 Bit werte vorhanden ist. Bei der Softwarelösung müsste man die Zugriffe auf Counter im Hauptprogramm noch alle mit Cli() ... Sei() schützen, wenn es nicht zu seltenen Ausreißern kommen darf.

PinQin
16.04.2014, 19:13
Den 16-bit Timer kann ich leider nicht nutzen, da der schon verwendet wird. Ich habe es jetzt mit dem 8er Vorteiler realisiert. Die Auflösung reicht noch nicht ganz aus, aber vorerst haben mich eure Antworten ein ganzes Stück weiter gebracht. Ich kann die Distanz jetzt auf ein paar cm genau einstellen. Ich werde in den nächsten Tagen noch die Idee den Zählerwert direkt zu verwenden umsetzen, dann müsste das Ganze noch genauer werden. Der Counterwert wäre dann ja Counter + (überlauf*256)?!

Vielen Dank,

PinQin!

Besserwessi
16.04.2014, 20:36
Im Prinzip stimmt das mit Counter + (überlauf*256), aber man muss aufpassen ob ggf. noch ein Überlauf Interrupt ansteht, also der counter schon wieder klein ist, aber die ISR für den Überlauf noch nicht aufgerufen wurde.