PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mal wieder Servo (greifarm), sorry



morten1027
23.07.2010, 15:32
Servus zusammen,
da ich seit ein paar Tagen mal wieder richtig Zeit für den Robby hab, habe ich mir ein Projekt überlegt, und zwar einen Greifarm.

Dazu habe ich mir bereits die M32 Platine, und drei kleine Servos besorgt.

Ansteuern wollte ich jeden der Servos über einen freien I/O Port.

So, im moment bin ich soweit dass alles funktionstüchtig montiert ist, und der erste Test (mit einen Beispielprogramm eines users hier) auch funktioniert.


Meine Fragen sind eigentlich eher grundlegend.

Und zwar geht es mir darum wie ich eben alle 3 Servos "sauber" über den Timer/Counter steuern kann.

Ich kenne bisher nur einen andren Controller der dafür eine Compare Capture Unit hat. Dadurch kann man mit einem Reloadwert die 20ms einstellen und gleichzeitig dem timer-wert mit 8 Compare-Registern vergleichen. Dadurch war es eben anhand von ganz einfachen Konfigurationen möglich, 8 unabhängige pwm-signale zu erzeugen.

Leider hat der Mega32 diese einheit nicht, und ich Frage mich wie ich mehrere dieser Signale auf ähnliche strukturierte und saubere Art, hinbekomme.

Ich hab mich auch schon recht lang in das manual des controllers eingelesen, aber die Time/count funktionen sind so umfangreich, und meiner Meinung nach auch nicht gut beschrieben, dass ich nicht 100% durchblicke.

Daher die Frage an euch, welchen Timer, in welchem Modus nehme ich.
Wie ist die Vorgehensweise im Programm. Eine Art Algorithmus (in geschriebenem Wort), wie man bei der Konfiguration und Programmierung vorgeht wäre mir eine große Hilfe.

Paralle werde ich natürlich selbst tätig und studiere weiter bis ich etwas finde.

Danke schonmal an euch :)

morten1027
24.07.2010, 14:02
langsam aber sicher komme ich mit den timer-funktionen des controllers etwas voran. Als erweiterung eines funktionierenden programmes wollte ich nun einen zweiten servo, der langsamer ist dazuhängen.

Hierzu hab ich ein paar wenige änderungen in dem programm welches in einem andren thread gefunden habe, vorgenommen. ich markiere die änderungen mal fett. Leider geht der 2 servo an entsprechendem pin nicht, vll hat jemand einen tip woran das liegt.


edit: leider erkennt es bei den code tags das fette nicht, daher ohne code tag, sorry
MFG

/************************************************** ***************************/
// Includes:

#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!

/************************************************** ***************************/
// Defines:

// RP6 Control Servo Connection:
#define SERVO_OUT IO_PD5 // PIND5 (OC1A) I/O Pin 9

// Servo movement limits (depending on servo type):
#define LEFT_TOUCH 550 // Left servo touch
#define RIGHT_TOUCH 1700 // Right servo touch
#define MIDDLE_POSITION (RIGHT_TOUCH / 2) // Middle servo position

/************************************************** ***************************/
// Variables:

uint16_t position;
uint16_t position2;

/************************************************** ***************************/
// Functions:

/**
* INIT SERVO
*
* Call this once before using the servo function.
* Timer 1 is configured to work in "Phase and Frequency
* Correct PWM Mode".
*
*/
void initSERVO(void)
{
//DDRD |= SERVO_OUT; // SERVO_OUT -> OUTPUT
DDRD = 0b01100000; // port 5 und 6 = outputrichtung
cli();
// Timer 1:
// Clear OC1A when up-counting and set OC1A when down-counting,
// mode 8 (PWM, Phase and Frequency Correct, TOP ICR1), clk/8
TCCR1A = (1 << COM1A1) //com-register A freischalten
| (0 << COM1A0)
| (1 << COM1B1) // com-register B freischalten
| (0 << COM1B0)
| (0 << FOC1A)
| (0 << FOC1B)
| (0 << WGM11)
| (0 << WGM10);
TCCR1B = (0 << ICNC1)
| (0 << ICES1)
| (1 << WGM13)
| (0 << WGM12)
| (0 << CS12)
| (1 << CS11) //clk/8
| (0 << CS10);
// Set servo pulse repetition to 50Hz (20ms):
ICR1 = 20000; // 50Hz = clk / (2 * prescaler * ICR1)
// Set servo pulse length to middle position (~1,5ms):
OCR1A = LEFT_TOUCH + MIDDLE_POSITION;
OCR1B = LEFT_TOUCH + MIDDLE_POSITION;
// Disable output compare A match interrupts:
TIMSK &= ~(1 << OCIE1A);
sei();
}

