Lieber Besucher, herzlich willkommen bei: RCLine Forum. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

^____

RCLine User

  • »^____« wurde gesperrt

Wohnort: anonymisiert

Beruf: anonymisiert

  • Nachricht senden

21

Sonntag, 27. September 2009, 10:50

Hallo Helmut,

Nein, Du hast das richtig beschrieben. ich hatte nur den Eindruck, dass hier ein paar andere diese Vermutung hatten. Ich kann mich aber auch täuschen.
Stefan redet von seiner Schaltung und andere von uP's und initialisierung. Das war oft etwas wirr, denn nicht alle Srvo's haben uP's drin.

Gruss Bruno

wurpfel1

RCLine User

Wohnort: CH-rheintal

  • Nachricht senden

22

Sonntag, 27. September 2009, 12:52

hi leutz

die meisten servos haben sehr aggressive lageregler, der kunde wünscht ja "harte" reaktionen.
beim einschalten kann dass unerwünschte bewegungen zur folge haben :wall:


analoge schaltungen habe ich seit einigen jahren keine mehr gesehen, hier war es "einfach" mit etwas mehr C die reaktionen zu entschärfen.


heutige servo-uP sollten so programmiert werden dass bei fehlendem impulssignal nichts passiert, dh das ding verharrt im hold..
zuckt da irgendwas rum würde ich mal den impulsausgang der signalquelle anschauen, könnte ja sein dass hier die hausaufgaben nicht gemacht wurden und "wilde" strobs erzeugt werden. hier würde ein optokoppler und//oder ein aktiver tiefpass helfen.


besser wäre es die initialisierung der quelle "richtig" zu machen: es ist wirklich keine sache innert 50ms nach dem einschalten für jedes angeschlossene servo einen 1,5ms impuls mit 50Hz bereitzustellen.



das problem von Stefan löst OPENSERVO durch ersatz der servoelektronik grundsätzlich :evil:
neben dem feedback von stellung, stromverbrauch und motortemperatur stehen sequencer, erhöhte genauigkeit sowie alle PID-parameter zur verfügung.
es ist keine sache das servo ohne motor zu starten und dann SANFT die nullstellung anzufahren. im betrieb sind aggressive settings für reaktion und speed möglich.
wenn du willst kannst du einige platinen haben, selbstbau ist aber keine sache da open source :angel:





übrigends ;)
bei vielen servos im system ist es zudem notwendig der spannungsversorgung etwas mehr aufmerksamkeit zu widmen.
bin schon zu alt zum spielen.. macht aber gleichwohl spass ;-)

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »wurpfel1« (27. September 2009, 13:12)


swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

23

Montag, 28. September 2009, 07:27

Hallo zusammen,

ich muss gestehen dass das Servo, welches in den Endanschlag fuhr, nur gemacht hat was ich ihm gesagt habe.... :nuts: cih habe das Programm immer schrittweise für ein Servo geschrieben und auf Funktion getestet, beim einfügen des Codes für das zweite Servo bin ich mit einer Klammer verrutscht.

Das Zucken beim Einschalten ist nach einem Test am lebenden Objekt als relativ unkritisch zu sehen. Ich möchte es jedoch trotzdem weitgehend ausschalten, da die Drehachsen der angelenkten Türen konstruktionsbedingt aus Kunststoff sind.

Die Initialisierung des µC ist wie folgt:
- 16 kCycles + 14 kCycles + 64ms für einen 16MHz Quarz
- OCR1x auf Ausgang
- Timer 1 Initialisieren, OCR1x auf 1500 µs, ICP1 auf 20000 µs, Prescaler 8
- LED Ports auf Ausgang
- Tastenports auf Eingang
- Timer 0 initialisieren für Tastenabfrage

Wenn ich das richtig sehe, ist die einzige Möglichekeit zur Optimierung die Initialisierung des µC. Da möchte ich aber sehr vorsichtig sein, da ich die Güte der Spannungversorgung nicht vorraussehen kann. Die Versorgung soll über ein Steckernetzteil und einen 5V Längsregler erfolgen, allerdings soll das Gerät auch im nichteuropäischen Ausland eingesetzt werden.

Hier könnt Ihr sehen, worum es eigentlich geht: TRENT700

Gruß,
Stefan

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »swessels« (28. September 2009, 07:29)


wurpfel1

RCLine User

Wohnort: CH-rheintal

  • Nachricht senden

24

