PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Asuro ohne asuro.lib programmieren



Bongo1st
18.09.2009, 20:01
Hallo,

Bin am C erlernen. Einen kleinen Einblick habe ich mit Asuro bekommen. Nun wollte ich es einmal ohne der asuro.c und asuro.h Dateien probieren.
Bis jetzt habe ich mir erst das ein und ausschalten der Ports beigebracht.

Jetzt wollte ich mit dieser Funktion die H-Brücke ansteuern. So wie ich es verstanden kann ich PB1 und PB5 auf +5v stellen um den Motor mit voller Geschwindigkeit laufen zu lassen. Habe dies versucht, jedoch ohne Erfolg. Ich denke der Fehler liegt an der PWM Leitung. Muss PB1 immer ein PWM Signal senden. Theoretisch nicht und das bedeutet Vollgas.

Habe auch das Asuro-Wiki konsultiert, jedoch ohne erfolg.
Wo Liegt der Fehler?

Hier der Code:

#include <avr/io.h>

#define FRONT_LED (1<<PD6)
#define STATUS_LED_GRUN (1<<PB0)
#define STATUS_LED_ROT (1<<PD2)
#define BACK_LED_RECHTS (1<<PC0)
#define BACK_LED_LINKS (1<<PC1)
#define PORT_B5 (1<<PB5)
#define PORT_D5 (1<<PD5)
#define MOTOR_PWM_B (1<<PB1)
#define Motor_PWM_D (1<<PD1)

int main (void) {

DDRB |= STATUS_LED_GRUN | PORT_B5 | MOTOR_PWM_B;
DDRC |= BACK_LED_RECHTS | BACK_LED_LINKS;
DDRD |= FRONT_LED | STATUS_LED_ROT | PORT_D5 | Motor_PWM_D;


PORTB |= STATUS_LED_GRUN | PORT_B5 | MOTOR_PWM_B;
PORTC |= BACK_LED_RECHTS | BACK_LED_LINKS;
PORTD |= FRONT_LED | STATUS_LED_ROT | PORT_D5 | Motor_PWM_D;

return 1;
}

radbruch
18.09.2009, 20:10
while(1); fehlt vor return

Bongo1st
18.09.2009, 21:46
Hallo radbruch

Leider habe ich es noch nicht fertiggebracht die Räder zum drehen zu bringen. Immer hin habe ich am Port B1 1.6 V. Würde sagen ich habe ein PWM Signal erschaffen :shock:
Werde über das Wochenende ein wenig pröbeln. Falls ich nicht weiter komme Frage ich nochmals.
Danke für die Hilfe
mfg Bongo

radbruch
19.09.2009, 05:27
Hallo

Motor links: PB1 (PWM) und PD5(high) UND PD4(low)
Motor rechts: PB2 (PWM) und PB5(high) UND PB4(low)

Wenn du PB4/PD4 nicht als Ausgang und low schaltest steuern die Transistoren T1 und T5 nicht durch. Für links:

PD4 low, PD5 high und PB1 high =

T1 leitet (PD4low)!
low an ic1:12 (PD4low) und high an ic2:13 (PB1high) T2 sperrt

T3 sperrt (PD5high)
high an ic3:2(PD5high) und high an ic3:1 (PB1high) T4 leitet

Strom fließt von Vcc über T1 nach Motor nach T4 zu GND

Ich hoffe, nun passt es endlich

Gruß

mic

Bongo1st
20.09.2009, 16:16
Super, nun fährt der Asuro. Auch mit der Kombination mit dem PWM Signal funktioniert es. Danke!

Nun habe ich mich (seit 2 Tagen) mit der Sleep Funktion auseinander gesetzt. Doch leider klappt dies nicht.

#include <avr/io.h>



#define D6 (1<<PD6)

volatile unsigned char count72kHz;

int i;

int main (void) {


DDRD |= D6;


TCCR2= (1<<WGM21) | (1<<COM20) | (1<<CS20);
OCR2 = 0x6E;
TIMSK |= (1<<OCIE2);

while (1) {

PORTD |= D6;

for (i= 0; i < 1000; i++)
{
count72kHz = 0;
while (count72kHz < 72);
}


PORTD &= ~D6;


for (i= 0; i < 1000; i++)
{
count72kHz = 0;
while (count72kHz < 72);
}
}
return 1;
}