/**
* SET SERVO
*
* This is the servo positioning function.
* Because the servo is controlled by only one pulse
* each 20ms, it makes no sense calling this function
* at a higher frequency.
*
* pos = 0 : Left touch
* pos = MIDDLE_POSITION : Middle position
* pos = RIGHT_TOUCH : Right touch
*
* COMMENT: The pulse is generated by hardware PWM!
*
*/
void setSERVO(uint16_t pos,uint16_t pos2)
{
if (pos > RIGHT_TOUCH) {pos = RIGHT_TOUCH;}
OCR1A = LEFT_TOUCH + pos;
OCR1B = LEFT_TOUCH + pos2;
}

/**
* SERVO TASK
*
* This is the servo demo task.
* The positioning demo shows the servo lever rapidly
* moving to the left touch, then slowly moving to
* the right touch and so on ...
*
*/
void task_SERVO(void)
{
// -----------------------------------------------------------------------
// Your test code for positioning the servo here:
if (getStopwatch1() > 39) { // Change position every ~40ms
setCursorPosLCD(0, 0);
writeStringLCD_P("Servopos.: ");
writeIntegerLCD(position, DEC);
writeStringLCD_P(" ");
position += 50;
position2 += 8; // Next position to the right
if (position2 > RIGHT_TOUCH) {
position2 = 0; // position: 0..RIGHT_TOUCH
}
if (position > RIGHT_TOUCH) {
position = 0; // position: 0..RIGHT_TOUCH
}
setStopwatch1(0);
// -----------------------------------------------------------------------
setSERVO(position,position2); // Set the new servo position

}
}

/************************************************** ***************************/
// Main function - The program starts here:

int main(void)
{
initRP6Control(); // Always call this first! The Processor will not
// work correctly otherwise.

initLCD(); // Initialize the LC-Display (LCD)
// Always call this before using the LCD!

// Write some text messages to the LCD:
showScreenLCD("################", "################");
mSleep(1500);
showScreenLCD("<<RP6 Control>>", "<<LC - DISPLAY>>");
mSleep(2500);
showScreenLCD(" Servo - Test 2 ", " Version 1.00 ");
mSleep(2500);
clearLCD(); // Clear the whole LCD Screen

// Clear the four Status LEDs:
setLEDs(0b0000);

initSERVO();
startStopwatch1(); // Used for the demo task

while(true)
{
task_SERVO();
mSleep(5);
}
return 0;
}

Dirk
24.07.2010, 17:29
Hallo morten1027,

leider ist PD6 nicht OC1B, sondern PD4.
OC1B ist schon belegt und wird auf der RP6 Control M32 Platine für Strobe von IC3 verwendet.

Da bleibt nur Soft-PWM.

Gruß Dirk

Thund3r
01.08.2010, 01:45
Hallo

Ich bin mir jetz nicht sicher ob ich deine Frage richtig verstanden hab aber einen(oder mehrere) Servos kann man über die M32 sehr einfach ansteuern.
Du nimsmt einen freien I/O Port und benutzt folgende Methode:

void Servo(uint8_t pos)
{
DDRC |= IO_PC2; // zB IO PC2
PORTC |= IO_PC2; // Impulsstart
sleep(pos); // 1,5ms warten
PORTC &= ~IO_PC2; // Impulsende
sleep(185); // 18,5ms warten
}

dann rufst du im Hauptprogamm zB


int c;

for(c=0;c<=50;c++)
{


Servo(17); // Werte 1 -25
}

Gruß Thund3r

morten1027
01.08.2010, 11:13
hey, danke für deine Antwort.

Genau diese Methode schwebt mir im Kopf auch schon seit längerem vor, nur ist leider meine Freundin da, wo ich mich nicht drum kümmern kann... also um dem robby :D