Montag, 28. September 2009, 08:20

hi Stefan

wenn die initialisierung passt kommt das zuck-problem von der servoelektronik, das lässt sich grundsätzlich nur durch ersatz mit openservo lösen.

der code sollte auch auf einem ATm88 zum laufen zu bringen sein, als leistungsstufe taugt ein ULN2803, eine schrittmotorendstufe L298 oder sonst ne käufliche H-brücke.

ein vorteil für deine anwendung ist das abfahren von bewegungsprofilen, zb langsam die türe aufmachen, schnell öffnen und sanft zuziehen. mit der strombegrenzung lässt sich gleich noch das abrauchen beim einklemmen von fremdkörpern verhindern.

openservo beseitigt servo-alzheimer durch poties, es ist die einzige möglichkeit mehrere servos hintereinander auf einem tastarm oder roboterbein zuverlässig laufen zu lassen.
ausgeführt wurden achtfüssige spinnen mit 40servos, das teil bewegt sich absolut fliessend ohne zucker ==[]
bin schon zu alt zum spielen.. macht aber gleichwohl spass ;-)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »wurpfel1« (28. September 2009, 08:22)


swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

25

Montag, 28. September 2009, 10:38

Hallo wurpfel,

ich habe mir openservo mal kurz angesehen, gefällt mir gut. Allerdings bekomme ich die Elektronik wohl nicht in ein HS125 hinein.

Das Ruckeln im Film kommt daher, dass wir sicherheitshalber manuell mit großen Schritten gefahren haben und die Mechanik noch nicht spielfrei ist.

Beim Einschalten fahre ich die SErvos erst einmal in Mittelstellung, dann sollte es gehen.

Gruß,
Stefan

wurpfel1

RCLine User

Wohnort: CH-rheintal

  • Nachricht senden

26

Montag, 28. September 2009, 20:22

hi Stefan

die elektronik muss nicht ins servo, mit fünf drähten kann man die einige 10cm weit weg platzieren. oft kann man die Hbrücke des servos von aussen ansteuern :w


die ULN2803-lösung passt sowieso nur in monsterservos oder zb ein selbstbau-EZFW ;)



da openservo offengelegt ist kann man sich vom code inspirieren lassen.
bin schon zu alt zum spielen.. macht aber gleichwohl spass ;-)

27

Dienstag, 29. September 2009, 09:31

Hallo Stefan,

warum nimmst Du nicht einfach Digital-Servo's? Vom Preis her sind die Teile heutzutage erschwinglich; und in diversen Groessen erhaeltlich.

Einschaltzucker treten definitiv nicht auf, zumindest bei FUTABA Servos. Initialisierunsprobleme sind bei uP-Schaltungen eigentlich per Definition ausgeschlossen, sauberes Design vorausgesetzt.

Achim

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

28

Dienstag, 29. September 2009, 13:18

Hallo Achim,

Zitat

warum nimmst Du nicht einfach Digital-Servo's


Die HS125 sind bereits vorhanden und in das Modell eingepasst. Ausserdem darf in einer großen Firma ja alles nichts kosten... :shake:

@wurpfel:
Für das nächste Projekt werde ich das alles mal ins Auge fassen. Das hier steht kurz vor der Fertigstellung, da ist nicht mehr viel Zeit.

Gruß,
Stefan

wurpfel1

RCLine User

Wohnort: CH-rheintal

  • Nachricht senden

29

Dienstag, 29. September 2009, 21:05

hi Stefan

wird schon klappen, viel erfolg!





@Achim
openservo sind RICHTIGE digitalservos :angel:
und deutlich preiswerter als was gekauftes..
bin schon zu alt zum spielen.. macht aber gleichwohl spass ;-)

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

30

Mittwoch, 30. September 2009, 07:34

Hallo wurpfel,

danke für die Aufmunterung. ;)
Ich lasse mir da noch was einfallen, wie ich bei fallender Versorgungsspannung die Servos in Neutrallage bringen kann. Dann sollte es keine Probleme mehr geben.

Gruß,
Stefan

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

31

Dienstag, 6. Oktober 2009, 07:13

Servozucken -- ich bin ein Esel

Hallo zusammen,

das Zucken ist jetzt weg bzw. nicht fühlbar.

Ursache:
Die Spannungsversorgung hat den Einschaltstromstoß nicht verkraftet. Man sollte so etwas nicht mit einem Steckernetzteil 9V / 300 mA (mein Experimentiernetzteil) versorgen :wall: :wall:

