Code:
#include <avr/io.h>
#include <avr/interrupt.h>
//minimale Impulsdauer
#define tmin1 50
#define tmin2 50
#define tmin3 50
#define tmin4 50
#define tmin5 50
#define tmin6 50
#define tmin7 50
#define tmin8 50
#define tmin9 50
#define tmin10 50
#define tmin11 50
#define tmin12 50
#define tmin13 50
#define tmin14 50
#define tmin15 50
#define tmin16 50
#define tmin17 50
#define tmin18 50
//maximale Impulsdauer
#define tmax1 220
#define tmax2 220
#define tmax3 220
#define tmax4 220
#define tmax5 220
#define tmax6 220
#define tmax7 220
#define tmax8 220
#define tmax9 220
#define tmax10 220
#define tmax11 220
#define tmax12 220
#define tmax13 220
#define tmax14 220
#define tmax15 220
#define tmax16 220
#define tmax17 220
#define tmax18 220
//Skalierungsfaktor von Grad auf Impulssekunden (tmax_i-tmin_i)/180 funktionier nicht, daher zunächst korrektur durch addition von impulsdauer
#define pulsfaktor1 0.9 //... läuft nicht
//Wert zur korrektur der schief sitzenden Servohörner --> Überflüssig, wenn die skalierung läuft
signed int calibrate[19] = {0,1,1,0,8,-8,-4,-6,2,-8,1,0,-6,-6,6,4,-1,-4,-7};
volatile unsigned char timer1 = 0;
volatile unsigned char timer2 = 8;
#define ready 0
#define nextpulse 1
#define pulsestarted 2
#define pulseready 3
volatile unsigned char state = ready;
//Das Element [0] ist leer, damit die Indizes zu den servobezeichnern passen
// später sind die arrays mit richtigen winkeln gefüllt, jetzt habe dich die winkel vorab mit meinem skalierungsfaktor multipliziert.
//unsigned char angle[19] = {0,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60};
unsigned char angle[19] = {0,45,140,95,32,135,85,45,140,95,32,135,85,45,140,95,36,135,85};//stehen tief
//unsigned char angle[19] = {0,95,80,95,85,70,85,95,80,95,85,70,85,95,80,95,85,70,85};//stehen hoch
//eigentlich waren die pulse auch ein Array, aber der compiler hat gemeckert, weil ich die Einträge als Vergleichswert in einer if Bedingung benutzen wollte.
unsigned char pulse1 = 135; //Mittelstellung
unsigned char pulse2 = 135;
unsigned char pulse3 = 135;
unsigned char pulse4 = 135;
unsigned char pulse5 = 135;
unsigned char pulse6 = 135;
unsigned char pulse7 = 135;
unsigned char pulse8 = 135;
unsigned char pulse9 = 135;
unsigned char pulse10= 135;
unsigned char pulse11= 135;
unsigned char pulse12= 135;
unsigned char pulse13= 135;
unsigned char pulse14= 135;
unsigned char pulse15= 135;
unsigned char pulse16= 135;
unsigned char pulse17= 135;
unsigned char pulse18= 135;
SIGNAL (SIG_OVERFLOW0) //frisst ~7% der ProzessorLeistung
{
TCNT0 = 256 - 160; //Timer0 mit 96 neu vorladen
timer1++;
if(timer1 == 250)
{
timer1=0; //timer1 endet bei 2,5ms
timer2--; //timer2 wird im 2,5ms Intervall herabgezählt
}
if(timer2 == 0){
timer2 = 8;
state = nextpulse;} //
}
void pulsegenerator(void)
{
if(state == nextpulse) //alle 20ms alle Signalleitungen auf 1 setzen
{
PORTA |= (1 << PA0);
PORTB |= (1 << PB0);PORTB |= (1 << PB1);PORTB |= (1 << PB2);PORTB |= (1 << PB3);PORTB |= (1 << PB4);
PORTC |= (1 << PC2);PORTC |= (1 << PC3);PORTC |= (1 << PC4);PORTC |= (1 << PC5);PORTC |= (1 << PC6);PORTC |= (1 << PC7);
PORTD |= (1 << PD2);PORTD |= (1 << PD3);PORTD |= (1 << PD4);PORTD |= (1 << PD5);PORTD |= (1 << PD6);PORTD |= (1 << PD7);
state = pulsestarted;
}
if(state == pulsestarted)
{ //Signal des jeweiligen Servos beenden
if(timer1 >= pulse1){
PORTC &= ~(1 << PC7);}
if(timer1 >= pulse2){
PORTC &= ~(1 << PC6);}
if(timer1 >= pulse3){
PORTC &= ~(1 << PC5);}
if(timer1 >= pulse4){
PORTC &= ~(1 << PC2);}
if(timer1 >= pulse5){
PORTC &= ~(1 << PC3);}
if(timer1 >= pulse6){
PORTC &= ~(1 << PC4);}
if(timer1 >= pulse7){
PORTB &= ~(1 << PB2);}
if(timer1 >= pulse8){
PORTB &= ~(1 << PB3);}
if(timer1 >= pulse9){
PORTB &= ~(1 << PB4);}
if(timer1 >= pulse10){
PORTB &= ~(1 << PB1);}
if(timer1 >= pulse11){
PORTB &= ~(1 << PB0);}
if(timer1 >= pulse12){
PORTA &= ~(1 << PA0);}
if(timer1 >= pulse13){
PORTD &= ~(1 << PD4);}
if(timer1 >= pulse14){
PORTD &= ~(1 << PD3);}
if(timer1 >= pulse15){
PORTD &= ~(1 << PD2);}
if(timer1 >= pulse16){
PORTD &= ~(1 << PD5);}
if(timer1 >= pulse17){
PORTD &= ~(1 << PD6);}
if(timer1 >= pulse18){
PORTD &= ~(1 << PD7);}
}
if (timer2 <= 7){ // nach 2,5ms ist die pulsgenerierung beendet
state = pulseready;}
}
void pulsecalculator(void) //in dieser funktion bestehen die probleme mit dem skalierungsfaktor, daher zunächst die ungenaue berechnung mit konstanter anpassung angle ist jetzt kein winkel sondern eine impulsdauer, bei der 0-190 = 0-1,9ms = 0°-180° gilt. (unpraktisch)
{
pulse1 = (tmin1 + calibrate[1] + (180-angle[1])); //bei andersherum montierten servos: (180-angle)
pulse2 = (tmin2 + calibrate[2] + (180-angle[2])); //*
pulse3 = (tmin3 + calibrate[3] + (180-angle[3])); //*
pulse4 = (tmin4 + calibrate[4] + angle[4]);
pulse5 = (tmin5 + calibrate[5] + angle[5]);
pulse6 = (tmin6 + calibrate[6] + angle[6]);
pulse7 = (tmin7 + calibrate[7] + (180-angle[7]));
pulse8 = (tmin8 + calibrate[8] + (180-angle[8]));
pulse9 = (tmin9 + calibrate[9] + (180-angle[9]));
pulse10= (tmin10 + calibrate[10] + angle[10]);
pulse11= (tmin11 + calibrate[11] + angle[11]);
pulse12= (tmin12 + calibrate[12] + angle[12]);
pulse13= (tmin13 + calibrate[13] + (180-angle[13]));
pulse14= (tmin14 + calibrate[14] + (180-angle[14]));
pulse15= (tmin15 + calibrate[15] + (180-angle[15]));
pulse16= (tmin16 + calibrate[16] + angle[16]);
pulse17= (tmin17 + calibrate[17] + angle[17]);
pulse18= (tmin18 + calibrate[18] + angle[18]);
}
int main (void)
{
//Ausgänge definieren
DDRA = 0b00000001; //PA0 Servo 12
DDRB = 0b00011111; //PB0-4 Servo 11/10/7/8/9
DDRC = 0b11111100; //PC2-7 Servo 4/5/6/3/2/1
DDRD = 0b11111100; //PD2-7 Servo 15/14/13/16/17/18
//Timer0 Konfigurieren
TCNT0 = 256 - 160; //Timer0 mit 96 vorladen (10µs Timer)
TCCR0 |= (1 << CS00); //CS02/01/00 mit 001 belegen: Teiler 1
TIMSK |= (1 << TOIE0); //Timer0 Interrupt freigegeben
sei(); //Interrupts freigegeben
while(1) //Arbeitsschleife
{
pulsegenerator(); // Funktion, die alle 20ms die Servo PWMs erzeugt
if (state == pulseready) //hier können unterprogramme in der freizeit ausgeführt werden, aber nichts blockendes oder zu Zeitaufwendiges.
{
pulsecalculator(); // Wandelt Werte von Angle in Pulsweiten um.
}
}
return 1;
}
Der code ist ein horror, aber vielleicht weiß ja jemand, weshalb die multiplikation mit gebrochenrationalen zahlen so ein problem ist.
Lesezeichen