Der einzige Nachteil daran ist, dass man bei sehr umfangreichen (haupt-)Programmen evtl. die Zyklusdauer im Kopf behalten muss, da sonst die Pausendauer von 18,5ms zu lang werden könnte. Aber das ist ja erstmal das wenigste.

Naja... kanns garnet abwarten endlich wieder am Roboter zuschrauben... (und nicht an der Freundin) hahaha, Spaß.

Machts gut, bis bald ;)

radbruch
01.08.2010, 12:42
Hallo

Die blockierende Ansteuerung der Servos mit Sleep() ist natürlich eine Sackgasse. Ich verwende nur noch diese zwei Ansätze:

Klassisch, libverträglich mit geringer Auflösung:

// Servoansteuerung mit Timer1 31.1.2010 mic

// Einfach und elegant, warum finde ich das erst jetzt? Timer1 (RP6-Motoransteuerung)
// läuft ja sowieso im Hintergrund. Deshalb kann man die "klassische" Servoansteuerung
// in die Overflow-ISR einbauen und mit ca. 19kHz aufrufen lassen. Timersetup der Lib:
// Mode 10, Phase Correct mit ICR1 als Top ergibt bei ICR1=210 ca. 8MHz/420=19047,6Hz ;)

// Drehbereich meiner RS-2-Servos ist von ca. 14 bis ca. 38

#include "RP6RobotBaseLib.h"

volatile uint8_t servo1, servo2, servo3, p; // Servopositionen und Impulszähler
uint8_t c; // ein Char zur freien Verfügung

int main(void)
{
initRobotBase();
servo1=servo2=servo3=26; // Servomitte?
TIMSK |= (1 << TOIE1); // Die Timer1 Overflow-ISR zur Servoansteuerung
DDRA |= (E_INT1); // Servopins auf Ausgang setzen
DDRC |= (SCL | SDA);
setLEDs(1); // und los!
startStopwatch1();
startStopwatch2();
startStopwatch3();
while(1)
{
for(c=0;c<6;c++) // 6 mal ein einfaches Demo....
{
setLEDs(1<<c);
servo1=servo2=servo3=26; // mitte
p=50; while(p); // warten bis 50 Impulse gesendet (ca. 1 Sek.)
servo1=servo2=servo3=14; // links
p=50; while(p);
servo1=servo2=servo3=38; // rechts
p=50; while(p);
}
setStopwatch1(0);
setStopwatch2(0);
setStopwatch3(0);
while(c) // und 6 mal ein etwas anspruchsvolleres Demo
{
setLEDs(1<<c);
if(getStopwatch1()>1000)
{
setStopwatch1(0);
switch(servo1)
{
case 38: servo1=30; break;
case 30: servo1=20; break;
case 20: servo1=14; break;
case 14: servo1=21; break;
case 21: servo1=31; break;
case 31: servo1=38; break;
}
}
if(getStopwatch2()>100)
{
setStopwatch2(0);
servo2++;
if (servo2 > 38) { servo2=14; c--; }
}
if(getStopwatch3()>300)
{
setStopwatch3(0);
if (servo3 == 10) servo3=50; else servo3=10;
}
task_RP6System(); // Verträglichkeitstest ;)
}
}
return 0;
}
ISR (TIMER1_OVF_vect)
{
static uint16_t servocount=1;
if(servocount > servo1) PORTA &= ~E_INT1; else PORTA |= E_INT1; // PA4 XBUS 8
if(servocount > servo2) PORTC &= ~SCL; else PORTC |= SCL; // PC0 XBUS 10
if(servocount > servo3) PORTC &= ~SDA; else PORTC |= SDA; // PC1 XBUS 12
if(servocount < 400) servocount++; else {servocount=1; if(p) p--;} // p = 1/50 Sek
}(Aus https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=483757#483757)

Etwas komplizierter, aber resourcenschonender:

//Servos mit Timer2 Overflow-ISR 27.2.2008 mic

#include "RP6RobotBaseLib.h"

uint8_t pos[3]={255,170,85};

int main(void)
{
initRobotBase();
DDRA |= 16;
PORTA &= ~16;
DDRC |= 3;
PORTC &= ~3;

//Timer2 Initialisierung
TCCR2 = (0 << WGM21) | (0 << COM20) | (1 << CS22); // Normal Mode, prescaler /64
TIMSK |= (1 << TOIE2); // Timer2 Overflow-Interrupt erlauben

while(1)
{
pos[0]=pos[1]=pos[2]=85;
mSleep(1000);
pos[0]=pos[1]=pos[2]=255;
mSleep(1000);
}
return(0);
}
ISR (TIMER2_OVF_vect)
{
static uint8_t servo_nr=0;
static uint16_t impulspause;
if(servo_nr)
{
if(servo_nr==1) {TCNT2=-pos[0]; PORTC |= 1; impulspause-=pos[0];}
if(servo_nr==2) {TCNT2=-pos[1]; PORTC &= ~1; PORTC |= 2; impulspause-=pos[1];}
if(servo_nr==3) {TCNT2=-pos[2]; PORTC &= ~2; PORTA |= 16; impulspause-=pos[2];}
if(servo_nr==4) {PORTA &= ~16; servo_nr=0;}
if(servo_nr) servo_nr++;
}
else
{
if(impulspause>256) impulspause-=256;
else {TCNT2=-impulspause; servo_nr++; impulspause=2000-256;}
}
}(Aus https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=46624)

Ich erspare mir jetzt die Beschreibung der verwendeten Verfahren. Bei Interesse einfach nachfragen ;)