Gruß,
Stefan

32

Dienstag, 6. Oktober 2009, 12:08

RE: Servozucken -- ich bin ein Esel

Das bestätigt ja wieder mal die alte Elektroniker-Regel: meistens ist das Netzteil schuld!

Grüße
Malte

33

Dienstag, 6. Oktober 2009, 16:20

Zitat

Original von swessels
das Zucken ist jetzt weg bzw. nicht fühlbar.


endlich angekommen in der Realen Welt der Elektronik...

Vermutlich gabs dazuhin auch noch mehrfache Resets beim Microcontroller.

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

34

Mittwoch, 7. Oktober 2009, 08:22

Hallo zusammen,

Zitat

meistens ist das Netzteil schuld


nö, das Netzteil kann nichts dafür, nur der ESEL der kein passendes auswählt.

Zitat

endlich angekommen in der Realen Welt der Elektronik...


Ich gebe zu, dass ich da etwas aus der Übung bin, aber man lernt ja wieder dazu...

Gruß,
Stefan

35

Mittwoch, 7. Oktober 2009, 14:57

Schuld im technischen, nicht im moralischen Sinne .

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

36

Mittwoch, 14. Oktober 2009, 12:33

Seltsames Phänomen

Hallo zusammen,
ich stehe hier vor einem Problem: Meine Schaltung funktionert auf dem Steckbrett einwandfrei, auf der Streifenrasterplatine zeigen sich seltsame Effekte.

Es geht um die Ansteuerung zweier Servos. Es gibt 3 Tasten, eine zum fahren in jede Richtung und eine zum umschalten von Manuell auf Automatik und umgekehrt.
Der jeweilige Betriebszustand wird durch LEDs sinalsiert.

Sollverhalten:
- Beim Einschalten / Reset sollen die Servos auf Mittelstellung fahren
- Beim kurzen drücken einer Richtungstaste fahren die Servos einen Schritt in die jeweilige Richtung
- Beim langen drücken einer Richtungstaste fahren die Servos in die jeweilige Endstellung
- Beim drücken der Umschalttaste wird zwischen den Modi gewechselt
- Im Automatikbetrieb fahren die Servos schrittweise von Endstellung zu Endstellung, jeweils mit 2 Sekunden Pause

Auf dem Steckbrett klappt das auch alles.

Auf der Platine passiert folgendes:
- Einschalten / Reset ok
- Umschalten der Modi ok
- beim kurzen drücken der Richtungstasten wird in die jeweilige Richtung gefahren, aber nur bis zur Mitte
- beim langen drücken der Richtungstaste wird jeweils die selbe Endstellung angefahren
- in beiden modi ist der Weg auf die Hälfte reduziert, d.h. die Mittelstellung von 1,5ms ist ein Anschlag

Die einzige Modifikation sind andere Vorwiderstände für die LEDs (220R statt 1k), da in der realen Schaltung keine Lowpower LEDs verwendet werden. Die Tasten sind mit 220R gegen Masse geschaltet.

Habt Ihr da ne Idee?

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
//Steuerprogramm Für TRENT 700 Modell
//(c) 2009 Stefan Weßels, all rights reserved
//$VERSION 0
//$MINOR 3

//defines
#ifndef F_CPU
    #define F_CPU 16000000UL
#endif
#define MAN 0
#define AUTO 1
#define OPEN 0
#define CLOSE 1

//end defines

//includes
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include "keys.h"
#include "servo.h"
#include <util/delay.h>
//end includes

//function prototypes
void init(void);
void manual_cont(void);
void auto_cont(void);
//end function prototypes

//variables
struct {
    unsigned s0mode:1;            //Laufrichtung, siehe servo.h
    unsigned s1mode:1;            //Laufrichtung, siehe servo.h
    unsigned door_direction:1;    //Richtung der Doors
    unsigned mode:1;            //Betriebsmodus
    unsigned pgm:1;                //Programmiermodus 0 -> nein, 1 -> ja
    unsigned valid_data:1;        //Sinnvolle daten EEPROM? 0 -> nein, 1 -> ja
} flags;

servo servo0;
servo servo1;
//end variables

