Hallo,
ich habe folgendes Problem und einen Bugfix, den ich mir nicht erklären
kann:
Ich habe einen STM32F4, bei dem mittels internem Timer der ADC gestartet
wird, die Daten werden anschließend per DMA in ein Array geschaufelt.
Der Timer feuert alle 25us (40kHz), und es werden je Timertrigger 3
Werte aufgenommen. anschließend wird eine ISR aufgerufen und die Werte
verarbeitet und 3 neue Werte daraus berechnet. Die Messung an sich ist
völlig autonom sollte man meinen. Ich kann auch sicher stellen, dass die
ISR planmäßig und zyklisch ausgeführt wird. Da gibt es keine Probleme.
Des zu messende Signal ist ein Sinus mit 50Hz + DC-Offset.
Nun ist es allerding so, dass wenn ich im Sytick_Handler eine Taster
drücke und diesen Entprelle (Debounce) der ADC sich geringfügig vermisst
und sich der DC-Offset ändert (5mV mit DMM Typ Fluke 189 gemessen). Die
5mV habe ich gefunden, indem ich die eingelesenen Werte direkt wieder
über den DAC ausgebe. Diese 5mV verursachen eine Sprung im errechneten
Signal, dieser Sprung klingt nach dem Entprellen wieder ab.
Nach langem Suchen bin ich darauf gestoßen, dass die CPU den ADC stört
bzw. die CPU immer eine gewisse Grundlast haben muss.
main:
if(++LCDReinitcounter>=196){// Reeinit each 196 Updates => 10,0352s, takes 800ms
17
// Init_EA_DOGM163();
18
LCDReinitcounter=0;
19
}else{// 2ms
20
Update_Screen();
21
}
22
Flags.Update_LCD=OFF;
23
}else{
24
// MyDelayMS( 2 );
25
}
26
}
Systick:
1
voidSysTick_Handler(void)
2
{
3
staticuint32_tLCDCounter=0;
4
5
if(LCDCounter%4096==0){
6
Flags.Cursorblinker^=ON;
7
// Toggle_LED( LED_GREEN );
8
}
9
10
if(LCDCounter%512==0){
11
Flags.Update_LCD=ON;
12
}
13
14
// Poll USART Interface
15
USART_Handling();
16
17
// Scan for Increments
18
Scan_Encoder();
19
20
// Encoderbutton
21
if(BUTTON_PRESSED&&Debounce==0){
22
Debounce=DEBOUNCETIME;
23
Flags.Buttonpressed=ON;
24
}
25
26
// Userbutton
27
if(USER_BUTTON_PRESSED&&Debounce==0){
28
Debounce=DEBOUNCETIME;
29
Flags.PSR_State=OFF;
30
}
31
32
// Set Hardware Enable at PSR
33
Enable_PSR(Flags.PSR_State);
34
35
// diverse Counter
36
LCDCounter++;
37
if(MSDelayCounter)MSDelayCounter--;
38
if(Debounce){
39
Debounce--;
40
Set_LED(LED_GREEN);
41
}else{
42
Clear_LED(LED_GREEN);
43
}
44
}
Ist das MyDelayMS(2) auskommentiert, habe ich die CPU-Lastabhängigen
Beulen, die Schaltung nimmt sich 92mA
Mit dem Delay sind die Beulen weg, dass errechnete Signal ist stabil,
die Schaltung nimmt sich 109mA.
Ich zwinge der CPU eine Grundlast auf, das scheint zu klappen. Auf den
Bildern kann man erkennen, dass wenn die Variable "Debounce" != 0 ist
(gelb), die Beule auftaucht (lila).
Hat jemand eine Erklärung dafür, ich habe nun 2 Tage gebraucht, alles
auf Herz und Nieren geprüft, alle Spannungen und Signale gechecked. Das
Eingangssignal am ADC ist sauber und stabil, der Fehler liegt scheinbar
wirklich im Chip.
Hier noch die Delay-Funktion:
Schaut man sich "Ohne_Delay.jpg" genau an, sieht man auf der Hüllkurve
der errechneten Signals zusätzlich zu der satten Beule eine
Oberwelligkeit, die der Frequenz der LCD-Updates ("Update_Screen()")
zeigt.
Ingo L. schrieb:> Des zu messende Signal ist ein Sinus mit 50Hz + DC-Offset.
Versuch es nur mit DC-Offset...
& Messe die Versorgung bzw. ADC-Ref. Spannung mit...
St. D. schrieb:> Versuch es nur mit DC-Offset...
Habe ich, auch dieser verschiebt sich aus Sicht des µC. Am ADC Pin ist
alles sauber, lasse ich mir die eingelesenen Werte (auch nur den Offset)
ausgeben, misst man eine Verschiebung. Dabei ist nicht immer
reproduzierbar ob diese Verschiebung positiv oder negativ ist.
> & Messe die Versorgung bzw. ADC-Ref. Spannung mit...
Die Versorung ist auch stabil, ADC-Ref. gibt es bei diesem Modell nicht,
es misst leider immer gegen seine VCC. Aber diese zuckt keine Stück.
Ich erinnere da dunkel was mit dem Flash-ACR vs. ADC, weiß aber
nichtmehr, welcher STM32 das war. Versuch mal probehalber, beim
System-Init die D/I-Caches abzuschalten (bzw. nicht anzuschalten) und
teste neu.
Nop schrieb:> Versuch mal probehalber, beim> System-Init die D/I-Caches abzuschalten (bzw. nicht anzuschalten) und> teste neu.
Wenn ich die Caches abschalte bzw. garnicht erst einschalte tritt der
Fehler (Beule beim Entprellen) wieder auf, sehr spannend!
Ingo L. schrieb:> es misst leider immer gegen seine VCC.
Und gegen GND. Wenn der zappelt, dann misst er Mist.
> Aber diese zuckt keine Stück.
Ist an allen Massepins tatsächlich der selbe Pegel?
Ingo L. schrieb:> ich habe folgendes Problem
Mit welcher Hardware? Wie sieht das Layout aus? Im Besonderen ist hier
die Versorgung interessant.
Ingo L. schrieb:> Nun ist es allerding so, dass wenn ich im Sytick_Handler eine Taster> drücke und diesen Entprelle (Debounce) der ADC sich geringfügig vermisst
Kommt dieser Fehler vom Taster allein oder von der Programmaktion, die
du darauf folgend ausführst? Was passiert, wenn du "im Prinzip" die
Hardware samt Taster gleich lässt und in der Software nicht auf den
Taster reagierst? Löst der Taster sonst noch eine Aktion aus, die den
Strombedarf ändert?
Ingo L. schrieb:> Nein, sollte ich das tun? Wenn ja, wie macht man das?
Wenn es genau werden muss oder auch mangels besserer Alternativen.
Welchen f4 hast du? Beim f407 und f432 liegt die auf einem internen adc
Kanal der ganz normal gemessen werden kann. Die Spannung der Referenz
wird bei der Produktion gemessen und daraus kann dann vdd berechnet
werden. Und damit wiederum die tatsächlich gemessene Spannung. Es gibt
ne appnote dazu Und auch einen Abschnitt im Datenblatt und ref Manual.
Lothar M. schrieb:> Und gegen GND. Wenn der zappelt, dann misst er Mist.
Ja, so sauber sieht das GND wirklich nicht aus, sehr viel Noisefloor...
Lothar M. schrieb:> Ist an allen Massepins tatsächlich der selbe Pegel?
Ja
Lothar M. schrieb:> Mit welcher Hardware? Wie sieht das Layout aus? Im Besonderen ist hier> die Versorgung interessant.
Siehe Anhang. Ich habe bewusst auf eine Massefläche verzichtet, damit
ich Analog-µC vom externen DAC trennen kann. Hoffentlich fällt es mir
jetzt nicht auf die Füße...
Lothar M. schrieb:> Kommt dieser Fehler vom Taster allein oder von der Programmaktion, die> du darauf folgend ausführst? Was passiert, wenn du "im Prinzip" die> Hardware samt Taster gleich lässt und in der Software nicht auf den> Taster reagierst? Löst der Taster sonst noch eine Aktion aus, die den> Strombedarf ändert?
Der Taster ohne Softwareaktion bewirkt garnichts. Es ist allein die
Rechenzeit. Es ist reproduzierbar, wenn man statt des Taster einen
Zähler hochzählt, der bei erreichen eines gewünschten Zählerstandes
ebenfalls Debounce auslöst.
Karl schrieb:> f407
Ich habe einen 405er.
> Die Spannung der Referenz> wird bei der Produktion gemessen und daraus kann dann vdd berechnet> werden
Du meinst quasi eine ratiometrische Messung?
Wenn ich die Funktion "Init_EA_DOGM163()" rein nehme und diese etwa alle
10s ausgeführt wird, sieht man die Beule auch ohne eine
Benutzerinteraktion (ohne das Dummyload MyDelayMS(2)). Mit der
Dummyload ist alles ok. Offensichtlich generiert die CPU genug Noise um
den ADC sauber zu stören...
Ingo L. schrieb:> Offensichtlich generiert die CPU genug Noise um> den ADC sauber zu stören...
Die CPU hast immer irgendeinen schwankenden Strombedarf.
Aufgrund der miesen Masse hebt und senkt sich der Bezugs-
pegel der CPU und damit ergeben sich schlichtweg (fast)
beliebige Fehlmessungen.
OMG schrieb:> Aufgrund der miesen Masse
Ground Bouncing war gleich mein erster Verdacht...
Ingo L. schrieb:> damit ich Analog-µC vom externen DAC trennen kann.
Das geht aber so nicht. Sondern da macht man eine Massefläche unter dem
uC, an die alle GND Pins direkt angeschlossen sind. Und trennt dann
Analog und Digital räumlich auf der Platine. Nicht umsonst steht im
Datenblatt an allen GND Pins das selbe Signal. Dann muss da auch an
allen Pins das selbe Potential sein. Jegliche Abweichung verändert bzw.
verschlechtert irgendwas...
Wenn da so ein Strom irgendwo in dem uC fließt, dann muss er auch wieder
raus. Und wenn er an einem GND Pin rausfließt und über diese
hochimpedante Masse zurück zur Quelle, dann hebt dieser Strom den GND
Pin um ein paar mV an. Und wenn dieser GND Pin auch noch was mit dem ADC
zu tun hat, dann verfälscht dieser Strom das Messergebnis.
BTW: die schlecht platzierten Blockkondensatoren verbessern die Sachlage
dann nicht im Mindesten...
@ INgo
Vielleicht könntest Du ja nochmal mit dem Oszi nachmessen, wie sich die
Versorgungsspannung VDDA gegen VSSA verhält. Und zwar direkt an den
Pins. Es wäre vielleicht nützlich weil überzeugend, wenn man das
Ground-Bouncing direkt sieht und wie es mit der CPU-Last zusammenhängt.
Ich fürchte allerdings auch, dass Du das Layout nochmal gründlich
überarbeiten musst.
Christian W. schrieb:> Seid nicht so hart, sieht aus wie Target. Da is ein beschissenes Layout> quasi n Feature ;)
So ein Unsinn...
Ich vermute auch das die Masseführung scheisse is, ich werde die Masse
mal etwas verstärken...
Ingo L. schrieb:> ich werde die Masse mal etwas verstärken...
Damit sind die Blockkondensatoren noch immer nicht an der richten
Stelle.
Die gehören direkt an den Pin. Und da geht es um Millimeter, wenn es
dir um mV geht. Nicht umsponst haben es die Chipdesigner geschafft, die
Vcc und GND Pins paarweise auftreten zu lassen: VDDA+VSSA = 12+13,
VSS-VDD = 18+19 und 63+64. Genau dorthin an diese Pins müssen die
Blockkondensatoren. Die müssen auch nicht so megamäßig groß und sogar
auf der anderen Seite sein. 100nF gibt es auch in 0402 oder noch
wesentlich kleiner.
Blockkondensatoren müssen den Strom für schnelle interne
Schaltaktivitäten bereitstellen. Fahre einfach mal den Weg von einem
Blokkondensatoranschluss über die VCC-VDD Anschlüsse des µC und schau
wie lang der Weg und entsprechend wirkungslos der Kondensator ist.
BTW: Vias im Pad sind eine ganz schlechte Idee. Ein EMS Dienstleister
(Elektronikfertiger) würde dir dieses Layout als "nicht fertigbar" oder
"auf eigene Gefahr" bewerten. Und der DRC sollte dir da einen Fehler
vorwerfen...
Lothar M. schrieb:> Die müssen auch nicht so megamäßig groß und sogar> auf der anderen Seite sein. 100nF gibt es auch in 0402 oder noch> wesentlich kleiner.
ich verwende bereits 0603, so groß ist das garnicht.
Lothar M. schrieb:> VDDA+VSSA = 12+13,> VSS-VDD = 18+19 und 63+64.
63/64 und 18/19 sind meiner Meinung nach sehr kurz angebunden, 12/13
sind eher suboptimal, stimmt.
Ich werde glaube ich im nächsten Aufguss auf einen externen ADC setzen
um ganz sicher zu gehen...
> Und der DRC sollte dir da einen Fehler> vorwerfen...
Je nachdem was man einstellt ;).
Ingo L. schrieb:> // Update LCD, Handle HMI> if ( Flags.Update_LCD == ON ){ //19,53125 Updates/Second
Mal noch was anderes: wozu sollte man ein Textdisplay mit 20 Hz updaten?
Das kann man eh nicht sehen. Mehr als einmal oder allerhöchstens zweimal
pro Sekunde ist sinnlos.
> if ( ++LCDReinitcounter >= 196 ){ // Reeinit each 196 Updates> => 10,0352s, takes 800ms
Und wozu sollte man alle zehn Sekunden das Display neu initialisieren?
Pack die 100nF Kondensatoren direkt an die Pins auf dem gleichen Layer
und spendiere der Controller ein komplette Massefläche.
Dein Layout ist für langsame, digitale Signale o.k. Aber nicht für etwas
analoges mit <10mV Auflösung.
Ein externer ADC muss auch entsprechend gut gelayoutet werden sonst
kommt es zu genauso lustigen Effekten..
Nop schrieb:> Mehr als einmal oder allerhöchstens zweimal> pro Sekunde ist sinnlos.
Naja, ich finde es sehr unergonomisch, wenn man Werte per
Incrementalgeber ändert und diese sich optisch nur sekündlich ändern.
Aber wenn du keinen Wert auf Ergonomie legst, brauchs du das auch nicht
häufiger machen.
Nop schrieb:> Und wozu sollte man alle zehn Sekunden das Display neu initialisieren?
Ich verstehe den Zusammenhang zwischen meinem Problem und deiner Frage
nicht...
Ingo L. schrieb:> 63/64 und 18/19 sind meiner Meinung nach sehr kurz angebunden
Stimmt, dank "Via-In-Pad" Technik.
> 12/13 sind eher suboptimal, stimmt.
Und was war jetzt nochmal die Funktion dieser Pads? Irgendwas mit
"Analog"? ;-)
> ich verwende bereits 0603, so groß ist das garnicht.
Für die paar Blockkondensatoren pro IC nehme ich tatsächlich 0201. Die
sind aber echt mickrig.
Ingo L. schrieb:> Naja, ich finde es sehr unergonomisch, wenn man Werte per> Incrementalgeber ändert und diese sich optisch nur sekündlich ändern.
Man muss dann ja nicht das ganze Bild neu zeichnen. Ein paar anders
positionierte Pixel verändern eine Zahl grundlegend. Man darf sich da
runih mal anschauen, wie andere das machen: ein schlechtes
(Windows-)Programm zeichnet bei jeder Änderung den ganzen Bildschirm
neu. Das bessere und schnellere zeichnet nur den Bereich, der sich
ändert.
> Aber wenn du keinen Wert auf Ergonomie legst, brauchs du das auch nicht> häufiger machen.
Obacht Retourkutsche:
Aber wenn man die Rechenleistung hat und nicht drüber grübeln will, wie
es besser und schneller geht, kann man auch immer den ganzen Screen neu
malen. ;-)
Ingo L. schrieb:> Naja, ich finde es sehr unergonomisch, wenn man Werte per> Incrementalgeber ändert und diese sich optisch nur sekündlich ändern.
Ablesen kannst Du das sowieso nicht so schnell, das verschwimmt auf dem
Display nur und erzeugt unnütz CPU-Last. Wobei das im Systick mit dem
LCDCounter % 512 doch begrenzt wird, hatte ich nicht gesehen. :-)
> Ich verstehe den Zusammenhang zwischen meinem Problem und deiner Frage> nicht...
Es sieht nach einem weiteren Problem mit notdürftigem Workaround aus,
denn Textdisplays stürzen normalerweise nicht dauernd ab, so daß man sie
neu initialisieren müßte. Die kann man stundenlang so betreiben, sofern
man bei der Anbindung mit dem Flachbandkabel nichts verkehrt gemacht
hat.
Lothar M. schrieb:> Man muss dann ja nicht das ganze Bild neu zeichnen.
Wer sagt das ich das tue? Ist im übrigen ein Text-LCD, ich muss nicht
"malen" ;)
> Und was war jetzt nochmal die Funktion dieser Pads? Irgendwas mit> "Analog"? ;-)
Ja, leider. 0402 oder gar 0201 gebe ich mir nicht ;)
Nop schrieb:> Es sieht nach einem weiteren Problem mit notdürftigem Workaround aus,
Nein, ist kein Workaround. Es ist inzwischen auch raus. Das war halt zu
provozieren der Beule ganz gut geeignet.
Lothar M. schrieb:> Stimmt, dank "Via-In-Pad" Technik.
Da ich keine maschinelle Bestückun habe komme ich damit gut zurecht.
Ingo L. schrieb:> Ist im übrigen ein Text-LCD, ich muss nicht "malen" ;)
Bei Text-Displays male ich pro Timertick (üblicherweise der übliche 1ms
Interrupt oder beim STM32 der Systemtimertick) einen einzigen Buchstaben
vom µC-Display-Buffer ins Display. Bei einem 4x20 Display bin ich dann
nach 80ms fertig mit dem Screen-Update. Und eine Neuinitialisierung des
Display mache ich nur 1 einziges Mal beim Powerup. Wenn du öfters mal
eine Neuinitialisierung brauchst, dann hast du vermutlich noch
weitere/andere EMV-Probleme im Design.
> 0201 gebe ich mir nicht ;)
Trotzdem gut, wenn man da ein paar "zur Hand" hat. Denn die kann man
immer mal schnell zum Test irgendwo dazwischenlöten. Und die nehmen ja
im Prinzip keinen Platz weg.
Ingo L. schrieb:> if ( ++LCDReinitcounter >= 196 ){ // Reeinit each 196 Updates> => 10,0352s, takes 800ms
Mein Vorschlag: denk nicht so menschlich in Zehnerpotenzen, die CPU ist
binär sortiert. Wenn du hier das Update erst nach 256 Durchläufen statt
den willkürlichen 196 (vermutlich um die "menschlichen" 10,0 Sekunden zu
erreichen) machen würdest, reicht es, das Byte zu inkrementieren und
danach das Zero-Flag abzufragen...
> //19,53125 Updates/Second
So genau und stabil ist dein Quarz gar nicht... ;-)
Lothar M. schrieb:> Wenn du öfters mal> eine Neuinitialisierung brauchst, dann hast du vermutlich noch> weitere/andere EMV-Probleme im Design.Ingo L. schrieb:> Das war halt zum> Provozieren der Beule ganz gut geeignet.> Mein Vorschlag: denk nicht so menschlich in Zehnerpotenzen, die CPU ist> binär sortiert. Wenn du hier das Update erst nach 256 Durchläufen statt> den willkürlichen 196 (vermutlich um die "menschlichen" 10,0 Sekunden zu> erreichen) machen würdest, reicht es, das Byte zu inkrementieren und> danach das Zero-Flag abzufragen...
Kann man machen
Als Nachtrag:
"... und täglich grüsst das Murmeltier"
Immer wieder kommt diese Struktur auf:
Zuerst ins Verderben rennen (erst mal drauf los und irgend-
eine Hardware zusammenschustern) und dann hier im Forum
rumjammern.
Dabei wäre es doch so einfach sich erst im Forum bezüglich
Schaltung und Layout beraten zu lassen und dann hinterher
nicht ins Verderben zu rennen sondern durchzustarten.
Der TO ist lang genug hier dabei um diese Erkenntnis schon
gewonnen haben zu können.