Mal wieder Servo (greifarm), sorryIch bastle auch an einem Greifarm für meinen RP6;)

Gruß

mic

[Edit]
Ach, es geht ja um das M32. Hab' ich überlesen, sorry. Die Methoden sollten aber auch mit dem M32 funktionieren, wenn man die höhere Taktfrequenz des M32 berücksichtigt.

morten1027
05.08.2010, 16:08
Servus zusammen.

Ich hab die erste Version von Radbruch (vielen Dank dafür) mal etwas verändert und hab den Timer mal etwas anders konfiguriert - eigentlich nur die interrupt-frequenz erhöht, um eine höhere Auflösung bei der Ansteuerung zu erhalten.

Das funktioniert soweit auch super und problemlos. Werte die im Programm für links und rechts Anschlag stehen hab ich mit meinem kleinen
Modelcraft ES - 05 Servo ermittelt - durch probieren.

jetzt wollte ich aber mal an die anderen beiden ausgänge auch noch jeweils einen Servo hängen. Einer davon ist der kleine oben genannte, und der andere ein etwas größerer Modelcraft RS - 2.

Problem dabei ist, dass wenn ich den "großen" Servo dranhänge, schaltet meine Platine ab, schaut aus als würde kurz die Spannung zusammenbrechen. Das selbe passiert wenn ich zu dem kleinen, noch den andren kleinen hänge.

Jetzt ist natürlich die Frage:
Liegt das am Controller, dass dieser bei zu hohem (gesamt-)Strom abschaltet, oder liegt dass an der Spannungsversorung von der Hauptplatine?

Ich hab hier mal meine Servo-Ansteuerung angehängt, auch wenn diese vorerst nicht das Thema sein soll.

ps: zum code: ich wusste nicht ob der timer1 auf der m32 verwendet wird, und ob er so wie auf der base verwendet wird, daher habe ich ihn per Hand konfiguriert

// Servoansteuerung mit Timer1 31.1.2010 mic

// Einfach und elegant, warum finde ich das erst jetzt? Timer1 (RP6-Motoransteuerung)
// läuft ja sowieso im Hintergrund. Deshalb kann man die "klassische" Servoansteuerung
// in die Overflow-ISR einbauen und mit ca. 19kHz aufrufen lassen. Timersetup der Lib:
// Mode 10, Phase Correct mit ICR1 als Top ergibt bei ICR1=210 ca. 8MHz/420=19047,6Hz ;)

// Drehbereich meiner RS-2-Servos ist von ca. 14 bis ca. 38
/************************************************** ***************************/
// Includes:

#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!

/************************************************** ***************************/
// Variales:

volatile uint16_t servo1, servo2, servo3, p; // Servopositionen und Impulszähler
uint8_t c; // freie variable