int main(void) {

init();

PORTC |= (1<<PC2);    //Power LED an

while(1) {
    //Modus auswählen
    if(get_key_press(1<<KEY2)) {
        if(flags.mode == 0)
            flags.mode = 1;
        else if(flags.mode == 1)
            flags.mode =0;
    }
    
    //Manueller Modus
    if(flags.mode == MAN) {
        TIMSK1 &= ~(1<<TOIE1);    //Timer 1 Overflow Interrupt abschalten
        PORTC |= (1<<PC0);        //MAN LED an        
        PORTC &= ~(1<<PC1);        //AUTO LED aus
        manual_cont();
    }
    
    //Automatischer Modus
    else if(flags.mode == AUTO) {
        if(servo0.pos >= servo0.max || servo0.pos <= servo0.min || servo1.pos >= servo1.max || servo1.pos <= servo1.min) {
            if(flags.door_direction == OPEN) {
                flags.door_direction = CLOSE;
            }
            else if(flags.door_direction == CLOSE) {
                flags.door_direction = OPEN;
            }
        }
            _delay_ms(2000);
        TIMSK1 |= (1<<TOIE1);    //Timer 1 Overflow Interrupt einschalten
        PORTC |= (1<<PC1);        //AUTO LED ein
        PORTC &= ~(1<<PC0);        //MAN LED aus
    }
}
return(1);
}

void init(void) {

    //LED Port, OCR1x Ports auf Ausgang
    DDRC |= (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5);
    PORTC = 0x00;
    DDRB |= (1<<PB1) | (1<<PB2);

    //Tasten
    keys_init();

    //Grundeinstellungen Flags
    flags.s0mode = REV;
    flags.s1mode = NORM;
    flags.door_direction = OPEN;
    flags.mode = MAN;
    flags.pgm = 0;
    flags.valid_data = 0;

    //Grundeinstellungen Servos
    /*
        TO DO: Abfrage auf sinnvolle EEPROM Daten
    */
    if(flags.valid_data == 0) {
        //sinnvolle defaults
        servo0.min = SERVOMIN;
        servo0.max = SERVOMAX;
        servo0.center = SERVOCENTER;
        servo0.pos = SERVOCENTER;
        servo1.min = SERVOMIN;
        servo1.max = SERVOMAX;
        servo1.center = SERVOCENTER;
        servo1.pos = SERVOCENTER;
    }
    else if(flags.valid_data == 1) {
        //TO DO
    }
    
    //Timer0, Mode PWM
    ICR1=SERVOFRAME;
    OCR1A=servo0.pos;
    OCR1B=servo1.pos;
    
    TCCR1A |= (1<<COM1A1) | (1<<COM1B1) |(1<<WGM11);
    TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS11);

    //global Interrupt enable
    sei();
}    
void manual_cont(void) {
    //Wenn Taste 0 (Close) kurz gedrückt wird schrittweise zufahren
    if(get_key_short(1<<KEY0)) {
        if(flags.s0mode == NORM && servo0.pos < servo0.max) {
            servo0.pos +=STEP;
        }
        if(flags.s0mode == REV && servo0.pos > servo0.min) {
            servo0.pos -= STEP;
        }
        if(flags.s1mode == NORM && servo1.pos < servo1.max) {
            servo1.pos +=STEP;
        }
        if(flags.s1mode == REV && servo1.pos > servo1.min) {
            servo1.pos -= STEP;
        }
    }
    
    //Wenn Taste 0 (Close) lang gedrückt wird komplett zufahren
    if(get_key_long(1<<KEY0)) {
        if(flags.s0mode == NORM) {
            servo0.pos = servo0.max;
        }
        if(flags.s0mode == REV) {
            servo0.pos = servo0.min;
        }
        if(flags.s1mode == NORM) {
            servo1.pos = servo1.max;
        }
        if(flags.s1mode == REV) {
            servo1.pos = servo1.min;
        }
    }
            
    //Wenn Taste 1 (Open) kurz gedrückt wird schrittweise auffahren
    if(get_key_short(1<<KEY1)) {
        if(flags.s0mode == NORM && servo0.pos > servo0.min) {
            servo0.pos -=STEP;
        }
        if(flags.s0mode == REV && servo0.pos < servo0.max) {
            servo0.pos += STEP;
        }
        if(flags.s1mode == NORM && servo1.pos > servo1.min) {
            servo1.pos -=STEP;
        }
        if(flags.s1mode == REV && servo1.pos < servo1.max) {
            servo1.pos += STEP;
        }
    }        
            
    //Wenn Taste 1 (Open) lang gedrückt wird komplett auffahren
    if(get_key_long(1<<KEY1)) {
        if(flags.s0mode == NORM) {
            servo0.pos = servo0.min;
        }
        if(flags.s0mode == REV) {
            servo0.pos = servo0.max;
        }
        if(flags.s1mode == NORM) {
            servo1.pos = servo1.min;
        }
        if(flags.s1mode == REV) {
            servo1.pos = servo0.max;
        }
    }
    OCR1A = servo0.pos;
    OCR1B = servo1.pos;
}

