www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega8 als Servo Switch


Autor: Sven Fabricius (mr_sven)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem Taster hatte ich einfach blanco von nem Eval Board 
übernommen, aber werd die mal parallel drauf schalten.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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/Entprellun...

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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ne, sorry hab mich verguckt

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

#define KEY_DDR         DDRC
#define KEY_PORT        PORTC
#define KEY_PIN         PINC
#define KEY_SELECT      0
#define KEY_LEFT        1
#define KEY_RIGHT       2
#define ALL_KEYS        (1<<KEY_SELECT | 1<<KEY_LEF | 1<<KEY_RIGHT)
 
#define REPEAT_MASK     (1<<KEY_LEFT | 1<<KEY_RIGHT)

....


#define NR_SERVOS  5

uint8_t ServoNr;
uint8_t ServoPos[NR_SERVOS];

...

int main()
{

  ...

  ServoNr = 0;

  while(1){
    if( get_key_short( 1<<KEY_SELECT )) {
      ServoNr++;
      if( ServoNr == NR_SERVOS )
        ServoNr = 0;
    }
 
    if( get_key_press( 1<<KEY_LEFT ) || get_key_rpt( 1<<KEY_LEFT )) {
      ServoPos[ ServoNr ]++;
    }

    if( get_key_press( 1<<KEY_RIGHT ) || get_key_rpt( 1<<KEY_RIGHT )) {
      ServoPos[ ServoNr ]--;
    }

    ...
  }
}

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke, werde das heute Abend testen, das mit dem array ist ne super 
idee, hatte daran noch garnicht gedacht.

Autor: Josh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bestätigen kann ich das nicht, aber es ist möglich, da ich die Schaltung 
der Taster auch übernommen habe.

Autor: Alexander Schmidt (esko) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Später soll das ganze über eine entsprechende Versorgung ermöglicht 
werden, aber momentahn ist 1 maximal 2 Servos dran zum testen.

Autor: Josh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt auch nochmal gesucht und in

