• Hallo TT-Modellbahner, schön, dass du zu uns gefunden hast.
    Um alle Funktionen nutzen zu können, empfehlen wir dir, dich anzumelden. Denn vieles, was das Board zu bieten hat, ist ausschließlich angemeldeten Nutzern vorbehalten. Du benötigst nur eine gültige E-Mail-Adresse und schon kannst du dich registrieren.
    Deine Mailadresse wird für nichts Anderes verwendet als zur Kommunikation zwischen uns.
    Die Crew des TT-Boardes

PIC oder Atmel? Aller Anfang ist schwer...

Fragen an die, die schon eine funktionierende Servoansteuerung geschrieben haben:
- Aller wieviel ms wiederholt Ihr den Steuerimpuls?
- Muss die Periode immer gleich sein oder kann man der Einfachheit halber (ich weiß nicht, ob ich's brauch) den Low-Teil konstant lang sein lassen?
- Welche Auflösung nehmt Ihr für die Impulsbreite - 8bit (0x00..1ms, 0xFF...2ms, ~4µs Auflösung)?
 
Fragen an die, die schon eine funktionierende Servoansteuerung geschrieben haben...

alles Betriebsgeheimnisse :allesgut:

Der Servo hat eine Pulsweite von 20ms. Die sollte man nicht unterschreiten, kann man aber überschreiten.
Als Auflösung benutze ich 16 Bit, allerdings nur den Wertebereich von 1000 -2000 entspricht dann 1000 - 2000µs, da ich mit dem PIC mit 4 MHz internem Takt keine größere Auflösung hinbekomme.
(je nach Servo funktionieren Werte von etwa 0,7 bis 2,3ms)

Die Änderung der Pulsbreite bestimmt dann die Geschwindigkeit des Servos.

Wenn die Endstellung erreicht ist, schalte ich den Impuls ganz aus, also nur noch Low (verhindert ein zittern in der Endstellung).

Holger
 
Die Pause von 20ms sollte schon etwa eingehalten werden. Ist die Pausenzeit zu lang reagiert der Servo träge. Erzeugt wird die Pausenzeit durch einen Timer und in dieser Zeit erledigt der µC die Berechnungen für den nächsten Zyklus und die DCC Dekodierung. Ich habe eine Auflösung von 8Bit genommen weil da die Berechnung einfacher ist. Da mein Programm ürsprünglich für 32 Servos gedacht war und man für Weichen nicht den kompletten Stellbereich braucht habe ich den Stellbereich eingeschränkt. Nach meinen Erfahrungen können die billigen Servos von C eh nicht mehr als 2-3µs auflösen.
 
Sorry, ein paar Fragen.

Mein Testprogramm, das Pollin-Board und mein Testboard laufen. :fasziniert:

1. Doppeltbelegung der Pin und Pollin-Board, ATTiny2313
An PB5-PB7 liegen ja auch MOSI, MISO, SCK. Das es bei angesteckter serieller Verbindung nicht richtig funktioniert ist logisch, aber auch ohne Verbindung sind die Einganspegel von PB5 und PB7 nur 3,5V. Bei 0,7 x Vcc klappt das gerade so, im Datenblatt stand auch was von 0,6 x Vcc (für Reset-Pin als I/O). Jedenfalls ist das recht knapp und unsicher. Verursacht wird das wohl durch die Widerstände in Reihe und die Z-Dioden D1 und D2 zur Masse am RS232-ISP. Kann man dem irgendwie abhelfen das der Pegel wenigstens 4V beträgt? In der späteren Einsatzschaltung gibt es das ja nicht mehr.

2. Pull-up
Mein Testboard hat ja externe Pull-Up's. Würde ich wegen dem Pegelmessen gern beibehalten. Reicht es um später die internen zu nutzen diese nur einzuschalten oder ist das Verhalten anders als mit externen PU? Reicht es eigentlich die Internen zu nutzen oder empfehlen sich in der Einsatzschaltung externe? Die zusätzliche Löterei würde ich mir gern ersparen.

3. C-Code
Ich möchte gern mit selbstredenden Variablen arbeiten, also z.b für Weichenstellung Stammgleis an Weiche 4 "W4S" bzw. "W4A" für Abzweig. Ist ja alles rein BOOL.
Nun bin ich in C nicht sooo fit. Daher wäre ich für ein Beispiel einer "eleganten" Zuweisung dankbar. Ich bekomm das zwar hin, aber meist muss ich dann später feststellen das es eleganter und flexibler geht.
Kann man Pins auch einzeln abfragen und zuweisen? Also z.B.
W4S = PINB7;
,so würde ich mir das vorstellen.

Ähh, Frage am Rande, was ist bei einer Bogenweiche nun eigentlich Stamm und Abzweig? Da hab ich schon gegensätzliche Meinungen gehört.


So, reicht erstmal.
flic
 
3. C-Code
Ich möchte gern mit selbstredenden Variablen arbeiten, also z.b für Weichenstellung Stammgleis an Weiche 4 "W4S" bzw. "W4A" für Abzweig. Ist ja alles rein BOOL.
Nun bin ich in C nicht sooo fit. Daher wäre ich für ein Beispiel einer "eleganten" Zuweisung dankbar. Ich bekomm das zwar hin, aber meist muss ich dann später feststellen das es eleganter und flexibler geht.
Als bekennender Java-Entwickler empfehle ich, Variablen (z.B. timerCountDown) und Funktionen (z.B. initTimer()) klein beginnen zu lassen und nur Konstanten komplett groß zu schreiben (z.B. MAX_VALUE).
Kann man Pins auch einzeln abfragen und zuweisen? Also z.B.
W4S = PINB7;
,so würde ich mir das vorstellen.
Ich hab mir ein paar Konstanten definiert:
#define BIT0 (uint8_t)(1 << 0)
...
#define BIT7 (uint8_t)(1 << 7)
und frage dann entsprechend ab:
if ((PIND & BIT0) != 0) {
// do something
}
Vielleicht geht es aber noch eleganter.
 
Ich hab mir ein paar Konstanten definiert:
#define BIT0 (uint8_t)(1 << 0)
...
#define BIT7 (uint8_t)(1 << 7)
und frage dann entsprechend ab:
if ((PIND & BIT0) != 0) {
// do something
}
Vielleicht geht es aber noch eleganter.

Zum Beispiel so?:

if (bit0(PIND) !=0) //bit0 als entsprechende Funktion
{
// do something
}
(um mal deine Syntax beizubehalten).

Wobei das wahrscheinlich eher Hochsprache ist und deins eher hardwarenah (und damit schneller).
 
@tsinger @Per
Im Moment blick ich zwar beide Bsp. noch nicht, aber ich hab festgestellt das AVR-Studio und WinAVR mit "bool" nix anfangen können. Was ich so recherchiert hab muss das als Integer auf 0 oder != 0 abgefragt werden. Grusel...
Wäre so schön einfach gewesen :
"if W1A {" oder "if !W1A {"
Oder lieg ich das falsch? Verdammt viel neues im Moment...

Ähh, ich hab mir nen Wolf gesucht was dieses "uint8_t" z.B. bedeutet, ist aber wohl alternativ für "unsigned char".

flic
 
1. Doppeltbelegung der Pin und Pollin-Board, ATTiny2313
An PB5-PB7 liegen ja auch MOSI, MISO, SCK. Das es bei angesteckter serieller Verbindung nicht richtig funktioniert ist logisch, aber auch ohne Verbindung sind die Einganspegel von PB5 und PB7 nur 3,5V. Bei 0,7 x Vcc klappt das gerade so, im Datenblatt stand auch was von 0,6 x Vcc (für Reset-Pin als I/O). Jedenfalls ist das recht knapp und unsicher. Verursacht wird das wohl durch die Widerstände in Reihe und die Z-Dioden D1 und D2 zur Masse am RS232-ISP. Kann man dem irgendwie abhelfen das der Pegel wenigstens 4V beträgt? In der späteren Einsatzschaltung gibt es das ja nicht mehr.

2. Pull-up
Mein Testboard hat ja externe Pull-Up's. Würde ich wegen dem Pegelmessen gern beibehalten. Reicht es um später die internen zu nutzen diese nur einzuschalten oder ist das Verhalten anders als mit externen PU? Reicht es eigentlich die Internen zu nutzen oder empfehlen sich in der Einsatzschaltung externe? Die zusätzliche Löterei würde ich mir gern ersparen.


flic

zu1. die Widerstände enden an einem Ende (zumindest wenn der Stecker abgezogen ist) im Nichts, dürften somit keinen Einfluss haben. Bleiben noch die Dioden die sind bei 3,5V aber auch noch gesperrt. Abhilfe die Verwendung eines externen ISP Adapter. Da spar man sich das Umstecken der IC da in der Zielschaltung nur ein ISP Anschluss mit vorgesehen werden muß. Ansonsten mach die Pull Up Widerstände kleiner damit müsste der H Pegel steigen.

zu2. die internen Pull Up sind ziemlich hochohmig. Ich hatte bei der Abfrage einer Tastaturmatrix das Problem das die Ladung über die internen nicht schnell genug aufgebaut wurden. Mit externen Widerständen hat es dann geklappt.
 
@ Flicflac

Zu 1:
Habe ich dich richtig verstanden, das der Pegel am Eingang, wo MISO/MOSI und SLK anliegen nicht über 3,5V kommen?
Also da dort nur eine 5,1V-Z-Diode gegen masse liegt, dürfte das eigendlich nicht passieren!
Erklärung 1:
Du hast das Programierkabel noch drann, und das ziehr über den R die Spannung runter, weil am eingang -12V oder 0V anliegen.
Erklärung 2:
Die Z-Dioden sind nicht in ordnung.Dann andere einsetzen, oder gleich 5,6V-Typen, das ist aber der Grenzwert. Ich hatte es mal in einer Schutzbeschaltung mit 4,7V-Z-Dioden probiert und ähnliche Probleme. Jetzt habe ich in meiner Schutzschaltung 5,6V-Typen drin. Aber da du ja ständig die Z-Diode in den Z-Bereich fährst ist an dieser stelle eine 5,6V-Type extrem kritisch ( = kann gefährlich für den Chip werden)

Zu 2.

Ob der interne Pull-up-R reicht ist vom Ausgangswiderstand des Steuerbausteins abhängik. Ist der zu niederohmig im H-Zustand kann es zu fehldeutungen kommen, dürfte aber selten sein.
Im Zweifellsfall ein Widerstandsarray einplanen, das sind diese schwarzen "kämme", in denen 8 Widerstände von 8 Pin auf einen gemeinsamen 8. geschaltet sind. Kostet auch nicht die welt, und wenn ein ganzes Port als eingang genutzt wird, dann reicht eine Lötaugenreihe neben den Pins, und der 9. dann an Ub.
Werden nicht alle ports als eingang genommen, einfach entsprechendes Bein vom array abschneiden oder weg biegen.

Zu 3:

Da kann ich nur fürs AVR-Studio sprechen.
Einzelpinabfrage kann auf verschiedene wege erfolgen. Hatte ich in meinen Beispielen schon mal genutzt.
Befehl:
sbis/sbic/sbrs/sbrc
Funktion Überspringt nächsten befehl, wenn Bit vom Inputport/Register Set/claer (= gesetzt/gelöscht; 1/0) ist
Beispiel:
.def portA = 0x.. ;(Registeradresse für AusgangsportA laut Datenblatt)
.def w4s = 0 ;(Weiche 4 Stamgleis auf Pin 0)
.def w4a = 1 ;(Weiche 4 Abzweiggleis auf Pin 1)
.def w5s = 2
.def w5a = 3
,def pinB = 0x.. ;(Registeradresse für eingangsportb laut Datenblatt)
.def TA1 =0
.def TA2 =1
.def TA3 =2

:
:
:
ldi r20.FF
out pinb-2,r20 ; Eingangspullupwiderstände Einschalten
out portb,r20 ; Port B auf High setzen, damit die Weichen nicht angesteuert werden
out Portb+1,r20 ; Port B auf Ausgang Stellen

:
:
:

tastaturabfrage:
sbis pinb, ta1 :Taste1 gedrückt?
rjmp gleis1 ;Ja, Springe zum Weichen stellen
sbis pinb, ta2 :Taste2 gedrückt?
rjmp gleis2 ;Ja, Springe zum Weichen stellen
sbis pinb, ta3 :Taste3 gedrückt?
rjmp gleis3 ;Ja, Springe zum Weichen stellen
ldi r20,0xFF ;keine Taste gedrückt, alle ausgänge Setzen
out porta,r20
rjmp tastaturabfrage;Tastaturabfrageschleife wiederholen
Gleis1: ; Weichen für Gleis 1
cbi porta,w4s ;Weiche 4 auf Stammgleis
sbi porta,w4a
cbi porta,w5s ;Weiche 5 auf Stammgleis
sbi porta,w5a
rjmp tastaturabfrage
Gleis2:
cbi porta,w4s
sbi porta,w4a
sbi porta,w5s
cbi porta,w5a
rjmp tastaturabfrage
Gleis3:
sbi porta,w4s
cbi porta,w4a
rjmp tastaturabfrage


Mit diesem Programmstück wird
1. Adresse der Ausgänge Port A Definiert (0x00-0xFF = Hexa; 0-255 = Dezimal; 0b00000000-0b11111111 als Binär)
2. Die Bits (Pins) den Weichenstellungen zugeordnet (0-7 = Pin 0-Pin7)
3. Adresse der Eingänge Port B Definiert (wie 1.)
4. Die Bits (Pins)der Taster zugeordnet
5. Platz für nötige Initialisierung der Ports (nicht komplett geschrieben)
6. Tastaturabfrageschleife. Hier wird solange gekreist, bis ein Eingang von einer Taste auf Low gezogen wird. Ist keine Taste gedrückt, werden alle Weichenausgänge auf Hihg geschltet, so das die angeschlossenen Optokoppler (gegen + geschaltet) nicht leuchten, und somit die Weichen nicht angesteuert werden.
7. Ist eine Taste gedrückt, so werden die Weichen so angesteuert, das die Weichenstraße auf das Gleis weisen. Nicht benotigte Weichen (gleis 3 Weiche 5) werden nicht angesteuert. Danach wird die Tastaturabfrage weiter ausgeführt.
Werden 2 Tasten gedrückt, so hat die erste in der Abfragekette Priorität.

Sollte nix weiter Abgearbeitet werden, so währe das bereits ein Lauffähiges Programm zum Weichen stellen für die 3 Gleise einer Gleisharfe.

Da W4S genauso wie TA1 auf 0 Definirt sind, ist hier nur der PIN definier, nicht das Port! Wenn also bei der Abfrage stats TA1 W4S stehen würde, so währe das für uns beim lesen horender Blötsinn, der Prozessor würde jedoch problemlos laufen, da er beides mal nur Pin0 ddas Eingangsportes B abfragt.

Sollte dir das noch zu kompliziert sein, so könntest du Macros definiren. Das sähe dann so aus (die Definitionen von oben gelten weiter)

Macro setw4a
cbi porta,w4a
sbi porta,w4s
endmacro

Macro setw4s
sbi porta,w4a
cbi porta,w4s
endmacro

Im Programm stände dann:

Gleis1:
setw4s
setw5s
rjmp Tastaturabfrage

Der Compiler ersetzt dann immer deinen befehl "SET W_nr_Richtung) mit der dafür nötigen Befehlsfolge.
Mit der Mackrofunktion kannst du also eigene "Befehle" erfinden, die ganze Befehlsfolgen enthalten. So konnte man auch Signale einbinden, oder wenn der Timer genutzt wird ein Signal verzögert schalten.

Hoffe, das es für dich Brauchbar ist.
 
@tsinger @Per
Im Moment blick ich zwar beide Bsp. noch nicht, aber ich hab festgestellt das AVR-Studio und WinAVR mit "bool" nix anfangen können. Was ich so recherchiert hab muss das als Integer auf 0 oder != 0 abgefragt werden. Grusel...
Gruselig wird es erst, wenn man die == oder != weglässt, da C ja kein boolean kennt. Bei Bit-Abfragen ist es aber ganz einfach:

if ((PIND & BIT0) != 0) {
// do something
}

bedeutet nichts anderes, als dass der Wert des Portes D (PIND) mit der Bitmaske (hier BIT0 = 0b00000001) und-verknüpft (&) wird (nur dort, wo in beiden Werten im gleichen Bit eine 1 steht, bleibt sie erhalten). Exakt wäre eigentlich

if ((PIND & BIT0) == BIT0) {
// do something
}

aber wenn man die Bitmaske (hier BIT0) austauschen will, weil ein anderes Bit abgefragt werden soll, dann muss man an beiden Stellen BIT0 ersetzen. Für die Abfrage einzelner Bits ist die oben geschriebene Kurzform also weniger fehlerträchtig.

Wäre so schön einfach gewesen :
"if W1A {" oder "if !W1A {"
Oder lieg ich das falsch?
Erstmal fehlen die runden Klammern um den zu prüfenden Ausdruck. Du kannst Dir ja vielleicht ein Macro für W1A definieren. Könnte ungefähr so aussehen (nagel mich nicht darauf fest, meine C-Kenntnisse sind schon ein paar Jahre eingerostet und ein C-Freak war ich nie):

#define W1A ((PIND & 0x01) != 0)

Dann könntest Du so etwas wie

if (W1A) {
}

oder

if (!W1A) {
}

schreiben. Gilt aber nur zum Lesen (da PIND und nicht PORTD)!

Ähh, ich hab mir nen Wolf gesucht was dieses "uint8_t" z.B. bedeutet, ist aber wohl alternativ für "unsigned char".
Ich weiß nicht genau, ob der (uint8_t)-Präfix wirklich *notwendig* ist, aber er macht nichts anderes als einen cast auf vorzeichenloses 8-bit Integer durchzuführen. Jedenfalls stehen alle möglichen Konstanten mit diesem cast in den .h-Dateien drin.
 
So langsam kommen wir (ich) der Sache näher.
Nur was das Beschreiben angeht, es bringt mich zur Verzweiflung. Stecker dran und ab ist ja ok, aber zum Beschreiben muss ich noch dran denken dass PB5 - PB7 nicht auf Masse liegen oder mein Testboard abgeschaltet ist. Da muss ich mir noch was einfallen lassen. Am einfachsten 2polig die Spannung am Testboard abschalten.

Zurück zum Programm...

@ptlbahn
Danke das du dir so viel Mühe gibst. Im Moment beschränke ich mich erstmal auf C solange es ausreicht. Ist viel Neues zu verarbeiten und zu kapieren. Da kocht die Rübe schon genug. Aber ich werde das kleine Progrämmchen auch mal in ASM probieren wenn es richtig läuft.

@tsinger
Das mit dem Makro klappt ja wunderbar. Obwohl ich mich zum Verständnis erstmal belesen musste. Ich kannte #define nur zur Definition von Konstanten. So 100%ig begriffen hab ich's noch nicht, aber vielleicht taugt mein C-Buch nicht so richtig.
Port Einlesen ist ja nun einfachst gelöst. Nun aber zur Ausgabe.


int main(void)
{

#define W1S ((PINB & 0x01) != 0) //W1 Stamm
#define W1A ((PINB & 0x02) != 0) //W1 Abzweig
#define W2S ((PINB & 0x04) != 0) //W2 Stamm
#define W2A ((PINB & 0x08) != 0) //W2 Abzweig
#define BRG1 ((PINB & 0x10) != 0) //Bremsen G1
#define BRG2 ((PINB & 0x20) != 0) //Bremsen G2
#define LSBR ((PINB & 0x40) != 0) //Lichtschranke Bremsen
#define OPT ((PINB & 0x80) != 0) //Option (frei)


int BRON1 = 0; //Bremstrecke 1 ein
int BRON2 = 0; //Bremstrecke 2 ein

DDRD = 0x7f; // PortD als Ausgang deklarieren

// PORTB = 0x00; // activate internal pull-up
PORTD = 0x00; // Ports auf LOW schalten


for ( ; ; ) {

if (W1A) { // W1 auf Abzweig
if ((W2S) && (BRG2)) //W2 Stamm und Bremsen G2 ein
BRON1 = 1; //kurze Bremstrecke aktiv
else
BRON1 = 0;

if ((W2A) && (BRG1)) { // W2 Abzweig und G1 Bremsen ein
BRON1 = 1; // lange Bremstrecke aktiv, kurze
BRON2 = 1; // + Zusatz
}
else
BRON2 = 0;

if (LSBR) { // bei Auslösen Lichtschranke entsprechende Bit HI für Bremsrelais
if (BRON1) PORTD |= (1<<PD5); else
PORTD &= ~(1<<PD5);

if (BRON2)
PORTD |= (1<<PD6);
else
PORTD &= ~(1<<PD6);
}
}
else {
PORTD &= ~(1<<PD5);
PORTD &= ~(1<<PD6);
}
}
}



Das funktioniert zwar, aber da stellt sich wieder die Frage nach der "Eleganz". Ich stell mir da eine kompakte Ausgabe aller Bits vor und nicht so zerstückelt.

Ich bin ja begeistert. Gestern wollte ich den ganzen Schei.. schon in die Ecke schmeißen, nun ist bis auf zwei kleine Ungereimtheiten mein erstes Progrämmchen, Dank euerer Hilfe, eigentlich funktionsfähig. :fasziniert: :fasziniert:

So, nun ab in die Heia. Urlaub und die Nacht wird zum Tag. Es bestätigt sich wieder, Programmierer sind die Nutzer des billigen Nachtstroms ... :D

flic
 
@ Flicflac

Nun, wenn du mit C besser zurecht komst, dann Programiere in C. Ich empfinde gerade hier C für zu Kompliziert. ( Wie, wenn ich einen Hiltie- Bohrhammer mit SDS nehme, um die Löcher für mein Bäume in die Landschaft zu bohren)
Nur bei C kann ich nicht weiter helfen.
 
ich schließe mich der Meinung von ptlbahn an. Wenn man die Harware die in einem µC steckt verstehen will ist Assembler besser geeignet. Nur für komplexe Aufgaben wie eine Lastregelung würde ich höhere Programmiersprachen nehmen.
 
Für solchen einfachen Aufgaben ist es eigentlich egal, ob C oder ASM. Was einem halt besser taugt. Ich versuche es auch momentan in C, um mir keine Gedanken um die benutzten Register machen zu müssen.

if ((W2A) && (BRG1)) { // W2 Abzweig und G1 Bremsen ein
...
Du kannst die inneren Klammern weglassen, da sie schon in den Macros existieren:

if (W2A && BRG1) { // W2 Abzweig und G1 Bremsen ein
...

PORTD &= ~(1<<PD5);
PORTD &= ~(1<<PD6);
Das kannst Du kompakter machen:
PORTD &= ~(1 << PD5 | 1 << PD6); // willst' die LEDs anschalten?

Tom
 
C-Programmierung

Um ehrlich zu sein: allzu viel halte ich nicht von Makros, da sie den Code schnell unübersichtlich machen. Man sieht nicht, was passiert. Möglicherweise ist es sinnvoller, statt Macros Funktionen zu definieren. Mit den höheren Optimierungsstufen inlined diese der Compiler, so dass auch effizienter Code rauskommt:

int isWeiche1Stamm(void) { return (PINB & 0x01) != 0; }
int isWeiche1Abzweig(void) { return (PINB & 0x02) != 0; }
int isBremsenG1(void) { return (PINB & 0x10) != 0; }
int isBremsenG2(void) { return (PINB & 0x20) != 0; }

if (isWeiche1Stamm() & isBremsenG1()) {
}

Am besten, Du schreibst gleich die Variablen-/Funktionsnamen so, dass Du keine Kommentare benötigst. Auch empfehle ich, JEDEN Codeblock mit {} zu umklappern, auch wenn er nur einen Befehl beinhaltet.

Ein weiterer Vorteil von Funktionen statt Macros ist die Möglichkeit, Breakpoints reinzusetzen.
 
Mitleser

Hallo ich lese die ganze Zeit schon auch sehr aufmerksam mit, da meine Kenntnisse zur Programmierung (1989/90 seit dem nichts mehr) sehr lange zurück liegen und noch auf der U880 Basis liegen, ist hier alles sehr interessant für mich. Vor allen Danke an Tom für den Hinweis auf die Internetseite (letztes Post), das ist wirklich gut dargestellt und beschrieben für den Neueinstieg habe mir es auch gleich mal Ausgedruckt.
Macht weiter so, sehr lehrreich, Danke.
 
@tsinger

Jo ist sehr gut. Scheint das Standard-Web-Tutorial zu sein. Da wird von fast jeder ASM Seite drauf verwiesen. Schade das es das nicht als PDF gibt :-(

Das mit den Funktionen probiere ich auch noch aus. In meinem betagten C-Buch stand das Makros längeren Code verursachen. gerade das gilt es ja zu vermeiden.

@pltbahn @Gordon
Nun schimpft doch nicht gleich :)
Ich bin gerade dabei den C-Code zu optimieren (außer if gibts ja noch andere Möglichkeiten) und parallel versuche ich es auch in ASM. Jetzt wo die Hardware und das übetragen funktioniert und die Sache mit den Ports klar ist sind auch die ASM Befehle verständlicher. ASM schon deshalb weil das bisschen C-Code schon über 500 Byte hex erzeugt hat. Scheint aber im Prozessor nicht so viel zu belegen. Na mit der Speicherbelegung beschäftige ich mich später. So lange wie es reinpasst ist gut.

flic
 
Das mit dem Platz fressen ist ja auch meine Meinung. 0,5kbyt für dieses Programm ist doch schon eine Menge Holz.
Aber ich schimpf ja nicht, wenn euch C lieber ist, dann nutzt es. Nur ich sehe es so, das es eigendlich egal ist, mit welcher Sprache man sich Quält, um das System zu verstehen, aber warum soll man eine Sprache Nutzen, die nicht der "kürzeste" weg ist?
Anderst würde ich es vieleicht sehen, wenn Ihr C-Programmierprofies währt, und nur der Prozessor ein anderer währe.
Übrigens:
Ich habe mir die 2 Tabellen am ende der Dokumentation (Befehlssatz in Assembler und Registerzuordnung) zum genutzten Prozessor ausgedruckt. so habe ich das beim Programieren immer zur hand, kann mir noch ein paar Notizen machen (zB welches kürzel im Programm steht, oder was der Standartwert sein muß oä.)
 
Das beste wird sicher eine gesunde Mischung aus beiden sein. In C ist man eben schneller am Ziel und schließlich sind die AVRs ja speziell für C optimiert und ab einer bestimmten Größe wird Assembler auch ziemlich unübersichtlich.
 
So, viel Zeit hatte ich am WE leider nicht mich der Sache zu widmen. Habe mich auch etwas in ASM probiert, aber nur Funktionstest.
Der fertige Code des C-Progs belegt im µC 288 Byte.
Code:
Program:     288 bytes (14.1% Full)
(.text + .data + .bootloader)
Dass mir das der Compiler sagt und das nicht die Größe des Hex-files auschlag gebend ist hab ich auch erst rausgefunden. /me muss noch viel lernen, gg. Die Code-Funktion hier im Board hab ich ebenfalls erst heute entdeckt (ja auch noch nie gebraucht). Aber ich lasse es lieber mal das Board mit meinem Spagetti-code zuzumüllen.

Funktionen statt Makros ändern an der Größe des erzeugten Code absolut nichts.
Interessant finde ich die *.lss. Dem Studium habe ich mich hingegeben, macht dann doch ASM verständlicher wenn man einen Bezug hat.
Nun stellt sich mir die Frage ob der Code direkt in ASM programmiert bedeutend kürzer wäre.
Ich versuche mich mal mit Programmierung des Zwischen-Bhf, was etwas umfangreicher ist. Mal sehen wie groß die Sache wird.

flic
 
Dann gib mal Gleisplan, Pultplan und gewünschte Bedingungen, dann versuche ich es mal in Assembler zu schreiben, mal sehen ob ich es Kleiner hin bekommen wie du oder C.
(oder machen wir gleich ein Programierwettstreit aller Programierer draus?)
 
Hey, das ist unfair... Das Küken herrausfordern... :ballwerf:

Ne, im Ernst, wäre interessant was du rausholst. Zwischenbhf. fällt aus, da braucht es gar Nichts. Aber der dreigleisige Schattenbhf. stände an.
Ich versuchs mal zu erläutern (wenn du wirklich Lust hast):
  • je Gleis ein Eingang für Bremssignal: BremsenG1 (PB4) BremsenG2 (PB5) BremsenG3 (PB6)
  • je ein Eingang für Weichenstellung: W8Stamm (PB0), W8Abzweig (PB1), dto. für W9 (PB2 und PB3)
  • ein Eingang für Lichtschranke (PB7)
  • In Auswertung der Weichenstellung auf "Zielgleis steht auf Bremsen" müssen die Bremsstrecken aktiviert werden.
  • Für Gleis 1 nur Bremsstrecke 1, für Gleis 2 und 3 Bremsstrecke 1 und 2.
  • Ausgang Bremsstrecke 1 (PD6), Bremsstrecke 2 (PD5)
  • Aktivierung des Bremsvorganges durch Lichtschranke.
  • Das Signal an den Gleisen 1-3 für Bremsen kann permanent anliegen auch wenn es nicht das Zielgleis ist.
  • Wenn Lichtschranke aktiviert und deaktiviert (z.B Lücke zwischen den Wagen) müssen Bremsabschnitte aktiv bleiben.
  • Deaktivierung der Bremsabschnitte bei Änderung der Weichenstellung (Zielgleis) und/oder Bremsen Zielgleis ausgeschalten

Ich hoffe das ich es einigermaßen verständlich geschrieben habe. Wäre schön wenn du die vorgeschlagenen Ports nehmen könntest. Könnte ich dann auf meinem Testboard direkt testen.

flic
 

Anhänge

  • AVR-Test2.jpg
    AVR-Test2.jpg
    70,6 KB · Aufrufe: 18
Ich gehe mal davon aus das W1 die Ausfahrtsweiche und W9 die Einfahrtsweiche ist.
Soll der µC die Fahrspannung in BS1 & 2 runter regeln, oder wird da nur über Relais ein Bremsbaustein angesteuert?
Je einen Eingang für Bremssignal G1-3? Sollen das Ausgänge sein, oder kommt hier ein Signal vom Bremsgenerator, und wenn ja wann und warum/wie? Und wie arbeiten die Bremsstrecken?
Du schreibst je einen EINGANG für W8/9A/S, sollen die Weichen von wo anderst gesteuert werden, und du nimmst nur die RM oder meintest du AUSGÄNGE um die Weichen zu stellen?
Ich würde folgendes Erwarten:
3 E(ingänge) Taster Weichenstellung 1-3 einfahrt
3 E Taster Gleis 1-3 Ausfahrt
1 E Lichtschranke (PB7)
5 A(usgänge) Bremsstrecken 1/2 und GS1-3 (PD5/6:pB 4-6)
4 A Weiche 8/9 (PB0-3)

sind noch 6 Eingangssignale (Einfahrtsziehlwahl, Ausfahrtswahl) über. Ports sind noch (tiny2313) PD0-4 = 5 über (ohne PA).
Währe eine 2x3 Tastermatrix die Lösung.
Allerdings müßten dann die Stopstellen über Spannungslose isolirte Abschnitte sein, die nur für ausfahrt zu geschaltet werden (in deinem Gleisplan nicht eingezeichnet)
Ein Punktgenaues Stoppen ist ohne Fahrspannungssteuerung in abhängigkeit von der Lok ja nicht möglich.
Ausserdem, soll W1 in die Ausfahrtsweichenstraße mit einbezogen werden?
Ich würde sie entweder mit einbeziehen, oder die Stellung auswerten, ob die Züge ausfahren können.
PS ich wollte dich nicht in der heraus fordern, sondern es gin mir mehr darum, dir eine Referens zu schaffen, bei der du dann vergleichen kanst, was du machst, und was andere dabei "denken", denn nur so können sich alle verbessern.
Wie du schon oben siehst, gehen wir beide ja schon irgendwie unterschiedlich an die sache, oder du hast einiges noch nicht berücksichtigt.
Noch eine Frage, wozu ist BS 1 und 2? die könnten meiner meinung nach eigendlich entfallen.
 
Zurück
Oben