PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Software für Roboer funktioniert nicht wie erwartet



Torrentula
04.08.2011, 19:57
Hallo ich bin es mal wieder!

Ich bin gerade dabei meinen Roboter zu programmieren. Das Mainboard ist das RN-Control mit Mega32 und als Hilfs-µC verwende ich einen ATmega8 beide laufen bei 16MHz. Beide sitzen auf dem Chassis des Robby RP5 von Conrad. Der ATmega8 liest periodisch den SRF05 aus und der Mega32 holt sich über I2C die Daten beim ATmega8 ab. Die Datenübertragung funktioniert, das habe ich bereits getestet. Wenn ich nun den Mega32 die Entfernung verarbeiten lasse und daraufhin die Motoren ansteuern lassen will, drehen die Motoren nur in kurzen "schüben".

Solange der Abstand zu einem Objekt mehr als 50cm beträgt, rollt der Roboter einfach weiter geradeaus. Wenn der SRF05 ein Hindernis in weniger als 50cm Entfernung erkennt, bremst der Roboter ab, fährt zurück, dreht sich ein kurzes Stück nach links und fährt wieder vorwärts los.

Die Software treibt mich schon den ganzen Tag in den Wahnsinn und hoffe, dass andere vielleicht einen simplen Fehler entdeckt, den ich einfach nicht finde...



#include <avr/io.h>
#include <util/delay.h>
#include "twimaster.c"
#include "rncontrol.h"

uint8_t data = 0;

void getDistance(void){

i2c_start_wait(0x50+I2C_WRITE);
i2c_write(0xB8);
i2c_stop();

i2c_rep_start(0x50+I2C_READ);
data = i2c_readNak();
i2c_stop();

data += 1;
}