/************************************************** ***************************/
int main(void)
{
initRP6Control();

showScreenLCD("################", "################");
mSleep(1000);
showScreenLCD("<<Mein Test", "<<LC - DISPLAY>>");
mSleep(2000);
showScreenLCD(" Servo - Test 2 ", " Version 1.00 ");
mSleep(2000);
clearLCD(); // Clear the whole LCD Screen





cli();
// Timer 1:
// Clear OC1A when up-counting and set OC1A when down-counting,
// mode 8 (PWM, Phase and Frequency Correct, TOP ICR1), clk/8
TIMSK |= (1 << TOIE1);// Die Timer1 Overflow-ISR zur Servoansteuerung

TCCR1A = (1 << COM1A1)
| (0 << COM1A0)
| (0 << COM1B1)
| (0 << COM1B0)
| (0 << FOC1A)
| (0 << FOC1B)
| (1 << WGM11) //mode10
| (0 << WGM10);//mode10
TCCR1B = (0 << ICNC1)
| (0 << ICES1)
| (1 << WGM13) //mode10
| (0 << WGM12) //mode10
| (0 << CS12) //ohne vorteiler
| (0 << CS11) //ohne vorteiler
| (1 << CS10); //ohne vorteiler

ICR1 = 50; // 8mhz/(2*100) =160 kHz
sei();

DDRC = IO_PC5 | IO_PC6 |IO_PC7 ; // Servopins auf Ausgang setzen


servo1=servo2=servo3=26; // Servomitte?
setLEDs(0b1001); // und los!
//startStopwatch1();
//startStopwatch2();
//startStopwatch3();
while(1)
{

for(c=0;c<6;c++) // 6 mal ein einfaches Demo....
{
setLEDs(1<<c);
servo1=servo2=servo3=220; // mitte
p=50; while(p); // warten bis 50 Impulse gesendet (ca. 1 Sek.)
servo1=servo2=servo3=75; // links
p=50; while(p);
servo1=servo2=servo3=365; // rechts
p=50; while(p);
}
/*
setStopwatch1(0);
setStopwatch2(0);
setStopwatch3(0);
while(c) // und 6 mal ein etwas anspruchsvolleres Demo
{
setLEDs(1<<c);
if(getStopwatch1()>1000)
{
setStopwatch1(0);
switch(servo1)
{
case 38: servo1=30; break;
case 30: servo1=20; break;
case 20: servo1=14; break;
case 14: servo1=21; break;
case 21: servo1=31; break;
case 31: servo1=38; break;
}
}
if(getStopwatch2()>100)
{
setStopwatch2(0);
servo2++;
if (servo2 > 38) { servo2=14; c--; }
}
if(getStopwatch3()>300)
{
setStopwatch3(0);
if (servo3 == 10) servo3=50; else servo3=10;
}
task_RP6System(); // Verträglichkeitstest ;)
} */
}

return 0;
}
ISR (TIMER1_OVF_vect)
{
static uint16_t servocount=1;
if(servocount > servo1) PORTC &= ~IO_PC5; else PORTC |= IO_PC5; // IO Pin 3
if(servocount > servo2) PORTC &= ~IO_PC6; else PORTC |= IO_PC6; // IO Pin 4
if(servocount > servo3) PORTC &= ~IO_PC7; else PORTC |= IO_PC7; // IO Pin 1
if(servocount < 3200) servocount++; else {servocount=1; if(p) p--;} // p = 1/50 Sek
}

Wär super wenn mir jemand einen Tip zum "Absturz" des Robbies geben kann.

Gruß!

morten1027
05.08.2010, 18:54
so, ich hab das jetzt nochmal untersucht.

Es scheint doch irgendwie am controller, oder evtl. dessen beschaltung zu tun zu haben. Denn wenn + und gnd angelötet sind, und ich wären dem Programm-ablauf den pwm anschluss auf den dementrsprechenden pin halte (ohne etwas zu überbrücken o.ä.) geht er auch kurzzeitig aus.

Und wenn ich mit dem finger den pwm anschluss auf den dementsprechenden pin halte und während dem Programmablauf den Anschluss entferne, stürzt er auch ab.

(das ganze wenn ich es nur mit dem kleinen servo probiere, der auch funktioniert wenn alles fest angelötet ist)

