Erledigt
12345
Druckbare Version
Erledigt
12345
Hallo alle, diese alte Platine >> NICHT BESTÜCKT << .. verschenken oder verschrotten .. spätestens am 10 Sept 2021 in den Müll.
Update: Okt 2021 - weg issie
Guten Tag allen,
vor acht Jahren oder länger hatte ich geätzte Platinen für SMD/THD für meinen archie machen lassen. Profimässig - statt gefädelt auf Lochraster, war VIEL hübscher - und erheblich angenehmer zu Bestücken. Gefertigt bei >vermutlich< Seedstudio - einem chinesischen Hersteller. Günstig und sehr guter Service.
Derzeit möchte ich meine kleine 0,15liter-Coladose (Video siehe hier) aufbauen und dafür natürlich auch ne Platine mit einigem SMD machen.
Frage: welche(r) Hersteller sind aktuell zu empfehlen? Es sollte halt nicht zuu teuer werden.
Anm.: Vielleicht finde ich auch Nachbauer - die könnten mit ner fertigen Platine viel einfacher bauen . . .
Danke im Voraus für Eure Hilfe/n. Viele Grüße aus dem sonnigen Süden
Hi Joe,
seit Jahren erstelle ich meinen Platinen per:
https://easyeda.com/de
Und fertige sie über:
https://jlcpcb.com/
...es gibt eine direkte Schnittstelle, über die man die erstellten Gerberdateien zum Fertiger schieben kann...das Ganze mit komfortabler Voransicht, Kalkulation und dabei supergünstig.
Ich kann mich nicht erinnern, dass ich jemals im Endeffekt mehr als 2€ für eine Platine bezahlt habe, oft im wenigen Cent-Bereich - aber Achtung, das verleitet schnell dazu viel zuviele zu bestellen, was totaler Quatsch ist. ;-)
(so viele Vereinskollegen habe ich gar nicht)
Bild hier
Andree, danke für diese schnellen Auskünfte, hinter denen ja jede Menge Erfahrung steckt!Zitat:
.. seit Jahren erstelle ich meinen Platinen per: ... mit komfortabler Voransicht, Kalkulation und dabei supergünstig ...
*ggg*Zitat:
... aber Achtung, das verleitet schnell dazu viel zuviele zu bestellen ...
Danke Andree
Nur Test:
Code:/* >> Stand ..\C5_Ronny-5_etc\ALCo\ALCo_tmrij.c
=============================================================================== =
Target MCU : ATmega1284p
Target Hardware : siehe main
Target cpu-frequ. : siehe main 20 MHz Quarz, vgl. Current Conf. Options
=============================================================================== =
*** Versionsgeschichte:
x03 19Sep22 1730 alle Quellfiles : Filenummern aktualisieren auf ~03~
====================
x40 6Aug16 1204 Versionsupdate nach erfolgter Uebernahme ins Studio7 x
x00 14Jul15 1730 Übernahme des Originals ARCo_x23.c x23 14Jun15 1500
=============================================================================== =
*** Aufgabenstellung : Software RJjr, ArmLiController/Servobetrieb, ATmega1284p
Original: ...\C5_Ronny-5_etc\ARCo\ARCo_x.. siehe main
============================================================================== */
// FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP FP =
/* == Funktionsprototypen
// - - - - - - - - - - - - - - - -
void TC0PWM_init(void) ; // Tmr/Ctr0 initialisieren für PWM-Signal 36+ kHz
void IRLEDset (u8 speed1) ; // Relative Pulslänge auf OC0B/PB4 setzen
void TC1TMR_init(void) ; // Init Timer/Counter 1 für 2 ms Servoperiode
void TC1TMR_on(void) ; // Init Timer/Counter enable
void TC1TMR_off(void) ; // Init Timer/Counter disable
ISR (TIMER1_COMPA_vect) ; // Servo Svpt aktuell wählen + Servorampe starten
ISR (TIMER1_COMPB_vect) ; // VECTOR 9 S 65
void TC2TMR_init (void) ; // Init Tmr/Cntr2, 8-Bit bei 20 kHz => 50 µs
void TC2_stop (void) ; // Stoppe Tmr/Cntr 2
ISR (TIMER2_COMPA_vect) ; // Routine zählt hoch, bei 20 kHz => 50 µs
void wms (uint16_t ms) ; // Programm pausieren lassen
void wmus (uint16_t us) ; // Wait in MikrosekundenD
// FP FP FP FP FP FP FP FP FP FP FP FP FP ******************************* */
// FP FP FP FP FP FP FP FP FP FP FP FP FP
/* **************************************************************************** **
** **************************************************************************** */
// ============================================================================= =
// ============================================================================= =
// Routine initialisiert Timer0/PINB4 auf mega1284 für die IR-LED
// siehe KoCo .. Timerroutinen_zum_IR-LED_schalten.txt
// ===============================================================================
// == Initialisierung von Timer0/PINB4 auf mega1284 für die IR-LED
void TC0PWM_init(void) // Tmr/Ctr0 initialisieren für PWM-Signal 36+ kHz
{ //
TCCR0A |= (1<<WGM00); // Phase Correct PWM mode 106
TCCR0B |= (1<<WGM02); // ###>>> mit TOP = OCR0A 106
TCCR0B |= (1<<CS01); // => clk/8 => 35,7 kHz mit OCR0A=35 108
TCCR0A |= (1<<COM0B1); // Clr OC0B on Compare Match when up-counting 106
// Set OC0B on Compare Match when down-counting
OCR0A = 35; // Phase Correct PWM mode 5 => OCR0A ist TOP 106
OCR0B = 17; // =>PWM-Startwert => ca. 50 % duty cycle
// Anmerkg: OCR0A=35 und Vorteiler clk/8 => 20*10e6 / 8 / 35 / 2 = 35 714 Hz
// Die letzte Division (durch 2) macht die Frequenztheorie selbst *ggg*
// Steuern der IR-Modulationsfrequenz durch OCR0B als "zweiter" Vorteiler
// ###>>> Die ISR (TIMER2_COMPA.. enthält einen kleinen IR-LED-Wobbel !!
TIMSK0 &= ~(1<<OCIE0A); // Tmr/Cntr0 Oput CompA Mtch intrpt disabld
TIMSK0 &= ~(1<<OCIE0B); // Tmr/Cntr0 Oput CompB Mtch intrpt disabld
//TIMSK0 |= (1<<TOIE0); // Tmr/Cntr0 Overflow interrupt enabled
return; // Ende
} // Ende void TC0PWM_init(void)
// ============================================================================= =
// ============================================================================= =
void IRLEDset (u8 speed1) // Relative Pulslänge auf OC0B/PB4 setzen
{OCR0B = 60;} // z.B. für SFH5110
// ============================================================================= =
// ============================================================================= =
// == Timer Aufgabe: Servo mit Soft-PWM ansteuern auf wählbarem Port
// Beispiel: Set TCNT1 to 0x01FF : TCNT1 = 0x1FF;
// Read TCNT1 into i : i = TCNT1;
// - - - - - - - - - - - - - - - -
void TC1TMR_init(void) // Init Timer/Counter 1 für 2 ms Servoperiode
{ //
TCCR1B |= (1<<WGM12); // WGM12 => CTC, TOP = OCR1A S135
TCCR1B |= (1<<CS11); // CS11+10 <=> clk/8 => 2,500 MHz S136
OCR1A = OCR1AV; // 10x OCR1AV = 63990=> alle 25,60 ms 1 Interrupt
// Interrupt zählt bis 6400 !
OCR1B = OCR1BV; // OCR1B = {???} => 1-2 ms Rampe
// TIMSK1 |= (1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt enabled
// - - - - - - - - - - - - - - - -
SetBit (PORTC, L1r); // rtLED ein, Kontrolle für Servotimer-init
}
// ============================================================================= =
// ============================================================================= =
// == Timer1
// - - - - - - - - - - - - - - - -
void TC1TMR_on(void) // Init Timer/Counter enable
{ //
TIMSK1 |= (1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt enabled
Svpt = 1; // Zeiger auf den aktuellen Servo
}
// ============================================================================= =
// ============================================================================= =
// == Timer1
// - - - - - - - - - - - - - - - -
void TC1TMR_off(void) // Init Timer/Counter disable
{ //
TIMSK1 &= ~(1<<OCIE1A); // Tmr/Cntr1 Oput CompA Mtch intrrpt disabled
OCR1B = 0; // Servorampe auf Null setzen
Svpt = 1; // Zeiger auf den aktuellen Servo
}
// ============================================================================= =
// ============================================================================= =
// === ISR für TIMER1_COMPA_vect, VECTOR 16 (vgl. S 65) ==================== =
// Zehn Servos umlaufend ansteuern. Es gibt 2 Fälle:
// 1. SerPos1 _ODER_ SerPos2 ist =|= 0, dann ist dies Srv_tm
// 2. SerPos1 und SerPos2 sind belegt, dann MUSS SDelta auch belegt sein,
// sonst gilt SerPos1
// Es wird SerMal von Posa nach Posb oder zurück gefahren, je nach SDelta
/* **************************************************************************** **
** **************************************************************************** */
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ISR (TIMER1_COMPA_vect) // Servo[Svpt] wählen + dessen Rampe starten
{ //
u8 xt; // Kurzschreibweise für Servopointer
// xt = NxtSvpt; //
// - - - - - - - - - - - - - - -
Svpt ++; // Pointer für diesen, aktuellen Servo eins rauf
if ((Svpt < 1) || (Svpt > Svmx)) Svpt = 1; // und eingrenzen auf {1-10}
xt = Svpt + 1; // Pointer auf nächsten Servo berechnen
if ( xt >= 11) xt = 1; // .. Überlauf abfangen
// - - - - - - - - - - - - - - -
// Für den aktuellen Servopointer liegt ein korrekter Wert Srv_tm[nr] vor
// Den aktuellen Srv_tm-Wert auf zulässige Schranken begegrenzen, vgl. kal_0
// und vor dem Setzen Offset draufrechnen. ##########################
if ( SrvCHK ) // Prüfung nur, wenn ServoCHECK aktiv !!
{ //
if ( Srv_tm[Svpt] < SrvMin [Svpt] ) Srv_tm[Svpt] = SrvMin [Svpt];
if ( Srv_tm[Svpt] > SrvMax [Svpt] ) Srv_tm[Svpt] = SrvMax [Svpt];
} //
// - - - - - - - - - - - - - - - -
switch (Svpt) //
{ //
case 1: SetBit ( PC, Servo1 ); break;
case 2: SetBit ( PC, Servo2 ); break;
case 3: SetBit ( PC, Servo3 ); break;
case 4: SetBit ( PC, Servo4 ); break;
case 5: SetBit ( PC, Servo5 ); break;
case 6: SetBit ( PC, Servo6 ); break;
case 7: SetBit ( PA, Servo7 ); break;
case 8: SetBit ( PA, Servo8 ); break;
case 9: SetBit ( PA, Servo9 ); break;
case 10: SetBit ( PA, Servo10); break;
default: break; // hierher würde noch n Fehlerflag passen
} // Ende switch (Svpt)
// - - - - - - - - - - - - - - -
// OCR1B = Srv_tm[Svpt]; // Stellwert ist durch Rampenwert Srv_tm definiert
OCR1B = Srv_tm[Svpt] + Seroff [Svpt]; // Rampenwert ist mit Srv_tm definiert
TIFR1 |= (1<<OCF1B); // ??? Klappt immer wenn dies gesetzt wird
TIMSK1 |= (1<<OCIE1B); // Tmr/Cntr1 CompB Match interrupt enabled
// d.h. Timer1B starten <=> nächster Servo...
// - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - -
// ########>>>>>>>> Und nun wird der Interupt erlaubt, damit
// ########>>>>>>>> die ISR nicht zuuuu lange dauert.
sei(); // ########>>>>>>>> Erlaube nested Interrupts
//======
// - - - - - - - - - - - - - - -
// rtLED blinken => Servotimer-Funktionskontrolle etwa im Sekundentakt
if ( IsBitSet ( FlgLED, 2 )) Tglpt ++; // Togglepointer rauf wenn Flag
if (Tglpt == 368) Tglpt = 1; // Ca. Sekundentakt als Funktionskontrolle
if (Tglpt == 1) SetBit (PrtLED, L1r); //
if (Tglpt == 2) ClrBit (PrtLED, L1r); // EIN kurzer Blinkie pro Sekunde
// - - - - - - - - - - - - - - -
// - - Wert für nächsten Servo holen wenn möglich
// Servowert >>holen<< von SrvZa1 oder so derzeit nicht installiert
// es wird >>nur<< mit den Daten in SrvZa0 ff gefahren, solange
// SrvFg0 nicht Null ist.
if ( SrvFu0[xt] ) // Flag ist !0 wenn Daten existieren ! WENN nicht
{ // Null, dann Daten so lange auswerten, bis
// das letzte Teilstück gefahren wurde
switch (SrvFu0[xt]) //
{ //
// - - - - - - - - - - - - - - -
case 1: // Standardfahrt von akt. Pos. nach ~Za~
Srv_tm[xt] = SrvZa0[xt]; // Direktfahrt
SrvFu0[xt] = 0; // quittiere Datenübernahme
SrvFg0[xt] = 0; // und hier
break;
// - - - - - - - - - - - - - - - -
case 6: // Fahre erste Servoperiode Richtung "Anfang" = ~Za0~
// Aufgabenstellung:
// Fahre von ~tm~ nach ~Za~ mit reduzierter Geschwindigkeit
// ==> bestimme das vorzeichenrichtige SrvIc0
// prüfe ob das nächste Teilstück das Ziel erreicht
// dann Ende des ERSTEN Teilstücks,
// Rest wird in case 61 gefahren
// ansonsten fahre das erste Teilstück,
// Rest wird in case 61 gefahren
// Evtl. zweites Teilstück nach ~Zb0~ in case 62
// TeilstreckenAnzahl für Fahrt mit SrvZx0[]-Tupel
if ( Srv_tm[xt] == SrvZa0[xt] )
{ //
SrvFu0[xt] = 61; // ... Flag 61 für Weiterfahrt setzen
break;
}
// Prüfe ob vom aktuellen ~tm~ nach ~Za~ In- oder Decrement notwendig ist
if (Srv_tm [xt] > SrvZa0[xt] ) SrvIc0[xt] = - 1 * abs (SrvIc0[xt]);
if ( Srv_tm[xt] > SrvZa0[xt] ) // DEcrementieren wenn ~tm~ > Za0 =>
// Ab hier ist ~tm~ > ~Za0~ ! ! !
{ // => Negatives Vorzeichen sicherstellen
if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0[xt] )
// gehts schon beim ersten Teilstück zu WEIT ?!?!
{ //
Srv_tm[xt] = SrvZa0[xt]; // => dann fahre nur bis zum Teil-Ende
SrvFg0[xt] --; // Teilstreckenende = erreicht => dekrem.
if ( SrvFg0[xt] <= 0 ) // WENN letztes Teilstück
{ //
SrvFu0[xt] = 0; // quittiere sofort die Datenübernahme
SrvFg0[xt] = 0; // und TeilstreckenAnzahl auf Null setzen
// ###>>> Ein anschließendes break ist erstmal unsinnig, weil noch
// der zweite Punkt, ~Zb0~, angesteuert werden muss.
// ###>>> Ein anschließendes break ist erstmal unsinnig, weil noch
// KANN sinnvoll sein, WENN nur ein Teilstück möglich ist
} // Ende if ( SrvFg0[xt] <= 0 )
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0[xt] )
else // andernfalls ist das erste Teilstück hier nicht zu WEIT
{ // .. d.h. ~tm~ < ~Za0~ ! ! !
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // nächster Zielpunkt
SrvFu0[xt] = 61; // ... Flag 61 für Weiterfahrt setzenOK
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0[xt] )
} // NOCH if ( Srv_tm[xt] > SrvZa0[xt] ) ...
else // Ab hier ist ~tm~ < ~Za0 <=> also INcrementieren
{ //
SrvIc0[xt] = abs (SrvIc0[xt]); // Positives Increm. sicherstellen
if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0[xt] ) // ?? zu WEIT ??
{ //
Srv_tm[xt] = SrvZa0[xt]; // => dann fahre nur bis zum Teil-Ende
SrvFg0[xt] --; // dekrementieren
if ( SrvFg0[xt] <= 0 ) // WENN letztes Teilstück
{ //
SrvFu0[xt] = 0; // und quittiere sofort die Datenübernahme
SrvFg0[xt] = 0; // und TeilstreckenAnzahl auf Null setzen
// ###>>> Ein anschließendes break ist erstmal unsinnig, weil noch
// der zweite Punkt, ~Zb0~, angesteuert werden muss.
// KANN sinnvoll sein WENN nur ein Teilstück möglichnötig ist
} // Ende if ( SrvFg0[xt] <= 0 )
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0
else // andernfalls
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // nächster Zielpunkt
SrvFu0[xt] = 61; // ... Flag 61 für Weiterfahrt setzenOK
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0
} //
break; // Ende case 6: ... ERSTE Servoperiode Richtung ~Za0~
// - - - - - - - - - - - - - - - -
case 61: // Ausführung Hin-Herfahrt nach ~Za/Zb~ mit reduz Geschwindigkeit
// ###>>> HIER Fahrt nach ~Za0~ nach Abarbeiten von case 6
if (Srv_tm[xt] > SrvZa0[xt]) SrvIc0[xt] = - 1 * abs (SrvIc0[xt]);
if ( SrvIc0[xt] < 0 ) // Decrementieren oder ??
{ // ==> ab hier DE-crementieren
if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0[xt] ) // dann zu WEIT !!
{ //
Srv_tm[xt] = SrvZa0[xt]; // => Fahre nur bis zum Ziel ~Za0~
SrvFg0[xt] --; // Teilstrecke runtertickern
if ( SrvFg0[xt] == 0 ) // Alle Teilstrecken abgefahren ?
{ //
SrvIc0[xt] = 0; // Daten übernehmen
SrvFu0[xt] = 0; // Daten übernehmen
break; // und Ende der Fahrt
} //
SrvFu0[xt] = 62; // Umschalten auf Fahrt nach ~Zb0~
SrvIc0[xt] = -1 * SrvIc0[xt]; // Vorzeichenwechsel
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0
else // else if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // NUR nächster Zielpunkt
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZa0
} // Ende if ( SrvIc0[xt] < 0 )
else // Ab hier wird IN-crementiert
{ //
if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0[xt] ) // dann zu WEIT !!
{ //
Srv_tm[xt] = SrvZa0[xt]; // => Fahre nur bis zum Ziel
SrvFu0[xt] = 62; // Umschalten auf Fahrt nach ~Zb0~
SrvFg0[xt] --; // Teilstrecke runtertickern
if ( SrvFg0[xt] == 0 ) // Alle Teilstrecken abgefahren ?
{ //
SrvIc0[xt] = 0; // Daten übernehmen
SrvFu0[xt] = 0; // Daten übernehmen
break; // und Ende der Fahrt
} //
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0
else // andernfalls
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // NUR nächster Zielpunkt
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZa0
} //
break; // Ende case 61: ... Fahrt nach ~Za0~
// - - - - - - - - - - - - - - - -
case 62: // Ausführung Hin-Herfahrt nach ~Za/Zb~ mit reduz Geschwindigkeit
// HIER Fahrt nach ~Zb0~ nach Abarbeiten von case 6
if (Srv_tm[xt] > SrvZb0[xt]) SrvIc0[xt] = - 1 * abs (SrvIc0[xt]);
if ( SrvIc0[xt] < 0 ) // Decrementieren oder ??
{ // ==> ab hier also decrementieren
if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZb0[xt] ) // dann zu WEIT !!
{ //
Srv_tm[xt] = SrvZb0[xt]; // => Fahre nur bis zum Ziel ~Zb0~
SrvFg0[xt] --; // Teilstrecke runtertickern
if ( SrvFg0[xt] == 0 ) // Alle Teilstrecken abgefahren ?
{ //
SrvIc0[xt] = 0; // Daten übernehmen
SrvFu0[xt] = 0; // Daten übernehmen
break; // und Ende der Fahrt
} //
SrvFu0[xt] = 61; // Umschalten auf Fahrt nach ~Zb0~
SrvIc0[xt] = -1 * SrvIc0[xt]; // Vorzeichenwechsel
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZb0
else // andernfalls
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // NUR nächster Zielpunkt
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) < SrvZb0
} // Ende if ( SrvIc0[xt] < 0 )
else // Ab hier wird incrementiert
{ //
if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZb0[xt] ) // dann zu WEIT !!
{ //
Srv_tm[xt] = SrvZb0[xt]; // => Fahre nur bis zum Ziel
SrvFg0[xt] --; // Teilstrecke runtertickern
if ( SrvFg0[xt] == 0 ) // Alle Teilstrecken abgefahren ?
{ //
SrvIc0[xt] = 0; // Daten übernehmen
SrvFu0[xt] = 0; // Daten übernehmen
break; // und Ende der Fahrt
} //
SrvFu0[xt] = 61; // Umschalten auf Fahrt nach ~Zb0~
SrvIc0[xt] = -1 * SrvIc0[xt]; // Vorzeichenwechsel
} // NOCH if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZb0
else // andernfalls
{ //
Srv_tm[xt] = Srv_tm[xt] + SrvIc0[xt]; // NUR nächster Zielpunkt
} // Ende if ( (Srv_tm[xt] + SrvIc0[xt]) > SrvZb0
} //
break; // Ende case 62: ... Fahrt nach ~Zb0~
// - - - - - - - - - - - - - - -
case 9: // Standardfahrt von akt. Pos. nach ~a~
Srv_tm[xt] = SrvZa0[xt]; // Direktfahrt
SrvFu0[xt] = 0; // quittiere Datenübernahme
break; // Ende case 9: ... Standardfahrt von akt. Pos. nach ~a~
// - - - - - - - - - - - - - - -
default:
break;
} // Ende switch (SrvFu0[xt])
} // Ende if ( !( SrvFg0[xt] ) ) // Flag is..
return; //
// - - - - - - - - - - - - - - -
} // Ende ISR (TIMER1_COMPA_vect)
// ============================================================================= =
// ============================================================================= =
// === Nicht unterbrechbare ISR für TIMER1_COMPB_vect ===================== =
ISR (TIMER1_COMPB_vect) // VECTOR 18 S 65
{ //
TIMSK1 &= ~(1<<OCIE1B); // Tmr/Cntr1 CompB Match interrupt disabled
// - - - - - - - - - - - - - - -
switch (Svpt)
{ //
case 1: ClrBit ( PC, Servo1 ); ClrBit ( PA, Servo10); break;
case 2: ClrBit ( PC, Servo2 ); ClrBit ( PC, Servo1 ); break;
case 3: ClrBit ( PC, Servo3 ); ClrBit ( PC, Servo2 ); break;
case 4: ClrBit ( PC, Servo4 ); ClrBit ( PC, Servo3 ); break;
case 5: ClrBit ( PC, Servo5 ); ClrBit ( PC, Servo4 ); break;
case 6: ClrBit ( PC, Servo6 ); ClrBit ( PC, Servo5 ); break;
case 7: ClrBit ( PA, Servo7 ); ClrBit ( PC, Servo6 ); break;
case 8: ClrBit ( PA, Servo8 ); ClrBit ( PA, Servo7 ); break;
case 9: ClrBit ( PA, Servo9 ); ClrBit ( PA, Servo8 ); break;
case 10: ClrBit ( PA, Servo10); ClrBit ( PA, Servo9 ); break;
default: break; // hierher würde noch n Fehlerflag passen
}
// - - - - - - - - - - - - - - -
} // Ende ISR (TIMER1_COMPB_vect)
// ============================================================================= =
// ============================================================================= =
// === Initialisierung fuer Timer2 mega168 ==================================== =
void TC2TMR_init (void) // Init Tmr/Cntr 2, 8-Bit auf 20 kHz = 50 µs
{ //
TCCR2A |= (1<<WGM21); // Timer im CTC-Mode, Top=OCR2A doc S 156
TCCR2B |= (1<<CS21); // Prescaler 1/8 / Clock <- CPU doc S 157
OCR2A = 124; // Preset 124 für 50µs bei 20Mhz
TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled
// Izeit_1 = 20000; // Laufzeit nullen - unabhängig von Isecndn !!
ClrBit (PrtLED, L1g); // gnLED/PD4 ausschalten
tmr1 = tmrAN = 0; // Timer nullen
} //
// ============================================================================= =
// ============================================================================= =
// === Stoppen Timer2 mega168
void TC2_stop(void) // Stoppe Tmr/Cntr 2
{ //
TCCR2A &= ~(1<<WGM21); // Timer WGM21 resetten
TIMSK2 &= ~(1<<OCIE2A); // Tmr/Cntr2 CompA interrupt DIS abled
} //
// ============================================================================= =
// ============================================================================= =
// === Nicht unterbrechbare ISR für timer2 ==================================== =
// Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR für
// EXT_INT0 und -INT1 ausgelesen und den Werten Iz_yseci zugewiesen
ISR (TIMER2_COMPA_vect) // Vektor 7
{ //
// - - - - - - - - - - - - - - - -
if ( Izeit_1 ) //Interrupt-Timer = 1 ... 20 000 ... (1 sec blink)
// WENN Izeit_1 =|= Null => Ausdruck ist wahr => Anweisung wird ausgeführt
{ //
Izeit_1 --; // ###>>> Izeit_1 ist aktuell int16_t ==>>
// Izeit_1 bleibt bis 32000 in der int16-Grenze
} // siehe if ( Izeit_1 )
else // Eine Sekunde ist voll =>
{ //
Izeit_1 = 20000; // Rückstellen auf 20000
Isec_alt = Isecundn; // Die aktuelle Sekunde (Überlauf!!) sichern
Isecundn ++; // Boardzeit-Sekunden hochzählen, max 9 Std
Isec_lok ++; // Lokale Sekunden hochzählen, kann überlaufen,
// ... der wird IRGENDWO im Programm gebraucht
ToggleBit (PORTD, L1g); // LED/PC4 toggeln, HEARTBEAT
// Allzwecktimer tmr1 - siehe ~com~
if ( tmr1 ) tmr1 --; // einfach tickern bis Null
if ( tmrAN ) tmrAN --; // Downcounter 0,1 sec für ~AN1~
// - - - - - - - - - - - - - - - -
} // Ende if ( Izeit_1 )
if ( Izeit01 ) //Interrupt-Timer 01, Zehntelsekundentimer
{ //
Izeit01 --; // ###>>> Izeit01 für 0,1 sec - Timer
} // siehe if ( Izeit_1 )
else // Eine 1/10tel Sekunde ist voll =>
{ //
Izeit01 = 2000; // Rückstellen auf 20000
// Allzwecktimer - siehe ~com~
if ( tmrAN01 ) tmrAN01 --; // einfach tickern bis Null
// - - - - - - - - - - - - - - - -
} // Ende if ( Izeit01 )
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
return; //
} //
// ============================================================================= =
// ============================================================================= =
// ============================================================================= =
//### Programm 1 ms pausieren lassen !! Der Pausenwert ist nur experimentell !
void wms(uint16_t ms)
{
for(; ms>0; ms--)
{
uint16_t __c = 4000;
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__c)
: "0" (__c)
);
}
}
// ============================================================================= =
// ============================================================================= =
// ============================================================================= =
//### Programm 1 µs MIKROsekunde pausieren lassen !! Pausenwert EXerimentell !
void wmus (uint16_t us) // Wait in Mikrosekunden
{
for(; us>0; us--)
{
uint16_t __c = 4;
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__c)
: "0" (__c)
);
}
}
// ============================================================================= =
// ============================================================================= =
// ===== ENDE Subroutinen ================================================= =
// ============================================================================= =