ISR(TIMER1_OVF_vect) {
    if(flags.door_direction ==OPEN) {
        if(flags.s0mode == NORM && servo0.pos > servo0.min) {
            servo0.pos -=ASTEP;
        }
        if(flags.s0mode == REV && servo0.pos < servo0.max) {
            servo0.pos += ASTEP;
        }
        if(flags.s1mode == NORM && servo1.pos > servo1.min) {
            servo1.pos -=ASTEP;
        }
        if(flags.s1mode == REV && servo1.pos < servo1.max) {
            servo1.pos += ASTEP;
        }
    }
    
    if(flags.door_direction == CLOSE) {
        if(flags.s0mode == NORM && servo0.pos < servo0.max) {
            servo0.pos +=ASTEP;
        }
        if(flags.s0mode == REV && servo0.pos > servo0.min) {
            servo0.pos -= ASTEP;
        }
        if(flags.s1mode == NORM && servo1.pos < servo1.max) {
            servo1.pos +=ASTEP;
        }
        if(flags.s1mode == REV && servo1.pos > servo1.min) {
            servo1.pos -= ASTEP;
        }
    }    
    OCR1A = servo0.pos;
    OCR1B = servo1.pos;
}


Weiterer Code siehe nächsten Beitrag

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

37

Mittwoch, 14. Oktober 2009, 12:37

RE: Seltsames Phänomen

weiter gehts...

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/****************************************************************************************/
/*                                                                                        */
/*        Tastenentprellung  nach Peter Danneger, vielen Dank!        */
/*                                                                                        */
/****************************************************************************************/    

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "keys.h"

//Keys
volatile uint8_t key_state;                                    // debounced and inverted key state:
                                                              // bit = 1: key pressed
volatile uint8_t key_press;                                    // key press detect
 
volatile uint8_t key_rpt;                                      // key long press and repeat

ISR( TIMER0_OVF_vect )                                        // every 1ms
{
    static uint8_t ct0, ct1, rpt;
    uint8_t i;

        i = key_state ^ ~KEY_PIN;                       // key changed ?
        ct0 = ~( ct0 & i );                             // reset or count ct0
        ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
        i &= ct0 & ct1;                                 // count until roll over ?
        key_state ^= i;                                 // then toggle debounced state
        key_press |= key_state & i;                     // 0->1: key press detect

        if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
            rpt = REPEAT_START;                         // start delay
        if( --rpt == 0 ){
            rpt = REPEAT_NEXT;                          // repeat delay
            key_rpt |= key_state & REPEAT_MASK;
        }
}
 
void keys_init(void)
{
    //Keys
    KEY_DDR |= ALL_KEYS;
    KEY_DDR &= ~ALL_KEYS;                    // konfigure key port for input
      KEY_PORT |= ALL_KEYS;                    // and turn on pull up resistors
     //configure Timer0, 10ms
    OCR0A=77;
      TCCR0A |= (1<<WGM01) | (1<<WGM00);
    TCCR0B |= (1<WGM02) |(1<<CS02) | (1<<CS00);                    
      TIMSK0 |= (1<<TOIE0);                        // enable timer interrupt
}

///////////////////////////////////////////////////////////////////
//
// check if a key has been pressed. Each pressed key is reported
// only once
//
uint8_t get_key_press( uint8_t key_mask ) {
    cli();                                          // read and clear atomic !
    key_mask &= key_press;                          // read key(s)
    key_press ^= key_mask;                          // clear key(s)
    sei();
    return key_mask;
}

uint8_t get_key_short(uint8_t key_mask) {
    cli();
    return get_key_press(~key_state & key_mask);
}

uint8_t get_key_long(uint8_t key_mask) {
    cli();
    return get_key_press(get_key_rpt(key_mask));
}
 
