Oszi Trigger:
mit steigender Flanke Trigger außerhalb des Schirms kann es nicht mehr
die Pegellängen messen, aber ich sehe die fallende Flanke zittern. Das
sind weniger wie 5µs. Ohne Datenverkehr.
Mit Datenverkehr zittert es ca. 20µs, so gut man das eben erkennen kann.
LeyCroy kann ich mir nicht leisten. :-)
Ich wäre auch Rohde & Schwarz Fan. :-)
Falk B. schrieb:> https://scienceprog.com/avr-internal-oscillator-jitter-research/>> Früher war alles besser . . .
Das ist natürlich traurig zu sehen, weil ich annahm das der interne sehr
stabil ist laut Manual. Ist ja Temperatur stabilisiert. Ich hatte auch
zu Beginn der ganzen Geschichte mit Haarfön und Eiswürfel den ATtiny
geärgert. Das Timer Taktsignal von damals 100kHz veränderte sich
überhaupt nicht. Seitdem nahm ich an alles ist dufte.
@Veit Devil (devil-elec)
>mit steigender Flanke Trigger außerhalb des Schirms kann es nicht mehr>die Pegellängen messen,
Das ist egal.
> aber ich sehe die fallende Flanke zittern.
Das ist der Punkt!
> Das>sind weniger wie 5µs. Ohne Datenverkehr.
Ist immer noch zuviel, wenn man von einer idealen Taktquelle ausgeht.
>Mit Datenverkehr zittert es ca. 20µs, so gut man das eben erkennen kann.
Immerhin ist ein Unterschied sichtbar
Letze Idee für heute. Generiere ein Servosignal rein in Hardware per
OCR1A Pin ohne ISR etc, dazu die COMA1x Bits passend setzen. Damit kann
man den Jitter des RC-Oszillators sicher messen.
@ Veit Devil (devil-elec)
>Das ist natürlich traurig zu sehen, weil ich annahm das der interne sehr>stabil ist laut Manual.
Das ist relativ.
> Ist ja Temperatur stabilisiert.
Die Frequenz ja, aber Jitter ist, je nach Messung, ein Kurzzeiteffekt.
Hallo,
der RC Jitter beträgt laut Link ca. 100ns, was ca. 1 Takt entspricht.
Sollte sich das nicht permanent ausgleichen weil er ständig zittert?
Hardware OCR1A Messung mach ich morgen ... gute Nacht
>@mr. mistoffelees (Gast)>>Ich habe nicht alle 177 Beiträge gelesen...>Deswegen sind dir wesentliche Dinge entgangen.>>Das bedeutet, dass es warscheinlich>>>K6_'N'_ON ´s>>gibt, die du alle zum "selbem" Moment einschaltest.>Das Thema ist längst abgehakt.>>Du willst warscheinlich die Anzahl der Ausgänge leicht erweiterbar>>halten?>Nein.>>Konzept anwenden, um die Servos zu steuern. Das PPM wie es im Modelbau>>aus historischen Gründen noch meist benutzt wird.>Das haben wir schon lange in dieser Diskussion.>>verfolgst: In der ISR hast du einen stop_Timer1(); Aufruf.>Diese Code ist schon lange veraltet.
Im Ganzen wäre es viel einfacher einem Thread zu folgen, wenn nicht
grundsätzlich zwischendrin jemand anfangen würde dem TO eine andere
Hardware zu empfehlen, woraufhin dann erstmal eine Diskussion über die
vorgeschlagene Hardwareänderung entbrennt (in diesem Fall XMega) und das
dann noch gemischt mit persönlichen Meinungen zwischen verschiedenen
"Lagern".
Vielleicht sollten sich die Mods angewöhnen, solche Beitraäge ebenfalls
zu löschen.
DESHALB lese ich nicht alle vorigen Beiträge weil die ganz schnell am
Eröffnungsthred vorbeigehen.
HI,
nachdem ja alles läuft (ich wollte nicht auch noch "mitmachen")...
Was macht deine crc16-Geschichte. Wie lange dauert denn das alles so?
Die Debug-LED wird ja erst danach eingeschaltet.
Da würde mich ja mal das asm Listing interessieren. Ist es hinderlich,
mit dem "sizeof" Operator zu arbeiten oder sendDaten als Struct
anzulegen, statt eine eigene Variable zu verwenden? Ich frag nur aus
neugierde, ich bin eher in der Hardware zu Hause.
Ebenso möchte ich mich vorsichtig der oben gestellten Frage anschließen,
ob man bei einer Modellbahn mit RS485-Bus, 250KBaud und CRC arbeiten
muss.
Schade, das das Projekt für mich total undurchsichtig ist.
Ich lege immer alles in ein Verzeichns und zippe mir das weg.
Wenn dann jemand nach dem Code fragt, um mir helfen zu können, dann lade
ich das ZIP-File hoch und gut.
Aber: schön, wenn jetzt alles (länger als 2Stunden lang?) läuft.
Grüße Äxl
@Veit Devil (devil-elec)
>der RC Jitter beträgt laut Link ca. 100ns, was ca. 1 Takt entspricht.
Aber nur nach 10us trigger delay. bei 2ms sieht das anders aus.
>Sollte sich das nicht permanent ausgleichen weil er ständig zittert?
Das hängt von den Details ab, genauer, von der Amplitude der
Phasenmodulation. Wenn man will, kann man die Phase über große Zeiträume
sehr stark driften lassen und sie dann wieder genausoviel in die
Gegenrichtung driften lassen. im Langzeitmittel ist die Frequenz sehr
genau, kurzzeitig ist die Phase sonstwo 8-0
>Hardware OCR1A Messung mach ich morgen ... gute Nacht
Tu das. Danach solltest du deine Taktauswahl überdenken und dir einen 8
MHz Quarzoszillator besorgen und damit deinen AVR takten. Das kostet nur
ein IO-Pin, bringt dir aber einen ASTREINEN Takt. Für deine Zwecke ist
ein RC-Oszillator weder technisch noch ökonomisch sinnvoll bzw. nötig.
https://www.mikrocontroller.net/articles/AVR-Tutorial:_Equipment#Erg.C3.A4nzende_Hinweise_zur_Taktversorgung_.28kann_.C3.BCbersprungen_werden.29
@ Äxl (geloescht) (Gast)
>Da würde mich ja mal das asm Listing interessieren.
Warum? Das macht der Compiler schon ganz gut.
>Ist es hinderlich,>mit dem "sizeof" Operator zu arbeiten
Keine Sekunde, denn das ist praktisch eine Konstante.
>oder sendDaten als Struct>anzulegen, statt eine eigene Variable zu verwenden?
Auch kein Thema, das dröselt der Compiler normal auf und fertig.
>http://www.microchip.com/webdoc/avrlibcreferencema...>Ist das Pseudocode zu erklären
Nö, echtes C.
> oder warum muss die Zählvariable "i" ein>16 bittiges int sein?
Weil int halt Standard ist. Die Optimierer schreiben dort uint8_t hin,
die High Speed Optimierer uint_fast8_t.
> Dann die ganzen Parameter-Übergaben an die>Funktion. Das kommt mir alles total "viel" vor.
Was ist an ZWEI Parametern viel?
>Aber - ich hab nicht die>Mega-Ahnung, was den ganzen Pointer-Kram angeht und weis auch nicht, wie>weit der Compiler hier optimiert.
Weit genug. Wenn gleich man eine CRC nicht derartig krampfhaft noch in
eine Unterfunktion zerlegt. Im Normalfall kann man das direkt in einer
Funktion für einen Datenblock machen.
>Ebenso möchte ich mich vorsichtig der oben gestellten Frage anschließen,>ob man bei einer Modellbahn mit RS485-Bus, 250KBaud und CRC arbeiten>muss.
Muss man nicht, aber man kann.
Hallo,
möchte wirklich jemand eine Steuerung bauen ohne Netz und doppelten
Boden? Wenn ich einen Befehl auf Reise schicke, dann möchte ich sicher
sein das genau dieser Befehl an der richten Adresse unverstümmelt
ankommt. Stell euch mal vor ich baue keine Sicherheiten ein. Ich möchte
zum Bsp. eine Weiche stellen. Jetzt läuft die Übertragung wegen
irgendwas gegen den Baum. Danach fühlt sich der falsche Slave
angesprochen und der stellt dann keine Weiche, was sowieso die falsche
wäre, sondern schickt einen 2. Zug auf die Strecke. Möchte das wirklich
jemand ernsthaft von vornherein als Restrisiko einplanen? Ich denke
nicht.
Ich wundere mich ehrlich gesagt über die IoT Scheunentor offenen
Gerätschaften nicht mehr wirklich, wenn man an solche Dinge schlaksig
rangeht.
Die CRC Funktion wird mehrfach benötigt, deshalb als Funktion, zudem
einfacher wartbar.
sizeof wurde schon geändert, nur nicht in diesem Code der dann zum
Testcode wurde. Mache ich mit constexpr.
So, zurück zum Thema, RC Jitter. Ja der zappelt durchaus rum :-(
https://youtu.be/ts-UkvS9csw
Am Ende gehe ich auf 10µs/DIV bis 5µs/DIV runter.
Auf den Quarz hatte ich verzichtet, weil ich das Servoproblem damals
noch nicht kannte. Außerdem habe ich ohne Quarz genau 8 Pins frei,
perfekt für Byte Übertragung. Zudem der Platinenplatz mit den Steckern
auch gut ausgenutzt wird. Damit ich die Bauteile nicht umsonst gekauft
habe, werde ich nun für die Servos eigene Platinen bauen, mit Quarz. Ich
werde dann gleich einen 16MHz Quarz nutzen. Ich denke, dass klingt nach
einem Plan. :-)
Hallo,
wegen deinem LeyCroy:
Kann das Pulse etc. auch vermessen wenn diese außerhalb des Schirms
liegen?
zur Frage crc16 Funktion, wenn ich das so messe dauert es 28,2µs.
wegen Jitter vs. Servo:
auch wenn das bis zu 2° ausmacht, bei genauerer Überlegung reduziert
sich das wieder bis zur Weiche, durch Hebel ist da eine Untersetzung
drin usw. Ich denke vorerst auf größere Neubauten kann ich erstmal
Abstand nehmen. Wenn mich doch etwas stört, weiß ich gleich was ich
machen muss. Umsonst war die Übung jedenfalls nicht.
Der nächste Punkt war die tausend if in der handle Serial Funktion.
Umgebaut auf switch-case.
Was würdest du wegen dem enum "state_UART_MODE" ändern?
In der ISR(PCINT0_vect) wird der nach 60 Messungen auf CALC gesetzt.
In der Berechungsfunktion je nach Ergebnis auf REPEAT oder FINISH.
In der Ringbuffer Funktion bei uart Fehler auf ERROR.
Ich wüßte jetzt nicht was man daran verbessern oder trennen sollte?
Das hängt doch alles zusammen bzw. voneinander ab.
@Veit Devil (devil-elec)
>wegen deinem LeyCroy:>Kann das Pulse etc. auch vermessen wenn diese außerhalb des Schirms>liegen?
Nein. Aber für die Messung einer einfachen Pulsbreite reicht es, die 2.
Flanke exakt auf die Bildschirmmitte zu legen. Dann entspricht die
Triggerverzögerung (horizontal delay) exakt der Pulsbreite).
>drin usw. Ich denke vorerst auf größere Neubauten kann ich erstmal>Abstand nehmen. Wenn mich doch etwas stört, weiß ich gleich was ich>machen muss. Umsonst war die Übung jedenfalls nicht.
Ja, aber um den Effekt der Jitterreduzierung durch die clevere COMPA
Abschaltung zu messen, solltest du dennoch testweise ein Board mit einem
externen Quarzoszillator betreiben. Seeing is believing!
>Der nächste Punkt war die tausend if in der handle Serial Funktion.>Umgebaut auf switch-case.
Fast gut.
> case UART: // UART0 wird benutzt> handle_Serial_0_to_Serial_0();> break; // minimal 7,7µs ... maximal 18,2µs
Das break setze ich immer in die gleiche Einrückung wie das case, denn
es ist praktisch mit einer schließenden Klammer identisch.
> case CALC: // OSCCAL neu berechnen> Calibration_Calculation();> break;
Hier fehlt der Übergang des States, der sollte/darf NICHT unsichtbar an
anderen Stellen erfolgen. Das Gleiche gilt für deine anderen States.
Dort müssen die Übergangsbedingen rein, damit sie direkt sichtbar sind!
Die dürfen nicht im restlichen Programm verstreut sein, sonst wird man
wahnsinnig!
>Was würdest du wegen dem enum "state_UART_MODE" ändern?
Siehe oben.
>In der ISR(PCINT0_vect) wird der nach 60 Messungen auf CALC gesetzt.
Schlecht. Dort setzt man ein Flag ala calc_buffer_full und wertet dies
in der FSM aus und macht DORT den Zustandswechsel!
>In der Berechungsfunktion je nach Ergebnis auf REPEAT oder FINISH.>In der Ringbuffer Funktion bei uart Fehler auf ERROR.>Ich wüßte jetzt nicht was man daran verbessern oder trennen sollte?
Siehe oben. Man kann den Ablauf nicht nachvollziehen. Das Hin- und
Herspringen in den Funktionen um den Ablauf nachzuvollziehen ist Murks,
da würden dir die Kollegen in der Firma an die Gurgel gehen ;-)
>Das hängt doch alles zusammen bzw. voneinander ab.
Ja, aber es muss auch einfach und überschaubar dargestellt sein.
1
caseCALC:// OSCCAL neu berechnen
2
if(Calibration_Calculation()==true){
3
state_UART_MODE=FINISH;
4
}
5
break;
Außerdem ist es kosmetisch vorteilhaft, die States in der Reihenfolge
aufzuschreiben, wie sie im Normalfall durchlaufen werden, das
vereinfacht das Nachvollziehen ein wenig mehr.
> case RUN: // Dummy, virtueller Zustand, Takteinmesszyklus läuft> break;
Das würde im Normalfall bedeuten, daß dieser Zustand nie wieder
verlassen wird. Das ist aber bei dir nicht so. Ergo, der Leser wird
verarscht.
Regel: Schreibzugriffe auf die State-Variable erfolgen nur in der FSM
selber. Lesezugriffe von anderswo sind erlaubt, besonders von anderen
FSMs, damit die wissen, was ab geht.
Hallo,
jetzt wird mir das Problem für andere Codeleser klarer. Danke.
Wegen dem Quarz, mal sehen ob ich einen Quarz habe, irgendwo muss einer
rumliegen. Dann teste ich das nochmal.
@Veit Devil (devil-elec)
>Wegen dem Quarz, mal sehen ob ich einen Quarz habe, irgendwo muss einer>rumliegen. Dann teste ich das nochmal.
Quarzoszillator, das ist ein aktives Bauteil mit VCC, GND und Ausgang.
Ein Quarz allein ist rein passiv mit 2 Anschlüssen.
Hallo,
Tüte gefunden, sind 8MHz Quarze und die passenden Kondensatoren sind
auch dabei.
Code aufgeräumt:
nur das break komplett vorrücken gefällt mir optisch nicht :-)
Eine neue Zeile mit case ist mir für mich klar genug, zudem es farblich
unterschiedlich dargestellt wird. Die Einrückung ist in AS noch ein TAB
mehr, wird hier leider nicht dargestellt. Die enum Variable habe ich
auch gleich lokal gemacht. Die Reihenfolge ist angepasst, bis auf UART,
habe ich auf Anfang belassen, weil das der Standardzustand ist.
Die Nachrichtenlänge wird überall gleich als Konstante übergeben.
1
// definiere das Datenprotokoll
2
unionMessage
3
{
4
struct
5
{
6
uint8_ttoAddr;
7
uint8_tfromAddr;
8
uint8_tcmd;
9
int32_tdata;
10
uint16_tcrc;
11
};
12
uint8_tasArray[9];// Summe aller struct Datentypen, für Zugriff über Index
13
}empfDaten,sendDaten;// zwei gleiche union Buffer anlegen
@Veit Devil (devil-elec)
>nur das break komplett vorrücken gefällt mir optisch nicht :-)
Naja, ist halt nicht perfekt.
>Eine neue Zeile mit case ist mir für mich klar genug, zudem es farblich>unterschiedlich dargestellt wird. Die Einrückung ist in AS noch ein TAB>mehr, wird hier leider nicht dargestellt.
Weil TABs immer ungünstig sind. Man sollte seinen Editio so einstellen,
daß der immer gleich echte Leerzeichen draus macht. Oder wenigststens
vor dem Kopieren ins einen Beitrag.
Die Nachrichtenlänge wird überall gleich als Konstante übergeben.
>constexpr uint8_t length_Message = sizeof(Message);
Was soll der High Tec Unsinn it constexpr? Braucht hier kein Mensch.
K.I.S.S.!
> switch (state_UART_MODE) {> case UART: // UART0 wird benutzt
case muss eingerückt werden.
> handle_Serial_0_to_Serial_0();> if (countErrorsUART0 > 50000) { // erstmal ne wilde Hausnummer> state_UART_MODE = ERROR; }
DAS ist GANZ schlechter Stil, die schließende Klammer ans Ende zu
setzen! Das macht man nicht! Es gibt 2 wesentliche Formate, die
allgemein akzeptiert sind. Entweder so
1
// Klammer auf jeweils eigener Zeile
2
if(bla)
3
{
4
// yes
5
}
6
else
7
{
8
// no
9
}
10
11
//Oder mein Favorit mit etwas kompakterer Schreibweise mit
12
//öffnender Klammer auf der gleichen Zeile wie das einleitende Statement.
13
14
if(bla){
15
// yes
16
}else{
17
// no
18
}
Damit sieht man IMMMER die schließende Klammer zum öffnenen Statement in
einer Ebene!
Alle diversen Mischformen haben wenig bis keine Akzeptanz unter echten
Softwerkern. Das Gleiche gilt natürlich auch für andere Kontrukte wie
for(), while() oder switch().
> case CALC: // OSCCAL neu berechnen> if (Calibration_Calculation() == true) {> state_UART_MODE = FINISH; }> else { state_UART_MODE = REPEAT; }
Wenn schon Klammern, welche prinzipiell besser sind, dann auch die
Anweisung auf eine neue Zeile. Ist übersichlicher und leicher zu
erweitern.
>Wenn das so näher an irgendwelchen Stil Standards ist, würde ich mich>schon zufrieden geben.
Ist schon ganz OK.
Hallo,
gut, die Klammersetzung nehme ich zurück, wollte paar Zeilen einsparen.
Schlechter Stil, okay.
Bevor ich nun die Fuse setze für den Quarz frage ich lieber nochmal
nach, weil das Auswahlmenü in AS für mich nicht ganz klar ist was
gemeint ist, ich würde das blau ausgewählte nehmen. Richtig?
Quarz ist ein 8MHz, HC49.
ich bevorzuge diesses, macht es einfach übersichtlicher
Falk B. schrieb:> // Klammer auf jeweils eigener Zeile> if (bla)> {> // yes> }> else> {> // no> }
um Zeilen einzusparen geht auch
> { // yes> }> else> { // no> }
aber man sieht immer wo es beginnt und wo es endet
Hallo,
bist du dir sicher?
Laut der Einstellungen rückwärts geschaut sind alle 4 CKSEL Bits
gesetzt, was laut Datenblatt für einen Quarz > 8MHz sein müßte.
Müsste ich nicht laut Datenblatt S.30 auf die Bitfolge 1101 (SUT 0)
kommen? Das wäre dann die Auswahl über des blau markierten. Hab bammel
...
@ Veit Devil (devil-elec)
>Laut der Einstellungen rückwärts geschaut sind alle 4 CKSEL Bits>gesetzt, was laut Datenblatt für einen Quarz > 8MHz sein müßte.
So kritisch ist das nicht. Ob man nun die Einstellung 3-8 MHz oder
8-16MHz wählt.
>Müsste ich nicht laut Datenblatt S.30 auf die Bitfolge 1101 (SUT 0)>kommen? Das wäre dann die Auswahl über des blau markierten. Hab bammel>...
Wovor? Verfusen? Mein Gott, trag's wie ein Mann!
Hallo,
is ja gut :-) ich ändere zum erstenmal die Fuse bezüglich der
Taktquelle. Ansonsten hatte ich schon rumgefummelt. Es wäre Schade um
den Aufwand falsche Takt-Fuse zu korrigieren. Das war mein Anliegen.
Gesagt getan, läuft mit reinen Timertakt astrein ohne zittern. Selbst
mit 1µs/DIV nichts zu sehen. :-) Ich bau mal um und teste den
"Servocode".
@Joachim B. (jar)
>ich bevorzuge diesses, macht es einfach übersichtlicher
Meine Meinung basiert hierauf.
Strukturierte Programmierung auf Mikrocontrollern
ftp://ftp.idsoftware.com/idstuff/doom3/source/CodeStyleConventions.doc
Wenn DIE Jungs das so machen und auch sinnvoll begründen, kann es nicht
falsch sein. Und ich bin dann genau so cool wie die ;-)
Siehe Anhang, der Originallink ist im Moment nicht erreichbar.
Falk B. schrieb:> Meine Meinung basiert hierauf.
also offen und zu Klammer in einer Spalte gefällt mir ja auch, das mit
der offenen Klammer am Ende hat mich schon öfter aufs Glatteis geführt,
das lehne ich weiterhin rundum ab!
wer guckt denn immer am Ende, doch nur Hunde ;)
ausserdem ist mein Monitor nicht UHD 27"
und wenn man ans Ende scrollt sieht man vorne nicht.
Hallo,
die Servopulse haben ein Zittern von 10µs-20µs laut Datalogger und 20µs
laut Oszi. Egal ob uart Kabel angesteckt sind oder nicht. Das kleine
Servo ist für mich jedoch praktisch ruhig. Das größere Servo zuckt noch
ein klein wenig.
Laut Gehör zuckt das große Servo jedoch deutlich weniger, also fast
nicht mehr, wenn die uart unterbrochen wird. Einen kleinen Unterschieds
gibts laut Gehör noch.
@Veit Devil (devil-elec)
>die Servopulse haben ein Zittern von 10µs-20µs laut Datalogger und 20µs>laut Oszi.
Dann stimmt was nicht.
> Egal ob uart Kabel angesteckt sind oder nicht.
Dann erst recht nicht. 8-(
Hast du die letzte Änderung mit dem TXB80 Bit drin? Beim letzten Mal
ging die ja noch nicht. Aber auch ohne diese Änderung darf ohne
UART-Datenverkehr keine 10-20us Jitter passieren! Hast du die Fuses
richtig gesetzt?
Hallo,
das mit dem TXB80 Bit funktioniert nicht. Das ist das 9. Datenbit vom
Frame. Ich habe kein 9. Databit. Spielt auch erste eine Geige wenn ich
Unterschiede mit/ohne uart habe.
Ich habe nun auch die Compare A ISR rausgenommen, wird ohne uart nicht
benötigt. An den Messungen ändert das nichts. So eine Sch ...
Fuse, was soll falsch sein, der µC läuft doch.
Morgen kürze ich den Code mal wieder radikal ein, sodass nur noch die
Pulserzeugung stur läuft.
Veit D. schrieb:> Die Nachrichtenlänge wird überall gleich als Konstante übergeben.>
1
>// definiere das Datenprotokoll
2
>unionMessage
3
>{
4
>struct
5
>{
6
>uint8_ttoAddr;
7
>uint8_tfromAddr;
8
>uint8_tcmd;
9
>int32_tdata;
10
>uint16_tcrc;
11
>};
12
>uint8_tasArray[9];// Summe aller struct Datentypen, für Zugriff
13
>überIndex
14
>}empfDaten,sendDaten;// zwei gleiche union Buffer anlegen
15
>
16
>constexpruint8_tlength_Message=sizeof(Message);
17
>
An constexpr sehe ich, dass Du das ganze mit einem C++-11/14/17-Compiler
übersetzt. War mir bislang gar nicht aufgefallen - habe aber auch nicht
alles hier gelesen. Allerdings greifst Du dann sicher C-like in Deiner
union auch über das nicht-aktive Member zu (das habe ich jetzt aber
nicht in Deinem Code überprüft). Dies ist in C++ UB im Gegensatz zu C.
Ich habe zwar wirklich noch nie bei primtiven DT in der union hier
jemals ein Problem erlebt bei C++, aber es ist trotzdem UB und dem
sollte man sich bewusst sein.
Hallo,
ich habe die Option "-std=c++11" gesetzt.
Zu welchen Problem kann das führen mit dem nicht aktiven Member?
Das wird in der read_Ringbuffer Funktion verwendet.
Den Code konnte ich noch kürzen, geht ja schnell. Was soll ich sagen,
kein einziger Jitter. Obwohl der nichts anderes macht wie der komplette
Code mit auskommentierten Funktionen.
1
#include<util/delay.h>
2
#include<avr/io.h>
3
#include<stdio.h>
4
#include<stdlib.h>
5
#include<avr/interrupt.h>
6
#include<util/atomic.h> // für cli() und sei() mit SREG Sicherung
7
#include"pinDefi.h" // eigene I/O Definitionen
8
#include"timer.h" // alles was mit Timern zu tun hat ausgelagert
9
10
#define NOP __asm__ __volatile__ ("nop")
11
12
#ifndef sbi
13
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // setzt das angegebene Bit auf 1
14
#endif
15
#ifndef cbi
16
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // setzt (löscht) das angegebene Bit auf 0
17
#endif
18
19
20
intmain(void)
21
{
22
Led1_OUT;// Pin auf Ausgang konfigurieren
23
Led2_OUT;
24
Led3_OUT;
25
Led4_OUT;
26
Led5_OUT;
27
Led6_OUT;
28
// Led7_OUT; Quarz
29
// Led8_OUT; Quarz
30
31
32
preSet_Timer1();
33
run_Timer1();
34
35
while(1)// Hauptprogramm
36
{
37
38
}
39
}
40
41
42
/* *** Funktionen *** */
43
ISR(TIMER1_COMPB_vect)// dauert 6,2µs, wird aller >1ms aufgerufen
@Veit Devil (devil-elec)
>das mit dem TXB80 Bit funktioniert nicht.
Mist.
>Das ist das 9. Datenbit vom>Frame. Ich habe kein 9. Databit.
Ja eben darum kann man es für andere Dinge nutzen ;-)
Soweit die Theorie ;-)
>Spielt auch erste eine Geige wenn ich>Unterschiede mit/ohne uart habe.
Ja.
>Ich habe nun auch die Compare A ISR rausgenommen, wird ohne uart nicht>benötigt. An den Messungen ändert das nichts. So eine Sch ...
Du sagst es.
>Fuse, was soll falsch sein, der µC läuft doch.
Er könnte aber auch noch mit dem RC-oszillator laufen!
Die Fuses sehen aber OK aus! Quarz und beide Kondensatoren ordentlich
kontaktiert?
>Morgen kürze ich den Code mal wieder radikal ein, sodass nur noch die>Pulserzeugung stur läuft.
Falscher Ansatz. Für den reinen Pulstest schreibt man ein einfaches,
extra Testprogramm und lädt das einfach. Immer dermaßen im Quelltext
rumfuhrwerken ist nicht sinnvoll.
Ich hoffe, dass an dieser Stelle z.B. UART0_TxBuf noch nicht zu einem
Zeigertyp zerfallen (decay) ist, denn dann liefert UART0_TxBuf was
falsches;-)
Wenn Du schon C++ nimmst, dann solltest Du für so etwas dann auch
std::array verwenden.
@Veit Devil (devil-elec)
>Den Code konnte ich noch kürzen, geht ja schnell. Was soll ich sagen,>kein einziger Jitter.
Schon mal ein Ansatz. Jetzt musst du den Rest schrittweise wieder
aktivieren.
@ Wilhelm M. (wimalopaan)
>Wenn Du schon C++ nimmst, dann solltest Du für so etwas dann auch>std::array verwenden.
Falsch. Er sollte von C++ die Finger lassen und vernünftiges C ohne
unsinnige Stunts programmieren! Das reicht für seine Anwendung als
Hobbyprogrammierer vollkommen aus! Er braucht keine Sekunde C++11,
bestenfalls C99.
Falk B. schrieb:> @ Wilhelm M. (wimalopaan)>>>Wenn Du schon C++ nimmst, dann solltest Du für so etwas dann auch>>std::array verwenden.>> Falsch. Er sollte von C++ die Finger lassen und vernünftiges C ohne> unsinnige Stunts programmieren! Das reicht für seine Anwendung als> Hobbyprogrammierer vollkommen aus! Er braucht keine Sekunde C++11,> bestenfalls C99.
Deswegen sage ich das ja!
Ich vermute, dass er constexpr nur an Stellen verwendet, wo es nicht
notwendig ist und sonst nichts von C++ einsetzt. Dann kann er den Code
auch einfach als C99/C11 mit einem C-Compiler übersetzen und er ist das
UB los.
(Trotzdem ist m.E. std::array wesentlich besser rohe Arrays ...)
>> Ich hoffe, dass an dieser Stelle z.B. UART0_TxBuf noch nicht zu einem> Zeigertyp zerfallen (decay) ist, denn dann liefert UART0_TxBuf was> falsches;-)
Sorry, verschrieben: gemeint war ... dann liefert sizeof(UART0_TxBuf)
was falsches ...
Hallo,
alleine für bool benötigt man schon C++. Was ist denn an C++ nun wieder
falsch? Ich kam auch darauf, weil ich bestimmte Berechnungen zur
Compilerzeit erledigt habe, deswegen kenne ich constexpr. Ihr wollt mir
das jetzt nicht verbieten?
Das Buffer löschen kann ich eigentlich rausnehmen, weil uart_init tail
und Head sowieso gleich setzt. Meine Messwerte sollte es nicht
verändern. Probiere ich aus. Wobei das alles keinen Einfluss haben
sollte, uart Fehler habe ich keinen einzigen.
Hauptthema:
Habe den Kondensator an Pin 2 rausgenommen, lief immer noch. Kondensator
an Pin 3 rausgenommen, zappelte alles, Quarz entfernt, es funktionierte
nichts mehr, ich schlussfolgere Fuse passen.
Morgen bau ich die Funktionen Schrittweise wieder ein.
Erstmal Danke bis hier hin.
Edit:
Was meinst du mit UB?
@Veit Devil (devil-elec)
>alleine für bool benötigt man schon C++.
Keine Sekunde. C funktioniert seit über 40 Jahren ohne "echtes" bool.
Wenn es tausende andere C-User können, kannst du das auch.
> Was ist denn an C++ nun wieder falsch?
Wer fliegen will, sollte erstmal laufen lernen. Man kann nicht mit dem
Fliegen anfangen.
Lern erstmal SOLIDES C, dann kannst du dich VIELLEICHT mit C++
beschäftigen, denn das ist ein GANZ anderes Kaliber!
> Ich kam auch darauf, weil ich bestimmte Berechnungen zur>Compilerzeit erledigt habe, deswegen kenne ich constexpr. Ihr wollt mir>das jetzt nicht verbieten?
Doch, denn du brauchst es keine Sekunde. Das ist nur akademischer
Unsinn.
Du hast keine hochdynamischen Datenstrukturen, nur ein triviales
Datenpaket!
>Habe den Kondensator an Pin 2 rausgenommen, lief immer noch. Kondensator>an Pin 3 rausgenommen, zappelte alles, Quarz entfernt, es funktionierte>nichts mehr, ich schlussfolgere Fuse passen.
OK.
Veit D. schrieb:> Hallo,>> alleine für bool benötigt man schon C++.
Nein, hat C auch.
> Was ist denn an C++ nun wieder> falsch? Ich kam auch darauf, weil ich bestimmte Berechnungen zur> Compilerzeit erledigt habe, deswegen kenne ich constexpr. Ihr wollt mir> das jetzt nicht verbieten?
Ich möchte Dir gar nichts verbieten, und bin hier ganz klar von der
C++-Fraktion ;-)
Aber in Deinem Code, den ich aber nur sehr flüchtig angesehen habe, habe
ich weder klassische OOP Ansätze (dyn. Polymorphie) (also eher
Arduino-like und wie man es m.E. auf µC nicht machen sollte) noch stat.
Polymorphie (also templates und TMP) noch eine starke Verwendung des
Typsystems (domänenspezifische DT) gesehen. Insofern schließe ich mich
der Vermutung von Falk an, dass vielleicht hier die Kenntnisse fehlen
und es deswegen besser ist, sich auf C zu konzentrieren. Dies soll bitte
keine Wertung sein ... Aber schon der Einsatz von rohen Arrays und ihren
Problemen deuten eben darauf hin.
Falk B. schrieb:> @Veit Devil (devil-elec)>>>alleine für bool benötigt man schon C++.>> Keine Sekunde. C funktioniert seit über 40 Jahren ohne "echtes" bool.
Falsch: Seit C99 in C enthalten.
@ Wilhelm M. (wimalopaan)
>>>alleine für bool benötigt man schon C++.>>> Keine Sekunde. C funktioniert seit über 40 Jahren ohne "echtes" bool.>Falsch: Seit C99 in C enthalten.
Erwischt, meine Aussage stimmt trotzdem. Es geht auch ohne echtes bool,
wenn gleich es bisweilen etwas schwammig wird. Ich bin pragmatischer
Hardwerker, noch Fragen? ;-)
Ein schneller Test scheint die freie Verwendbarkeit des TXB80 Bits zu
bestätigen. Wenn es also in der Software nicht funktioniert, liegt der
Fehler woanders.
1
/*
2
* UART test for TXB80 bit use as software control bit
Hallo,
können wir das mit C vs. C++ auf später verschieben? Sonst kämpfe ich an
mehreren Fronten gleichzeitig. Ihr seit ja alle angemeldet und bekommt
neue Beiträge gemeldet. Ich greife das am Ende wieder auf. Nur eine
Frage brennt mir unter den Nägeln, memset ist doch Standard C, was soll
da schief gehen? Mit sizeof verhindere ich auch ein schreiben ins
Nirwarna.
Test:
habe den Timer 0 aktiviert und die Pulse zittern wieder - aber anders.
Nicht ständig sondern alle Sekunde nach Gefühl. Mit Timer 0 habe ich mir
einen ms und s Timer gebaut. Sekundenvariable rausgenommen. Pulse zucken
dennoch ca. aller einer Sekunde. Wobei ich millis() noch nicht verwende,
nur der Timer 0 läuft für sich alleine.
Ich baue den Code mal weiter zusammen, mal sehen wann es schlimmer wird
oder der Timer 0 später noch mehr Störung verursacht. Der Timer 0
alleine kann es nicht sein, laut meinem Gefühl. ;-)
Auszug aus der timer.cpp
@Veit Devil (devil-elec)
>können wir das mit C vs. C++ auf später verschieben? Sonst kämpfe ich an
Sicher. Hat mit dem aktuellen Problem auch gar nichts zu tun.
>Frage brennt mir unter den Nägeln, memset ist doch Standard C, was soll
Ja.
>da schief gehen?
Nix.
>habe den Timer 0 aktiviert und die Pulse zittern wieder - aber anders.
Was macht denn Timer 0? Ich dachte, der ist nur während der Kalibrierung
aktiv?
>Nicht ständig sondern alle Sekunde nach Gefühl. Mit Timer 0 habe ich mir>einen ms und s Timer gebaut. Sekundenvariable rausgenommen. Pulse zucken>dennoch ca. aller einer Sekunde. Wobei ich millis() noch nicht verwende,>nur der Timer 0 läuft für sich alleine.
Ja klar! Es müssen ALLE Interrupts außer COMPB im COMPA gesperrt werden,
das ist ja der Trick! Daß Timer 0 da im Hintergrund noch läuft war mir
bis jetzt nicht klar!
>Ich baue den Code mal weiter zusammen, mal sehen wann es schlimmer wird>oder der Timer 0 später noch mehr Störung verursacht. Der Timer 0>alleine kann es nicht sein, laut meinem Gefühl. ;-)
FALSCH! Das hast du doch selber gerade bewiesen, denn ohne Timer 0 gibt
es keinen Jitter.
Brauchst du wirklich Millisekunden oder nur etwas "in dem Bereich"?
Was ist der Bereich den du auswertest/auf den du wartest? __ms...__ms
Falls sich das irgendwie mit dem Timer1-Zyklus deckt, dann nimm Comp1A
zum millis zählen.
BTW, wie groß ist millis? Mit 16Bit kann man bis zu 65,x Sekunden
warten. Die 2^32/1000/60/60/24 oder 49 Tage der Arduino-Lib braucht man
nicht wirklich.
Falk B. schrieb:> @Veit Devil (devil-elec)>>>können wir das mit C vs. C++ auf später verschieben? Sonst kämpfe ich an>> Sicher. Hat mit dem aktuellen Problem auch gar nichts zu tun.>>>Frage brennt mir unter den Nägeln, memset ist doch Standard C, was soll>> Ja.>>>da schief gehen?>> Nix.
Doch. Das kommt ganz darauf an.
Anhand des zitierten Beispiels konnte ich nicht sagen, wie / wo das
Ziel(Array) deklariert / definiert ist.
Wenn der Compiler die vollständige Definition gesehen hat und der
Array-Bezeichner nicht zu einem Zeiger zerfallen ist, wird die Größe
korrekt durch sizeof() ermittelt. In diesem Fall wird also das ganze
Array(?) genullt.
Ist es aber kein Array-Bezeichner mehr, sondern nur noch ein Zeiger
(etwa weil Du den Array-Bezeichner als Zeiger an eine Funktion
übergibst), so bestimmt sizeof() die Größe des Zeigers (wohl 2 Bytes auf
einem AVR8). Dann werden nur die ersten zwei Bytes des Ziels genullt.
Nur so zur Info: ich habe so einen RC-Controller mit dem
AtMega328PB@20MHz. Der bedient einen Uart mit 115KB/VollDuplex, einen
Uart mit 19200B/VollDuplex, eine SoftPPM mit 8-Kanälen per ISR wie bei
Dir, eine I2C, eine OneWire, zwei HardPWM, zwei Drehzahlsensoren und
8-AD-Kanäle. Relevant sind hier die beiden im Interrupt betriebenen
Uarts und die SoftPPM per Timer-Interrupt. I2C läuft im Polling-Mode und
OneWire arbeitet mit kurzen ISR-Sperren. Hard-PWM braucht keine CPU und
die A/D-Kanäle werden gepollt.
Da habe ich 1 - 1,5 µs Jitter auf den SoftPPM-Kanälen und meine analogen
Servos bleiben ruhig. Rechnet man linear auf 8MHz runter wären das 2,5 -
3,75µs Jitter.
Hallo,
ich nutze Timer 2 zum kalibrieren. Steht in der ISR(PCINT0_vect) drin,
habe daran nie etwas geändert. Tut mir leid wenn das jemand nicht
gesehen hat. Ich weiß wie schwer es ist fremden Code zu lesen.
Kurzer Umriss, ich habe mit Arduino vor paar Jahren angefangen. Beim
nackten ATtiny möchte ohne Arduino IDE zurechtkommen. Allein schon wegen
Speicherplatz. Deswegen Atmel Studio und die millis Funktion nachgebaut.
Damit wollte ich später noch einen TimeOut realisieren wenn was seitens
ATtiny schief geht. Kann ich aber wie ich sehe und ihr gesehen habt nun
auch mit Timer 1 machen und ein 1ms Intervall benötige ich sicherlich
auch nicht.
Auf Grund von Timer 0 habe ich den dann auch flux mit in der Timer 1
Compare ISR getoppt und gestartet. Brachte leider noch nichts. Erst als
ich das Timing-Window erhöht habe wurde es besser. Hatte bis jetzt immer
7 Timercounts.
Mit 10 Counts (Led1 15µs) immer noch leichter Jitter aber mit starken
sporadischen Ausreißern.
Ab 15 Counts (Led1 20µs) wird es besser, nur noch minimaler Jitter ohne
Ausreißer. Eine weitere Erhöhung bringt nichts.
Erst wenn ich in der Hauptschleife die millis Abfrage auskommentiere ist
fast absolute Jitterruhe. Ich denke ein Restjitter wird immr bleiben,
weil das Programm ja immer ertst wohin springen muss. Oder? Kann ja
nicht alles gleichzeitig machen.
Das Timingwindow muss doch nur soweit vorher aktiv werden, für die Zeit
im voraus, wie alle Maßnahmen in der Timer 1 Compare A benötigen? Also
so lange wie ein uart Byte abholen dauern würde und zusätzlich wie lange
die Timer 0 Compare ISR benötigt. So war das doch gedacht?
Nur wird Timer 1 nicht regelmäßig aufgerufen. Das schwankt ja zwischen
1ms und 20ms bis zur kompletten Abschaltung was ich ganz am Ende machen
möchte. Oder ich muss gänzlich auf einen Zeitzähler verzichten. Ich
mache erstmal das Timer 0 Aufrufintervall größer 1ms.
Aktueller Stand hängt dran.
Zu memset(): mit den o.g. Deklarationen ist es in Ordnung, da
UART_Tx_Buf ein Array-Bezeichner ist und bei memset() nicht zu einem
Zeiger zerfallen ist. Trotzdem ist sowas gefährlich. Warum benutzt Du
nicht gleich UART_RX_BUFFER_SIZE?
Wilhelm M. schrieb:>> Ist es aber kein Array-Bezeichner mehr, sondern nur noch ein Zeiger> (etwa weil Du den Array-Bezeichner als Zeiger an eine Funktion> übergibst), so bestimmt sizeof() die Größe des Zeigers (wohl 2 Bytes auf> einem AVR8). Dann werden nur die ersten zwei Bytes des Ziels genullt.
Was noch fehlt:
Würde man statt
xy_t array[32]
schreiben
std::array<xy_t,32> array;
dann könnte man dieses als Referenz an eine Funtion übergeben
void func( std::array<xy_t,32>& array);
und hätte die komplette Typ-Info.
BTW, std::array macht das mit Zero-Overhead. Keine extra Daten, kein
extra Code, kein malloc.
@Wilheml: ich benutze das bei AVR in einer eigenen
(minimalst)Implementierung. Kennst du eine für AVR?
Hallo,
@Wilhelm:
ich nutze den uart Ringbuffer mit zum kalibrieren. Damit ich keinen 2.
Buffer anlegen muss der danach sinnlos Speicher frist. Deswegen muss ich
die Sichtbarkeit erweitern. Die letzten beiden Zeilen nutzen wir zum
uart ISR steuern. Eben wegen dem Jitter.
Carl D. schrieb:> Wilhelm M. schrieb:>>>> Ist es aber kein Array-Bezeichner mehr, sondern nur noch ein Zeiger>> (etwa weil Du den Array-Bezeichner als Zeiger an eine Funktion>> übergibst), so bestimmt sizeof() die Größe des Zeigers (wohl 2 Bytes auf>> einem AVR8). Dann werden nur die ersten zwei Bytes des Ziels genullt.>> Was noch fehlt:> Würde man statt> xy_t array[32]> schreiben> std::array<xy_t,32> array;> dann könnte man dieses als Referenz an eine Funtion übergeben> void func( std::array<xy_t,32>& array);> und hätte die komplette Typ-Info.
Das hatte ich doch oben schon vorgeschlagen ...
> @Wilheml: ich benutze das bei AVR in einer eigenen> (minimalst)Implementierung. Kennst du eine für AVR?
Ja, meine eigene ;-)
Veit D. schrieb:> Hallo,>> @Wilhelm:> ich nutze den uart Ringbuffer mit zum kalibrieren. Damit ich keinen 2.> Buffer anlegen muss der danach sinnlos Speicher frist. Deswegen muss ich> die Sichtbarkeit erweitern. Die letzten beiden Zeilen nutzen wir zum> uart ISR steuern. Eben wegen dem Jitter.
Ja, aber man will doch die Deklaration nicht in jeder
Implementierungsdatei wiederholen, deswegen gehört das in die
korrespondierende Header-Datei.
@Veit Devil (devil-elec)
>Erst wenn ich in der Hauptschleife die millis Abfrage auskommentiere ist>fast absolute Jitterruhe.
Die Abfrage ist ein Kopieren unter ISR Sperre und das mit maximaler
CPU-Last, wenn nix zu tun ist! Das ist Irrsinn! Und es wirkt ebenso wie
eine ISR, sie erzeugt Jitter.
> Ich denke ein Restjitter wird immr bleiben,>weil das Programm ja immer ertst wohin springen muss. Oder?
Oder! Wenn im normalen Programm KEINE (kurzzeitge) ISR-Sperre genutzt
wird, wie in deiner millis() Funktion, dann wird bei einerem Interrupt
nur der aktuelle Assemblerbefehl zu Ende ausgeführt und sofort die ISR
ausgeführt. Der dadurch entstehende Jitter liegt bei max. 1-2
CPU-Takten!
>Kann ja nicht alles gleichzeitig machen.
Muss es auch nicht, aber Interrupts
>Das Timingwindow muss doch nur soweit vorher aktiv werden, für die Zeit>im voraus, wie alle Maßnahmen in der Timer 1 Compare A benötigen?
Nein, wie alle anderen ISRs im Extremfall (worst case) dauern können).
>Also>so lange wie ein uart Byte abholen dauern würde und zusätzlich wie lange>die Timer 0 Compare ISR benötigt. So war das doch gedacht?
Ja.
>Nur wird Timer 1 nicht regelmäßig aufgerufen. Das schwankt ja zwischen>1ms und 20ms bis zur kompletten Abschaltung was ich ganz am Ende machen>möchte. Oder ich muss gänzlich auf einen Zeitzähler verzichten. Ich>mache erstmal das Timer 0 Aufrufintervall größer 1ms.
Musst du nicht, wenn du auch Timer 0 im COMPA kurz deaktiverst und in
COMPB wieder einschaltest. Aber du mußt die unsinnige und wahnsinnige
Kopierei mit deiner millis() Funktion rausnehmen.
>ich nutze Timer 2 zum kalibrieren. Steht in der ISR(PCINT0_vect) drin,>habe daran nie etwas geändert. Tut mir leid wenn das jemand nicht>gesehen hat. Ich weiß wie schwer es ist fremden Code zu lesen.
In gut strukturiertem Quelltext würde man das direkt sehen . . .
Falk B. schrieb:> Der dadurch entstehende Jitter liegt bei max. 1-2 > CPU-Takten!
Sicher?
z.B. (max. Dauer)
RCALL 3
ICALL 3
RET 4
RETI 4
CPSE 1/2/3
SBRC 1/2/3
SBRS 1/2/3
SBIC 1/2/3
SBIS 1/2/3
Hallo,
@ Wilhelm:
das ist doch in der uart Lib deklariert, nur muss ich ja irgendwie
darauf zugreifen wegen der Doppelnutzung, deswegen musste ich die
Sichtbarkeit erweitern. Ich weiß im Moment nicht worauf du hinaus
möchtest.
kompletter Code >> Beitrag >> Datum: 29.12.2017 23:37
Beitrag "Re: ISR Code schneller machen?"
@ Falk:
Habe das Timer 0 Intervall auf 10ms erweitert. Ändert nichts.
Wie auch, millis() wird ja dennoch ständig aufgerufen. Ich weiß nicht
wie ich sonst den aktuellen Zählerstand von millis abfragen soll?
Irgendwie muss ich ja auf zugreifen und wegen >Byte atomar.
Habe mal vermessen.
ohne uart, keine Kabel dran, ohne ohne millis() ... 1µs Jitter
ohne uart, keine Kabel dran, mit millis() ......... 3µs Jitter
mit uart, Kabel dran, ............... 16µs Jitter, egal ob mit/ohne
millis()
@Dieter F. (jim_quakenbush)
>> Der dadurch entstehende Jitter liegt bei max. 1-2 > CPU-Takten!>Sicher?
Nicht ganz ;-)
>RCALL 3>ICALL 3>RET 4
OK, ist einer der längsten Befehle.
>RETI 4
Kann nicht durch eine ISR unterbrochen werden, es sei denn man macht
verschachtelte Interrupts per Software.
>CPSE 1/2/3>SBRC 1/2/3>SBRS 1/2/3>SBIC 1/2/3>SBIS 1/2/3
Das sind meistens nur 1-2 Takte, weil selten eine 2-Wort Anweisung
danach kommt.
Falk B. schrieb:> Das sind meistens nur 1-2 Takte, weil selten eine 2-Wort Anweisung> danach kommt.
Meistens <> max. - darum ging es mir :-) (und hier speziell um RET)
@ Veit Devil (devil-elec)
>das ist doch in der uart Lib deklariert,
Aber nur lokal (static), damit man es von außen nicht sieht.
> nur muss ich ja irgendwie>darauf zugreifen wegen der Doppelnutzung, deswegen musste ich die>Sichtbarkeit erweitern.
Eben das static weglassen ;-)
>Habe das Timer 0 Intervall auf 10ms erweitert. Ändert nichts.>Wie auch, millis() wird ja dennoch ständig aufgerufen.
Und warum? Was soll der Unsinn?
> Ich weiß nicht>wie ich sonst den aktuellen Zählerstand von millis abfragen soll?
Deine "Abfrage" ist im Moment 100% sinnlos!
>Irgendwie muss ich ja auf zugreifen und wegen >Byte atomar.
Dazu muss man aber nicht STÄNDIG 32 Bit Variablen kopieren! Das macht
man nur dann, wenn es WIRKLICH nötig ist. Ist es in deinem Programm im
Moment nie!
Und wenn man das nur für einen Timeout braucht, zählt man den in der ISR
runter. Dann braucht man immer nur eine direkte Abfrage im normalen
Programm, im Idealfall direkt atomar mit nur 8 Bit. Die reichen für
normale Timeouts locker. Dann braucht man NIRGENDWO eine ISR-Sperre und
alles ist gut und es gibt keinen zusätzlichen Jitter.
1
volatileuint8_ttimeout;
2
3
...
4
5
isr(timer0){
6
...
7
if(timeout)timeout--;
8
}
9
10
...
11
12
imProgramm
13
14
timeout=100;
15
16
irgendwoanders
17
18
if(!timeout){// timeout }
>ohne uart, keine Kabel dran, ohne ohne millis() ... 1µs Jitter
Das muss weniger sein, aber dein Logicanalyzer zeigt die Zeiten nur mit
1us Auflösung an, dem kann man da nicht mehr vertrauen. Miss mit dem
Oszi.
>ohne uart, keine Kabel dran, mit millis() ......... 3µs Jitter
Siehe oben, das millis() ist Unsinn.
>mit uart, Kabel dran, ............... 16µs Jitter, egal ob mit/ohne>millis()
Weil das mit dem UDRIE im usart0_putc() noch nicht funktioniert, da mußt
du nochmal ran. Das sollte so wie von mir skizziert eigentlich laufen.
Wenn GAR NICHTS gesendet wird, gibt es irgendwo einen grundlegenden
Fehler, den findet man aber. Das TXB80 ist frei verfügbar, wenn man
nicht im 9 Bit UART-Modus arbeitet.
Falk B. schrieb:> @Veit Devil (devil-elec)>>>Erst wenn ich in der Hauptschleife die millis Abfrage auskommentiere ist>>fast absolute Jitterruhe.>> Die Abfrage ist ein Kopieren unter ISR Sperre und das mit maximaler> CPU-Last, wenn nix zu tun ist! Das ist Irrsinn! Und es wirkt ebenso wie> eine ISR, sie erzeugt Jitter.
Jetzt haben wir den Übeltäter endlich :) Respekt Falk, dass du so lange
drangeblieben bist.
Was dagegen tun?
1) millis() seltener aufrufen (so wie aktuell hast du geschätzt 2/3 der
Zeit die Interrupts deaktiviert, kein Wunder, dass das dauernd Jittert)
dann tritt der Jitter immerhin seltener auf
2) in millis() nicht alle Interrupts deaktivieren, sondern nur
denjenigen, der deine >1Byte-Variable ändern kann - dann wird sich den
Servosignal nicht mehr daran stören
3) andere Infrastruktur, z.B. im Millisekunden-Timer keine
32Bit-Variable hochzählen, sondern ein Flag setzen oder eine
8Bit-Variable weiterzählen und das im Hauptprogramm auswerten -> bietet
allerdings das Risiko, dass du Millisekunden verlierst
Dass du mit uart+Kabel noch mehr Jitter erhältst - lass mich raten, in
irgendeinem der case-Äste in handle_Function_UART0_Pins(); schaltest du
auch für "lange" Zeit Interrupts ab? Und zwar in einem, der nur aktiv
ist, wenn du Daten empfängst? Oder dein Receive-ISR ist "zu lang",
länger als dein Timing-Window?
MfG, Arno
@Veit Devil (devil-elec)
>die in main verwendeten uart Variablen sind nicht static.
Ach?
>in uart.cpp>volatile uint16_t UART0_TxBuf[UART_TX_BUFFER_SIZE];>in main.cpp>extern volatile uint16_t UART0_RxBuf[UART_RX_BUFFER_SIZE];
Merkt er was?
@Veit Devil (devil-elec)
>Man muss es doch extern bekannt machen.
Ja, aber die Deklaration von Variablen in uart.cpp gehört in uart.h,
welche dann wo auch immer per #include eingefügt wird.
Hallo,
du machst mich jetzt total irre. Wenn ich das in die uart.h verschiebe,
dann meckert die main.cpp und uart.cpp rum. Dann geht gar nichts mehr.
Angeblich ist alles nicht deklariert.
In main.cpp und uart.cpp ist jedoch schon immer #include "usart.h"
inkludiert.
Anfangs dachte ich ich hätte den Mechanismus dahinter verstanden, je
länger der Thread dauert umso weniger verstehe ich.
In der main.cpp sind die 4 Zeilen raus und in der uart.h steht
1
#include<avr/pgmspace.h>
2
3
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405
4
#error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !"
Hallo,
habe das erstmal wieder rückgängig gemacht und mich danach nochmal ans
TXB80 Bit gemacht. Ich hatte übersehen das ich das auch von Hand setzen
soll. Ich dachte die uart soll das setzen und löschen und hatte mich die
ganze Zeit gewundert wie das funktionieren soll wenn ich das 9. Bit
nicht nutze im Datenframe. Jetzt gehts damit.
Laut Datenlogger hat Servo 1 einen 5µs Jitter. Die anderen beiden 2µs.
Muss ein Messfehler sein, weil laut Oszi alle gleich zucken. Alles mit
Kommunikation aber ohne millis() Abfrage. Mit millis Abfrage zuckt es am
Oszi wieder etwas wilder.
Jetzt mal eine grundlegende Frage. Ohne millis. Dieser Restjitter ist
doch jetzt System bedingt oder muss der auch noch weg? Also ist das
überhaupt möglich?
Das Timer 0 Intervall hatte ich erhöht, damit nicht aller 1ms sondern
erst aller 10ms dessen ISR zuschlägt.
Veit D. schrieb:> Hallo,>> du machst mich jetzt total irre. Wenn ich das in die uart.h verschiebe,> dann meckert die main.cpp und uart.cpp rum. Dann geht gar nichts mehr.> Angeblich ist alles nicht deklariert.> In main.cpp und uart.cpp ist jedoch schon immer #include "usart.h"> inkludiert.>
#include "usart.h" oder #include "uart.h"?
> Anfangs dachte ich ich hätte den Mechanismus dahinter verstanden, je> länger der Thread dauert umso weniger verstehe ich.>
Auch wenn es manchmal noch anders gemacht wird, die extern Deklaration
einer Variable kommt in den Header (foo.h oder foo.hh) des selben Moduls
(foo.c oder foo.cpp), wo die Variable definiert wird.
Hallo,
die Dateien heißen alle usart.xxx und werden auch so mit usart.h
inkludiert, sonst hätte das noch nie funktioniert. Das war hier im
Thread ein Tippfehler. Geläufig sagt man uart obwohl es eine usart ist.
Auch wenn ich die in der usart.h als extern volatile deklariere werden
diese nicht gefunden.
Hallo,
der aktuelle Stand ist jedenfalls der, ohne millis() Abfrage, dass die
Servos selbst nicht zucken, auch wenn ich am Oszi das restliche zittern
sehe mit 1µs/DIV bzw. Datalogger. Das ist schon einmal sehr sehr schön
das mit Euch (Falk) geschafft zu haben. Vielen Dank.
Was nun mit der geänderten usart.h falsch ist weiß ich nicht. Könnt ihr
mir da helfen?
Die millis() Funktion gehe ich an.
@ Veit Devil (devil-elec)
>TXB80 Bit gemacht. Ich hatte übersehen das ich das auch von Hand setzen>soll.
OMG!
> Ich dachte die uart soll das setzen und löschen und hatte mich die>ganze Zeit gewundert wie das funktionieren soll wenn ich das 9. Bit>nicht nutze im Datenframe. Jetzt gehts damit.
AHA!
>Laut Datenlogger hat Servo 1 einen 5µs Jitter. Die anderen beiden 2µs.>Muss ein Messfehler sein, weil laut Oszi alle gleich zucken.
Bist du sicher, daß dein Logicanalyzer immer mit voller Abtastrate von
24 MHz arbeitet und nicht irgendwann mal auf eine geringere Rate
runterschaltet?
> Alles mit>Kommunikation aber ohne millis() Abfrage. Mit millis Abfrage zuckt es am>Oszi wieder etwas wilder.
Klingt schon mal gut, wenn gleich da theoretisch noch etwas weniger
Jitter drin sein müßte.
>Jetzt mal eine grundlegende Frage. Ohne millis. Dieser Restjitter ist>doch jetzt System bedingt oder muss der auch noch weg?
Muss nicht, aber kann.
> Also ist das>überhaupt möglich?
Ich meine ja. Hast du Timer 0 deaktiviert bzw. schaltest du ihn im COMPA
kurzzeitig aus?
Man sollte auf ca. 0,5us Jitter runterkommen, das sind 4 Takte bei 8
MHz.
>Das Timer 0 Intervall hatte ich erhöht, damit nicht aller 1ms sondern>erst aller 10ms dessen ISR zuschlägt.
Ist weniger oft aber immer noch oft genug. Siehe oben.
@ Veit Devil (devil-elec)
>>ATOMIC_BLOCK (ATOMIC_RESTORESTATE) { // wegen ISR(TIMER1_COMPA_vect)>> if (UCSR0B & (1<<TXB80)) {>> UART0_CONTROL |= _BV(UART0_UDRIE); // enable UDRE interrupt>> return;>> }>>}>Wenn man den atomic Block mittendrin verlässt, wird dann das SREG>Register noch richtig behandelt?
Ja, darum kümmern sich das Macro und diverse Compilertricks hinter
ATOMIC_BLOCK.
@ Veit Devil (devil-elec)
>du machst mich jetzt total irre. Wenn ich das in die uart.h verschiebe,>dann meckert die main.cpp und uart.cpp rum.
Weil irgendwelche anderen Abhängigeiten nicht passen. Aber das kann man
korrigieren.
> Dann geht gar nichts mehr.>Angeblich ist alles nicht deklariert.
Ist wahrscheinlich auch so.
Lange Rede, kurzer Sinn. Lad mal dein GESAMTES Projekt als Zip-File
hoch, dann kann ich das anschauen und gerade rücken. Das alles per
Beitrag zu kommentieren ist irgendwann ermüdend.
>Anfangs dachte ich ich hätte den Mechanismus dahinter verstanden, je>länger der Thread dauert umso weniger verstehe ich.
;-)
Eigentlich (tm) ist es einfach. In jeder Headerdatei steht drin, was der
Rest der Welt von der .c Datei wissen muss.
- Funktionsdeklarationen von Funktion, die von außen sicht- und nutzbar
sein sollen
- Variablendeklarationen von Funktion, die von außen sicht- und nutzbar
sein sollen
- #define
- Typdesfinitonen
- Inline-Funktionen mit echtem C-Code (nicht nur Deklarationen)
https://www.mikrocontroller.net/articles/FAQ#Header_File_-_wie_geht_das
Hallo,
okay soweit. Timer 0 wird in Timer 1 Compare aus- und eingeschalten.
Der Datalogger wird sicherlich mit 4 Kanälen nicht mehr mit 24MHz
abtasten.
Zurück wegen der usart.h und extern volatile
Ich halte mich aktuell genau an das Bsp., in einem c++ Forum gesehen.
in main.c
int var=5;
und in header.h
extern int var;
usart.h
nach der UART_TX_BUFFER_SIZE / UART_RX_BUFFER_SIZE Definition
in main.cpp
[c]
volatile uint16_t UART0_TxBuf[UART_TX_BUFFER_SIZE];
volatile uint16_t UART0_RxBuf[UART_RX_BUFFER_SIZE];
volatile uint8_t UART0_TxHead;
volatile uint8_t UART0_TxTail;
/c]
>> multiple definition
Lasse ich das in main.cpp weg, so wie ihr sagt, dann ist alles komplett
undefined reference. Ich blicke nicht mehr durch was vorne und hinten
ist.
Ich lade das mal hoch Danke für die Unterstützung. Ich bringe es vorher
in den Urzustand wie es bis jetzt immer funktionierte ...........
Möchtest du als Dank für die sportliche Herausforderung ein oder zwei
ATtiny841 haben? Unbenutzt. Kann den Quarz mit reinlegen. Kann die auch
noch auf eine Adapterplatine löten.
@ Veit Devil (devil-elec)
> ATtiny841_MAX487_032_Slave3.zip (128 KB, 0 Downloads)
Schau ich mir gleich mal an.
>Der Datalogger wird sicherlich mit 4 Kanälen nicht mehr mit 24MHz>abtasten.
Doch, aber nicht unbedingt bei jeder Zeitauflösung. Das machen
Digitaloszis auch nicht.
>Ich halte mich aktuell genau an das Bsp., in einem c++ Forum gesehen.
Was zum Geier hast du immer mit deinem C++? Du kannst nicht mal richtig
gut C.
>in main.c>int var=5;>und in header.h>extern int var;
Stimmt.
>usart.h>nach der UART_TX_BUFFER_SIZE / UART_RX_BUFFER_SIZE Definition>extern volatile uint16_t UART0_TxBuf[UART_TX_BUFFER_SIZE];>extern volatile uint16_t UART0_RxBuf[UART_RX_BUFFER_SIZE];>extern volatile uint8_t UART0_TxHead;>extern volatile uint8_t UART0_TxTail;>in main.cpp>volatile uint16_t UART0_TxBuf[UART_TX_BUFFER_SIZE];>volatile uint16_t UART0_RxBuf[UART_RX_BUFFER_SIZE];>volatile uint8_t UART0_TxHead;>volatile uint8_t UART0_TxTail;>/c]
Ist Murks, weil man nicht quer durch Dateien Deklarationen schreibt.
>Lasse ich das in main.cpp weg, so wie ihr sagt, dann ist alles komplett>undefined reference. Ich blicke nicht mehr durch was vorne und hinten>ist.
Das wird wieder. Dauert nicht allzu lang.
>Ich lade das mal hoch Danke für die Unterstützung. Ich bringe es vorher>in den Urzustand wie es bis jetzt immer funktionierte ...........
Gut.
>Möchtest du als Dank für die sportliche Herausforderung ein oder zwei>ATtiny841 haben? Unbenutzt. Kann den Quarz mit reinlegen.
Mach mal. Leg noch ne Flasche Martini Bianco rein und alles wird gut ;-)
>Kann die auch noch auf eine Adapterplatine löten.
Nein, wenn dann beides getrennt. Löten kann ich im Fall der Fälle
selber.
>>Möchtest du als Dank für die sportliche Herausforderung ein oder zwei>>ATtiny841 haben? Unbenutzt. Kann den Quarz mit reinlegen.>> Mach mal. Leg noch ne Flasche Martini Bianco rein und alles wird gut ;-)>>>Kann die auch noch auf eine Adapterplatine löten.>> Nein, wenn dann beides getrennt. Löten kann ich im Fall der Fälle> selber.
Das mach ich doch glatt. :-) Den Rest per PN/Mail.
Arno schrieb:> Falk B. schrieb:>> @Veit Devil (devil-elec)>>>>>Erst wenn ich in der Hauptschleife die millis Abfrage auskommentiere ist>>>fast absolute Jitterruhe.>>>> Die Abfrage ist ein Kopieren unter ISR Sperre und das mit maximaler>> CPU-Last, wenn nix zu tun ist! Das ist Irrsinn! Und es wirkt ebenso wie>> eine ISR, sie erzeugt Jitter.>> Jetzt haben wir den Übeltäter endlich :) Respekt Falk, dass du so lange> drangeblieben bist.
.
> Was dagegen tun?>> 1) millis() seltener aufrufen (so wie aktuell hast du geschätzt 2/3 der> Zeit die Interrupts deaktiviert, kein Wunder, dass das dauernd Jittert)> dann tritt der Jitter immerhin seltener auf
Wenn millis() aufgerufen wurde und noch weiter gewartet werden soll,
dann braucht man nicht weiter nach millis() zu fragen, sondern kann in
IDLE Sleep gehen, denn erst beim nächsten Interrupt besteht die Chance
daß sich millis() geändert haben könnte. Und selbst wenn viele andere
Interrupts kommen, dann sorgt dieses Vorgehen dafür, daß mills() erst
NACH einem Int die INT's global für kurze Zeit sperrt.
Hallo,
irgendein Sleep Mode kommt nicht in Frage. Wenn ich auf einem Slave
nicht alle freien Pins für Servos benötige, dann werden das wohl
Eingänge werden um Sensoren abzufragen. Entweder ich frage im
Hauptprogramm so oft es geht ab oder aller paar ms (mit millis) so wie
es angedacht war. Eigentlich benötige ich einen globalen Zeitzähler den
ich dann wie von Arduino gewohnt in den Funktionen lokal verarbeiten
kann. Um damit irgendwelche Funktionen zum Bsp. aller 20 oder 30ms
aufzurufen. Dort macht man das so. Was ja nicht dumm ist.
1
voidupdate()
2
{
3
staticunsignedlonglast_ms=0;
4
constbytezeit=20;// intervall
5
6
if(millis()-last_ms>zeit){
7
last_ms=millis();
8
...
9
machwassinnvolles
10
...
11
}
12
}
oder
1
voidupdate()
2
{
3
staticunsignedlonglast_ms=0;
4
constbytezeit=20;// intervall
5
6
if(millis()-last_ms<zeit)return;
7
last_ms+=zeit;
8
9
...
10
machwassinnvolles
11
...
12
}
Ich denke erstmal über den Vorschlag von Falk nach, wie man millis
anders macht. Wenn man hier wie aktuell verstanden jedoch nur auf ein
Zeitintervall festgelegt ist, dann ist das auch blöd. Dann kann man
nicht eine Funktion aller 10ms und eine andere aller 50ms aufrufen. Was
ich mit den beiden Bsp. jedoch locker machen könnte.
>> Wenn man den atomic Block mittendrin verlässt, wird dann das SREG> Register noch richtig behandelt?
Wenn Du Dir das Macro anschaust (oder die Doku dazu liest) stellst Du
fest, dass dort eine Gcc C-Extension verwendet wird, die in C etwas
nachbildet, was in C++ ein ganz einfaches und ganz oft genutztes Idiom
ist: RAII. Sprich: wenn der Block auf irgendeinem Weg verlassen wird,
wird in C eine spezielle cleanup-function aufgerufen. Das erreicht man
in C++ durch einen DTor (eines lokalen Objektes) ohne jede
non-Standard-Spracherweiterung ;-)
Falk B. schrieb:>>in main.cpp>>volatile uint16_t UART0_TxBuf[UART_TX_BUFFER_SIZE];>>volatile uint16_t UART0_RxBuf[UART_RX_BUFFER_SIZE];>>volatile uint8_t UART0_TxHead;>>volatile uint8_t UART0_TxTail;>>/c]>> Ist Murks, weil man nicht quer durch Dateien Deklarationen schreibt.
Das obige sind keine Deklarationen, sondern Definitionen. Also schlägt
hier die ODR (one-definition-rule) zu und Du erhälst eine multiple
definition.
Deklarieren kann man eine Entität sooft wie man will, solange alle
Deklarationen übereinstimmen. Genau deswegen darf / sollte man das in
Header-Dateien machen.
>>Lasse ich das in main.cpp weg, so wie ihr sagt, dann ist alles komplett>>undefined reference. Ich blicke nicht mehr durch was vorne und hinten>>ist.
Ist nicht nachvollziehbar.
Du solltest Dir vielleicht mal an einem Beispiel klar machen, was
Programm-globale oder Übersetzungseinheit-globale Variable sind, wie man
sie definiert und deklariert.
@Veit Devil (devil-elec)
So, ich hab mal deinen Code gesichtet. Ich hab kein Atmelstudio 7, nur
6.2, d.h. ich mußte ein neues Projekt erstellen und die Quelltexte rüber
kopieren (die Projekte sind nicht rückwärtskompatibel, naja)
Dann hab ich mal deine .cpp Endungen wieder in .c umbenannt, den mit C++
hat dein Projekt rein gar nichts zu tun!
Dabei kommen beim 1. Kompilieren 3 Fehler.
1. bool ist unbekannt, wird durch #include <stdbool.h> behoben
2. PCINT2 kennt er nicht, fehlt auch in iotn841.h, hab ich mal manuell
korrigiert
3. 'Message' undeclared here (not in a function),
Das ist dein Eiertanz mit den Deklarationen. Hab ich geändert, indem ich
sizeof(empfDaten) geschrieben habe. Denn messeage ist weder eine
Variable noch ein Datentyp, deswegen kann sizeof nichts berechnen. Die
restlichen, verwirrenden Details dürfen andere erklären ;-)
uart0_putc() hab ich noch ein bisschen aufgebohrt, um die kurze
Interruptsperre zu vermeiden, wenn die "kritische Phase" zwischen COMPA
und COMPB ISR durchlaufen wird. Sieht komisch aus (doppelt gemoppelt),
sollte aber funktionieren und muss so gemacht werden!
In read_Ringbuffer_0() hast du die UART-Fehlercodes dezimal drin, das
ist Unsinn. In Hex ist das besser sichtbar, welches Bit was
signalisiert. Außerdem sind die schon in uart.h definiert, das reicht.
Doppelt aufschreiben bringt nix, eher Fehler. Außerdem besteht der Witz
von enums oder auch einfachen #define darin, daß man sich mit den
kodierten Zahlen NICHT beschäftigen muss und nur mit den
selbsterklärenden Worten arbeitet.
Wenn du Timer 0 in COMPA abschaltest, solltest du alle CSxy Bit auf 0
setzen, damit es auch bei anderen Prescalern ohne Änderung funktioniert,
so wie du es schon in stop_Timer0() gemacht hast.
In main hab ich am meisten aufgeräumt und sämtliche Deklarationen und
typedefes in main.h verschoben. Die UART-Deklarationen natürlich in
uart.h
War eigentlich unkompliziert. Schau's dir mal an.
Falk B. schrieb:> Wenn du Timer 0 in COMPA abschaltest, solltest du alle CSxy Bit auf 0> setzen, damit es auch bei anderen Prescalern ohne Änderung funktioniert,> so wie du es schon in stop_Timer0() gemacht hast.
Halt, der Plan war doch, da nur den IRQ abzuschalten, oder?
MfG, Arno
#pragma once
wieder was gelernt
ich mag aber weiterhin
#ifndef usart_h
#define usart_h
weil
https://msdn.microsoft.com/de-de/library/4141z1cx.aspx
Wir empfehlen das #include-Schutz-Idiom, wenn Code für Compiler portabel
sein muss, die die #pragma once-Richtlinie nicht implementieren, um die
Konsistenz mit vorhandenem Code aufrechtzuerhalten
@ Arno (Gast)
>> Wenn du Timer 0 in COMPA abschaltest, solltest du alle CSxy Bit auf 0>> setzen, damit es auch bei anderen Prescalern ohne Änderung funktioniert,>> so wie du es schon in stop_Timer0() gemacht hast.>Halt, der Plan war doch, da nur den IRQ abzuschalten, oder?
Stimmt, das war der Plan! Ist wohl durchgerutscht 8-0
Denn so geht der Timer 0 falsch!
Wenn kein sleep möglich ist, dann vielleicht das versuchen, was das
sleep einfach sicherstellen sollte: weniger oft die Ints sperren.
Man kann in millis() auch ohne Sperre auskommen, in dem man
- zusätzlich zum Wert selber ein Bit/Byte anlegt,
- in das die ISR wenn sie am Wert gefummelt hat eine 1 reinschreibt.
millis():
- setzt als erstes das Bit/Byte auf 0, was atomar ist,
- liest den Wert in eine temp. Variable und
- überprüft danach das "geändert" Flag
Sollte es gesetzt sein, einfach nochmal lesen. Das Flag muß dabei nicht
mehr angesehen werden, falls man sich sicher ist, daß die diversen ISRen
millis() nie länger als 1ms unterbrechen.
Damit wird man zuverlässig die Interruptsperren los und kann millis
bedenkenlos in einer Warteschleife benutzen.
Joachim B. schrieb:> #pragma once> wieder was gelernt>> ich mag aber weiterhin> #ifndef usart_h> #define usart_h>> weil> https://msdn.microsoft.com/de-de/library/4141z1cx.aspx> Wir empfehlen das #include-Schutz-Idiom, wenn Code für Compiler portabel> sein muss, die die #pragma once-Richtlinie nicht implementieren, um die> Konsistenz mit vorhandenem Code aufrechtzuerhalten
Die Vorteile überwiegen m.E. allerdings. Und: welcher Compiler
unterstützt heute kein #pragma once ?
Hallo,
oh ha, so muss man das also machen. Man sieht auch sofort die
Handschrift eines richtigen Programmierers. Alles aufgeräumter. Letzte
Code Korrektur ist auch vollzogen. Vielen vielen herzlichen Dank - Falk.
Und alle anderen die ihre Idee eingebracht haben. Kann man nicht in
Worte fassen was in den letzten Tagen alles mit dem Code passiert ist
nur um den Jitter in den Griff zubekommen.
Falls jemand die ATtiny841 Definitionsdatei benötigt, hängt dran.
Jetzt muss ich natürlich fragen was der funktionale Unterschied ist
zwischen
1
if(UCSR0B&(1<<TXB80)){
2
3
/* enable UDRE interrupt */
4
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){// wegen ISR(TIMER1_COMPA_vect)
für mich sieht das gleich aus.
Zum Abschluss noch ein Filmchen zur Jittermessung. Alles nur ohne millis
Abfrage.
https://youtu.be/Y5rib4x1k60
Man beachte die Zeiteinstellung von 500ns/DIV.
Bewegt sich alles innerhalb 1µs, ganz ganz selten scheint es einen
größeren Ausschlag zugeben. Der stört aber nicht, die Servos verhalten
sich ruhig. Deswegen kann ich auf die Servoabschaltung verzichten, was
ich am Anfang drin hatte. Kein zucken, kein brummen, keine
Stromaufnahme. Der Code zur Pulserzeugung ist auch in der Hinsicht
besser das nicht alle Servos zeitgleich Strom ziehen.
@Carl, den Timer 0 Compare müssen wir aber kurz sperren, auf alles
andere kann verzichtet werden nach Umbau.
Wegen mehreren Zeitvergleichen habe ich auch eine Idee, brachte mich
eure Flag Idee drauf, wenn ich zum Bsp. 3 Intervalle benötige, kann ich
diese in die Timer 0 Comp ISR schreiben und entweder ein Flag setzen mit
> Vergleich und nullen oder mit Modulo. Mit Modulo Vergleich benötige
ich keine zusätzlichen Variablen, nur noch so viele Flags wie ich
Intervalle benötige.
Zum Bsp.
1
ISR(TIMER0_COMPA_vect)
2
{
3
millis_count++;// der ms Zähler
4
5
if(millis_count%20){
6
Flag1setzen...// für Funktion die aller 20ms aufgerufen werden soll
7
}
8
if(millis_count%30){
9
Flag2setzen...// für Funktion die aller 30ms aufgerufen werden soll
10
}
11
if(millis_count%40){
12
Flag3setzen...// für Funktion die aller 40ms aufgerufen werden soll
13
}
14
}
Wäre das sinnvoll und Ressourcen schonend? In der Funktion frage ich
dann das Flag ab ob sie ausgeführt werden soll oder nicht, wenn ja,
setze ich das Flag zurück.
>Flag1setzen...// für Funktion die aller 20ms aufgerufen
7
>werdensoll
8
>}
9
>if(millis_count%30){
10
>Flag2setzen...// für Funktion die aller 30ms aufgerufen
11
>werdensoll
12
>}
13
>if(millis_count%40){
14
>Flag3setzen...// für Funktion die aller 40ms aufgerufen
15
>werdensoll
16
>}
17
>}
18
>
>> Wäre das sinnvoll und Ressourcen schonend? In der Funktion frage ich> dann das Flag ab ob sie ausgeführt werden soll oder nicht, wenn ja,> setze ich das Flag zurück.
vor allem: verzichte auf 16-Bit Modulo in einer ISR! das dauert!
Nochmal ein Versuch:
Wenn du nicht exakt 10/20/30 ms, sondern eher n*Größenordnung
Timer1-Zyklus (vielleicht ist der ja auch nicht in Stein gemeißelt, dann
das millis-Zählen am Ende des Comp1B. Da ist der Jitter-kritische Puls
durch.
Nico W. schrieb:> Dauert nicht nur. So ist sie auch falsch.> if (!(millis % 30)) ist wahrscheinlich das was gewünscht ist.
Vermutlich doch:
Im Abstand von 30ms ein Flag setzen, denn nur dann ist der Rest einer
Division durch 30 nicht ungleich 0.
Nur, wenn das die einzige Verwendung von millis ist, warum dann nicht
nur alle 10ms auf 1/2/3 zählen?
@ Veit Devil (devil-elec)
>Falls jemand die ATtiny841 Definitionsdatei benötigt, hängt dran.
Hier sind die PCINTx jetzt drin
>Jetzt muss ich natürlich fragen was der funktionale Unterschied ist>zwischen
Ist es aber nicht, weil das spezielle Timings von ISRs berücksichtigt
wird.
>für mich sieht das gleich aus.
Da muss man den gesamten Codeabschnitt betrachten.
Außerdem sollte man sich das Timing von COMPA und COMPB ISR vor Augen
halten.
In der kurzen Zeit zwischen COMPA und COMPB sind alle anderen ISRs
gesperrt und auch das normale Hauptprogramm sollte KEINE ISR-Sperren
durchführen, um den Jitter von COMPB zu minimieren. Ebenso dürfen in der
Zeit vom Hauptprogramm keine ISRs freigegeben werden.
1
voiduart0_putc(uint8_tdata)
2
{
3
uint8_ttmphead;
4
5
tmphead=(UART0_TxHead+1)&UART_TX_BUFFER_MASK;
6
7
while(tmphead==UART0_TxTail){
8
;/* wait for free space in buffer */
9
}
10
11
UART0_TxBuf[tmphead]=data;
12
UART0_TxHead=tmphead;
13
14
/*
15
Wenn hier TXB80 HIGH ist, befinden wir uns zeitlich vor der
16
COMPA-ISR. Eine kurze ISR-Sperre durch ATOMIC_BLOCK erzeugt keinen Jitter für COMPB.
17
*/
18
if(UCSR0B&(1<<TXB80)){
19
/* enable UDRE interrupt */
20
/*
21
Die COMPA-ISR kann aber JEDERZEIT aktiv werden, auch 1 CPU-Takt nach
22
dem erfolgreichen Vergleich! Also muss die endgültige Abfrage + Setzen von
23
UART0_UDRIE unter Interruptsperre erfolgen, damit eben nicht aus Versehen
24
COMPA schon aktiv wurde und UART0_UDRIE gelöscht ist!!! Wenn während der ISR-Sperre COMPA aktiv wird, wird in COMPA Jitter erzeugt, das ist aber unkritisch.
25
*/
26
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){// wegen ISR(TIMER1_COMPA_vect)
27
if(UCSR0B&(1<<TXB80)){
28
/*
29
Wenn TXB80 immer noch HIGH ist, können wir UART0_UDRIE sicher löschen und die Funktion verlassen, alles palletti!
-TXB80 beim 1. Vergleich ohne ISR-Sperre LOW war, dann befinden wir uns zeitlich zwischen COMPA und COMPB ISR. Während dieser Zeit darf keinerlei anderer Interrupt freigegeben werden, wir müssen auf das Ende von COMPB warten
41
42
-TXB80 beim 2. Vergleich mit ISR-Sperre LOW war, weil COMPA in der kurzen Zwischenzeit aktiv wurde.
43
44
Der doppelte Vergleich, einmal ohne und einmal mit ISR-Sperre wird gemacht, um keinen zusätzlichen Jitter für COMPB zu erzeugen, welche eine ISR-Sperre erzeugt. Denn wenn TXB80 schon beim 1. Vergleich LOW ist, wissen wir, daß gerade die heiße Sperrphase der Interrupts aktiv ist und wir keine ISR-Sperre durchführen dürfen. Wenn das beim 2. Vergleich passiert ist es unkritisch, denn das ist der ANFANG der Sperrphase, da ist noch genug Zeit bis zum COMPB Interrupt und es entsteht kein Jitter, denn der zeitliche Abstand TIMING_WINDOW verhindert das.
45
*/
46
// warte auf das Ende der ISR-Sperre
47
// reiner Lesezugriff ist atomar, daher kein atomic block nötig
48
while(!(UCSR0B&(1<<TXB80)));
49
50
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){// wegen ISR(TIMER1_COMPA_vect)
>Zum Abschluss noch ein Filmchen zur Jittermessung. Alles nur ohne millis>Abfrage.>Youtube-Video "OpenCam 20180105 112525">Man beachte die Zeiteinstellung von 500ns/DIV.>Bewegt sich alles innerhalb 1µs, ganz ganz selten scheint es einen>größeren Ausschlag zugeben.
Super! Die Messung wird noch ein wenig besser, denn du das Nachleuchten
im Oszi einschaltest (display persistance, da gibt es irgendwo ein
Menu).
>eure Flag Idee drauf, wenn ich zum Bsp. 3 Intervalle benötige, kann ich>diese in die Timer 0 Comp ISR schreiben und entweder ein Flag setzen mit>> Vergleich und nullen oder mit Modulo.
Modulo ist aber ungünstig, denn das braucht eine echte Division und die
ist auf einem AVR relativ langsam. Außerdem wird die meist mit einem
Funktionsaufruf gemacht, was in einer ISR zusätzlichen Aufwand fürs
Registersichern kostet. Zählen und Vergleichen ist deutlich schneller
und einfacher.
>Wäre das sinnvoll und Ressourcen schonend?
Nur ohne Modulo.
>In der Funktion frage ich>dann das Flag ab ob sie ausgeführt werden soll oder nicht, wenn ja,>setze ich das Flag zurück.
Genau.
Carl D. schrieb:> Nico W. schrieb:>> Dauert nicht nur. So ist sie auch falsch.>> if (!(millis % 30)) ist wahrscheinlich das was gewünscht ist.>> Vermutlich doch:> Im Abstand von 30ms ein Flag setzen, denn nur dann ist der Rest einer> Division durch 30 nicht ungleich 0.
Denke nicht.
1
28%30==28->!(28)==0
2
29%30==29->!(29)==0
3
30%30==0->!(0)==1
4
31%30==1->!(1)==0
Im Interrupt könnte man sowas basteln, wenn der pro ms einmal aufgerufen
wird:
Hallo,
das IC kenne ich, möchte ich aber nicht.
TXB80. Danke für die Erklärung, jetzt verstehe ich das auch.
Der Module Vergleich sollte eigentlich so aussehen. :-)
1
if(millis_count%20==0){
2
Flag1setzen...
3
}
Aber ihr habt recht mit euren neuen Hinweisen. Das Timer 0 Comp
Intervall ist nicht in Stein gemeißelt. Der Timer 0 kann ja auf das
kleinste benötigte Intervall eingestellt werden. Und mit der Methode
reicht ein Byte als Zähler. Größere Intervalle wie 255ms werden nicht
benötigt. Guter Hinweis. Muss aber auch sagen, dass sind alles
Optimierungen die ganz schön ans Eingemachte gehen. Hoffe ich versaue
das durch spätere Programmerweiterungen nicht wieder. Wobei nicht mehr
viel dazu kommt.
1
ISR(TIMER0_COMPA_vect)
2
{
3
staticuint8_tmillis_count=0;
4
staticuint8_tlast_1;
5
staticuint8_tlast_2;
6
staticuint8_tlast_3;
7
8
millis_count++;// der ms Zähler
9
10
if(millis_count-last_1>20){
11
last_1=millis_count;
12
Flag1setzen...
13
}
14
if(millis_count-last_2>30){
15
last_2=millis_count;
16
Flag2setzen...
17
}
18
if(millis_count-last_3>40){
19
last_3=millis_count;
20
Flag3setzen...
21
}
22
}
Oder wäre jeweils ein Vergleich auf 0 noch besser? Hatte mal wo gelesen
das dies noch 1-2 Takte sparen würde?
Dieter F. schrieb:> Falk B. schrieb:>> ber den Sinn und zweck derartig genauer Servopulse und 250kBaud für ne>> Modellbahn kann man streiten. Als sportliche Herausforderung in Punkto>> Software taugt es allemal und man kann es an anderer Stelle irgendwann>> sinnvoll einsetzen.>> Ja.
Nachdem Du nun Scheibchenweise weitergekommen bist und sicher die Bilder
Beitrag "Re: ISR Code schneller machen?"
noch im Hinterkopf hast - glaubst Du immer noch an die
Modellbahn-Version?
Sportlich würde ich eine hardwarenahe Lösung vorziehen - möglichst ohne
Jitter (wobei das bei 08/15-Modellbau-Servos keine Rolle spielen
dürfte). Interrupts sind eher hinderlich - obwohl es da auch
Möglichkeiten gibt, den Jitter (ohne den MC-Jitter) weitgehend zu
eliminieren.
Die 250 kB-Kommunikation im Hobby-Bereich kann ich nach wie vor nicht
nachvollziehen - genau wie die Festlegung auf den ATTiny841 mit 12 Pins
incl. Quarz und Reset - wenn auch noch Pins für Sensoren etc. geplant
sind.
Nur mal so - am Rande ... (und z. B. Open-DCC im Blickfeld) :-)
@Dieter F. (jim_quakenbush)
>noch im Hinterkopf hast - glaubst Du immer noch an die>Modellbahn-Version?
Ist mir eigentlich schnuppe, MIR ging es nur um den Beweis der
Jitterminimierung der Servosignale.
>Sportlich würde ich eine hardwarenahe Lösung vorziehen - möglichst ohne>Jitter
Kann man machen, erfordert aber eine Hardwareänderung.
@ Dieter F. (jim_quakenbush)
>> Den Lerneffekt aber nicht.>Mit komplettem Link aber schon :-)>https://learn.adafruit.com/16-channel-pwm-servo-dr...
Was lernt man da? Wie man 16 Sollwert per I2C an einen IC schickt?
C'mon!
Falk B. schrieb:> Kann man machen, erfordert aber eine Hardwareänderung.
Yep - analog des zusätzlichen Quarzes ... im Cent-Bereich, wobei es im
"Hobby-Bereich" auf 1 - 10 (oder wie auch immer) € nicht ankommen sollte
:-)
Falk B. schrieb:> Was lernt man da?
Exakt: Was man über die Arduino-Servo-Library lernen kann :-)
Nicht mein Fall und auch nicht meine Intension - aber gut abgelenkt :-)
Hallo,
Dieter, ich baue mir meine Steuerung genauso wie ich es möchte. Ich
möchte eben nicht irgendwo eine riesige Zentrale mit hunderten
Porterweiterungen stehen haben um dann von dort aus tausende Drähte
unter der Anlage zuverlegen. Ich möchte nah vor Ort die Slaves setzen
und kurze Wege zu dem was sie steuern oder abfragen sollen. Das ist
modern. Warum 841er? Habe ich auch schon mehrfach erklärt. Auf der
10x10cm Platine bekomme ich nicht mehr unter. Selbst wenn ich einen
größeren IC nehme, fehlt mir der Platz für die zusätzlichen
Klemmleisten. Komplett auf LED Anzeige möchte ich aber auch nicht
verzichten. 10x10 deshalb, weil die mich bei elecrow praktisch nichts
kosten im Vergleich zu anderen Größen. In Summe aller Kosten Nutzung
Rechnungen ist das für mich optimal. Das macht auch kein größerer IC und
dann weniger Platinen wieder gut. Die Platinenkosten explodieren
förmlich und im dümmsten Fall sitzt dann irgendwo eine Platine die kaum
genutzt wird. Nur wenige der möglichen Pins meine ich.
Ganz blöd bin ich nun auch nicht!
Die Frage "ob ich jetzt noch sicher bin ..." verstehe ich nun nicht
wirklich. Gerade jetzt wo der Jitter weg ist bzw. so klein ist, dass er
nicht stört. Hast du scheinbar überlesen. Das unterstelle ich dir mal im
positiven Sinne. Denn ich unterstelle niemanden was negatives den ich
nicht kenne.
Bei Vollbestückung kosten mich die Bauteile ca. 17,- Euro pro Platine +
2,- Euro Platine. Die erste Bauteilbestellung bei Mouser war für 10
Platinen ausgelegt. Für 30 Platinen ginge auf 15,- runter.
-----------------------------------------------------------------
Übrigens gehts jetzt sogar ohne Quarz. Der Code ist jetzt dermaßen
optimiert, dass selbst der größere Jitter vom internen RC die Servos
nicht animiert zu zucken. Wie geil ist das denn. :-)
ATtiny841, Quarz, Jittermessung, mit nachleuchten
https://youtu.be/HxyHFqIxtho
ATtiny841, interner RC, Jittermessung, mit nachleuchten
https://youtu.be/tvNKzUWxUtY
Veit D. schrieb:> Ich> möchte eben nicht irgendwo eine riesige Zentrale mit hunderten> Porterweiterungen stehen haben um dann von dort aus tausende Drähte> unter der Anlage zuverlegen.
Du weisst aber schon, dass DCC eine Bus-Lösung ist?
Veit D. schrieb:> Warum 841er? Habe ich auch schon mehrfach erklärt. Auf der> 10x10cm Platine bekomme ich nicht mehr unter.
Mir kommen die Tränen - der Chip verliert sich auf der Prototyp-Platine.
Veit D. schrieb:> Selbst wenn ich einen> größeren IC nehme, fehlt mir der Platz für die zusätzlichen> Klemmleisten.
Rundum - bei aktuell max. 10 Pins incl. Reset - da fühle ich mich leicht
veralbert :-) bei 10 * 10 cm
Veit D. schrieb:> In Summe aller Kosten Nutzung> Rechnungen ist das für mich optimal.
Im Hobby-Bereich - klar.
Veit D. schrieb:> Das macht auch kein größerer IC und> dann weniger Platinen wieder gut. Die Platinenkosten explodieren> förmlich und im dümmsten Fall sitzt dann irgendwo eine Platine kaum> genutzt wird.
dto.
Veit D. schrieb:> Bei Vollbestückung kosten mich die Bauteile ca. 17,- Euro pro Platine +> 2,- Euro Platine. Die erste Bauteilbestellung bei Mouser war für 10> Platinen ausgelegt. Für 30 Platinen ginge auf 15,- runter.
Hobby - klar.
Veit D. schrieb:> Übrigens gehts jetzt sogar ohne Quarz. Der Code ist jetzt dermaßen> optimiert, dass selbst der größere Jitter vom internen RC die Servos> nicht animiert zu zucken. Wie geil ist das denn. :-)
Für jemanden der große Chargen plant - Supergeil :-)
Nico W. schrieb:> Carl D. schrieb:>> Nico W. schrieb:>>> Dauert nicht nur. So ist sie auch falsch.>>> if (!(millis % 30)) ist wahrscheinlich das was gewünscht ist.>>>> Vermutlich doch:>> Im Abstand von 30ms ein Flag setzen, denn nur dann ist der Rest einer>> Division durch 30 nicht ungleich 0.
.
> Denke nicht.>
1
>28%30==28->!(28)==0
2
>29%30==29->!(29)==0
3
>30%30==0->!(0)==1
4
>31%30==1->!(1)==0
5
>
Ja stimmt, irgendwo hatte ich das Ausrufezeichen gesehen, vermutlich
weil ich das gar nicht anders erwartet hatte.
Veit D. schrieb:> Warum 841er? Habe ich auch schon mehrfach erklärt. Auf der> 10x10cm Platine bekomme ich nicht mehr unter
echt jetzt?
da würde ich doch locker auch den ATmega328p sehen als DIL oder als SMD
auch den m1284p nach Bedarf.
Kosten bei Hobby? die CPU machts da ja wohl nicht
@Veit Devil (devil-elec)
>nicht animiert zu zucken. Wie geil ist das denn. :-)
TOP!
>ATtiny841, Quarz, Jittermessung, mit nachleuchten>Youtube-Video "Oszi Restjittermessung mit nachleuchten"
Hier sieht man schön die diskreten Linien im Jitter, weil der Quarz sehr
stabil ist.
>ATtiny841, interner RC, Jittermessung, mit nachleuchten>Youtube-Video "Oszi Jitter Messung mit nachleuchten"
Beim RC-Oszillator verschwimmt alles. Trotzdem noch relativ gut.
@Dieter F. (jim_quakenbush)
>Falk B. schrieb:>> TOP!>Darf ich das als kostenloses Beratungs-Angebot für künftige Projekte>verstehen?
???
Meine Kommentare hier im Forum sind für alle kostenlos, wenn gleich
sicher nicht umsonst ;-)
Falk B. schrieb:> Meine Kommentare hier im Forum sind für alle kostenlos, wenn gleich> sicher nicht umsonst ;-)
d'accord :-) - manches Mal halt nur für Andere lukrativ ...
Joachim B. schrieb:> Veit D. schrieb:>> Warum 841er? Habe ich auch schon mehrfach erklärt. Auf der>> 10x10cm Platine bekomme ich nicht mehr unter>> echt jetzt?>> da würde ich doch locker auch den ATmega328p sehen als DIL oder als SMD> auch den m1284p nach Bedarf.>> Kosten bei Hobby? die CPU machts da ja wohl nicht
Hallo,
bitte alles im Zusammenhang lesen und verstehen, sonst macht das alles
keinen Sinn. Zuerst müsste mehr Platz für weitere Klemmleisten
geschaffen werden. Hier sehe ich keine Chance. Erst wenn das möglich
wäre, macht ein größer µC Sinn.
Veit D. schrieb:> bitte alles im Zusammenhang lesen und verstehen,
hatte ich, deine liegenden R verbrauchen viel Platz, stehend würde auch
gehen, oder gar SIL Array oder wenns seriell sein muss als DIL Arrays.
Einige KerKos könnten auch in SMD sein.
Die Jumper mit 3 Reihen könnten auch DIP switch sein?
spart alles etwas Platz
@Veit Devil (devil-elec)
>das ändert jetzt was am Platz der Klemmleisten außen herum?
Nichts. Trotzdem herrscht auf deiner Platine gähnende Leere. Wenn man
auf moderate SMD-Bauteile umschwenkt, ist mindestens ein ATmega88/328 im
TQFP32 Gehäuse drin. Man muss ja nicht auf 0402er Kondensatoren gehen,
0805 geht hier auch locker. Dann bleibt immer noch Platz für ein
Mäusefußballfeld ;-)
Deine 3x1 Jumper kann man ins normale 2,54mm Raster ohne Lücke setzen,
spart Platz und man kann einfach eine passende 3reihige Stiftleiste
einlöten.
Und selbst wenn man bei THT Bauteilen bleiben will ist da Platz für
einen ATmega328 im DIL28 Gehäuse. Das kriegt man auch verdrahtet,
schließlich hast du 2 Lagen + VIAs, das war vor 30 Jahren selbst im
Massenkonsumerbereich purer Luxus! ;-)
Da wäre auch Platz für 2x 8-Fach-Mux um bis zu 16 Servos per HW ohne
Softwareverränkungen jitterfrei bekommt. Aber vielleicht lernt ja die
Version 3 etwas aus der Software V2.2
Carl D. schrieb:> Da wäre auch Platz für 2x 8-Fach-Mux um bis zu 16 Servos per HW ohne> Softwareverränkungen jitterfrei bekommt
Ja - da gibt es Beispiele.
Aber - unsportlich :-) - wobei ich das bei einem Pin mit 16 Servos und
20 ms "Fenster" gerne sehen würde; (ein Pin bei max. 8 Servos mit max.
2,5 ms/Servo wäre so meine Vorstellung) ...
Aber - zeig mal :-)
Hallo,
aus Eurer Sicht mag die Platine leer sein, aus meiner Sicht ist die
schon gut gefüllt. Für Leiterbahnen muss ja auch Platz sein. Und solange
ich außen herum nicht mehr Platz habe, macht es keinen Sinn innen mehr
Platz zu schaffen. Das sollte einleuchten. Zudem THT Bauteile auch
Vorteile beim routen haben. Ich werde nochmal darüber nachdenken, mal
sehen was mir noch so einfällt, vielleicht verabschiede ich mich von den
praktischen Steckklemmleisten, nur dann wäre mehr Platz. Es ist ja nicht
so als wenn ich das mal soeben ohne Überlegungen hingerotzt hätte. Dafür
sieht das viel zu gut aus. :-)
Auf der anderen Seite hatte ich auch schon angeführt, macht es keinen
echten Sinn mehr Pins pro Slave zu haben, sonst ziehe ich wieder endlose
Drähte unter der Anlage von A nach B.
Zurück zur Softwarethematik.
Auch auf die Gefahr hin das dieses Thema ein heißes Eisen ist.
Was war falsch daran den Code als C++ kompilieren zulassen?
C++ wird laut meiner Meinung ständig weiterentwickelt. Version C++ 18
steht in den Startlöchern. C ist mit Version C11 irgendwie stehen
geblieben.
Zudem ich angefangen habe das Buch "C++ Die Programmiersprache" von
Bjarne Stroustrup zu lesen. Hier stehen sehr informative Dinge drin.
Irgendwann möchte auch Templates usw. anwenden.
@ Veit Devil (devil-elec)
>Was war falsch daran den Code als C++ kompilieren zulassen?
Sagte ich bereits.
Beitrag "Re: ISR Code schneller machen?">C++ wird laut meiner Meinung ständig weiterentwickelt. Version C++ 18>steht in den Startlöchern. C ist mit Version C11 irgendwie stehen>geblieben.
Wenn du das "alte C" einigermaßen gut beherrscht, kannst du fast alle
machen.
>Zudem ich angefangen habe das Buch "C++ Die Programmiersprache" von>Bjarne Stroustrup zu lesen. Hier stehen sehr informative Dinge drin.>Irgendwann möchte auch Templates usw. anwenden.
Auf kleinen Mikrocontrollern? Vergiss es! Du kannst dir bestenfalls in
Arduino-Manier ein paar nette Klassen mit Vererbung und bissel
Polymophie zusammenbastlen, das reicht locker, um sehr gute,
leistungsfähige Programme zu entwickeln.
Die Gefahr für dich und andere Anfänger/Fortgeschritte liegt bei C++
schlicht im deutlich größeren Funktionsumfang sowie der deutlich
größeren Komplexität. Da kann man sich ganz fix verheddern und
beschäftigt sich dann nur noch mit dem Werkzeug C++ anstatt dem
eigentlichen Problem.
Uund wie immer gilt. SOLIDE Grundlagen sind durch NICHTS zu ersetzen.
Grundlagen lernt man aber eher mit einfachen Werkzeugen wie C und nicht
mit C++ oder Java. Das kleine 1x1 der Mathematik lernt man auch nicht
mit dem Smartphone, im GEGENTEIL!
Veit D. schrieb:> Zurück zur Softwarethematik.> Auch auf die Gefahr hin das dieses Thema ein heißes Eisen ist.
In der Tat ;-)
> Was war falsch daran den Code als C++ kompilieren zulassen?
Hatte ich bereits geschrieben: ggf. UB bei unions.
Ansonsten: m.E. nur Vorteile!
> C++ wird laut meiner Meinung ständig weiterentwickelt.
Ist wirklich so.
> Version C++ 18> steht in den Startlöchern.
Nein. C++20. Der Release-Zyklus ist ab C++11 alle 3 Jahre.
Falk B. schrieb:> Auf kleinen Mikrocontrollern? Vergiss es!
Falsch!
Richtig gemacht, d.h. eben nicht so wie Arduino, ist es definitiv
zero-overhead.
> Du kannst dir bestenfalls in> Arduino-Manier ein paar nette Klassen mit Vererbung und bissel> Polymophie zusammenbastlen,
Wenn möglich sollte man dynamische Polymorphie vermeiden. Man kann
(meistens) alles in statische Polymorphie umformen lassen, d.h mit
Template-Meta-Programmierung. Auf die Art spart man sich V-Tables im Ram
und zusätzliche Indirektionen.
> Die Gefahr für dich und andere Anfänger/Fortgeschritte liegt bei C++> schlicht im deutlich größeren Funktionsumfang sowie der deutlich> größeren Komplexität.
Was m.E. sehr wichtig ist, aber von den meisten Leuten übersehen wird,
ist, dass es ohne Overhead möglich ist, sich ein "reiches" Typsystem zu
schaffen, mit dem man schon zur Compile-Zeit viele Fehler ausschließen
kann. Leider denken viele bei C++ zunächst an OOP im klassichen Sinn,
also dyn. Polymorphie und Liskov. Das ist aber in der µC-Welt nur
nachrangig. Viel wichtiger ist stat. Polymorphie (templates) und
Typ-Algebren/-Systeme (Template-Meta-Programmierung). Zugegeben: das
lernt man nicht in 21 Tagen und es weicht vom gängigen Programmierschema
eben stark ab.
> Uund wie immer gilt. SOLIDE Grundlagen sind durch NICHTS zu ersetzen.> Grundlagen lernt man aber eher mit einfachen Werkzeugen wie C und nicht> mit C++ oder Java. Das kleine 1x1 der Mathematik lernt man auch nicht> mit dem Smartphone, im GEGENTEIL!
Wer C++ wirklich lernen will, und das heißt dann neben der OOP auch
funktionale und generische Programmierung, der sollte m.E. zunächst gar
nicht C lernen ("stop teaching C") und er sollte nicht versuchen, C++ in
Verbindung mit µC zu lernen. C++ Stärke ist die Abstraktionsmöglichkeit,
da ist ein µC zunächst nur hinderlich. Das lernt man mit einer guten IDE
am PC - und natürlich mit guten Büchern, die man allerdings auch lesen
muss ;-)
Wilhelm M. schrieb:> Was m.E. sehr wichtig ist, aber von den meisten Leuten übersehen wird,> ist, dass es ohne Overhead möglich ist, sich ein "reiches" Typsystem zu> schaffen, mit dem man schon zur Compile-Zeit viele Fehler ausschließen> kann. Leider denken viele bei C++ zunächst an OOP im klassichen Sinn,> also dyn. Polymorphie und Liskov. Das ist aber in der µC-Welt nur> nachrangig. Viel wichtiger ist stat. Polymorphie (templates) und> Typ-Algebren/-Systeme (Template-Meta-Programmierung). Zugegeben: das> lernt man nicht in 21 Tagen und es weicht vom gängigen Programmierschema> eben stark ab.
Sei mir nicht böse - aber was will ich ich auf einem (Hardare-nahen) MC
mit C++. Polymorphie etc. Diese sind nicht unbedingt angebracht auf
einem 8-Bit-Prozessor - oder?
Dieter F. schrieb:> Wilhelm M. schrieb:>> Was m.E. sehr wichtig ist, aber von den meisten Leuten übersehen wird,>> ist, dass es ohne Overhead möglich ist, sich ein "reiches" Typsystem zu>> schaffen, mit dem man schon zur Compile-Zeit viele Fehler ausschließen>> kann. Leider denken viele bei C++ zunächst an OOP im klassichen Sinn,>> also dyn. Polymorphie und Liskov. Das ist aber in der µC-Welt nur>> nachrangig. Viel wichtiger ist stat. Polymorphie (templates) und>> Typ-Algebren/-Systeme (Template-Meta-Programmierung). Zugegeben: das>> lernt man nicht in 21 Tagen und es weicht vom gängigen Programmierschema>> eben stark ab.>> Sei mir nicht böse - aber was will ich ich auf einem (Hardare-nahen) MC> mit C++. Polymorphie etc. Diese sind nicht unbedingt angebracht auf> einem 8-Bit-Prozessor - oder?
Sorry, hast Du das obige gelesen ... und verstanden?
Welche Art von Polymorphie meinst Du(!) denn?
Wilhelm M. schrieb:> Sorry, hast Du das obige gelesen ... und verstanden?>> Welche Art von Polymorphie meinst Du(!) denn?
Erkläre es bitte mal :-) - bin ich wahrscheinlich zu unbedarft ...
Hallo,
>> Zurück zur Softwarethematik.>> Auch auf die Gefahr hin das dieses Thema ein heißes Eisen ist.> In der Tat ;-)
solange es sachlich bleibt wie bis jetzt sollten alle damit kein Problem
haben.
Wenn in C keine Klassen mit Vererbung möglich ist, dann habe ich ein
Problem. Denn ich habe eine Klasse mit Vererbung schon fertig. Das müßte
ich demzufolge zurück in Funktionen "zerlegen"?
Wilhelm. Ich merke du bist C++ Programmierer. Ich lese auch daraus, dass
C++ nur Sinn bei PC Anwendungen bringt. Da ich nur meine µC
programmieren werde, macht da aus deiner Sicht C++ noch Sinn? Weil ich
bin auch der Meinung das man C und C++ beim erlernen nicht mischen
sollte. Momentan stecke ich dummerweise dazwischen ohne es richtig
bemerkt zu haben und muss mich entscheiden um irgendwann programmieren
zu können. Egal ob das dann C oder C++ wird.
Veit D. schrieb:> Hallo,>>>> Zurück zur Softwarethematik.>>> Auch auf die Gefahr hin das dieses Thema ein heißes Eisen ist.>>> In der Tat ;-)>> solange es sachlich bleibt wie bis jetzt sollten alle damit kein Problem> haben.>> Wenn in C keine Klassen mit Vererbung möglich ist, dann habe ich ein> Problem. Denn ich habe eine Klasse mit Vererbung schon fertig. Das müßte> ich demzufolge zurück in Funktionen "zerlegen"?>> Wilhelm. Ich merke du bist C++ Programmierer. Ich lese auch daraus, dass> C++ nur Sinn bei PC Anwendungen bringt.
Habe ich mich oben so undeutlich ausgedrückt. C++ macht m.E. auf µC
absolut Sinn! Ich programmieren nur in C++. Aber eben in einer
speziellen Art - hatte ich oben kurz angerissen. Wie gesagt, der
Schlüssel zum Erfolg liegt in stat. Polymorphie, d.h. generischer
Programmierung mit templates. Und eine besondere Variante sind sog.
Meta-Funktionen, die die wiederum der Template-Meta-Programmierung
bedient.
> Da ich nur meine µC> programmieren werde, macht da aus deiner Sicht C++ noch Sinn?
Ja.
Wilhelm M. schrieb:> Habe ich mich oben so undeutlich ausgedrückt. C++ macht m.E. auf µC> absolut Sinn! Ich programmieren nur in C++. Aber eben in einer> speziellen Art - hatte ich oben kurz angerissen. Wie gesagt, der> Schlüssel zum Erfolg liegt in stat. Polymorphie, d.h. generischer> Programmierung mit templates. Und eine besondere Variante sind sog.> Meta-Funktionen, die die wiederum der Template-Meta-Programmierung> bedient.
Ja :-)
@Wilhelm M. (wimalopaan)
>> Auf kleinen Mikrocontrollern? Vergiss es!>Falsch!>Richtig gemacht, d.h. eben nicht so wie Arduino, ist es definitiv>zero-overhead.
Kann sein, weiß ich nicht, hab von C++ nicht wirklich Ahnung ;-)
Das ist aber gar nicht der Punkt.
>Wenn möglich sollte man dynamische Polymorphie vermeiden. Man kann>(meistens) alles in statische Polymorphie umformen lassen, d.h mit>Template-Meta-Programmierung. Auf die Art spart man sich V-Tables im Ram>und zusätzliche Indirektionen.
Glaubst du ernsthaft, daß der OP auf DEM Level ist, um mit diesem Zeug
was anfangen kann? Als Hobbybastler?
>> Die Gefahr für dich und andere Anfänger/Fortgeschritte liegt bei C++>> schlicht im deutlich größeren Funktionsumfang sowie der deutlich>> größeren Komplexität.>Was m.E. sehr wichtig ist, aber von den meisten Leuten übersehen wird,>ist, dass es ohne Overhead möglich ist, sich ein "reiches" Typsystem zu>schaffen, mit dem man schon zur Compile-Zeit viele Fehler ausschließen>kann.
Dito! Das berfordert in der Situation mehr als es hilft!
>Leider denken viele bei C++ zunächst an OOP im klassichen Sinn,>also dyn. Polymorphie und Liskov. Das ist aber in der µC-Welt nur>nachrangig. Viel wichtiger ist stat. Polymorphie (templates) und>Typ-Algebren/-Systeme (Template-Meta-Programmierung). Zugegeben: das>lernt man nicht in 21 Tagen und es weicht vom gängigen Programmierschema>eben stark ab.
AHA!
>Wer C++ wirklich lernen will,
Will das der OP? Braucht das der OP? Nein!
>Verbindung mit µC zu lernen. C++ Stärke ist die Abstraktionsmöglichkeit,>da ist ein µC zunächst nur hinderlich.
AHA!
> Das lernt man mit einer guten IDE>am PC - und natürlich mit guten Büchern, die man allerdings auch lesen>muss ;-)
Und durcharbeiten = denken!
C++ ist für die meisten uCs und Hobbybastler genauso daneben wie
Assembler! Assembler kann zu wenig, C++ viel zu viel!
@Veit Devil (devil-elec)
>Wenn in C keine Klassen mit Vererbung möglich ist,
In C gab es noch nie Klassen und Vererbung, nur schnöde Funktionen.
> dann habe ich ein>Problem. Denn ich habe eine Klasse mit Vererbung schon fertig.
Wirklich? Zeig mal.
> Das müßte ich demzufolge zurück in Funktionen "zerlegen"?
Kann sein.
>sollte. Momentan stecke ich dummerweise dazwischen ohne es richtig>bemerkt zu haben und muss mich entscheiden um irgendwann programmieren>zu können. Egal ob das dann C oder C++ wird.
In der Tat!
Hallo,
so sieht das aus. Beim programmieren stehe ich sicherlich noch am
Anfang, dass gebe ich gern zu. Den "normalen" Encoder (nicht den für
Alps) brauche ich mehrfach pro µC. Der Gray Code basiert auf dem von
Peter Dannegger.
Falk B. schrieb:>>Wenn möglich sollte man dynamische Polymorphie vermeiden. Man kann>>(meistens) alles in statische Polymorphie umformen lassen, d.h mit>>Template-Meta-Programmierung. Auf die Art spart man sich V-Tables im Ram>>und zusätzliche Indirektionen.>> Glaubst du ernsthaft, daß der OP auf DEM Level ist, um mit diesem Zeug> was anfangen kann? Als Hobbybastler?
Nein, derzeit kann er nicht mal richtig C. Aber das ist nicht
entscheidend: ich traue es zunächst mal jedem zu ;-)
>>Was m.E. sehr wichtig ist, aber von den meisten Leuten übersehen wird,>>ist, dass es ohne Overhead möglich ist, sich ein "reiches" Typsystem zu>>schaffen, mit dem man schon zur Compile-Zeit viele Fehler ausschließen>>kann.>> Dito! Das berfordert in der Situation mehr als es hilft!
Und genau das ist m.E. ein Trugschluß: Programme, die nicht compilieren,
weil sie fehlerhaft sind, sind besser als Programme, die compilieren und
zur Laufzeit fehlerhaft sind.
>>Leider denken viele bei C++ zunächst an OOP im klassichen Sinn,>>also dyn. Polymorphie und Liskov. Das ist aber in der µC-Welt nur>>nachrangig. Viel wichtiger ist stat. Polymorphie (templates) und>>Typ-Algebren/-Systeme (Template-Meta-Programmierung). Zugegeben: das>>lernt man nicht in 21 Tagen und es weicht vom gängigen Programmierschema>>eben stark ab.>>Wer C++ wirklich lernen will,>> Will das der OP? Braucht das der OP? Nein!
Ob er es braucht, weiß ich nicht. Aber wenn er es will: warum nicht.
Doch sollte er dabei völlig losgelöst von irgendwelchen µC
Fragestellungen es zunächst in einer normalen Laufzeitumgebung (aka PC)
erlernen.
>>Verbindung mit µC zu lernen. C++ Stärke ist die Abstraktionsmöglichkeit,>>da ist ein µC zunächst nur hinderlich.>> AHA!
Die Betonung lag auf: zunächst! Hat man diese Möglichkeiten erst einmal
begriffen, kann man sie sehr gewinnbringend auch auf dem µC einsetzen
(s.o. reiches Typsystem).
>> Das lernt man mit einer guten IDE>>am PC - und natürlich mit guten Büchern, die man allerdings auch lesen>>muss ;-)>> Und durcharbeiten = denken!
Ganz genau: und die Menge der guten(!) Bücher ist sehr begrenzt.
> C++ ist für die meisten uCs und Hobbybastler genauso daneben wie> Assembler! Assembler kann zu wenig, C++ viel zu viel!
Ich denke, man sollte grob Assembler lesen können. Schreiben braucht man
es m.E. nicht.
Dieter F. schrieb:> Carl D. schrieb:>> Da wäre auch Platz für 2x 8-Fach-Mux um bis zu 16 Servos per HW ohne>> Softwareverränkungen jitterfrei bekommt>> Ja - da gibt es Beispiele.>> Aber - unsportlich :-) - wobei ich das bei einem Pin mit 16 Servos und> 20 ms "Fenster" gerne sehen würde; (ein Pin bei max. 8 Servos mit max.> 2,5 ms/Servo wäre so meine Vorstellung) ...>> Aber - zeig mal :-)
Bekanntlich hat der Timer1 2 Compare-Kanäle, deshalb auch 2x 1:8 Mux.
Veit D. schrieb:> Hallo,>> so sieht das aus. Beim programmieren stehe ich sicherlich noch am> Anfang, dass gebe ich gern zu. Den "normalen" Encoder (nicht den für> Alps) brauche ich mehrfach pro µC. Der Gray Code basiert auf dem von> Peter Dannegger.
Was sind denn Deiner Ansicht nach Getter? Vllt sollte man sie besser
Beobachter nennen (nein, ich meine nicht das Observer-Pattern). Hast
schon mal die verschiedenen Bedeutungen von const gehört?
Möchtest Du Deine Klasse mit dyn. Polymorphie verwenden? Dann ist sie
klassisch falsch.
Aber ich glaube, dieser Thread sollte nicht als Grundkurs C++
"missbraucht" werden. Vllt machst Du einen neuen auf?
@Veit Devil (devil-elec)
> GrayEncoder.h (1,73 KB, 0 Downloads) | Codeansicht> GrayEncoder.cpp (1,54 KB, 0 Downloads) | Codeansicht
Soso, ein "Klasse". ;-)
Das ist un gefähr so, wie wenn ich ne Tütensuppe koche und mich dann als
"Koch" bezeichnen würde . . .
>so sieht das aus. Beim programmieren stehe ich sicherlich noch am>Anfang, dass gebe ich gern zu.
Eben darum ist C++ gar nichts für dich.
> Den "normalen" Encoder (nicht den für>Alps) brauche ich mehrfach pro µC. Der Gray Code basiert auf dem von>Peter Dannegger.
Ja und? Wo braucht man da C++? Das kriegt man mit plain, old C SPIELEND
hin! Sogar in Mehrfachausführung!
Beitrag "Re: Mehrere Drehencoder gleichzeitig abfragen"
@Wilhelm M. (wimalopaan)
>Aber ich glaube, dieser Thread sollte nicht als Grundkurs C++>"missbraucht" werden. Vllt machst Du einen neuen auf?
Weise Worte. Danke.
Falk B. schrieb:> Eben darum ist C++ gar nichts für dich.
Warum so abfällig?
Ich bin nur der Meinung, er sollte C++ eben nicht versuchen in µC
Anwendungen zu erlernen (s.o.).
>> Den "normalen" Encoder (nicht den für>>Alps) brauche ich mehrfach pro µC. Der Gray Code basiert auf dem von>>Peter Dannegger.>> Ja und? Wo braucht man da C++? Das kriegt man mit plain, old C SPIELEND> hin! Sogar in Mehrfachausführung!
Ich denke, dass weiß er. Es geht ihm um den Lerneffekt ...
@ Wilhelm M. (wimalopaan)
>> Eben darum ist C++ gar nichts für dich.>Warum so abfällig?
Weil es so ist! Gibt man einem 3 Jährigen, der Spaß an Musik hat, ein 50
Mann Orchester?
>Ich bin nur der Meinung, er sollte C++ eben nicht versuchen in µC>Anwendungen zu erlernen (s.o.).
Er will aber nur uCs programmieren!
Kennst du keinen Rückwärtsgang?
>> Ja und? Wo braucht man da C++? Das kriegt man mit plain, old C SPIELEND>> hin! Sogar in Mehrfachausführung!>Ich denke, dass weiß er. Es geht ihm um den Lerneffekt ...
Das glaube ich nicht. Er ist verliebt in den "SchickMicki" von C++.
Ist ja auch viel cooooler und plain old C was für Doofe.
Würde ich mal so interpretieren.
Wilhelm M. schrieb:> Falk B. schrieb:>>> Eben darum ist C++ gar nichts für dich.>> Warum so abfällig?>> Ich bin nur der Meinung, er sollte C++ eben nicht versuchen in µC> Anwendungen zu erlernen (s.o.).
.
>>> Den "normalen" Encoder (nicht den für>>>Alps) brauche ich mehrfach pro µC. Der Gray Code basiert auf dem von>>>Peter Dannegger.>>>> Ja und? Wo braucht man da C++? Das kriegt man mit plain, old C SPIELEND>> hin! Sogar in Mehrfachausführung!>> Ich denke, dass weiß er. Es geht ihm um den Lerneffekt ...
Es spricht doch nichts dagegen einfache Klassen-Hierachien zu bauen.
Blos weil das in C noch geht, soll man es in C++ nicht machen? Wie
sonst, wenn nicht mit einfachen Beispielen soll man Neues lernen. Was
bei "Lernen an Kompliziertem" rauskommt, kann man hier ja lesen:
Ablehnung.
@ Carl Drexler (jcw2)
>Es spricht doch nichts dagegen einfache Klassen-Hierachien zu bauen.>Blos weil das in C noch geht, soll man es in C++ nicht machen?
Klassen in C? Hab ich was verpaßt?
> Wie>sonst, wenn nicht mit einfachen Beispielen soll man Neues lernen.
Der OP sollte erstmal ein paar mehr solide Grundlagen lernen als sich
mit "SchickiMicki" abzulenken.
> Was>bei "Lernen an Kompliziertem" rauskommt, kann man hier ja lesen:>Ablehnung.
Zu Recht. Lernen tut man schrittweise erstmal an einfachen Beispielen
mit stiegendem Schwierigkeitsgrad. Man fängt in der 1.Klasse an und
nicht beim Abitur.
Hallo,
Getter Methoden sind doch Standard um irgendwelche Werte abzuholen etc.
Nur warum das obige keine Klasse sein soll verstehe ich nicht. Was ist
"plain"? Noch nie davon gehört. Habe mal gegoogelt. Gibts in C gar
nicht.
@Veit Devil (devil-elec)
>ist der Fall wo klar. Nur warum das obige keine Klasse sein soll>verstehe ich nicht.
Das ist bestenfalls ein Grundgerüst einer Klasse. Aber für die Lösung
deiner Aufgabe, mehreren Drehgeber abzufragen braucht man das
Werkzeug "Klasse" nicht. Ist ungefähr so wie wenn man sagt, man braucht
unbedingt ein Smartphone mit Navi, um von Dresden nach Berlin zu fahren
8-0
> Was ist "plain"? Noch nie davon gehört. Habe mal>gegoogelt. Gibts in C gar nicht.
Willst du mich verarschen? "plain" ist was es im Englischen immer war.
"einfach"
plain, old C ist einfaches, altes C. ;-)
Hallo,
Falk, sorry, ich möchte niemanden verarschen, war nur dermaßen mit all
den C vs. C++ beschäftigt, dass ich nicht mehr unterscheiden konnte.
Naja, irgendwo hat unser C Liebhaber auch recht. Letztenendes macht
jeder Compiler daraus Assembler bzw. dann Maschinencode. Nur sind
Hochsprachen einfacher zu erlernen und zu lesen. Man muss sich nicht um
jedes Bit selbst kümmern. Meine persönliche Meinung. Zudem ich schon
soweit in C stecke, dass ich mir bestimmte Dinge nicht vorstellen kann
wie man die in Assembler schreiben soll mit dem begrenzten Befehlssatz.
Dabei muss man wie er schon sagte komplett anders denken, was mir jetzt
schwer fallen würde komplett umzudenken. Zudem dass dann auch um Faktor
x mehr Codezeilen werden, schon deshalb leidet die Lesbarkeit.
@Veit Devil (devil-elec)
>Naja, irgendwo hat unser C Liebhaber auch recht.
Hat er nicht.
> Letztenendes macht>jeder Compiler daraus Assembler bzw. dann Maschinencode.
Darum geht es gar nicht.
> Nur sind>Hochsprachen einfacher zu erlernen und zu lesen.
Darum schon eher! Der entscheidende Vorteil von Hochsprachen ist, daß
sich der Compiler um viel Verwaltungskram kümmert, Speicheraufteilung,
Variablenverwaltung, Typprüfung etc. Krümelkram, der gut automatisierbar
ist. Durch die größere Abstraktion kann man auch viel komplexere
Probleme viel leichter und flexibler angehen! C ist, wenn man es
halbwegs gescheit nutzt, plattformunabhängig. Assembler nie im Leben.
> Man muss sich nicht um>jedes Bit selbst kümmern. Meine persönliche Meinung.
Eben.
> Zudem ich schon>soweit in C stecke, dass ich mir bestimmte Dinge nicht vorstellen kann>wie man die in Assembler schreiben soll mit dem begrenzten Befehlssatz.
Man muss jeden Krümlkram von der Pike auf neu erfinden. Viel Spaß!
Hallo,
da hier sowieso die Fronten aufeinander prallen, macht eine weitere
Diskussion zwischen Assembler und C keinen Sinn. Ich denke jeder soll in
der Sprache programmieren die für ihn am leichtestens erlernbar ist. Man
hat ja freie Wahl. Ich sehe es auch nicht für schlimm an, wenn man aus
Speichermangel einen größeren µC nimmt. Warum manche Ausführungen so arg
knapp ausgestattet sind weiß wohl nur der Hersteller.
Für mich nehme ich mit, ich muss mich alleine zwischen C oder C++
entscheiden.
Ich bedanke mich bei allen für die aufschlussreiche Unterhaltung zum
Thema Programmiersprachen. Ich werde den Thread nochmal überfliegen,
paar Themen hatte ich bewusst zurückgestellt. Falls die noch wichtig
sind greife ich diese auf. Ansonsten war es das erstmal aus meiner
Sicht.
Tschau
Veit
Hallo,
die letzten beiden gelöschten konnte ich nicht mehr lesen. Naja, ich
werde es überleben. Falls die provokant gegen meine Person gerichtet
waren, dann vielleicht besser so.
Die beiden gelöschten darüber darüber hatten wirklich keinen Grund zur
Klage. War alles sachlich gewesen. Weiß auch nicht warum. Den letzten
Beitrag von Dieter hätte er in dem Zuge dann mit löschen können.
Ansonsten gibts aus dem Thread wirklich viel zum mitnehmen worüber ich
mir Gedanken machen kann und sollte. Man muss nicht immer einer Meinung
sein, man muss nur zuhören, den anderen verstehen wollen, mitdenken,
sachlich bleiben. Wenn das alle machen hat jeder etwas davon. Aus meiner
Sicht ist alles i.O.
Tschau
Veit
Wilhelm M. schrieb:> Ganz genau: und die Menge der guten(!) Bücher ist sehr begrenzt.
Ich möchte den (interessanten) Thread ja nicht hijacken, aber wenn sie
so begrenzt ist, dann wäre doch Platz für ein oder zwei Beispiele, oder?
Oder im Wiki...
np r. schrieb:> Wilhelm M. schrieb:>> Ganz genau: und die Menge der guten(!) Bücher ist sehr begrenzt.> Ich möchte den (interessanten) Thread ja nicht hijacken, aber wenn sie> so begrenzt ist, dann wäre doch Platz für ein oder zwei Beispiele, oder?> Oder im Wiki...
Dafür erscheint es mir am besten, Du / jemand stellt eine konkrete Frage
;-)
Und auch nicht in diesem Thread, sondern mach dazu einen eigenen auf.
Wenn ich den Thread dann entdecke und Zeit habe, werde ich gerne
antworten und eigene Vorschläge machen. Auf der anderen Seite gibt es
hier ja schon einige andere Threads, in denen auch ich schon ne ganze
Menge inkl. Beispiele gepostet habe. Vielleicht einfach mal da anfangen
...
Wilhelm M. schrieb:> sondern mach dazu einen eigenen auf.
Nein.
Warum nicht? Weil:
Wilhelm M. schrieb:> Auf der anderen Seite gibt es hier ja schon einige andere Threads, in> denen auch ich schon ne ganze Menge inkl. Beispiele gepostet habe.
jeder Thread in diesem Forum, in dem jemand nach "guten" Büchern oder
Wegen fragt, um C++ "richtig" (tm) zu erlernen, die Gefahr birgt, in
einen Flame-War C vs. C++ auszuarten. Und Java, Assembler oder Tofu ist
sowieso viel besser.
Der Grund, dass ich überhaupt gefragt habe, ist dieser:
Du hast mehrfach "gute Bücher" als Notwendigkeit bezeichnet. Ohne
irgendeines beim Namen zu nennen, ist diese "Hilfestellung" für den TO
und alle Mitleser wertlos und nur eine "Selbstbeweihräucherung".
Edit: Wobei ich sagen muss, dass dieser Thread für dieses Forum
überraschend friedlich und konstruktiv verlaufen ist. Kompliment!
np r. schrieb:>> Edit: Wobei ich sagen muss, dass dieser Thread für dieses Forum> überraschend friedlich und konstruktiv verlaufen ist. Kompliment!
Es macht ja auch keinen Sinn mit bestimmten Teilnehmern diskutieren zu
wollen, in der Zeit beschäftige ich mich lieber mit dem
Diskussionsobjekt.
np r. schrieb:> Wilhelm M. schrieb:>> sondern mach dazu einen eigenen auf.> Nein.> Warum nicht? Weil:
Ok, Deine Entscheidung.
> Wilhelm M. schrieb:>> Auf der anderen Seite gibt es hier ja schon einige andere Threads, in>> denen auch ich schon ne ganze Menge inkl. Beispiele gepostet habe.> jeder Thread in diesem Forum, in dem jemand nach "guten" Büchern oder> Wegen fragt, um C++ "richtig" (tm) zu erlernen, die Gefahr birgt, in> einen Flame-War C vs. C++ auszuarten. Und Java, Assembler oder Tofu ist> sowieso viel besser.
Das ist aber m.E. kein Grund, nicht trotzdem das Thema anzuschneiden.
Ansonsten ist es ja ein Bankrotterklärung.
> Der Grund, dass ich überhaupt gefragt habe, ist dieser:> Du hast mehrfach "gute Bücher" als Notwendigkeit bezeichnet. Ohne> irgendeines beim Namen zu nennen, ist diese "Hilfestellung" für den TO> und alle Mitleser wertlos und nur eine "Selbstbeweihräucherung".
Hier ist extra ein Thread zu dem Thema:
Beitrag "Informationen zu C vs C++ / aka Futter für die Diskussion"
Und hier wurde auch schon viele besprochen:
Beitrag "AVR GPIOR Bit Verwaltung C++"
Und mit ein klein bisschen Suchen findest Du hier ne ganze Menge.
Als Bücher füge ich hinzu (wenn man schon ein Grundverständnis der
Sprache hat):
Meyers: Effective modern C++
Kormanyos: RealTime C++
Josuttis: C++ Standard Library
Vandervoorde: C++-Templates
Pohmann: C++17
Zu TMP kenne ich wirklich kein gutes Buch. Die Ideen kann man sich aber
anhand diverser aktuelle Vorträge auf CppCon15/16/17 abholen.
Carl D. schrieb:> Es macht ja auch keinen Sinn mit bestimmten Teilnehmern diskutieren zu> wollen
Ohne Teilnehmer zu diskutieren kann aber sehr mühsam werden. ;-)
Wenn man ausschließlich mit Sachargumenten und nicht mit ad hominem
diskutiert, gerät das Diskussionsobjekt auch nicht aus dem Blick.
Dann ist es auch egal, ob der Diskussionspartner C liebt oder hasst,
Praktiker oder Hochschullehrer oder gestern 12 geworden ist.
Oder ob Veit sich nun (wie oben schon einmal anklang) gnadenlos
bereichert hat und die Steuerung samt Software in Großserie verkauft.
;-)
Wilhelm M. schrieb:> Als Bücher füge ich hinzu
Danke!
Jeder Beitrag besteht ja naturgemäß in unterschiedlichen Anteilen aus
Meinung und Information.
Hiermit hast Du Deiner Meinung die Information hinzugefügt. ;-)
np r. schrieb:> Oder ob Veit sich nun (wie oben schon einmal anklang) gnadenlos> bereichert hat und die Steuerung samt Software in Großserie verkauft.
Solch falsche Unterstellung verbitte ich mir. Völlig egal wie diese
gemeint sind.
Falk B. schrieb:> @Veit Devil (devil-elec)>> case UART: // UART0 wird benutzt>> handle_Serial_0_to_Serial_0();>> break; // minimal 7,7µs ... maximal 18,2µs>> Das break setze ich immer in die gleiche Einrückung wie das case, denn> es ist praktisch mit einer schließenden Klammer identisch.>
Das break ist schon ok und die Einrückung entspricht üblichen
Coding-Rules.
Case / break ist auch keine "Klammer": Während "break" eher wie eine
normale Anweisung agiert, ist "case" eher als Code-Label anzusehen. Zum
Beispiel würde die Einrückung bei bedingtem break sein:
Hallo,
als letzte öffentliche Ergänzung zum Thema zeige ich noch die verzögerte
Servopulsabschaltung. Wurde doch wieder notwendig, weil die Servos bei
leichten Gegendruck anfangen zu brummen, wollen ja gegen regeln.
Timer 1 ist auf 5ms konfiguriert. Setzt aller 5ms ein flag auf true.
das alles in die "Hauptschleife" eingebaut sieht dann so aus.
staticstate_usartstate_USART_MODE=FINISH;// mit externen 8MHz Quarz
5
6
switch(state_USART_MODE){
7
8
caseUSART:// UART0 wird benutzt
9
handle_Serial_0_to_Serial_0();
10
if(countErrorsUART0>50000){// erstmal ne wilde Hausnummer
11
state_USART_MODE=ERROR;
12
}
13
14
turn_on_off_servos();
15
if(flag_servos_updated==true){
16
calc_ServoPositions();
17
flag_servos_updated=false;
18
}
19
break;
und wenn die Servos nicht abschalten sollen, dann nimmt man den
Funktionsaufruf 'turn_on_off_servos()' einfach raus. Die neue
Servoposition kommt über die serielle rein in 'servo[x].pulscount_New'