Was habe ich übersehen? Ich weiss, dass ich es auch mit der Funktion delay ms hinkriegen würde.
Gibt es eigentlich Tabellen werte wo ich für den counter die Werte WGM, COM und CS ablesen kann?

Danke für die Hilfe.
Gr Bongo

radbruch
20.09.2009, 16:45
Hallo

Die Timerwerte muss man sich selbst errechnen, im Datenblatt des Mega8 (Pflichtlektüre für mit ohne Lib Programmierer!) stehen die Tabellen für die Registerbits.

while (count72kHz < 72);

Hast du mal darüber nachgedacht wie count72kHz es schaffen soll so groß wie 72 zu werden? Was bedeutet denn das "volatile"?

Gruß

mic

Bongo1st
20.09.2009, 18:11
Hallo radbruch

Ich hatte früher für die Sleep-Funktion folgende Formel benutzt:
for (i=0; i<1000; i++) {Sleep(72); // 72/72=1ms -> 1000 wiederholen

Und diese habe ich nun versucht aufzulösen.
Das volatile habe ich aus der asuro.c

radbruch
20.09.2009, 19:06
Hallo

Das es aus asuro.c stammt ist schon klar, ich wollte dich nur etwas in Richtung der Lösung "schieben". Da du dir schon einiges selbst erarbeitest hast wollte ich dir den Weg zeigen die Lösung selbst zu finden.

Der Timer wird im Overflow-Mode betrieben, das bedeutet, immer wenn der Timerzähler 255 überschreitet (Timer2 ist ein 8 Bit-Timer) passiert irgendwas. Nach dem Überlauf startet der Timer in diesem Modus beim Wert der in OCR2 steht. Standartmässig ist in der Lib der Interrupt aktiviert:

TIMSK |= (1<<OCIE2);

Im Timermaskregister wird so das Bit gesetzt welches den Overflow-Interrupt erlaubt (O verflow C ounter I nterrupt E nable 2). Wenn das Register überläuft wird zur Interruptserviceroutine ISR) für den Überlauf des Timer 2 gesprungen. Das ist so ähnlich wie der Aufruf einer Funktion. In der Lib wird eine ältere Schreibweise für die ISR verwendet:

SIGNAL (SIG_OVERFLOW2)
{
}

Das solltest du in asuro.c auch finden und dort wird auch count72kHz geändert. Diese ISR must du nun selbst einfügen sonst setzt der Kompiler hier nur eine Dummy-ISR mit einem return ein. Und hier gehört auch das "volatile" dazu: Es teilt dem Kompiler mit das es eine Variable ist die in einer ISR verändert wird. Dadurch muss er sie anders speichern, aber ich schweife ab...

Die ISR wird während deiner while (count72kHz < 72);-Schleife quasi im Hintergrund ausgeführt. Deshalb wird count72kHz nach 72 Aufrufen (=Interrupts) so groß wie 72 und deine Schleife wird beendet.

Neben dem Bit im TIMSK müssen auch die globalen Interrupts freigegeben werden:

sei();

Gruß

mic

Ceos
21.09.2009, 08:22
bitte beachte, dass du den timer noch passend initialisieren musst, kannst dir ja datenblatt und die asuro lib zur hilfe nehmen, damit du auch wirklich eine zählfrequenz von 72kHz bekommst ;)

radbruch
21.09.2009, 08:58
Hallo

Das Timersetup stammt aus der orginalen asuro-(CD)-Lib mit 72kHz-Takt, dort wird ein anderer Interrupt verwendet:

SIGNAL (SIG_OUTPUT_COMPARE2)

Deshalb stimmt meine Beschreibung oben überhaubt nicht. Wie das wirklich funktioniert ist nicht nur für mich schwer durchschaubar:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=31409

Das ist mehr als kniffelig :)

Gruß

mic

[Edit]
Ich habe jetzt etwas gestöbert und bin auf diese Beschreibung von Sternthaler gestoßen:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=452634#452634

