Hallo, Ich hab da nen kleines Problem. Mein Ziel ist es über einen Atmega8 8 Servos an zu Steuern, dass heißt ich habe 5 Servo Eingänge, wovon 4 jeweils auf 4 Servoausgänge geschaltet werden. Die Umschaltung erfolgt über den 5. Eingang. Die Servos die nicht angesteuert werden sollen dann in eine Defaultposition fahren. Diese Defaultpositionen sollen dann über 3 Taster (INC,DEC,SERVO) eingestellt werden. Momentan bin ich erstmal dabei das Programm für die Defaultpositionierung zu scheiben. Dazu lege ich über einen Timer den 20ms Puls für alle Servos fest und über einen Counter für jedes Servos die entsprechende Länge des Puls. Das Funktioniert soweit. Wenn ich jetzt allerdings eine der Tasten drücke macht der ganze Atmel einen Neustart, dies habe ich nur herausfinden können weil das Servo Kurz zuckt und wieder in die Ausgangsposition fährt. Testweise hatte ich nach dem Incrementieren oder Decrementieren die Werte in den EEPROM übernommen, dann hatte das Servo die Position auch nach dem Neustart gehalten, nur leider ist das erstens unschön, und zweitens macht das Servo beim Starten des Atmels natürlich erstmal Sprünge bis die Werte aus dem EEPROM wieder geladen sind. Jetzt meine Frage, kann es was mit der Doppelbelegung der Ports zu tun haben, oder wie ich die Tasten angeschlossen habe? Ich bin ziemlich ratlos.
Sven Fabricius schrieb: > Wenn ich jetzt allerdings eine der Tasten drücke macht der ganze Atmel > einen Neustart, dies habe ich nur herausfinden können weil das Servo > Kurz zuckt und wieder in die Ausgangsposition fährt. Wenn ein Servo anfährt und dein µC in diesem Moment abstürzt, dann liegt das Problem in der Versorgungsspannung. Servos können ziemliche Schweine sein, bei dem was sie auf der Versorungsspannung an Schmutz einkoppeln. Den musst du loswerden. Am besten wäre es, wenn die Servos ihre eigene Versorgungsspannung komplett getrennt von der µC-Versorgungsspannung hätten. Wenn das nicht geht, musst du Spulen und oder Kondensatoren einbauen, die dir den Schmutz vom µC fernhalten. Das du dem Mega8 nicht mal die üblichen 100nF an den Versorgungspins spendiert hast, ist eigentlich nur mit einem Wort zu beschreiben: leichtsinnig
>Das du dem Mega8 nicht mal die üblichen 100nF an den Versorgungspins >spendiert hast, ist eigentlich nur mit einem Wort zu beschreiben: >leichtsinnig Noch leichtsinniger ist es die 330nF zu schalten. Wenn die leer sind ziehen sie beim schalten kurzfristig sehr viel Strom. Die 330nF gehören parallel zum Schalter und nicht zum Pullup/down.
Den 100nF hatte ich jetzt in der Zeichnung nicht berücksichtigt, ist aber drinne. Hatte das ganze auf nem Streifenraster aufgebaut. Habe zur Spannungsversorung mal 5V 1,5A angeschlossen und gehofft das würde helfen. Das komische ist, dass der Atmel auch resettet auch wenn ich die Servo Wechsel Taste drücke die garkeine Positionsveränderung auslößt.
Das mit dem Taster hatte ich einfach blanco von nem Eval Board übernommen, aber werd die mal parallel drauf schalten.
Sven Fabricius schrieb: > Das mit dem Taster hatte ich einfach blanco von nem Eval Board > übernommen, aber werd die mal parallel drauf schalten. Lass sie weg. Tastenentprellen kann man prima in Software. http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29 Da kriegst du dann als Zugabe auch noch gratis, dass du auf dem Taster draufbleiben kannst, und die Entprellroutine liefert dir ständig Tastendruck-Impulse. Ideal für dich, oder willst du die Defaultposition von links nach rechts ändern, indem du 200 mal auf die Taste drückst? Und Tasten baut man bei AVR's so ein, dass sie nach Masse schalten. Dann kann man den im µC eingebauten Pullup Widerstand benutzen.
Ok, war mir mit den Tasten immer nicht so sicher, im bezug auf Fehlerquellen. Wenn ich die Tasten gegen Masse schalte, dann muss ich die Abfrage der Tasten dann aber invertiern, oder?
Sven Fabricius schrieb:
> Ach ne, sorry hab mich verguckt
Nein, stimmt schon.
Aber wenn du die verlinkten Source Code Quelle benutzt, brauchst du dich
nicht mehr um die Details kümmern. Einfach ein paar #define richtig
stellen und so wie in der Demo gezeigt abfragen. Fertig.
1 | #define KEY_DDR DDRC
|
2 | #define KEY_PORT PORTC
|
3 | #define KEY_PIN PINC
|
4 | #define KEY_SELECT 0
|
5 | #define KEY_LEFT 1
|
6 | #define KEY_RIGHT 2
|
7 | #define ALL_KEYS (1<<KEY_SELECT | 1<<KEY_LEF | 1<<KEY_RIGHT)
|
8 | |
9 | #define REPEAT_MASK (1<<KEY_LEFT | 1<<KEY_RIGHT)
|
10 | |
11 | ....
|
12 | |
13 | |
14 | #define NR_SERVOS 5
|
15 | |
16 | uint8_t ServoNr; |
17 | uint8_t ServoPos[NR_SERVOS]; |
18 | |
19 | ...
|
20 | |
21 | int main() |
22 | {
|
23 | |
24 | ...
|
25 | |
26 | ServoNr = 0; |
27 | |
28 | while(1){ |
29 | if( get_key_short( 1<<KEY_SELECT )) { |
30 | ServoNr++; |
31 | if( ServoNr == NR_SERVOS ) |
32 | ServoNr = 0; |
33 | }
|
34 | |
35 | if( get_key_press( 1<<KEY_LEFT ) || get_key_rpt( 1<<KEY_LEFT )) { |
36 | ServoPos[ ServoNr ]++; |
37 | }
|
38 | |
39 | if( get_key_press( 1<<KEY_RIGHT ) || get_key_rpt( 1<<KEY_RIGHT )) { |
40 | ServoPos[ ServoNr ]--; |
41 | }
|
42 | |
43 | ...
|
44 | }
|
45 | }
|
danke, werde das heute Abend testen, das mit dem array ist ne super idee, hatte daran noch garnicht gedacht.
Hallo, ich habe genau dasselbe Problem mit Atmega32 auf Pollin-Atmel-Evaluationsboard-V201. Die Beschaltung der Taster 33k/330n scheint vom Pollin-Board zu sein. Getrennte Versorgung des Servo bringt bei mir keinen Unterschied. Tastendrücke führen gelegentlich/häufig zu Reset. Kann das jemand bestätigen, dass die Ladestromspitzen bei der Beschaltung einen Reset auslösen können? Ist das bei dem Pollin-Atmel-Evaluationsboard-V201 so? Danke Josh
Bestätigen kann ich das nicht, aber es ist möglich, da ich die Schaltung der Taster auch übernommen habe.
Josh schrieb: > Getrennte Versorgung des Servo bringt bei mir keinen Unterschied. > Tastendrücke führen gelegentlich/häufig zu Reset. Teste es doch einfach mal indem du den Servo abklemmst. Drückst du dann einen Taster und er resetet immer noch, lag es am Servo. Aus meiner Erfahrung kann ich sagen, dass die Servos unheimlich die Versorgung versauen. Daher auf jeden Fall entkoppeln. Am einfachsten ein zweites Netzteil dazu hängen und GNDs verbinden. Oder ein zweiter 7805. 1,5A erscheint mir für 8 Servos, die gleichzeitig bewegt werden zu knapp. Kommt natürlich auf die Größe und die Last an.
Später soll das ganze über eine entsprechende Versorgung ermöglicht werden, aber momentahn ist 1 maximal 2 Servos dran zum testen.
Ich habe jetzt auch nochmal gesucht und in [[http://www.mikrocontroller.net/articles/Pollin_ATMEL_Evaluations-Board]] wird die Problematik mit den Tastern angesprochen. Ich werde testen ob es bei mir ohne Benutzung der Taster keine Resets mehr gibt.
Also, habe gestern das alles nochmal getestet, und ich muss sagen es geht. Die Pollin Tasterschaltung löst definitiv einen Reset aus auch bei 1,5 A Stromversorgung und ohne Servo. Jetzt komme ich natürlich so langsam an die Grenzen des Atmegas. Habe den Code jetzt soweit optimiert dass ich gerade mal eine Auflösung von 50 Positionen habe. Dabei habe ich noch nicht mal die Eingänge programmiert. Ich könnte den Atmel zwar noch auf 16MHz takten aber, das bringt mir gerade mal 100 Positionen und eigentlich wollte ich ne auflösung von 200 haben, vieleich sollte ich auf nen anderen Atmel wechseln oder das irgentwie aufteilen.
> Jetzt komme ich natürlich so langsam an die Grenzen des Atmegas.
Das glaube ich kaum, meist liegt die Grenze an der Software. Wenn man
mit C schreibt kann es sehr schnell passieren das man etwas
ungeschicktes macht und damit sehr viel rechenzeit verbraucht ohne das
zu wissen.
z.b. ein binary Shift mit Variablen.
Wenn der Code nicht zu geheim ist, dann lass ihn mal sehen. Es finden
sich bestimmt genug stellen um entwas zu optimiern.
Ja, also er Code is natürlich nicht geheim, hab ihn aber gerade nicht zur hand, aber ich denke ich kann einiges aus dem Kopf was wichtig ist
1 | ...
|
2 | #define SERVOPORT RORTD
|
3 | #define Servo0 PD0
|
4 | #define Servo1 PD1
|
5 | #define Servo2 PD2
|
6 | #define Servo3 PD3
|
7 | #define Servo4 PD4
|
8 | #define Servo5 PD5
|
9 | #define Servo6 PD6
|
10 | #define Servo7 PD7
|
11 | |
12 | unsigned int ServoCnt[8]; |
13 | unsigned int ServoUp; |
14 | |
15 | |
16 | ISR( TIMER1_COMPA_vect ) |
17 | {
|
18 | cli(); |
19 | ServoUp++; |
20 | if ( ServoUp == 1000U ) // ServoUp = CPU-Takt / 8 (prescaler) / 20 (Compare) / 50 (20ms) |
21 | {
|
22 | SERVOPORT = 0xFF; |
23 | ServoUp = 0U; |
24 | }
|
25 | if ( ServoUp == ServoCnt[0] ) SERVOPORT &= ~( 1<<Servo0 ); |
26 | if ( ServoUp == ServoCnt[1] ) SERVOPORT &= ~( 1<<Servo1 ); |
27 | if ( ServoUp == ServoCnt[2] ) SERVOPORT &= ~( 1<<Servo2 ); |
28 | if ( ServoUp == ServoCnt[3] ) SERVOPORT &= ~( 1<<Servo3 ); |
29 | if ( ServoUp == ServoCnt[4] ) SERVOPORT &= ~( 1<<Servo4 ); |
30 | if ( ServoUp == ServoCnt[5] ) SERVOPORT &= ~( 1<<Servo5 ); |
31 | if ( ServoUp == ServoCnt[6] ) SERVOPORT &= ~( 1<<Servo6 ); |
32 | if ( ServoUp == ServoCnt[7] ) SERVOPORT &= ~( 1<<Servo7 ); |
33 | sei(); |
34 | } // laut Disassembler so ca 87 Schritte |
35 | // muss also dem Compare ein bisschen puffer für andere Instruktionen geben,
|
36 | // hier jetzt 160 Schritte.
|
37 | |
38 | ...
|
39 | |
40 | int main(void) |
41 | {
|
42 | TCCR1B = (1<<CS11)|(1<<WGM12); // prescaler = CPU-Takt / 8 |
43 | OCR1A = 20; // Compare = 160 Schritte / 8 |
44 | TIMSK = (1<<OCIE1A); |
45 | sei(); |
46 | |
47 | ... // Funktionen für tasten etc. |
48 | }
|
was soll denn das cli(); und das sei(); dafür ist der Compiler da, das
sollte man nur in der main verwenden um kurzeitig zu verhindern das ein
interupt aufgerufen wird.
Dann könnte man das ganze sehr stark optimieren, was aber ein größere
Umbau ist.
du müssten intern die Daten so ablegen das du in der ISR sie direkt
verwenden kannst.
> if ( ServoUp == ServoCnt[0] ) SERVOPORT &= ~( 1<<Servo0 );
SERVOPORT = Daten[ ServoUp ]
das ganze braucht aber recht viel speicher 1000 * 8 byte. Da müsste man
sich noch etwas einfallen lassen und es sinnvoller zu speichern.
Mit dem cli und sei wollte ich nur verhindern das der Interupt ncht durch den für die tasten unterbrochen wird.
Peter schrieb: > du müssten intern die Daten so ablegen das du in der ISR sie direkt > verwenden kannst. > >> if ( ServoUp == ServoCnt[0] ) SERVOPORT &= ~( 1<<Servo0 ); > SERVOPORT = Daten[ ServoUp ] Äh. Nein ServoUp ist bei ihm der PWM Zähler
Sven Fabricius schrieb: > Mit dem cli und sei wollte ich nur verhindern das der Interupt ncht > durch den für die tasten unterbrochen wird. Das wird er sowieso nicht. In einer ISR sind Interrupts automatisch gesperrt und sie werden auch automatisch wieder freigegeben. Und nein, es ist nicht egal ob du selbst das sei() in der ISR machst. Machst du das selbst, dann erfolgt das sei() einen Tick zu früh.
dann lies dir erstmal die Doku von den Atmels durch. Ein Iterrupt kann nicht durch einen anderen Interupt unterbrochen werden. Durch dein sei(); hast du aber genau das erreicht und schlimmsten fall der Stack überläuft.
> ServoUp ist bei ihm der PWM Zähler
und warum sollte das dageben sprechen? Damit kann du mit einer zuweisung
alles erledigen. Braucht aber leider viel speicher.
Was noch was bringen würde: wenn es dir gelingt die unsigned int auf unsigned char runterzuholen. Die Arithmetik bzw. die Vergleiche brauchen dann nur noch die halbe Taktanzahl
Die Idee mit
> SERVOPORT = Daten[ ServoUp ]
ist garnicht so blöd weil ich ja wenn dann nur ne auflösung von 200
Schritten haben will, dass heist ich müsste dann nur 200 * 1 Byte in dem
Array haben.
if ( ServoUp >= 200 && ServoUp < 400 )
SERVOPORT = Daten[ ServoUp - 200 ];
schwieriger ist dann nur die INC und DEC geschichten zu realisieren,
allerdings sind diese dann nicht Zeitkritisch.
Sowas is mir gerade durch den Kopf gegangen. DEC { Daten[ServoCnt[ServoId]] &= ~(1<<ServoId); ServoCnt[ServoId]--; } INC { ServoCnt[ServoId]++; Daten[ServoCnt[ServoId]] |= (1<<ServoId); }
Peter schrieb: >> ServoUp ist bei ihm der PWM Zähler > und warum sollte das dageben sprechen? Damit kann du mit einer zuweisung > alles erledigen. Braucht aber leider viel speicher. Ja. Ich habe nicht behirnt, worauf du hinaus willst. Ein grosses Daten Array in dem die einzelnen Indizes die Zeitachse repräsentieren.
Genau, so in etwa: Daten: 1111000 .... 1100000 1111000 1100000 1111110 1100000 1111110 1100000 | 1ms | ._________ | |______ Servo 0 ._______ | |________ Servo 1 ._________ | |______ Servo 2 ._______ | |________ Servo 3 .___________ | |____ Servo 4 ._______ | |________ Servo 5 .___________ | |____ Servo 6 ._______ | |________ Servo 7
Man könnte darüber nachdenken, da so etwas wie ein Run-Length Encoding einzubauen, wenn die Größe des Datenarrays ein Problem ist. Der Update einer Servoposition ist dann zwar besch...eiden, aber die Auswertung in der ISR wäre immer noch kein Problem.
Hab jetzt leider kein WinAVR zur Verfügung, kann denn jemand mal nach checken wie viele Schritte das sind:
1 | unsigned char Daten[200]; |
2 | unsigned int ServoUp; |
3 | |
4 | ISR( TIMER1_COMPA_vect ) |
5 | {
|
6 | ServoUp++; |
7 | if ( ServoUp == 1000U ) |
8 | {
|
9 | SERVOPORT = 0xFF; |
10 | ServoUp = 0U; |
11 | }
|
12 | if ( ServoUp >= 200U && ServoUp < 400U ) |
13 | SERVOPORT = Daten[ ServoUp - 200U ]; |
14 | }
|
Nur compiliert. Die ISR ist exakt 100 Bytes lang (43 Assembler Tokens). 11 Assembler Tokens bilden den Teil if ( ServoUp >= 200U && ServoUp < 400U ) SERVOPORT = Daten[ ServoUp - 200U ]; Wobei der then Zweig aus c6: ee 59 subi r30, 0x9E ; 158 c8: ff 4f sbci r31, 0xFF ; 255 ca: 80 81 ld r24, Z cc: 8b bb out 0x1b, r24 ; 27 besteht.
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | #define SERVOPORT PORTA
|
5 | |
6 | unsigned char Daten[200]; |
7 | unsigned int ServoUp; |
8 | |
9 | ISR( TIMER1_COMPA_vect ) |
10 | {
|
11 | ServoUp++; |
12 | if ( ServoUp == 1000U ) |
13 | {
|
14 | SERVOPORT = 0xFF; |
15 | ServoUp = 0U; |
16 | }
|
17 | if ( ServoUp >= 200U && ServoUp < 400U ) |
18 | SERVOPORT = Daten[ ServoUp - 200U ]; |
19 | }
|
20 | |
21 | int main() |
22 | {
|
23 | }
|
1 | Servo.elf: file format elf32-avr |
2 | |
3 | Sections: |
4 | Idx Name Size VMA LMA File off Algn |
5 | 0 .text 000000ec 00000000 00000000 00000074 2**1 |
6 | CONTENTS, ALLOC, LOAD, READONLY, CODE |
7 | 1 .bss 000000ca 00800060 00800060 00000160 2**0 |
8 | ALLOC |
9 | 2 .debug_aranges 00000020 00000000 00000000 00000160 2**0 |
10 | CONTENTS, READONLY, DEBUGGING |
11 | 3 .debug_pubnames 00000040 00000000 00000000 00000180 2**0 |
12 | CONTENTS, READONLY, DEBUGGING |
13 | 4 .debug_info 000000c0 00000000 00000000 000001c0 2**0 |
14 | CONTENTS, READONLY, DEBUGGING |
15 | 5 .debug_abbrev 00000080 00000000 00000000 00000280 2**0 |
16 | CONTENTS, READONLY, DEBUGGING |
17 | 6 .debug_line 0000009f 00000000 00000000 00000300 2**0 |
18 | CONTENTS, READONLY, DEBUGGING |
19 | 7 .debug_frame 00000030 00000000 00000000 000003a0 2**2 |
20 | CONTENTS, READONLY, DEBUGGING |
21 | 8 .debug_str 00000092 00000000 00000000 000003d0 2**0 |
22 | CONTENTS, READONLY, DEBUGGING |
23 | |
24 | Disassembly of section .text: |
25 | |
26 | 00000000 <__vectors>: |
27 | 0: 0c 94 2a 00 jmp 0x54 ; 0x54 <__ctors_end> |
28 | 4: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
29 | 8: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
30 | c: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
31 | 10: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
32 | 14: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
33 | 18: 0c 94 3e 00 jmp 0x7c ; 0x7c <__vector_6> |
34 | 1c: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
35 | 20: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
36 | 24: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
37 | 28: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
38 | 2c: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
39 | 30: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
40 | 34: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
41 | 38: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
42 | 3c: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
43 | 40: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
44 | 44: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
45 | 48: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
46 | 4c: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
47 | 50: 0c 94 3c 00 jmp 0x78 ; 0x78 <__bad_interrupt> |
48 | |
49 | 00000054 <__ctors_end>: |
50 | 54: 11 24 eor r1, r1 |
51 | 56: 1f be out 0x3f, r1 ; 63 |
52 | 58: cf e5 ldi r28, 0x5F ; 95 |
53 | 5a: d4 e0 ldi r29, 0x04 ; 4 |
54 | 5c: de bf out 0x3e, r29 ; 62 |
55 | 5e: cd bf out 0x3d, r28 ; 61 |
56 | |
57 | 00000060 <__do_clear_bss>: |
58 | 60: 11 e0 ldi r17, 0x01 ; 1 |
59 | 62: a0 e6 ldi r26, 0x60 ; 96 |
60 | 64: b0 e0 ldi r27, 0x00 ; 0 |
61 | 66: 01 c0 rjmp .+2 ; 0x6a <.do_clear_bss_start> |
62 | |
63 | 00000068 <.do_clear_bss_loop>: |
64 | 68: 1d 92 st X+, r1 |
65 | |
66 | 0000006a <.do_clear_bss_start>: |
67 | 6a: aa 32 cpi r26, 0x2A ; 42 |
68 | 6c: b1 07 cpc r27, r17 |
69 | 6e: e1 f7 brne .-8 ; 0x68 <.do_clear_bss_loop> |
70 | 70: 0e 94 71 00 call 0xe2 ; 0xe2 <main> |
71 | 74: 0c 94 74 00 jmp 0xe8 ; 0xe8 <_exit> |
72 | |
73 | 00000078 <__bad_interrupt>: |
74 | 78: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> |
75 | |
76 | 0000007c <__vector_6>: |
77 | |
78 | unsigned char Daten[200]; |
79 | unsigned int ServoUp; |
80 | |
81 | ISR( TIMER1_COMPA_vect ) |
82 | { |
83 | 7c: 1f 92 push r1 |
84 | 7e: 0f 92 push r0 |
85 | 80: 0f b6 in r0, 0x3f ; 63 |
86 | 82: 0f 92 push r0 |
87 | 84: 11 24 eor r1, r1 |
88 | 86: 2f 93 push r18 |
89 | 88: 8f 93 push r24 |
90 | 8a: 9f 93 push r25 |
91 | 8c: ef 93 push r30 |
92 | 8e: ff 93 push r31 |
93 | ServoUp++; |
94 | 90: 80 91 60 00 lds r24, 0x0060 |
95 | 94: 90 91 61 00 lds r25, 0x0061 |
96 | 98: 01 96 adiw r24, 0x01 ; 1 |
97 | 9a: 90 93 61 00 sts 0x0061, r25 |
98 | 9e: 80 93 60 00 sts 0x0060, r24 |
99 | if ( ServoUp == 1000U ) |
100 | a2: 88 5e subi r24, 0xE8 ; 232 |
101 | a4: 93 40 sbci r25, 0x03 ; 3 |
102 | a6: 31 f4 brne .+12 ; 0xb4 <__vector_6+0x38> |
103 | { |
104 | SERVOPORT = 0xFF; |
105 | a8: 8f ef ldi r24, 0xFF ; 255 |
106 | aa: 8b bb out 0x1b, r24 ; 27 |
107 | ServoUp = 0U; |
108 | ac: 10 92 61 00 sts 0x0061, r1 |
109 | b0: 10 92 60 00 sts 0x0060, r1 |
110 | } |
111 | if ( ServoUp >= 200U && ServoUp < 400U ) |
112 | b4: e0 91 60 00 lds r30, 0x0060 |
113 | b8: f0 91 61 00 lds r31, 0x0061 |
114 | bc: e8 5c subi r30, 0xC8 ; 200 |
115 | be: f0 40 sbci r31, 0x00 ; 0 |
116 | c0: e8 3c cpi r30, 0xC8 ; 200 |
117 | c2: f1 05 cpc r31, r1 |
118 | c4: 20 f4 brcc .+8 ; 0xce <__vector_6+0x52> |
119 | SERVOPORT = Daten[ ServoUp - 200U ]; |
120 | c6: ee 59 subi r30, 0x9E ; 158 |
121 | c8: ff 4f sbci r31, 0xFF ; 255 |
122 | ca: 80 81 ld r24, Z |
123 | cc: 8b bb out 0x1b, r24 ; 27 |
124 | } |
125 | ce: ff 91 pop r31 |
126 | d0: ef 91 pop r30 |
127 | d2: 9f 91 pop r25 |
128 | d4: 8f 91 pop r24 |
129 | d6: 2f 91 pop r18 |
130 | d8: 0f 90 pop r0 |
131 | da: 0f be out 0x3f, r0 ; 63 |
132 | dc: 0f 90 pop r0 |
133 | de: 1f 90 pop r1 |
134 | e0: 18 95 reti |
135 | |
136 | 000000e2 <main>: |
137 | |
138 | int main() |
139 | { |
140 | } |
141 | e2: 80 e0 ldi r24, 0x00 ; 0 |
142 | e4: 90 e0 ldi r25, 0x00 ; 0 |
143 | e6: 08 95 ret |
144 | |
145 | 000000e8 <_exit>: |
146 | e8: f8 94 cli |
147 | |
148 | 000000ea <__stop_program>: |
149 | ea: ff cf rjmp .-2 ; 0xea <__stop_program> |
Compiliert mit -Os
43, na das ist doch ne hausnummer, dann kann ich den comperator noch halbieren auf 10, dann habe ich 80 inclusive puffer und dann mach ich noch nen 16er Quarz drann und habe meine 200 Schitte auflösung
Ich habe mir jetzt nicht alles durchgelesen, aber ich glaube, du machst einen Denkefehler. Du brauchst nicht alle Servoimpulse sozusagen gleichzeitig erzeugen, sondern kannst das ganz gemütlich Stück für Stück machen. |-|__________ Servo1 ___|-|________ Servo2 usw. Beim Einlesen ebenfalls, die kommen nacheinander.
Grundsätzlich hast du recht, so kommen sie ja auch aus dem Empfänger, für das Servo ist es wurscht. Der Empfänger macht ja nix anderes als das Sendersignal auf die Kanäle zu demuxen. Ich weiß nur nicht inwiefern es die sache vereinfachen würde
>Ich habe mir jetzt nicht alles durchgelesen, aber ich glaube, du machst >einen Denkefehler. Du brauchst nicht alle Servoimpulse sozusagen >gleichzeitig erzeugen, sondern kannst das ganz gemütlich Stück für Stück >machen. >|-|__________ Servo1 >___|-|________ Servo2 >usw. >Beim Einlesen ebenfalls, die kommen nacheinander. Du hast leider nur teilweise recht. Nur die guten, alten PPM Sendeanlagen arbeiten so. Wie es bei den PCM Anlagen ausschaut weis ich nicht aber bei den 2G4 Anlagen kommen immer mehrere Signale gleichzeitig beim Empfänger raus. Die meißten neuen Graupner Empfänger geben sogar alle Signale (fast) gleichzeitig aus.
Ich bin gerade am überlegen ob ich den Atmel als reinen default signalgeber verwende und die Umschaltung der 4 Input Kanäle auf die Outputs über ne Art von Latch mit Output Enable mache. Denn jetzt noch die Abfrage der Inputs da rein zu bringen, könnte kompliziert werden. Mit zwei von denen (74HCT573) dahinter sollte man das doch recht einfach hin bekommen oder, ich weiß nur nicht ob die Ausgänge das verkraften wenn ich die einfach auf ein ander lege?
Das ist jetzt meine Idee dazu. Ich habe nur Bauchschmerzen dabei die Ausgänge der Latches einfach so auf einander zu legen. Oder sollte ich lieber noch 2 74HCT32 integrieren?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.