[[http://www.mikrocontroller.net/articles/Pollin_ATM...]]

wird die Problematik mit den Tastern angesprochen. Ich werde testen ob
es bei mir ohne Benutzung der Taster keine Resets mehr gibt.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hatte gestern leider keine Zeit um das zu testen, hoffe heute Abend.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
...
#define SERVOPORT RORTD
#define Servo0 PD0
#define Servo1 PD1
#define Servo2 PD2
#define Servo3 PD3
#define Servo4 PD4
#define Servo5 PD5
#define Servo6 PD6
#define Servo7 PD7

unsigned int ServoCnt[8];
unsigned int ServoUp;


ISR( TIMER1_COMPA_vect )
 {
  cli();
  ServoUp++;
  if ( ServoUp == 1000U )   // ServoUp = CPU-Takt / 8 (prescaler) / 20 (Compare) / 50 (20ms)
   {
     SERVOPORT = 0xFF;
     ServoUp = 0U;
   }
  if ( ServoUp == ServoCnt[0] ) SERVOPORT &= ~( 1<<Servo0 );
  if ( ServoUp == ServoCnt[1] ) SERVOPORT &= ~( 1<<Servo1 );
  if ( ServoUp == ServoCnt[2] ) SERVOPORT &= ~( 1<<Servo2 );
  if ( ServoUp == ServoCnt[3] ) SERVOPORT &= ~( 1<<Servo3 );
  if ( ServoUp == ServoCnt[4] ) SERVOPORT &= ~( 1<<Servo4 );
  if ( ServoUp == ServoCnt[5] ) SERVOPORT &= ~( 1<<Servo5 );
  if ( ServoUp == ServoCnt[6] ) SERVOPORT &= ~( 1<<Servo6 );
  if ( ServoUp == ServoCnt[7] ) SERVOPORT &= ~( 1<<Servo7 );
  sei();
 }   // laut Disassembler so ca 87 Schritte
     // muss also dem Compare ein bisschen puffer für andere Instruktionen geben,
     // hier jetzt 160 Schritte.
 
...
 
int main(void)
 {
   TCCR1B = (1<<CS11)|(1<<WGM12);  // prescaler = CPU-Takt / 8
   OCR1A = 20;                     // Compare = 160 Schritte / 8
   TIMSK = (1<<OCIE1A);
   sei();

   ...  // Funktionen für tasten etc.
 }

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dem cli und sei wollte ich nur verhindern das der Interupt ncht 
durch den für die tasten unterbrochen wird.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sowas is mir gerade durch den Kopf gegangen.

DEC
{
  Daten[ServoCnt[ServoId]] &= ~(1<<ServoId);
  ServoCnt[ServoId]--;
}

INC
{
  ServoCnt[ServoId]++;
  Daten[ServoCnt[ServoId]] |= (1<<ServoId);
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab jetzt leider kein WinAVR zur Verfügung,
kann denn jemand mal nach checken wie viele Schritte das sind:
unsigned char Daten[200];
unsigned int ServoUp;

ISR( TIMER1_COMPA_vect )
 {
  ServoUp++;
  if ( ServoUp == 1000U )
   {
     SERVOPORT = 0xFF;
     ServoUp = 0U;
   }
  if ( ServoUp >= 200U && ServoUp < 400U )
   SERVOPORT = Daten[ ServoUp - 200U ];
 }

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

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

#define SERVOPORT PORTA

unsigned char Daten[200];
unsigned int ServoUp;

ISR( TIMER1_COMPA_vect )
 {
  ServoUp++;
  if ( ServoUp == 1000U )
   {
     SERVOPORT = 0xFF;
     ServoUp = 0U;
   }
  if ( ServoUp >= 200U && ServoUp < 400U )
   SERVOPORT = Daten[ ServoUp - 200U ];
 }

 int main()
 {
 }

Servo.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000000ec  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .bss          000000ca  00800060  00800060  00000160  2**0
                  ALLOC
  2 .debug_aranges 00000020  00000000  00000000  00000160  2**0
                  CONTENTS, READONLY, DEBUGGING
  3 .debug_pubnames 00000040  00000000  00000000  00000180  2**0
                  CONTENTS, READONLY, DEBUGGING
  4 .debug_info   000000c0  00000000  00000000  000001c0  2**0
                  CONTENTS, READONLY, DEBUGGING
  5 .debug_abbrev 00000080  00000000  00000000  00000280  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_line   0000009f  00000000  00000000  00000300  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_frame  00000030  00000000  00000000  000003a0  2**2
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_str    00000092  00000000  00000000  000003d0  2**0
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
   0:  0c 94 2a 00   jmp  0x54  ; 0x54 <__ctors_end>
   4:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
   8:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
   c:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  10:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  14:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  18:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__vector_6>
  1c:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  20:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  24:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  28:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  2c:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  30:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  34:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  38:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  3c:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  40:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  44:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  48:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  4c:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>
  50:  0c 94 3c 00   jmp  0x78  ; 0x78 <__bad_interrupt>

00000054 <__ctors_end>:
  54:  11 24         eor  r1, r1
  56:  1f be         out  0x3f, r1  ; 63
  58:  cf e5         ldi  r28, 0x5F  ; 95
  5a:  d4 e0         ldi  r29, 0x04  ; 4
  5c:  de bf         out  0x3e, r29  ; 62
  5e:  cd bf         out  0x3d, r28  ; 61

00000060 <__do_clear_bss>:
  60:  11 e0         ldi  r17, 0x01  ; 1
  62:  a0 e6         ldi  r26, 0x60  ; 96
  64:  b0 e0         ldi  r27, 0x00  ; 0
  66:  01 c0         rjmp  .+2        ; 0x6a <.do_clear_bss_start>

00000068 <.do_clear_bss_loop>:
  68:  1d 92         st  X+, r1

0000006a <.do_clear_bss_start>:
  6a:  aa 32         cpi  r26, 0x2A  ; 42
  6c:  b1 07         cpc  r27, r17
  6e:  e1 f7         brne  .-8        ; 0x68 <.do_clear_bss_loop>
  70:  0e 94 71 00   call  0xe2  ; 0xe2 <main>
  74:  0c 94 74 00   jmp  0xe8  ; 0xe8 <_exit>

00000078 <__bad_interrupt>:
  78:  0c 94 00 00   jmp  0  ; 0x0 <__vectors>

0000007c <__vector_6>:

unsigned char Daten[200];
unsigned int ServoUp;

ISR( TIMER1_COMPA_vect )
 {
  7c:  1f 92         push  r1
  7e:  0f 92         push  r0
  80:  0f b6         in  r0, 0x3f  ; 63
  82:  0f 92         push  r0
  84:  11 24         eor  r1, r1
  86:  2f 93         push  r18
  88:  8f 93         push  r24
  8a:  9f 93         push  r25
  8c:  ef 93         push  r30
  8e:  ff 93         push  r31
  ServoUp++;
  90:  80 91 60 00   lds  r24, 0x0060
  94:  90 91 61 00   lds  r25, 0x0061
  98:  01 96         adiw  r24, 0x01  ; 1
  9a:  90 93 61 00   sts  0x0061, r25
  9e:  80 93 60 00   sts  0x0060, r24
  if ( ServoUp == 1000U )
  a2:  88 5e         subi  r24, 0xE8  ; 232
  a4:  93 40         sbci  r25, 0x03  ; 3
  a6:  31 f4         brne  .+12       ; 0xb4 <__vector_6+0x38>
   {
     SERVOPORT = 0xFF;
  a8:  8f ef         ldi  r24, 0xFF  ; 255
  aa:  8b bb         out  0x1b, r24  ; 27
     ServoUp = 0U;
  ac:  10 92 61 00   sts  0x0061, r1
  b0:  10 92 60 00   sts  0x0060, r1
   }
  if ( ServoUp >= 200U && ServoUp < 400U )
  b4:  e0 91 60 00   lds  r30, 0x0060
  b8:  f0 91 61 00   lds  r31, 0x0061
  bc:  e8 5c         subi  r30, 0xC8  ; 200
  be:  f0 40         sbci  r31, 0x00  ; 0
  c0:  e8 3c         cpi  r30, 0xC8  ; 200
  c2:  f1 05         cpc  r31, r1
  c4:  20 f4         brcc  .+8        ; 0xce <__vector_6+0x52>
   SERVOPORT = Daten[ ServoUp - 200U ];
  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
 }
  ce:  ff 91         pop  r31
  d0:  ef 91         pop  r30
  d2:  9f 91         pop  r25
  d4:  8f 91         pop  r24
  d6:  2f 91         pop  r18
  d8:  0f 90         pop  r0
  da:  0f be         out  0x3f, r0  ; 63
  dc:  0f 90         pop  r0
  de:  1f 90         pop  r1
  e0:  18 95         reti

000000e2 <main>:

 int main()
 {
 }
  e2:  80 e0         ldi  r24, 0x00  ; 0
  e4:  90 e0         ldi  r25, 0x00  ; 0
  e6:  08 95         ret

000000e8 <_exit>:
  e8:  f8 94         cli

000000ea <__stop_program>:
  ea:  ff cf         rjmp  .-2        ; 0xea <__stop_program>


Compiliert mit -Os

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: H.j.Seifert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Barny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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.

Autor: Sven Fabricius (mr_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Sven Fabricius (mr_sven)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.