PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Immer wieder Servos...



Radom
25.03.2017, 09:30
Hi an alle!

Zur Zeit versuche ich eine Weichensteuerung für die Lego Eisenbahn meines Sohnes zu realisieren.

Zur mir:
- bin recht neu in Arduino/Microcontroller
- lese gerade das AVR Lehrbuch von Roland Walter
- hab mir das meiste Programmieren selbst beigebracht (ca. 8 Jahre beruflich VBA, 2x C++ Kurs)
- Elektronik-Kenntnisse auch selbst beigebracht (Anfängerkenntnisse würde ich sagen)
- mit dem Projekt und den Bauteilen beschäftige ich mich jetzt ca. seit 5 Monaten, immer mal wieder am Wochenende, oder wenn es sich Abends ausgeht

Folgende Bauteile verwende ich:
- Arduino UNO
- MUX-Shield (1. Generation)
- umgebautes PC-Netzteil als ext. Stromquelle (so ähnlich wie das hier http://www.kondensatorschaden.de/2015/06/13/how2-experimentiernetzteil/ )
- Servos "Tower Pro SG90" (also die http://www.micropik.com/PDF/SG90Servo.pdf)
- Taster mit RC-Glied (10 k & 100nF)
- Shift-Register 74HC595

Jede Weiche hat einen Taster, dieser toggelt die Weiche. Für die Gerade Fahrt auf der Weiche brauche ich den Servo auf 45°, für die Abzweigung ganz links (0°).

Das Programm ist ungefähr so aufgebaut (Code am Ende):
# herzlichen Dank an Oberallgeier für die Lösung mit dem Timer PWM ! :) https://www.roboternetz.de/community/threads/61379-Kopfsache-und-ein-m1284-etliche-Servos-viel-Alu/page3?p=577715&viewfull=1#post577715
(hoffentlich hab ich es richtig verstanden :p )

- Timer 1 CompA
→ Prescaler 1:64
→ 4999 Ticks / n Servos um das 20ms Intervall für jeden Servo zu starten
→ setzt den Ausgang des Registers des aktuellen Servos auf 1
→ prüft auf Tastendruck
→→ wenn gedrückt, führe Funktion aus und setzt die Shift-Register der LEDs neu
(so gelöst damit die LEDs nicht flackern und dass TIMER 1 so wenig wie möglich gestört wird)
→ setzt den Wert für Timer 1 CompB

- Timer 1 CompB
→ sendet eine 0 an die Register und schaltet so das Servosignal ab


Im Grunde funktioniert es, ABER :p
- anders als im Datenblatt des Servos fahren die Servos nur auf die
→ linkeste Position, wenn die Pulsweite ~ 0,6 ms ist
→ 45° Position, wenn die Pulsweite ~ 1 ms ist
- manche Servos fahren spiegelverkehrt ( 0 = 180 und die Bewegung ist auch gespiegelt )
- der Puls ab dem 2. Schieberegister zappelt am Ende
→ Register 1: schönes Rechteck-Signal
→ Register 2: steigende Flanke sauber, das Zappeln beginnt ab dem eigentlichen Ende des Signals (z.B. 1ms) und verlängert das Signal um ca. 0,75 ms

Edit: irgendwo habe ich gelesen dass ein Servo ca. 1 A Strom braucht, wenn 12 Servos am Netzteil hängen, zeigt das Multimeter aber nur ~350 mA an - ist da was falsch ?

Und mir gehen jetzt die Ideen und Suchbegriffe aus um eine Lösung zu finden... :(


Hat jemand Lust sich das anzusehen und mir vielleicht Tipps zu geben? :confused: :D


PS: im Code habe ich 18 Weichen eingestellt, da ja (aktuell) die Pulsweite für die benötigten 45° nur 1ms sein muss (die Bahn hat auch 18 Weichen, das passt halt auch zu gut :) )
In den Versuchen macht es keinen Unterschied ob ich max. 18 oder max 10 einstelle.





// Define ************************************************** ************************************************** *****************
#define CONTROL0 6 // 5 //MUX control pin 0 (S3 is connected to Arduino pin 2)
#define CONTROL1 5 //4
#define CONTROL2 4 //3
#define CONTROL3 3 //2
/* --> das Shield wurde um einen Pin nach oben verschoben, um den Pin 2 fuer die Interrupt der Taster zu
* verwenden !!
*
* !! ALT !! -> Interrupt mit Taster sind nicht empfohlen, wegen Prellen
* -> meine Schaltungs-/Softwareversuche haben das bestaetigt...
*/

#define MUX0 14 //^= Analog 0
#define MUX1 15 //^= Analog 1
#define MUX2 16 //^= Analog 2


// Variablen / Konstanten ************************************************** ************************************************** *
// 1. konstante Vorgaben
const int PIN_TMR_INI_OK = 1; //Kontroll-LED für erfolgreiche Timer-Initialisierung
const int PIN_TMR_INI_NOK = 13; //Kontroll-LED für fehlgeschlagene Timer-Initialisierung -> wenn ocr1a < ocr1b ist !!

const int PIN_TAKT_SRV = 7; //Takteingang ( SH_CP )
const int PIN_SPEICHER_SRV = 8; //Speicher-Sendung ( ST_CP )
const int PIN_DATEN_SRV = 9; //Pin für den Binär-Wert ( DS )

const int PIN_TAKT_LED = 10; //Takteingang ( SH_CP )
const int PIN_SPEICHER_LED = 11; //Speicher-Sendung ( ST_CP )
const int PIN_DATEN_LED = 12; //Pin für den Binär-Wert ( DS )

const int TICKS_ABZW = 150; //Weiche abzweigend - 0.60 ms = 150 Ticks bei Prescaler 1 : 64
const int TICKS_GERADE = 250; //Weiche gerade - 1.00 ms = 250 Ticks bei Prescaler 1 : 64

const int nSRV_MAX = 18; //max Anzahl an Servos -> es sind max 18 Servos moeglich !
// -> ocr1a > ocr1b ist Pflicht
// -> 4999 / 250 = 19.9 -->> 18 fuer Puffer
// -> NUR wenn max Stell-Signal = 250 ist !!

const int FLAG_LED_GERADE = 0; //Offset um die LED des n-ten Servos fuer gerade Fahrt zu setzen
const int FLAG_LED_ABZW = 1; //Offset um die LED des n-ten Servos fuer abzweigende Fahrt zu setzen

const int IX_SRV_POS = 0; //Index der Positionen im Array
const int IX_RTG_LED = 1; //Index der LED-Flags im Array

// 2. variable Werte
int srv = -1; //der aktuelle Servo als Zähler - für OCR1A
int srvPositionen[ nSRV_MAX ][ 2 ]; //Array für die Servo-Positionen und den Pin fuer die Richtungs LED
int tasterStatus[ nSRV_MAX ]; //Logische Schaltung zur Erfassung der Taster-Status-Wechsel

int ocr1b; //variabler Wert für das, je Servo verschiedene, Steuersignal

int srvByte = 0; //1 Byte = 8 Bit, also ein Paket von 8 Servos
int srvZaehler = 0; //Zaehler zur Ermittlung in welchem Byte = Register sich der aktuelle Servo befindet

int ledByte = 0; //1 Byte = 8 Bit, also ein Paket von 4 Servos, da 1 Servo = 2 LED
int ledZaehler = 0; //Zaehler zur Ermittlung in welchem Byte = Register sich die LEDs befinden

int nShiftRegisterSrv; //Anzahl der vorhandenen/noetigen Register fuer die Servos
int nShiftRegisterLEDs; //Anzahl der vorhandenen/noetigen Register fuer die Richtungs-LEDs

// 3. Berechnete Werte
int ocr1a = 4999 / nSRV_MAX; //Intervall für OCR1A um für jeden Servo ein 20 ms Intervall zu erhalten ( 1 : 64 )



// Setup ************************************************** ************************************************** ******************
void setup ( ) {
// Serial Monitor
// Serial.begin ( 115200 );

// MUX Pins setzen
pinMode(CONTROL0, OUTPUT);
pinMode(CONTROL1, OUTPUT);
pinMode(CONTROL2, OUTPUT);
pinMode(CONTROL3, OUTPUT);

pinMode( MUX0, INPUT); //Multiplexer 0 zu input setzen - empfaengt die Taster-Eingaben
pinMode( MUX1, INPUT); //Multiplexer 1 zu input setzen - empfaengt die Taster-Eingaben
pinMode( MUX2, INPUT); //Multiplexer 2 unbenutzt

// Ausgaenge festlegen
pinMode ( PIN_TAKT_SRV, OUTPUT );
pinMode ( PIN_SPEICHER_SRV, OUTPUT );
pinMode ( PIN_DATEN_SRV, OUTPUT );

pinMode ( PIN_TAKT_LED, OUTPUT );
pinMode ( PIN_SPEICHER_LED, OUTPUT );
pinMode ( PIN_DATEN_LED, OUTPUT );

pinMode ( PIN_TMR_INI_OK, OUTPUT );
pinMode ( PIN_TMR_INI_NOK, OUTPUT );

//Es muss zwingend ocr1a > ocr1b sein! -> fuer ocr1b muss das laengste Servo-Signal angenommen werden (nServMax x laen. SrvSig)
if ( ocr1a < TICKS_GERADE ) {
digitalWrite ( PIN_TMR_INI_NOK, HIGH );
}
else {
// nShiftRegisterSrv bestimmen und Ueberlauf abfangen
nShiftRegisterSrv = nSRV_MAX / 8 + 1; //Register je aktueller Servo Nr., bzw. Anzahl Register bei nServMax

if ( nShiftRegisterSrv * 8 == nSRV_MAX ) //Korrektur bei einer Oktave ( 16 / 8 + 1 = 3, es sind aber nur 2 Byte ! )
nShiftRegisterSrv--;

// nShiftRegisterLEDs bestimmen und Ueberlauf abfangen
nShiftRegisterLEDs = ( nSRV_MAX ) / 4 + 1; //Teiler = 4 da es pro Servo 2 LEDs gibt (gerade Fahrt && abzweigende Fahrt)

if ( nShiftRegisterLEDs * 4 == nSRV_MAX ) //Korrektur bei einer Oktave ( 16 / 4 + 1 = 5, es sind aber nur 4 Byte ! )
nShiftRegisterLEDs--;

// Definiere Timer
cli ( ); //Interrupts abschalten

// Interrupt - Timer 1
TCCR1A = 0; //reset Register A
TCCR1B = 0; //reset Register B
TCNT1 = 0; //Zaehler nullen

OCR1A = ocr1a; //setze Intervall A
TCCR1B |= ( 1 << CS11 ) | ( 1 << CS10 ); //Prescaler Timer 1 auf 1 : 64 einstellen
TCCR1B |= ( 1 << WGM12 ); //Timer auf CTC mode stellen
TIMSK1 |= ( 1 << OCIE1A ); //Timer 1 aktivieren

sei ( ); //Interrupts einschalten

digitalWrite ( PIN_TMR_INI_OK, HIGH );

// Alle Positionen initialisieren
for ( int serv = 0; serv < nSRV_MAX; serv++ ) {
srvPositionen[ serv ][ IX_SRV_POS ] = TICKS_ABZW;
srvPositionen[ serv ][ IX_RTG_LED ] = FLAG_LED_ABZW;
tasterStatus[ serv ] = 0;
}
}

// Register der Servos loeschen
digitalWrite ( PIN_SPEICHER_SRV, LOW );
for ( int shift = nShiftRegisterSrv; shift >= 0; shift-- )
shiftOut ( PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
digitalWrite ( PIN_SPEICHER_SRV, HIGH );

// Register der LEDS setzen
setLEDs();
}
// // ************************************************** ************************************************** ********************



// ISR TIMER 1 COMP A ************************************************** ************************************************** *****
ISR ( TIMER1_COMPA_vect ) {
const int muxMax = 16; //max Anzahl Pins je MUX-Register (Anzahl, NICHT hoechste Pin-Nr !!)
const int mux0 = 14; //Pin des 1. MUX-Registers

int offsetMUXRegister; //Offset um das aktuelle MUX-Register aus dem aktuellen Servo zu errechnen
int muxReg; //MUX-Register des Servo-Tasters


int muxPin; //Pin des akt. Servos je MUX-Regisert


// Auf naechsten Servo zeigen
srv++;
if ( srv > nSRV_MAX - 1 ) { //Ueberlauf abfangen
srv = 0;
srvZaehler = 0;
srvByte = 0;
}

// Den n-ten Servo dem richtigen Register zuordnen
int servRegister = srv / 8 + 1;

// Dem n-ten Servo ueber das entsprechende Register das Steuersignal senden
digitalWrite ( PIN_SPEICHER_SRV, LOW );

for ( int shiftToRegister = nShiftRegisterSrv; shiftToRegister > 0; shiftToRegister-- ) {
if ( shiftToRegister == servRegister ) {
// sende an Shift-Register
// -> der Binaer-Wert ist 2^( srv - srvByte * 8 )
shiftOut ( PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 1 << ( srv - ( srvByte * 8 ) ) );

// Taster des aktuellen Servos auf Veraenderung pruefen
offsetMUXRegister = srv / 16;
muxReg = mux0 + offsetMUXRegister;
muxPin = srv - offsetMUXRegister * muxMax;

digitalWrite ( CONTROL0, ( muxPin & 15 ) >> 3 );
digitalWrite ( CONTROL1, ( muxPin & 7 ) >> 2 );
digitalWrite ( CONTROL2, ( muxPin & 3 ) >> 1 );
digitalWrite ( CONTROL3, ( muxPin & 1 ) );

if ( digitalRead ( muxReg ) && digitalRead ( muxReg ) != tasterStatus[ srv ] ) {
if ( srvPositionen[ srv ][ IX_SRV_POS ] == TICKS_ABZW ) {
srvPositionen[ srv ][ IX_SRV_POS ] = TICKS_GERADE;
srvPositionen[ srv ][ IX_RTG_LED ] = FLAG_LED_GERADE;
}
else {
srvPositionen[ srv ][ IX_SRV_POS ] = TICKS_ABZW;
srvPositionen[ srv ][ IX_RTG_LED ] = FLAG_LED_ABZW;
}

// bei Tastendruck die LEDs neu schalten
setLEDs();
}

tasterStatus[ srv ] = digitalRead ( muxReg );
}
else {
// sende an Shift-Register
shiftOut ( PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
}
}

digitalWrite ( PIN_SPEICHER_SRV, HIGH );

// Das Byte des naechsten Servos ermitteln
srvZaehler++;

if ( srvZaehler == 8 ) {
srvZaehler = 0;
srvByte++;
}

ocr1b = srvPositionen[ srv ][ IX_SRV_POS ]; //Länge des Steuersignals aus dem Array lesen
OCR1B = ocr1b; //Timer B setzen
TIFR1 |= ( 1 << OCF1B ); // ??? Klappt immer wenn das gesetzt wird
TIMSK1 |= ( 1 << OCIE1B ); //Timer B aktivieren
}
// // ************************************************** ************************************************** ********************



// ISR TIMER 1 COMP B ************************************************** ************************************************** *****
ISR ( TIMER1_COMPB_vect ) {
TIMSK1 &= ~ ( 1 << OCIE1B ); //CompB Match interrupt disabled

digitalWrite ( PIN_SPEICHER_SRV, LOW );
for ( int shift = nShiftRegisterSrv; shift >= 0; shift-- ) //das Steuersignal abschalten --> Shift-Ausgang = OFF
shiftOut ( PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
digitalWrite ( PIN_SPEICHER_SRV, HIGH );
}
// // ************************************************** ************************************************** ********************



// setLEDs ************************************************** ************************************************** ****************
void setLEDs() {
//Reset
shiftOut ( PIN_DATEN_LED, PIN_TAKT_LED, MSBFIRST, 0 );

//Senden der 0/1 Zustaende der LEDs an die Register
// -> festes setzen aller LEDs um Flackern zu verhindern

digitalWrite ( PIN_SPEICHER_LED, LOW );

for ( int srvLEDs = nSRV_MAX; srvLEDs >= 0; srvLEDs-- ) {
if ( srvPositionen [ srvLEDs ][ IX_RTG_LED ] == FLAG_LED_GERADE ) {
digitalWrite ( PIN_TAKT_LED, HIGH ); //"abzweigendes" Bit auf 0 setzen
digitalWrite ( PIN_TAKT_LED, LOW ); //Takt wieder abschalten

digitalWrite ( PIN_DATEN_LED, HIGH ); //"gerades" Bit auf 1 setzen
digitalWrite ( PIN_TAKT_LED, HIGH ); //"gerades" Bit uebertragen
digitalWrite ( PIN_DATEN_LED, LOW ); //Daten abschalten
digitalWrite ( PIN_TAKT_LED, LOW ); //Takt abschalten
}
else {
digitalWrite ( PIN_DATEN_LED, HIGH ); //"abzweigendes" Bit auf 1 setzen
digitalWrite ( PIN_TAKT_LED, HIGH ); //"abzweigendes" Bit uebertragen
digitalWrite ( PIN_DATEN_LED, LOW ); //Daten abschalten
digitalWrite ( PIN_TAKT_LED, LOW ); //Takt abschalten

digitalWrite ( PIN_TAKT_LED, HIGH ); //"gerades" Bit auf 0 setzen
digitalWrite ( PIN_TAKT_LED, LOW ); //Takt abschalten
}
}

Serial.println();
digitalWrite ( PIN_SPEICHER_LED, HIGH );
}
// // ************************************************** ************************************************** ********************



// loop ************************************************** ************************************************** *******************
void loop ( ) { }
// // ************************************************** ************************************************** ********************

oberallgeier
25.03.2017, 19:01
.. Weichensteuerung für die Lego Eisenbahn ..
- anders als im Datenblatt des Servos fahren die Servos ..
- manche Servos fahren spiegelverkehrt ( 0 = 180 und die Bewegung ist auch gespiegelt ) ..Ich habe bei den von mir bisher verwendeten Servos selten ein richtiges Datenblatt gesehen. Bei vielen Servos sehe ich bei gleichen Typen die Anschläge bei unterschiedlich langen Signalen; selbst der Gleichlauf paarig-auf-Umschlag angeordneter Servos war bei mir mal nicht gewährleistet und ich musste die Servos anders einbauen (=> neue Tragestruktur) um einen weitgehend simultanen (Ab-)Lauf zu erreichen. Letzteres dürfte für die Weichensteuerung aber eher nicht von Bedeutung sein.


.. → Register 2: steigende Flanke sauber, das Zappeln .. Dazu habe ich grad keine Idee, leider.


.. irgendwo habe ich gelesen dass ein Servo ca. 1 A Strom braucht, wenn 12 Servos .. aber nur ~350 mA an - ist da was falsch ? ..Das ist, glaube ich, schon richtig. Der Servo zieht entsprechend seiner Belastung mehr oder weniger Strom. Tip: fahre den Servo auf eine beliebige Stellung. Erst ohne Last, später mit verschiedenen Lasten (z.B. Servohebel händisch belasten). Dabei sollte die Stromaufnahme sinnvoll steigen bzw. fallen. Die 1A-Auskunft: Servos brauchen zum Anfahren ne satte Strommenge. Das war mir bei kräftigen Servos aufgefallen, als ich einen bestimmten Typ (siehe hier (https://www.roboternetz.de/community/threads/67677-Servo-singt-unter-Last-B-Ware-reparierbar-oder-M%C3%BCll?p=617532&viewfull=1#post617532))
a) in den USA einkaufte (pololu) und später
b) im Chinashop erwarb.

Lastlos zogen die Servos ca. 34 mA inclusive Nanoclone bei 9,5V Speisespannung und zwei, drei Kontroll-LEDs. Die Chinadinger waren für mich daher Schrott - zittriges Fahrverhalten, teils lausiges Zittern auf der Stelle statt Anfahrt an die ungefähr vorgewählte Stellung. Hatte diese Chinateile weggelegt. Später mal zufällig hervorgeholt und bei 4A max. zulässiger Stromstärke (Netzteileinstellung) bei sonst gleichen Bedingungen betrieben. Da fuhren die problemlos. Bei rund 1A als obere Stromgrenze spinnen sie wie eh und je . . . Das ist reproduzierbar.


.. Hat jemand Lust sich das anzusehen und mir vielleicht Tipps zu geben? ..Vielleicht hilft Dir das? Mehr Antwort ist jetzt, nach einer Woche Schifahren leider nicht drin.

hbquax
25.03.2017, 23:50
Ist ein Servo nicht Overkill für eine Weichensteuerung? Bei den klassischen Modelleisenbahnen tut es da eine einfach Spule, die je nach Weichenstellung bestromt wird. Andererseits sind Servos so spottbillig... Wie alle Elektromotoren brauchen Servos je nach Last mehr oder weniger Strom, 1 A ist schon relativ viel. Für die Weichen müssten doch Microservos genügen, die brauchen sicher nicht viel. Man übrigens auch ne Feder ins Gestänge einbauen, dann geht nichts kaputt, wenn der Endanschlag nicht genau stimmt.

Radom
26.03.2017, 09:44
Danke für eure schnellen Antworten!


selten ein richtiges Datenblatt gesehen.
Ui, in Datenblätter hatte ich bisher ein Urvertrauen...


später mit verschiedenen Lasten (z.B. Servohebel händisch belasten)
Es ist genau wie du sagst, in Ruhe verbrauchen sie die 350 mA und unter Last steigt es ein wenig.
Die Stromzufuhr definiert erhöhen kann ich ja nicht, oder? Das System zieht doch immer so viel Strom wie es benötigt und nicht mehr? :confused:


Vielleicht hilft Dir das? Mehr Antwort ist jetzt, nach einer Woche Schifahren leider nicht drin
Klar hilft mir das schon. Jetzt steht fest dass ich nicht davon ausgehen kann, dass ich alle Servos wirklich simultan hinbekomme.


Overkill für eine Weichensteuerung?
Kannst du mir eine "einfache" Spule als Bsp geben? Und meinst du dann den Magnetismus aus der Spule zum Weiche stellen verwenden?


Feder ins Gestänge
Danke dafür, da ist es mir gleich wie Schuppen von den Augen gefallen - wegen den verschiedenen Endpunkten der Servos.

Anbei ein Bild, wie die Weiche mit Servo (bisher) gedacht war:
32504

Einen schönen Sonntag wünsche ich euch!

i_make_it
26.03.2017, 13:40
ne Feder ins Gestänge einbauen

Grade im Modellbau sollte man das nicht unbedingt wörtlich nehmen im Sinne von ein zusätzliches Bauteil einbauen.
Da es den Draht für Servogestänge auch federhart gibt, macht man oft einfach ein "Z" ins Gestänge um federnde Eigenschaften zu implementieren.
32505






Kannst du mir eine "einfache" Spule als Bsp geben? Und meinst du dann den Magnetismus aus der Spule zum Weiche stellen verwenden?


Google dazu einfach mal nach "Märklin Weichenantrieb". Da findest Du den Aufbau mit Spulen.
Bei Youtube finden sich dann auch diverse Videos zu Lösungen mit Servos.

Da die Lego Bahn jetzt nicht unbedingt zu der klassischen Gruppe der Modellbahnen gehört die dauerhaft aufgebaut wird, sondern eher zu denen die fürs Spielen aufgebaut werden und dann wieder abgebaut, würde ich eher den Servo seitlich neben die Weiche an den manuellen Antrieb setzen, so das er oberhalb der Montageebene sitzt, eventuell sogar mit einem Legogehäuse (oder 3D-Druck) so das er als Baustein modular angebaut werden kann.

Ideen zu Kopplung eines Antriebgestänges kann man sich direkt bei den Legobastlern holen.
https://www.1000steine.de/de/gemeinschaft/forum/?entry=1&id=301222&PHPSESSID=0a02e9eca570cf839209e3ad27557c00

Radom
26.03.2017, 17:48
Danke, gut zu wissen wie das mit dem Gestänge eigentlich gemeint war... :cheesy:

Die Feder werde ich mir trotzdem noch gut überlegen.

Die Häuschen auf 1000steine.de hab ich natürlich schon gesehen - die sind auch wirklich toll gelöst und wir haben lange überlegt, schon als wir überlegt haben das Projekt überhaupt zu machen. Wir sind aber wieder davon abgekommen, da sie für uns zu viel Platz brauchen.
Tatsächlich haben wir mit der Lego-Bahn schon vor sie länger stehen zu lassen. Es gibt einen extra Kellerraum mit Tisch, Schattenbahnhof (wenn auch noch klein), einem Güterhof und aktuell zwei Personenbahnhöfen
die alle mehrere Gleise haben. Mein Sohn ist ein richtiger Zug-Fan und nimmt es da sehr genau, deshalb liegen die Schienen auch so wie sie real liegen (soweit das eben mit Lego geht), also sehr nah zusammen.
Für die Servos habe ich mich entschieden, weil ich sie unter die Schienen bauen kann und die Servos dann im Schotterbett verschwinden würden (kein Witz, echter Streu-Kies).

Der Charm am Lego ist, dass er noch lange wirklich damit spielen kann, also drauf klettern, Häuser umbauen, Autos in Unfällen zerlegen, die Züge crashen lassen und worauf die Kids halt so stehen... :cheesy:

Danke für den Suchtipp, damit werde ich mich jetzt mal beschäftigen. Magnetisch klingt sehr verlockend. :D

i_make_it
27.03.2017, 06:00
Ich meinte auch nur die Kopplung und nicht das ganze Häuschen.
Mit zwei von den runden Steckverbindern und zwei Technik Hebeln (1/3 Stein hoch) müsste sich was bauen lassen das direkt auf der Weiche geführt wird und in das ein Servohorn direkt eingreifen kann.
Bsp.:
32507
oder
32508

Mit Ein paar Steinen ein minimalistisches Gehäuse als Führung drum rum.

Radom
29.03.2017, 13:20
Die kleinen Servos sind leider zu schwach um die Weiche über den normalen Mechanismus zu stellen und ich will dich Weichen nicht öffnen und bearbeiten.
Sogar der größere Servo den ich zuhause habe hat das nicht ohne Übersetzung hingebracht - und Übersetzung heißt wieder Häuschen.

Danke dir auf jeden Fall für deine Ideen, doch Servo oben klappt einfach nicht - zumindest nicht so wie wir die Bahn jetzt haben.

Gerne würde ich wieder auf den obigen Code zurück kommen. Habt ihr ihn euch angesehen? Die letzten Tage war der Arduino aus und heute beim Einschalten ist auf einmal das Siganl an den nachfolgenden Schieberegistern wieder einwandfrei :confused: :confused: Das kann doch dann nicht mehr am Code liegen, oder doch ?

oberallgeier
29.03.2017, 17:14
Die kleinen Servos sind leider zu schwach um die Weiche über den normalen Mechanismus zu stellen ..Kann sein, dass Du das Folgende alles weißt und schon längst berücksichtigt hast. Aber ich weiß, dass kleine Servos schon einige KRAFT entwickeln können. Vielleicht . . . Mal ein paar Bemerkungen.

2tens: ich habe keine Ahnung wie schwergängig ne Weiche von der Legobahn ist oder ob Du vielleicht die Gartenbahnvariante von Lego hast (die gibts ja wohl garnicht).

1tens: Wir hatten in der Schule in Physik gelernt (zumindest gehört): Drehmoment ist Kraft mal Kraftarm bzw. Drehmoment ist Last mal Lastarm. Ein kurzer Kraft(Servo)arm gibt viel Kraft gegenüber einem langen Kraft(Servo)arm bei gleichem Drehmoment, sprich gleichem Servo, allerdings sind dann die Betätigungswege unterschiedlich.

Und was sagt uns das? Möglicherweise hängst Du Deine Schubstange vom Servo zur Weichenbetätigung mit zu groß geratenem Lastarm an, sprich: in ein Loch das zu weit weg ist von der Abtriebsachse des Servos. Lastarm ist Abstand Servo-Abtriebsachse zu Schubstangenanlenkung. Und zur Anpassung des Servos an den erforderlichen Betätigungsweg bzw. an die erforderliche Kraft haben viele Servoarme eine ganze Reihe von Betätigungslöchern *ggg* so wie hier (klicken) (https://www.freakware.de/p/des-alu-hochlast-servoarm-graupner-grp-7908-1-a55839.htm?ref=gs&gclid=CLu21K-N_NICFUG4GwodG5cNTg).

Wenn Du den ganzen Schwenkwinkel des Servos ausnützt, also die Schubstange möglichst nahe an der Abtriebsachse des Servos anlenkst, dann hast Du so etwa die maximal mögliche Kraft die der Servo erzeugt, siehe hier (klick) (http://www.east-wing-base.com/images/stories/ru-rm-05.jpg). Vorteil: große Kraft. Nachteil : der erfoderliche Schwenkwinkel für einen erforderlichen (Schub-)Weg ist lang, die Stellzeit ebenfalls. Aber bei üblichen Servos wird der maximal fahrbare Drehwinkel in drei bis sechs Zehntel Sekunden gefahren.

Hängst Du dagegen die Schubstange weit weg von der Servo-Abtriebsachse ein, siehe hier (nochnklick) (http://www.modellflugclub-ettringen.de/images/p105_1_01.png), dann ist der Stellweg gering. Vorteil : die Stellzeit ist gering, weil der erforderliche Schwenkwinkel gering ist. ABER gering ist dann auch die Kraft.

Radom
29.03.2017, 19:32
Hallo oberallgeier,

ja, die physikalischen Zusammenhänge sind mir bekannt. Die Bahn ist eine normale Lego RC (klick) (https://shop.lego.com/de-DE/Weichen-7895).

Ausprobiert habe ich die verschiedensten Varianten, wie gesagt von den Häuschen inkl. Übersetzung bis hin zu Fischertechnik Pneumatik Zylindern und vom Lego Motor bis eben zu den Servos. Und natürlich auch verschiedene Hebellängen.
Der interne Widerstand der Legoweichen ist teilweise so schwer, dass man sich sogar als Erwachsener beim ursprünglichen Lego-Handhebel ganz schön anstrengen muss.

Hab ich meine Frage falsch formuliert? Ich verstehe nicht ganz warum wir jetzt nur noch über die Stellung der Weichen sprechen. Natürlich bin ich euch dankbar für eure Erfahrungen & Tips (wie der Idee mit der Spule), doch ich brauche eure Hilfe bei dem Rechtecksignal und meinem Code und/oder der Hardware. :)

Habe ich einen Logikfehler drin?
Kennt ihr so ein Verhalten, dass es einmal geht und einmal nicht und dann wieder doch - dabei denke ich z.B. an Induktion von zu nah aneinander liegenden Kabeln. ← da bin ich einfach zu wenig Elektroniker um zu wissen ab wann sich so eine Verkabelung selbst stören kann :confused:

(Edit: Rechtschreibung :p)

i_make_it
30.03.2017, 06:03
→ linkeste Position, wenn die Pulsweite ~ 0,6 ms ist
→ 45° Position, wenn die Pulsweite ~ 1 ms ist


Das ist leider kein Einzelfall.
Bei mir in der Firma steht ein kleiner AREXX RA2-HOBBY Da war bei zwei Servos das selbe Problem 1-2ms ergaben nur +-45°
erst das erweitern der Pulsweite brachte +-90°. Da gab es dann allerdings Timingprobleme mit den anderen Servos.
Am Ende lief es auf einen Tausch gegen bessere (teurere) Servos raus.



- manche Servos fahren spiegelverkehrt ( 0 = 180 und die Bewegung ist auch gespiegelt )

Kommt vor. Moderne RC-Fernsteuerungen haben dafür eine Servo-Reverse Funktion (entweder Schalter oder Setting im Menü)
Zu Zeiten als es nur Robbe und Graupner gab, kam das fast nie vor. Aber mittlerweile gibt es Servos mit positivem und mit negativem Puls.
Und halt mit invertierter Polarität.
Eine Hardware Lösung wäre:
https://www.elektormagazine.de/files/attachment/166

Wenn ich mir die Videos von 1000 Steine ansehe,
https://youtu.be/w_zBPzvL0Ig
ist der notwendige Hub zum Betätigen der Weiche ca. 3mm.
Das Servohorn kann also so kurz wie möglich gehalten werden.
Da bei 1000 Steine bereits das Problem mit der nötigen Kraft angesprochen wird, hat man die Wahl zwichen größeren Servos und dem Ausbau der Federn aus den Weichen.

Größere Servos heist jetzt nicht unbedingt von den Dimensionen. Ich habe hier Servos die knapp 1kg an 0,5m Hebelarm halten können.
Das sind halt welche mit Metalgetriebe, entsprechend kräftigem Motor und deutlich jenseits der 5€ Klasse.
Mit einem Kniehelbel. sollte sich aber auch mit einem "kleinen" Servo für so einen kurzen Stellweg einiges an Kraft rausholen lassen.

Radom
05.04.2017, 13:25
Danke für die Informationen und den Link für den Polaritätswender. :)

Hast du auch noch eine Idee woran das mit dem Rechtecksignal liegen könnte?
Das Signal war auf 1 ms eingestellt und sah so aus (leider nur als Zeichnung, weil auf einmal ging's ja): 32531

Das macht mir schon noch Bauchschmerzen, weil ich es nicht nachvollziehen kann... :confused:

i_make_it
05.04.2017, 14:03
Das ist nicht pauschal zu beantworten, grade wenn es ohne ersichtlichen Grund auch wieder verschwindet.

Ein möglicher Kanidat, wäre das es ein Problem mit einem Stützkondensator gab und danach die Spannung einbrach bis andere Komponenten eine niedrigere verrauschte Spannung halten konnten.
Bis hin zu einem Hänger beim µC der nach längerem aus und Neustart nicht mehr da ist.

Wenn es nicht wiederkommt, ist es aber auch müßig nach der Ursache zu forschen, Du willst Ja keine Raumsonde ins All schicken, bei der man später keine Chance mehr hat was grade zu biegen.
Wenn Du mehrere Weichen baust und Dich die Ursache brennend interessiert UND Du Geld Loswerden willst, könnte man sich mit 8 Kanal Soundkarten und Soundkarten Osziloskopen befassen bzw. 8 Kanal Analog Messkarten.
Da bewegt man sich halt im Bereich von 200€ und mehr.
Wobei man da erst mal nur erfasst ob, wie oft und wo es zu dem Effekt kommt.
Das Zeitsynchone debuggen um daraus Rückschlüsse auf Registerzustände und grade verarbeitete Befehle während des Effekts zu erhalten ist dann nochmal ein schöner Zeitvertreib.

Wenn es wiederholt auftritt, wäre als erstes mal der Servo zu trennen und festzustellen ob ohne Last der Effekt überhaupt auftritt.
Dann kann man mal einen höherwertigen Qualitätsservo nehmen und da feststelle nob der Effekt auftritt.
Danach noch mal mit der Orginalkonfiguration und den Effekt reproduzieren.

Wenn es sich an einer Komponente festmachen lässt, dann kann man da ins Detail gehen.

oberallgeier
05.04.2017, 14:07
.. Hast du auch noch eine Idee woran das mit dem Rechtecksignal liegen könnte? ..
Die kleinen Servos sind leider zu schwach um die Weiche über den normalen Mechanismus zu stellen und ..
Wie siehts denn aus mit der Verschaltung des Ganzen? Siehe hier/klick (http://rn-wissen.de/wiki/index.php?title=Servos#Ansteuerung:_Signalform_und _Schaltung) - dann runterscrollen bis diese Zeichnung (http://rn-wissen.de/wiki/images/d/d6/Servoansteuerg_02.gif) erscheint. Denn mir kommt dieser Spannungseinbruch so vor, als würde die Versorgung des Servos nicht ausreichen (und eventuell weitere Störungen auftreten weil die Servos nicht weitgehend von der Controller(Board-)versorgung getrennt sind).

Nachtrag: i_make_it made it much schneller *gg*

Radom
07.04.2017, 12:49
Danke für eure Tips!

@ i_make_it
Da ich den Einbruch nicht reproduzieren kann, wird mir wohl nix übrig bleiben als abzuwarten ob es noch mal kommt und dann wie von dir vorgeschlagen zu analysieren.

@ oberallgeier
Die Servos haben eine eigene Stromversorgung (das umgebaute PC Netzteil) und der Arduino hängt aktuell noch über USB am PC, später hängt er mit dem passen Kabel in einer eigenen Steckdose.
Die beiden GND sind verbunden (da bin ich schon drüber gestolpert, weil es ohne dem ja gar nicht funktioniert :lol:)
Die Schieberegister werden über den Arduino versorgt.

Edit:
32535

021aet04
08.04.2017, 09:41
Auf was du noch achten solltest ist, das du die Massen (GND) sternförmig an der Versorgung anschließt. Also Versorgung->uC, Versorgung->Servo und nicht Versorgung->Servo->uC oder umgekehrt.

MfG Hannes

Radom
14.04.2017, 09:00
Hm, aber hier (http://rn-wissen.de/wiki/images/d/d6/Servoansteuerg_02.gif) ist es doch auch sternförmig :confused:
Leider verstehe ich nicht wie es dann aussehen sollte, kannst du mir bitte eine Skizze machen?

021aet04
15.04.2017, 07:34
Das die Masse verbunden sein muss ist klar, aber ob sternförmig oder nicht sieht man im Plan nicht. Das sieht man nur am tatsächlichen Aufbau. Es kann sein das du bei einem Servo keine Probleme hast, aber bei höheren Lasten kann es zu Problemen kommen. Jede Leiterbahn ist ein Widerstand an dem, je nach Strom, eine gewisse Spannung abfällt. Bei einem uC kann es dann passieren das er plötzlich resettet und du den Fehler nicht findest. Im Audiobereich sind Masseschleifen das gefährliche, die hört man (brummen).

MfG Hannes

Radom
24.04.2017, 06:30
...ob sternförmig oder nicht sieht man im Plan nicht.
Das verstehe ich nicht, dafür habe ich doch den Plan - damit es danach aufgebaut wird...

Meinst du dass ich eine Masseschleife durch Induktion bekommen könnte? Muss ich da wirklich schon bei so kleinen Strömen aufpassen?
So sieht der Aufbau zum testen aus:
32563 (Edit: Kritik erwünscht! ..hilft mir ja...)

Für die Bahn soll das natürlich nicht so bleiben, ich werde das auf Platinen verlöten sodass es (möglichst) keine Überschneidungen der Kabel gibt.
Alles soll na bei einander bleiben, außer natürlich den Servos, weil da geht's ja nicht.

i_make_it
24.04.2017, 06:44
Ein Schaltplan ist eine logische Darstellung der Schaltung, die nicht unbedingt etwas mit dem physikalischen Aufbau zu tun haben muß.
Man kann in einem Schaltplan auch an jedes Bauteil das mit GND verbunden ist einfach ein GND Symbol setzen, dann weis man was alles mit GND verbunden werden muß, aber nicht wie und wo.
Bei einem Verdratungsplan, kann man für mehrere Platinen/Module erkennen wie diese zu verdrahten sind und so sehen ob dort GND als Stern oder als Strang ausgeführt ist.
Über den Aufbau von GND auf einer Platine sagt einem dieser Plan aber auch nichts.
Das sieht man dann erst im Platinenlayout wo man die Leiterbahnführung darstellt.
Auch dort sieht man dann erst die Länge von einzelnen Leiterbahnen und ob es dadurch zu Versatz in der Signallaufzeit kommt. (gilt bei HF und hoch getakteten Digitalschaltungen).
Ebenso zeigen sich dort erst kapazitive und induktive Kopplungen so wie Leiterwiderstände die ggf. durch anderes Routung, zusätzliche GND Leiterbahnen als Schirm oder komplette GND Layer zu beheben sind. (nicht umsonst haben Computermotherboard mittlerweile weit über 10 Layer).

Dieses Thema wird also mit steigendem Komplexitätsgrad der Schaltung immer wichtiger.

Masseschleifen sollte man einfach generell vermeiden, dann muß man nie unterscheiden wo kann man sie vermeiden und wo muß man sie vermeiden.
Wenn du Signalspannungen von 220V und Signalströme von 1A und mehr hast, sind Dir mV und µA egal.
Aber bei einem 3,3V System und 5mA sind da schnell mal, bei identischen absoluten Beträgen, ein paar Prozent erreicht.
Dann noch etwas Dämpfung und Potentialunterschiede (wegen GND als Strang) und man hat Fehlerursachen an denen man sich einen Wolf suchen kann.

021aet04
25.04.2017, 08:24
1.) Masseschleife durch Induktion? Was meinst du damit?
2.) Wenig Strom ist das bei einem Servo definitiv nicht. Servos nehmen beim Verfahren mehrere Ampere auf (abhängig vom Servo) und das ist nicht wenig.
3.) Du musst dir vor Augen halten das jede Leiterbahn ein Widerstand ist und dieser einen lastabhängigen Spannungsabfall verursacht. Dadurch kann es z.b. zu einem Reset des uC kommen (im schlimmsten Fall).

MfG Hannes

Radom
25.04.2017, 09:13
@i_make_it
Davon bin ich weit entfernt! Wenn ich meinen Plan nicht so aufbaue, wie er dann auch tatsächlich verdrahtet wird, kenn ich mich nicht mehr aus, bin ja blutiger Anfänger mit Elektronik... :lol:
Edit: 10 oder mehr Layer, wegen Signalversatz auf die Länge der Leitung achten, da raucht mir der Kopf, wobei ich mich wahrscheinlich schon mit
kapazitive und induktive Kopplungen beschäftigen werde müssen

@Hannes
1) Masseschleife war falsch geschrieben, die habe ich ja nicht. Aber einen Störstrom könnte ich ja durch Induktion bekommen, oder? (weil das gibt es im Audiobereich ja auch)
2) Der gezogene Strom für die Servos läuft doch bei mir nicht über uC, wegen der extra Stromversorgung, deshalb macht man das doch, oder verstehe ich es falsch?
3) Der uC resetet ja nicht, sondern das Rechtecksignal zitterte am Ende

Danke für eure vielen Infos!

021aet04
25.04.2017, 09:46
Zu Punkt 2 musst du meinen Punkt 3 lesen => jede Leiterbahn ist ein Widerstand mit lastabhängigem Spannungsabfall
Zu Punkt 3 habe ich geschrieben das im schlimmsten Fall der uC resettet, es können aber auch andere Fälle eintreten (wiebei dir mit den Signalen).
Deswegen Lastkreis und Steuerkreis trennen, Massen an einem Punkt zusammenführen (Sternpunkt).

MfG Hannes

Radom
26.06.2017, 10:57
Ist schon einige Zeit her, aber das Thema war ja noch nicht vom Tisch.

Den Kabelsalat habe ich durch Platinen ersetzt. Es gibt jetzt nur noch längere an den Tastern und Servos, weil sie ja weiter weg sind.
Last- und Steuerkreis sind getrennt und Massen habe ich auch sauber zusammengeführt.

Danke für eure Tips und Infos !
Was auch immer es am Ende war es hat sich erledigt, jetzt läuft es !! :D :D

Zur Programmierung von zeitkritischen Sachen habe ich noch Fragen, bei denen ihr mir vielleicht noch mal Tips geben könnt:
Kann man eigentlich irgendwie messen wie lange bestimmte Anweisungen brauchen, oder bleibt da nur testen ?

Viele Anweisungen, die in der ISR ausgeführt werden sollen, habe ich ja eigentlich nicht (gefühlt):
Timer 1

Servo-Laufvariable resetten wenn > Anzahl Servos
3 einfache Berechnungen um am MUX-Shield den richtigen Pin auszulesen
je nach Taster-Status Werte in zwei Arrays schreiben
über eine for() jeweils 1x shiftOut() an insgesamt 3 Register senden
Länge für OCR1B aus dem Array lesen, dem Timer zuweisen und ihn starten


Timer 2

Timer interrupt abschalten
per shiftOut() das Steuersignal wieder abschalten


Anfangs hatte ich den Ablauf noch etwas anders, aufgeblähter, und ich musste die Routinen auf das obige reduzieren sonst war der Zeitablauf gestört und es lief natürlich nicht.
Am schlimmsten waren

Serial.print()
Serial.println()
die ich Anfangs einfach brauchte um meinen Code zu kontrollieren.

Die kürzeste Zeit, die der Arduino in meinem Programm zum Ausführen bis zum nächsten Interrupt hat, sind 0,6 ms - und mich wundert jetzt, dass bei einem Takt von 16 MHz, den der Arduino UNO ja hat, so wenige Zeilen da schon was ausmachen.
Also dass das ein Tick nicht genügt um eine Anweisung auszuführen ist mir klar, aber gibt es Anhaltswerte wonach ich gehen kann? Dass ich abschätzen kann wie viele Anweisungen in eine Zeit x passen?
Wie macht ihr das?


Viele Grüße, Radom

oberallgeier
26.06.2017, 16:01
.. Die kürzeste Zeit .. bis zum nächsten Interrupt hat, sind 0,6 ms .. gibt es Anhaltswerte wonach ich gehen kann? Dass ich abschätzen kann wie viele Anweisungen in eine Zeit x passen?
Wie macht ihr das? ..600 µs bei 16 MHz ergibt 9600 Taktzyklen. Das sind ja nu nicht sooo viel. Nen genauen Zeitbedarf bekommst Du aus der fooxxfile.lls heraus. Darin, in der *.lls steht nämlich neben allen möglichen Dingen auch der (dis-)assemblierte Code Deines Programms, siehe dieses Beispiel aus (m)einen Codevorrat :
arno_01.elf: file format elf32-avr

Sections:
Idx Name Size VMA LMA File off Algn
0 .data 00000366 00800100 000019cc 00001a80 2**0
CONTENTS, ALLOC, LOAD, DATA
1 .text 000019cc 00000000 00000000 000000b4 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .bss 00000165 00800466 00800466 00001de6 2**0
ALLOC
3 .eeprom 00000001 00810000 00810000 00001de6 2**0
CONTENTS, ALLOC, LOAD, DATA
4 .debug_aranges 00000020 00000000 00000000 00001de7 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_pubnames 000006d9 00000000 00000000 00001e07 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_info 000019a4 00000000 00000000 000024e0 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_abbrev 00000311 00000000 00000000 00003e84 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_line 0000141d 00000000 00000000 00004195 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_frame 000002e0 00000000 00000000 000055b4 2**2
CONTENTS, READONLY, DEBUGGING
10 .debug_str 00000649 00000000 00000000 00005894 2**0
CONTENTS, READONLY, DEBUGGING
11 .debug_loc 00000619 00000000 00000000 00005edd 2**0
CONTENTS, READONLY, DEBUGGING
12 .debug_ranges 000000c0 00000000 00000000 000064f6 2**0
CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
8: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
c: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
10: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
14: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
18: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
1c: 0c 94 6e 02 jmp 0x4dc ; 0x4dc <__vector_7>
20: 0c 94 a0 02 jmp 0x540 ; 0x540 <__vector_8>
24: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
28: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
2c: 0c 94 f4 01 jmp 0x3e8 ; 0x3e8 <__vector_11>
30: 0c 94 2c 02 jmp 0x458 ; 0x458 <__vector_12>
34: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
38: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
3c: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
40: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
44: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
48: 0c 94 90 00 jmp 0x120 ; 0x120 <__vector_18>
4c: 0c 94 bc 00 jmp 0x178 ; 0x178 <__vector_19>
50: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
54: 0c 94 5b 06 jmp 0xcb6 ; 0xcb6 <__vector_21>
58: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
5c: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
60: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>
64: 0c 94 51 00 jmp 0xa2 ; 0xa2 <__bad_interrupt>

..
00000120 <__vector_18>:
// ================================================== ============================ =


// ================================================== ============================ =
ISR( USART0_RX_vect )
{
120: 1f 92 push r1
122: 0f 92 push r0
124: 0f b6 in r0, 0x3f ; 63
126: 0f 92 push r0
128: 11 24 eor r1, r1
12a: 8f 93 push r24
12c: 9f 93 push r25
12e: ef 93 push r30
130: ff 93 push r31
u8 i = rx_in;
132: 90 91 af 04 lds r25, 0x04AF

ROLLOVER( i, RX0_SIZE );
136: 9f 5f subi r25, 0xFF ; 255
138: 90 34 cpi r25, 0x40 ; 64
13a: 08 f0 brcs .+2 ; 0x13e <__vector_18+0x1e>
13c: 90 e0 ldi r25, 0x00 ; 0
if( i == rx_out ){ // buffer overflow
13e: 80 91 b0 04 lds r24, 0x04B0
142: 98 17 cp r25, r24
144: 31 f4 brne .+12 ; 0x152 <__vector_18+0x32>
URX0_IEN = 0; // disable RX interrupt
146: 80 91 c1 00 lds r24, 0x00C1
14a: 8f 77 andi r24, 0x7F ; 127
14c: 80 93 c1 00 sts 0x00C1, r24
150: 0a c0 rjmp .+20 ; 0x166 <__vector_18+0x46>
return;
}
rx_buff[rx_in] = UDR0;
152: e0 91 af 04 lds r30, 0x04AF
156: f0 e0 ldi r31, 0x00 ; 0
158: 80 91 c6 00 lds r24, 0x00C6
15c: e1 59 subi r30, 0x91 ; 145
15e: fb 4f sbci r31, 0xFB ; 251
160: 80 83 st Z, r24
rx_in = i;
162: 90 93 af 04 sts 0x04AF, r25
}
166: ff 91 pop r31
168: ef 91 pop r30
16a: 9f 91 pop r25
16c: 8f 91 pop r24
16e: 0f 90 pop r0
170: 0f be out 0x3f, r0 ; 63
172: 0f 90 pop r0
174: 1f 90 pop r1
176: 18 95 reti

00000178 <__vector_19>:
// ================================================== =========================== =
..
..
// ================================================== =========================== =
..
000019c8 <_exit>:
19c8: f8 94 cli

000019ca <__stop_program>:
19ca: ff cf rjmp .-2 ; 0x19ca <__stop_program>


Anfangs allerlei Organisation. Beachte die beispielhafte ISR( USART0_RX_vect ), besonders die pushs am Beginn und die pops am Ende der ISR. Die sind blanker Overhead, weil die ISR erstmal alle von ihr benutzten (manchmal nicht benutzte) Register am Stack sichern - pushen - muss. Weil sie ja zu einem beliebigen Zeitpunkt/Codeabschnitt bedient wird, an dem "niemand" weiß, was gerade in den zentralen Registern der ALU steckt. Am Ende des eigentlich "sinnvollen" Codes der ISR werden die entsprechend der ISR-Startsituation gesicherten Register wieder zurückgeladen - gepopt. Zweimal je sieben pushs bzw. pops sind schon mal achtundzwanzig Maschinenzyklen - die aufgewendet werden müssen, damit alles seine Richtigkeit hat (im beispielhaften Controller pro push oder pull jeweils 2 Zyklen).

Dieser Overhead kostet Zeit wie jeder andere Prozessor-Codeschritt. Und so simpel wie eben von mir vorgerechnet kannst Du nun Routine für Routine durchgehen und die einzelnen Zeiten rauslesen (siehe Datenblatt, Instruction Set Summary, hier aus dem Atmel-42735B-ATmega328/P_Datasheet_Complete-11/2016). Dies gilt aber nur dann, wenn nicht innerhalb Deines betrachteten Codes eine - oder mehrere - ISR ausgelöst werden und abgearbeitet werden müssen . . . es sei denn, es geht um einen Abschnitt der z.B. mit cli (); (=Global Interrupt Disable) anfängt und mit sei (); (= Global Interrupt Enable) endet ODER wenn Interrupts z.B. noch garnicht erlaubt sind.

Klar ?