Irgendwie scheint es mir als wären die Port irgendwie "sensibel"...

Gut... im normalen Zustand verändert mit ja während dem Programmlauf ja nicht die Pinbelegung, aber woher es kommt dass der rp6 bei 2 kleinen, angelöteten, Servos ausgeht wüsst ich wirklich mal gerne....

Wäre super wenn jemand einen Tip hat.

RP6conrad
05.08.2010, 21:59
Servo sieht zu viel Strom und gibt ein Spannungseinbruch. Losung : getrennte Spannungsversorgung für servo und Hauptplatine. Getrennte accu (4 oder 5*1.2 Volt NiMh), Massen zusammen anschliessen an RP6/M32, der Plus von accu geht dan nur nach die Servo's. Eine zweite Spannungsregler an das RP6 accu geht auch (7805). Der puls bleibt einfach angesclhlossen an der M32

SlyD
06.08.2010, 11:10
Das Thema gab es hier schon häufiger (Suchfunktion!)
Lösung: LC Tiefpassfilter (Spule+Kondensator) in die Versorgungsleitung der Servos.
Idealerweise auch die Stromversorgung NICHT von den I/O Port Steckverbindern der M32 hernehmen (die sind nicht für sonderlich hohe Belastungen wie z.B. mehrere Servos ausgelegt!) sondern direkt von den XBUS Steckverbindern z.B. auf dem Experimentiermodul.

Noch besser: direkt ein Kabel an die VDD/GND Lötpads neben dem 5V Spannungsregler anlöten.



MfG,
SlyD

PS:

> wenn ich mit dem finger den pwm
> anschluss auf den dementsprechenden pin halte