void accelerate(void){

Mrechtsvor();
Mlinksvor();

for(uint8_t i = 0; i <= 200; i += 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(200);
setPWMrechts(200);
}

void slowdown(void){

for(uint8_t i = 200; i >= 0; i -= 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(0);
setPWMrechts(0);

Mlinksstop();
Mrechtsstop();
}

void goBack(void){

Mrechtszur();
Mlinkszur();

for(uint8_t i = 0; i <= 200; i += 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(200);
setPWMrechts(200);
_delay_ms(1000);

for(uint8_t i = 200; i >= 0; i -= 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

Mlinksstop();
Mrechtsstop();
}

void leftTurn(void){

// Turn a bit

Mlinkszur();
Mrechtsvor();

for(uint8_t i = 0; i <= 200; i += 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(200);
setPWMrechts(200);

while(data <= 50){

getDistance();
}

for(uint8_t i = 200; i >= 0; i -= 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(0);
setPWMrechts(0);

Mlinksstop();
Mrechtsstop();

accelerate();

}

int main(void)
{

i2c_init();
init_timer1();

DDRB |= 0x03; // Channels for right motor
DDRC |= 0xC0; // Channels for left motor
DDRD |= 0x30; // PWM-Channels for motors

accelerate();

while(1)
{

getDistance();

while(data > 50){

// Just wait
getDistance();
}
slowdown();
goBack();
leftTurn();
}
}


MfG Torrentula

radbruch
04.08.2011, 20:57
Hallo

Dein Programm sieht ja eher unaufällig aus, ein Fehler sticht mir auf Anhieb nicht ins Auge.

Hat die Library des RN-Contol keine eigenen Zeitfunktionen? delay.h funktioniert gelegentlich unerwartet bis seltsam. Teste mal, ob der Takt stimmt:

i2c_init();
init_timer1();
while(1)
{
led_on;
delay_ms(500);
led_off;
delay_ms(500);
}

sollte im Sekundentakt blinken.

Gruß

mic

Torrentula
05.08.2011, 07:10
Die Lib des RN-Control hat schon eigene Zeitfunktionen, doch ich hatte mit delay.h bis jetzt nie Probleme. Die LED blinkt auch im Sekundentakt also liegts wohl nicht an delay.h.

Der SRF05 gibt öfter mal den Wert 0 aus... Ich habe versucht dies durch Mittelwertbildung von 4 Messungen zu beheben trotzdem kein Erfolg...



for(uint8_t i = 0; i <= 3; ++i){
wert += SRF05_GetResponseTime() / 464;
_delay_ms(20);
}

txbuffer[0] = wert / 4;

_delay_ms(100);
wert = 0;


Gibt es sonst noch ideen?

Ich habe die Funktion zum holen der Daten nochmals angepasst und das Oversampling wieder aus dem Code entfernt:



void getDistance(void){

i2c_start_wait(0x50+I2C_WRITE);
i2c_write(0xB8);
i2c_stop();

i2c_rep_start(0x50+I2C_READ);
data = i2c_readNak();
i2c_stop();

if(data == 0){ // request new data from SRF05 if the distance is 0cm
i2c_start_wait(0x50+I2C_WRITE);
i2c_write(0xB8);
i2c_stop();

i2c_rep_start(0x50+I2C_READ);
data = i2c_readNak();
i2c_stop();
}
}


Die Software scheint aber garnicht auf Sensorwerte zu reagieren. Die Linksdrehung (wenn ich z.B. die Hand davor halte) wird garnicht eingeleitet. Es scheint so als würde die Fahrt-Schleife immer wieder abgebrochen.

sternst
05.08.2011, 10:13
Es scheint so als würde die Fahrt-Schleife immer wieder abgebrochen. Klingt so, als ob der Controller regelmäßig resettet. Da sehe ich 3 Möglichkeiten:
1) Watchdog ist aktiv. Prüfe die Fuses.
2) Interrupt ohne ISR. Wo ist der Code von init_timer1?
3) Hardwareproblem.

Torrentula
05.08.2011, 11:13
Punkt 1:

Watchdog ist nicht aktiv

Punkt 2:

init_timer1() ist die funktion aus der Library für das RN-Control aus dem Wiki.



void init_timer1(void) //Initialisierung des Timers für Erzeugung des PWM-Signals
{
/* normale 8-bit PWM aktivieren (nicht invertiert),
Das Bit WGM10 wird im Datenblatt auch als PWM10 bezeichnet */
TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);

/* Einstellen der PWM-Frequenz auf 14 kHz ( Prescaler = 1 ) */
TCCR1B = (1<<CS10);

/* Interrupts für Timer1 deaktivieren
Achtung : Auch die Interrupts für die anderen Timer stehen in diesem Register */
TIMSK &= ~0x3c;
}


Punkt 3:

Der 7805 sollte eigentlich nicht beim Anlaufen der Motoren in die Knie gehen, das Beschleunigen und Abbremsen der Motoren mit dem Code aus dem Demoprogramm funktioniert einwandfrei.



Mlinksvor();
Mrechtsvor();

setPWMlinks(0);
setPWMrechts(0);
waitms(40);

for(uint8_t i=0; i<255; i=i+5)
{
setPWMlinks(i);
setPWMrechts(i);
waitms(40);
}

setPWMlinks(255);
setPWMrechts(255);
waitms(40);

for(uint8_t i=255; i>0; i=i-5)
{
setPWMlinks(i);
setPWMrechts(i);
waitms(40);
}

setPWMlinks(0);
setPWMrechts(0);

Mlinksstop();
Mrechtsstop();
waitms(300);



Edit: Der Controller resettet sich nicht ständig selber. Dies habe ich gerprüft, indem ich vor der Hauptschleife des Programms den Controller einfach eine kleine Tonfolge abspielen lassen habe. Die Motoren laufen immer wieder von neuem an, die Tonfolge ist jedoch nur beim Einschalten zu hören. Somit kann es schonmal nichts mehr mit Resets aufgrundvon was auch immer zu tun haben...

Aktueller Code:



/*
* Master.c
*
* Created: 02.08.2011 07:56:05
* Author: Torrentula
*/

#include <avr/io.h>
#include <util/delay.h>
#include "twimaster.c"
#include "rncontrol.h"

uint8_t data = 0;

void getDistance(void){

i2c_start_wait(0x50+I2C_WRITE);
i2c_write(0xB8);
i2c_stop();

i2c_rep_start(0x50+I2C_READ);
data = i2c_readNak();
i2c_stop();

if(data == 0){ // request new data from SRF05 if the distance is 0cm
i2c_start_wait(0x50+I2C_WRITE);
i2c_write(0xB8);
i2c_stop();

i2c_rep_start(0x50+I2C_READ);
data = i2c_readNak();
i2c_stop();
}
}

void accelerate(void){

Mrechtsvor();
Mlinksvor();

for(uint8_t i = 0; i <= 200; i += 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(200);
setPWMrechts(200);
}

void slowdown(void){

for(uint8_t i = 200; i >= 0; i -= 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(0);
setPWMrechts(0);

Mlinksstop();
Mrechtsstop();
}

void goBack(void){

Mrechtszur();
Mlinkszur();

for(uint8_t i = 0; i <= 200; i += 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(200);
setPWMrechts(200);
_delay_ms(1000);

for(uint8_t i = 200; i >= 0; i -= 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

Mlinksstop();
Mrechtsstop();
}

void leftTurn(void){

// Turn a bit

Mlinkszur();
Mrechtsvor();

for(uint8_t i = 0; i <= 200; i += 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(200);
setPWMrechts(200);

while(data <= 50){

getDistance();
}

for(uint8_t i = 200; i >= 0; i -= 10){
setPWMlinks(i);
setPWMrechts(i);
_delay_ms(20);
}

setPWMlinks(0);
setPWMrechts(0);

Mlinksstop();
Mrechtsstop();

accelerate();

}

int main(void)
{

i2c_init();
init_timer1();

DDRB |= 0x03; // Channels for right motor
DDRC |= 0xC0; // Channels for left motor
DDRD |= 0xB0; // PWM-Channels for motors

sound(6, 270); //Startmelodie
sound(8, 270);
sound(11, 270);
sound(7, 270);
waitms(10);
sound(7, 270);
sound(6, 270);
sound(11, 540);

accelerate();

while(1)
{
getDistance();

while(data > 50){

// Just wait
getDistance();
}
slowdown();
goBack();
leftTurn();
}
}


Hoffe jemand anderes hat noch eine Idee....

Torrentula
08.08.2011, 19:07
bump

Ich habe echt keinen Dunst woran es liegen könbnte, dass der Roboter immer wieder abbremst und von neuem bschleunigt...