Das ist die Beschreibung der neueren (aktuellen?) 36kHz-Version (mit den ominösen 0x25;) die eine Pulsweitenmodulation der IR-Led erlaubt. Es ist meiner Meinung nach die bessere Initialisierung des Timer2 beim asuro.

Eine Beschreibung der orginalen 72kHz-Version von Henk persönlich habe ich hier gefunden:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=79918#79918

Ceos
21.09.2009, 09:57
ach stimmt ja, ist es in der neuen asurolib nicht sogar 36kHz ?!

radbruch
21.09.2009, 10:25
Hallo

Wir greifen vor, im Moment sind wir doch noch beim Aufruf der ISR.

Die eigentliche Funktion des Timer2 ist die Erzeugung des 36kHz-Trägersignals für die IR-Kommunikation. In der orginalen CD-Lib wurde im CTC-Mode beim Erreichen des OCR2-Wertes der OC2-Ausgang umgeschaltet (togglen) und der Zähler wieder bei 0 gestartet. Bei 72kHz ergibt das 36kHz an OC2-Pin. Die ISR wird aber mit 72kHz angesprungen.

Neuere Libs (mit FastPWM) schalten pro Zähldurchlauf des Timers2 (0x25-0xff) zweimal den OC2-Pin um, aber die ISR wird nur beim Überlauf am Ende mit 36kHz aufgerufen.

Die Änderung des Timer2 auf 36kHz gibt es seit Version 2.3(beta2) in der asuro-Lib (IR-Abstandsmessung von Waste):

/************************************************** *****************************
*
* File Name: asuro.c
* Project : ASURO
*
* Description: This file contains ASURO main features
*
* Ver. Date Author Comments
* ------- ---------- -------------- ------------------------------
* 1.00 14.08.2003 Jan Grewe build
* 2.00 14.10.2003 Jan Grewe LEFT_VEL, RIGHT_VEL -> MotorSpeed(unsigned char left_speed, unsigned char right_speed);
* LeftRwd(),LeftFwd(),RightRwd(),RigthFwd() -> MotorDir(unsigned char left_dir, unsigned char right_dir);
* GREEN_ON,GREEN_OFF,RED_ON,RED_OFF -> StatusLED(unsigned char color);
* LED_RED_ON, LED_RED_OFF -> FrontLED(unsigned char color);
* Blink(unsigned char left, unsigned char right) -> BackLED(unsigned char left, unsigned char right);
* Alles in Funktionen gefasst => leichter verständlich ?!?!
* 2.10 17.10.2003 Jan Grewe new Timer funktion void Sleep(unsigned char time36kHz)
*
* Copyright (c) 2003 DLR Robotics & Mechatronics
************************************************** ***************************/
/************************************************** **************************
*
* File Name: asuro.c
* Project : asuro library "Robotrixer Buxtehude"
*
* Description: This file contains additional functions:
*
* signal (SIG_ADC) interrupt/signal routine for encoder-counter
* signal (SIG_INTERRUPT1) signal for switches
* Encoder_Init() initializing encoder-counter
* Encoder_Start() start autoencoding
* Encoder_Stop() stop autoencoding
* Encoder_Set(int,int) set encodervalue
* Msleep(int delay) wait for delay in milliseconds
* Gettime() get systemtime in milliseconds
* PrintInt(int)
*
* modifications in Sleep, SIG_OUTPUT_COMPARE2, PollSwitch, LineData
*
* Ver. Date Author Comments
* ------- ---------- -------------- ------------------------------
* beta1 31.03.2005 Robotrixer asuro library
* ------- ---------- -------------- ------------------------------
* the encoder source is based on RechteckDemo.c ver 2.0 by Jan Grewe 22.10.2003
* Copyright (c) 2003 DLR Robotics & Mechatronics

************************************************** ***************************/
/************************************************** **************************
*
* File Name: asuro.c
* Project : asuro library modified for IR collision detector
*
* Description: modifications made in following functions:
*
* SIGNAL (SIG_OUTPUT_COMPARE2) -> SIGNAL (SIG_OVERFLOW2)
* Gettime() counts now 36kHz
* Init() timer2 modified for adjustable duty cycle
* Batterie() bug fixed
* Sleep() counts now 36kHz
* Msleep() counts now 36kHz
*
* Ver. Date Author Comments
* ------- ---------- -------------- ------------------------------
* beta2 11.06.2005 Waste asuro library
* ------- ---------- -------------- ------------------------------
************************************************** ***************************/
/************************************************** *************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* any later version. *
************************************************** *************************/