NICHT MIT DEN FINGERN AN IRGENDWELCHEN PINS RUMTATSCHEN!!! [-X
s. Sicherheitshinweise in der Anleitung zu ESD! Das kann jede offene Elektronik beschädigen wenn man nicht vorsichtig ist.

morten1027
07.08.2010, 15:14
Nur eine kurze Meldung meinerseits:

Es lag wohl an der Überstrom-Abschaltung vom Festspannungsregler.

Der Tiefpass hat nix gebracht, auch wenn er sehr gut dimensioniert war.

Besserung brachte eine Zweite Versorung (mit festspannungsregler) die ich auf die Base gelötet hab.

Komisch ist nur dass sich ein Servo genau entgegengesetzt dreht wie er eigentlich sollte?! In "meinem" geposteten Programm sollten sich ja alle Servos gleich drehen, einer dreht komischerweise genau andersrum, irgendwie doof. Programmiermäßig zwar kein rießen Aufwand, stört aber trotzdem....

radbruch
07.08.2010, 16:20
Hallo

Ja, das ist komisch. Man kann das zwar softwaremäßig anpassen, aber da der Drehwinkel der Servos meist nicht linear ist, fahren impulsgespiegelte Servos unterschiedliche Positionen an. Abhilfe schafft dann nur ein "Umpolen" des Servos. Das würde ich auch der Softwarelösung vorziehen:

https://www.roboternetz.de/phpBB2/viewtopic.php?p=462535#462535

Gruß

mic

morten1027
09.08.2010, 20:28
Servus mal wieder.

Ich habe mal wieder eine Frage was das verändern der Library betrifft, da bin ich nämlich absoluter Neuling.
(ich hoff es is ok in dem fred)

Und war bezieht sich das auf diesen Code:


#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!

/************************************************** ***************************/
// Variables and procedures:
void configServoTimer (void);
volatile uint16_t servo1, servo2, servo3, p; // Servopositionen und Impulszähler
uint8_t c; // freie variable

/************************************************** ***************************/
int main(void)
{
initRP6Control();


showScreenLCD("################", "################");
mSleep(1000);
showScreenLCD("<<Mein Test", "<<LC - DISPLAY>>");
mSleep(2000);
showScreenLCD(" Servo - Test 2 ", " Version 1.00 ");
mSleep(2000);
clearLCD(); // Clear the whole LCD Screen



configServoTimer();
DDRC = IO_PC5 | IO_PC6 |IO_PC7 ; // Servopins auf Ausgang setzen


servo1=servo2=servo3=220; // Servomitte?
setLEDs(0b1001); // und los!

while(1)
{
showScreenLCD("In main", "<<test");
mSleep(2000);
for(c=0;c<6;c++) // 6 mal ein einfaches Demo....
{
setLEDs(1<<c);
servo1=servo2=servo3=220; // mitte
p=50; while(p); // warten bis 50 Impulse gesendet (ca. 1 Sek.)
servo1=servo2=servo3=100; // links
p=50; while(p);
servo1=servo2=servo3=340; // rechts
p=50; while(p);
}

}

return 0;
}

void configServoTimer (void) {

cli();
// Timer 1:
// Clear OC1A when up-counting and set OC1A when down-counting,
// mode 8 (PWM, Phase and Frequency Correct, TOP ICR1), clk/8
TIMSK |= (1 << TOIE1);// Die Timer1 Overflow-ISR zur Servoansteuerung

TCCR1A = (1 << COM1A1)
| (0 << COM1A0)
| (0 << COM1B1)
| (0 << COM1B0)
| (0 << FOC1A)
| (0 << FOC1B)
| (1 << WGM11) //mode10
| (0 << WGM10);//mode10
TCCR1B = (0 << ICNC1)
| (0 << ICES1)
| (1 << WGM13) //mode10
| (0 << WGM12) //mode10
| (0 << CS12) //ohne vorteiler
| (0 << CS11) //ohne vorteiler
| (1 << CS10); //ohne vorteiler

ICR1 = 50; // 8mhz/(2*100) =160 kHz
sei();
return 0;
}

ISR (TIMER1_OVF_vect)
{
static uint16_t servocount=1;
if(servocount > servo1) PORTC &= ~IO_PC5; else PORTC |= IO_PC5; // IO Pin 3
if(servocount > servo2) PORTC &= ~IO_PC6; else PORTC |= IO_PC6; // IO Pin 4
if(servocount > servo3) PORTC &= ~IO_PC7; else PORTC |= IO_PC7; // IO Pin 1
if(servocount < 3200) servocount++;
else {servocount=1; if(p) p--;} // p = 1/50 Sek
}

Wie man sieht hab ich die Konfigurationen vom Timer als ersten schritt mal in eine eigene Procedur gepackt.
Jetzt hab ich mir gedacht ich schreibe diese Prozudur in die Lib rein, damit sie "weg" ist.

Also hab ich die Procedur erstellt und in die rp6control lib.c gepackt und compiliert. Im mainprogramm gibt es jetzt aber das problem dass die procedur wenn ich sie aufruf nicht "erkannt" wird.

Wie gesagt, so wie ich es getan hätte wäre es für mich logisch gewesen, aber ich hab auch noch nie eine Lib verändert, von daher kann ich auch irgendetwas vergessen hab.


PS: GANZ komisch ist, (das hab ich zuerst versucht) dass ich die ISR in die lib packe. komischerweiße wird die while schleife dann überhaupt nicht abgearbeitet. Das main-programm fängt immer wieder von vorne an?!?

Wär super wenn mir jemand Hilfestellung geben könnte :)

RP6conrad
09.08.2010, 21:19
Haben sie auch diese Function in den rp6controllib.h gepackt ? Da muss ess auch declariert werden, aber nur die "heading". Die eigentliche function bleibt in controllib.

morten1027
09.08.2010, 21:25
Haben sie auch diese Function in den rp6controllib.h gepackt ? Da muss ess auch declariert werden, aber nur die "heading". Die eigentliche function bleibt in controllib.

Das ist mir in Nachhinein auch gekommen.
Also hab ich sie dort auch deklariert, aber es kommt immernoch der selbe Fehler...

Aber mehr ist normal nichts zu tun oder, ich mal eine kleine Übersicht (so wie ICH denke):

1. Komplette Funktion in die rp6controllib.c schreiben
2. Den funktionskopf in der Headerdatei deklarieren
3. Im Hauptprogramm die Funktion aufrufen

radbruch
09.08.2010, 21:26
clean und make all?

In Mode 10 zählt der Timer von 0 bis ICR1 und wieder zurück, Takt bei M32 ist dann bei ICR1=50 etwa 16MHz/100=160kHz ;)

Gruß

mic