///////////////////////////////////////////////////////////////////
//
// check if a key has been pressed long enough such that the
// key repeat functionality kicks in. After a small setup delay
// the key is reported beeing pressed in subsequent calls
// to this function. This simulates the user repeatedly
// pressing and releasing the key.
//
uint8_t get_key_rpt( uint8_t key_mask ) {
    cli();                                          // read and clear atomic !
     key_mask &= key_rpt;                            // read key(s)
    key_rpt ^= key_mask;                            // clear key(s)
    sei();
    return key_mask;
}


Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#ifndef KEYS_H
#define KEYS_H

/****************************************************************************************/
/*                                                                                        */
/*        Tastenentprellung nach Peter Danneger, vielen Dank!                                */
/*                                                                                        */
/****************************************************************************************/    

#ifndef F_CPU
#error "F_CPU not defined!"
#endif


//Ports und Pins anpassen
//Taster
#define KEY_DDR         DDRD
#define KEY_PORT        PORTD
#define KEY_PIN         PIND
#define KEY0            7
#define KEY1            6
#define KEY2            5
#define ALL_KEYS        (1<<KEY0 | 1<<KEY1 | 1<<KEY2) 
#define REPEAT_MASK     (1<<KEY0 | 1<<KEY1)     // repeat: key1
#define REPEAT_START    30                      // after 300ms
#define REPEAT_NEXT     10                      // every 100ms


// Timer 0 Initialisieren

extern void keys_init(void);

// check if a key has been pressed. Each pressed key is reported only once

extern uint8_t get_key_press( uint8_t key_mask );

extern uint8_t get_key_short(uint8_t key_mask);

extern uint8_t get_key_long(uint8_t key_mask);

// check if a key has been pressed long enough such that the
// key repeat functionality kicks in. After a small setup delay
// the key is reported beeing pressed in subsequent calls
// to this function. This simulates the user repeatedly
// pressing and releasing the key.
//
extern uint8_t get_key_rpt( uint8_t key_mask );

#endif //KEYS_H


Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef SERVO_H
#define SERVO_H

//servo values
#define SERVOMAX 3799
#define SERVOMIN 2199
#define SERVOCENTER 2999
#define SERVOFRAME 29999
#define NORM 0
#define REV 1
#define STEP 50
#define ASTEP 10
//
//types
typedef struct {
    uint16_t min;
    uint16_t max;
    uint16_t center;
    volatile uint16_t pos;
} servo;
//end types
#endif //SERVO_H


so, das wars. Ich glaube zwar nicht das da estwas nicht stimmt, aber....

Gruß,
Stefan

38

Mittwoch, 14. Oktober 2009, 15:22

Deine globale Variable 'flags' wird in der ISR gelesen, ist aber nicht volatile. Eventuell wird sie also in der while(1) schleife in ein Register optimiert und steht in der ISR nicht zur Verfügung?

Und Regel1: Hast Du mal die Versorgungsspannung gecheckt (und 'nen kleinen Kondensator zwischen den Versorgungspins des Prozzies?)

Grüße
Malte

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

39

Donnerstag, 15. Oktober 2009, 12:26

Hallo Malte,

danke für Deine Mühe.

Die Variable "flags" wird in der ISR nicht verändert, muss also nach meinem Kenntnisstand nicht volatile sein.
Sollte es daran liegen dürfte es eigentlich auch auf dem Steckbrett nicht funktionieren.

Stromversorgung:
Ich verwende das CRUMB168USB von chip45.com, da ist alles drauf. Ansonsten ist da noch ein 100µF Elko direkt an den Sevoanschlüssen.
Das Problem tritt mit Steckerschaltnetzteilen und auch mit stabilisierter Spannung durch einen LM1084 auf, aber nur auf der Lochrasterplatine... :(

Ich werde die Schaltung noch einmal neu aufbauen, vielleicht sehe ich den Wald vor lauter Bäumen nicht....

Gruß,
Stefan

40

Donnerstag, 15. Oktober 2009, 13:03

Die Variable 'flags' wird aber im Hauptprogramm verändert. Wenn der Compiler sie dort in ein Register optimiert, bekommt die ISR diese Veränderung nicht mit!
Das Problem kann nach meinem Verständnis in beiden Richtungen auftreten. Welchen Grund sollte es geben, der dagegen spricht?


Wenn Dein Binärcode 100% identisch ist und es beides mal 168er sind, muss ein Fehler in der Verdrahtung vorliegen.

Wie sollen wir den aus der Source erkennen?


Grüße
Malte

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »DrM« (15. Oktober 2009, 13:05)