#include "asuro.h"
volatile unsigned char count36kHz;
volatile unsigned long timebase;
volatile int autoencode=FALSE;

/* uses timer2 (36kHz for IR communication */
SIGNAL (SIG_OVERFLOW2)
{
TCNT2 += 0x25;
count36kHz ++;
if (!count36kHz) timebase ++;
}

,,,

/* Init function Processor will be initalized to work correctly */
void Init (void)
{
//-------- seriell interface programmed in boot routine and already running -------
// prepare 36kHz for IR - Communication
TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20);
OCR2 = 0x91; // duty cycle for 36kHz
TIMSK |= (1 << TOIE2); // 36kHz counter for sleep
....


Gruß

mic

Bongo1st
21.09.2009, 19:08
Hallo miteinander,

Habe mich nochmals mit dem Ganzen befasst, mir ist nun einiges klarer geworden, doch leider noch nicht alles:
1. Warum rechnet der compare2 die 36kHz mal zwei?
2. Die ganzen Timer-Einstellungen (TCCR2,OCR2 und TIMSK) (habe die werde gefunden im ATmega8 Datenblatt, jedoch noch nicht verstanden. Werde es aber nochmals selbst versuchen)
3. Die Sekunde die er warten soll ist länger als eine Sekunde (habe ein eigenes makefile erstellt und dort eine ATmega8 und den Takt mit 8MHz definiert)

Hoffe ihr könnt mir bei der Frage 1 und 2 weiter helfen.
Hier noch mein Funktionierender Code:

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


//Front LED an Port D6
#define D6 (1<<PD6)


// unsigned char= Wertbereich ohne Vorzeichen von 0-255
// volatile = wird benutzt, um eine Variabel der Interrupt-Rutine zu geben
volatile unsigned char count72kHz;


// Rutine die mit 36Khz arbeite. Alle [1/(36*2)= 13.89müs] wird count72kHZ um 1 erhöht
SIGNAL (SIG_OUTPUT_COMPARE2) {count72kHz ++;}


// int = Wertbereich von (-32768)-32767
int i;


// main Prozess wird gestartet
int main (void) {


// Port D6 wird als Ausgang gesetzt
DDRD |= D6;


// WGM21 = Mode 2 -> CTC
// COM20 = auf OC2 auf gleichen Wert vergleichen
// CS20 = kein prescaling
TCCR2= (1<<WGM21) | (1<<COM20) | (1<<CS20);


// 0x6E 110
OCR2 = 0x6E;


//Overflow-Interrupt aktivieren
TIMSK |= (1<<OCIE2);

sei (); //alle Interrupts einschalten


while (1) { //Endlosschleife starten

PORTD |= D6; //Port D6 auf high
for (i= 0; i < 1000; i++) // i ist 0, warten bis i 500 hat, i plus 1
{
count72kHz = 0; //Variabel count72kHz ist 0
while (count72kHz < 72); //warten bis count72kHz 72 hat
}


PORTD &= ~D6; //Port D6 auf low
for (i= 0; i < 1000; i++) //sieh oben
{
count72kHz = 0;
while (count72kHz < 72);
}}

return 1; //zurück zu main, wird aber nicht erreicht
}

Danke für eure Hilfe
GR Bongo

radbruch
21.09.2009, 20:00
Hallo

Zu 1: Eine Periode mit 36kHz dauert zwei Halbwellen mit 72kHz. Nach 1/72000 high, nach weiteren 1/72000 wieder low. (Ich hoffe, ich habe die Frage richtig verstanden)

Zu 2: Da mußt du leider selbst durch ;)

Zu 3: Wieviel dauert die Sekunde denn länger?

Gruß

mic