Hallo,
ich habe einen ATmega328 (Arduino Nano) und möchte diesen gerne auf 1MHz
laufen lassen.
Mein Programm konnte unter den 16MHz vom Auslieferunszustand wunderbar
den DS18B20 und das 1602LCD betreiben. Als ich den PID Regler von der
Atmel Application Note 221 integrieren wollte, stand drin, dass man den
PID Rechenzyklus auf ca. 1 Hz bringen soll.
Also den Timer Prescaler für den PID auf 1024 gesetzt und F_CPU auf
1000000UL gesetzt und die Fuses für den Internen 8MHz Oszillator und
CLKDIV8 aktiviert.
Jetzt geht gar nix mehr. Weder Display noch DS18B20.
Wenn ich die CKOUT Fuse aktiviere, kann ich an PB0 den 8MHz Tackt
messen. Warum ändert sich dieser Tackt nicht, wenn ich die Fuse CLKDIV8
aktiviere und deaktiviere?
Das müsste doch 100% Code-Unabhängig sein. Egal was ich da für einen
Mist zusammengeschrieben habe. Weil wenn ich die CKOUT Fuse setze und
resette, kann ich das ja sofort am Oszi messen. Warum geht das mit dem
Tacktdividierer nicht?
Umgebung: AtmelStudio 7
Programmer: AVR Dragon über ISP
Kann mir jemand helfen?
Danke
Laut Datenblatt sollte das gehen: "If the system clock prescaler is
used, it is the divided system clock that is output. "
Hast du das Ding mal kurz Stromlos gemacht, nachdem du die Fuses
geändert hast?
Danke Stefan, dass Du das genauso siehst.
Ja, ich habe sogar die verschiedenen Delaytimes bei den 8MHz Fuses
ausprobiert und jedesmal einen Power-Reset gemacht.
Bringt leider nix. Der schwingt stur auf 8 Mhz.
Im DaBla konnte ich auch keinen Verweis finden, dass man noch andere
Fuses o.ä. setzen muss?!
Grüße
Jch
Jch schrieb:> PID Rechenzyklus auf ca. 1 Hz bringen soll.
Das macht man auf anderem Wege, als den SystemTakt runter zu setzen.
Dafür verwendet man z.B. einen der Timer.
Jch schrieb:> Warum ändert sich dieser Tackt nicht, wenn ich die Fuse CLKDIV8> aktiviere und deaktiviere?
Muss es !
Also machst du was falsch.
Sicher, dass du nicht nur den Simulator befummelst?
Arduino Fanboy D. schrieb:>> PID Rechenzyklus auf ca. 1 Hz bringen soll.>> Das macht man auf anderem Wege, als den SystemTakt runter zu setzen.> Dafür verwendet man z.B. einen der Timer.
Ähm ja. Aber bei 16 MHz und 8 Bit Timer und 1024er Prescaler komme ich
leider nicht wirklich nahe an den 1Hz Tackt ran und warum sollte ich
nicht den Systemtackt reduzieren dürfen? 1 MHz braucht weniger Leistung
als 16 MHz und den Quarz brauche ich nicht für die Genauigkeit.
Wenn ich den 128 kHz Oszillator auswähle, geht mein Tackt auf die 128kHz
runter, aber auch hier geht der CLKDIB8 nicht. Also auf 16kHz geht der
Pin nicht runter.
Auch meine PWM Timer ändern ihren Tackt nicht, egal ob den DIV8
aktiviere oder nicht.
Und der 1 MHz Tackt hätte noch den Vorteil, dass mein PWM MOSFET nicht
so heiss werden würde, weil der für die Heizung keine besonders hohe
frequenz schalten muss.
Grüße
Jch
Arduino Fanboy D. schrieb:> Jch schrieb:>> Warum ändert sich dieser Tackt nicht, wenn ich die Fuse CLKDIV8>> aktiviere und deaktiviere?> Muss es !
das denke ich auch, aber was mache ich falsch? Gibts da geheime
Hinterürchen?
Arduino Fanboy D. schrieb:> Sicher, dass du nicht nur den Simulator befummelst?
Nein, ansonsten könnte ich ja weder mit den 8MHz und 128 kHz am Oszi
spielen, noch würde ich mit dem CLKOUT Pin rumspielen können.
Und man kann auf dem Display den RESET beim flashen erkennen.
Grüße
Jch
Problem gelöst. Ob das die Ursche war, möchte ich Bezweifeln.
Ich habe einen Chip Erase gemacht und einfach nochmal mit den Fuses
gespielt. Nach dem Chip Erase konnte ich einfach so zwischen CLKVIV8 und
nicht-CLKDIV8 wechseln und am Oszi tut sich auch was.
Sehr merkwürdig. Ich dachte der Code auf dem Chip ist hierfür
irrelevant.
Sobald ich wieder den Code auf den µC hochlade, bin ich wieder bei 8
MHz.
Irgendwer überschreibt mir die Fuses. Kann das an den Toolchain
Compilereinstellungen liegen?
Wenn ja, wo muss ich da suchen? Bzw. nach was muss man da Googlen? Das
ist komplettes Neuland für mich
Jch schrieb:> Irgendwer überschreibt mir die Fuses.
Ich tippe eher darauf, dass dein eigenes Programm den Prescaler CLKPR
verändert und dadurch die Fuse unwirksam macht.
Jch schrieb:> Sehr merkwürdig. Ich dachte der Code auf dem Chip ist hierfür> irrelevant.
GCC power.h ->
https://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
Der Bootloader wird anscheinend auch immer mit programmiert?
Jch schrieb:> Irgendwer überschreibt mir die Fuses. Kann das an den Toolchain> Compilereinstellungen liegen?
Wird die .elf Datei oder die .hex hochgeladen?
Stefan ⛄ F. schrieb:> Jch schrieb:>> Irgendwer überschreibt mir die Fuses.>> Ich tippe eher darauf, dass dein eigenes Programm den Prescaler CLKPR> verändert und dadurch die Fuse unwirksam macht.
Tatsächlich im Init vom PID-Code wird der CLKPR auf Prescaler 1 gesetzt.
Somit muss ich mein Verständnis über fuses nochmal updaten. Ich dachte
Fuses sind mächtiger als der Code. Somit habe ich nicht im Code danach
gesucht.
Holger L. schrieb:> Der Bootloader wird anscheinend auch immer mit programmiert?
naja, das war noch eine Arduino-Leiche. Ich nutze keinen Bootloader.
Holger L. schrieb:> Jch schrieb:>> Irgendwer überschreibt mir die Fuses. Kann das an den Toolchain>> Compilereinstellungen liegen?>> Wird die .elf Datei oder die .hex hochgeladen?
ich nehme die .hex. Würde die .elf einen Unterschied machen? Die ist
doch nur dazu da um andere Einstellungen wie z.B.Fuses auch mit zu
flashen oder?
Danke schonmal. Da wäre ich warscheinlich so schnell nicht draufgekommen
Jch schrieb:> Somit muss ich mein Verständnis über fuses nochmal updaten. Ich dachte> Fuses sind mächtiger als der Code.
Sind sie. Aber du solltest mal nachlesen, was die CLKDIV8-Fuse
eigentlich tut.
Oliver
"388025I–AVR–02/09 ATmega48P/88P/168P/328P Seite 38
The CKDIV8 Fuse determines the initial value of the CLKPS bits. If
CKDIV8 is unprogrammed,the CLKPS bits will be reset to “0000”. If CKDIV8
is programmed, CLKPS bits are reset to“0011”, giving a division factor
of 8 at start up. This feature should be used if the selected
clocksource has a higher frequency than the maximum frequency of the
device at the present operat-ing conditions. Note that any value can be
written to the CLKPS bits regardless of the CKDIV8Fuse setting. The
Application software must ensure that a sufficient division factor is
chosen ifthe selected clock source has a higher frequency than the
maximum frequency of the device atthe present operating conditions. The
device is shipped with the CKDIV8 Fuse programmed"
mfG
@Jch
Hallo!
Ich habe hier auch den Arduino Nano V3 und hab mal nachgeschaut ob die
1Mhz
für den Internen Oszilator überhaupt gibt. Leider Nein.
Aber vllt. hilft dir das weiter:
Bei gestztem CLKDIV8 einfach mal F_CPU 8MHz, 4MhZ und 1Mhz
mit den Werten Spielen und beobachten was passiert.
#ifndef F_CPU // kann auch im Makefile definiert sein
//#define F_CPU 16000000UL // Takt als LONG definieren, da zu groß für
Integer
#define F_CPU 1000000UL // Takt als LONG definieren, da zu groß für
Integer
#endif
#include <avr/io.h> // Namen der IO Register
#include <util/delay.h> // Funktionen zum warten
// Achtung, damit delay richtig funktioniert muß mit Optimierung
compiliert werden
int main(void)
{
unsigned char test_c;
// LED an Port PB0 ist Low Aktiv angeschlossen
PORTB = 0x01; // Nur Pin PB0 aktiv
DDRB = 0x01; // PB0 als Ausgang definieren
while (1)
{
PORTB &= ~(1<<PB0);
_delay_ms(200);
PORTB |= (1<<PB0);
_delay_ms(200);
}
}
@Jch
Was passiert wenn Bei gestztem CLKDIV8 und 16 Mhz mit dem Blinkprogramm?
Richtig! Die Blinkfrequenz wird langsammer.
Es dürfte deinem Ziel schon näher kommen!
Gute Nacht!
Auf jeden Fall!
1. long ist auch ein Integer
2. long wird automatisch verwendet, wenn das Literal nicht in int passt
3. Das U könnte allerdings sinnvoll sein
Oliver S. schrieb:> Jch schrieb:>> Somit muss ich mein Verständnis über fuses nochmal updaten. Ich dachte>> Fuses sind mächtiger als der Code.>> Sind sie. Aber du solltest mal nachlesen, was die CLKDIV8-Fuse> eigentlich tut.
ich habe es im DaBla nachgelesen, aber anscheinend anders interprätiert,
als es gedacht ist.
Christian S. schrieb:> Note that any value can be> written to the CLKPS bits regardless of the CKDIV8Fuse setting.
ich habe das so verstanden, als ob man beim CLKPS z.B. ein Prescaler von
8 einstellen kann und die CKDIV8-Fuse das nochmal dividiert, sodass man
auf einen Prescaler von 64 kommt.
der nixwois schrieb:> Hallo!> Ich habe hier auch den Arduino Nano V3 und hab mal nachgeschaut ob die> 1Mhz> für den Internen Oszilator überhaupt gibt. Leider Nein.
danke dafür, aber wenn ich ein Oszi habe und den Clock direkt auf einen
Pin herausführen kann, muss ich kein Blinklicht mitstoppen ;-)
Klar hat der 328 keinen echten 1 MHz Clock, sondern nur einen vom 8 Mhz
RC welcher durch 8 geteilt wird durch die Fuse (oder durch andere Werte
mit dem Höllenregister)
Ich habe doch schon in folgendem Beitrag die Lösung geschrieben:
Jch schrieb:> Stefan ⛄ F. schrieb:>> Jch schrieb:>>> Irgendwer überschreibt mir die Fuses.>>>> Ich tippe eher darauf, dass dein eigenes Programm den Prescaler CLKPR>> verändert und dadurch die Fuse unwirksam macht.>> Tatsächlich im Init vom PID-Code wird der CLKPR auf Prescaler 1 gesetzt.> Somit muss ich mein Verständnis über fuses nochmal updaten. Ich dachte> Fuses sind mächtiger als der Code. Somit habe ich nicht im Code danach> gesucht.
Dieses Problem mit dem Takt ist gelöst, aber im Moment kämpfe ich noch
mit den Rückgabewerten vom PID Regler. Aber das ist eine andere
Geschichte...
Hi
>ich habe das so verstanden, als ob man beim CLKPS z.B. ein Prescaler von>8 einstellen kann und die CKDIV8-Fuse das nochmal dividiert, sodass man>auf einen Prescaler von 64 kommt.
Nein. Es gibt nur einen Prescaler. Beim setzen der CKDIV8-Fuse wird
dieser auf einen Teiler von 8 gestellt. Mit dem Setzen eines anderen
Prescalers wird das überschrieben.
MfG Spess
>ich habe es im DaBla nachgelesen, aber anscheinend anders interprätiert, >als es
gedacht ist.
>Christian S. schrieb:>Note that any value can be>written to the CLKPS bits regardless of the CKDIV8Fuse setting.>ich habe das so verstanden, als ob man beim CLKPS z.B. ein Prescaler von 8 >einstellen kann und die CKDIV8-Fuse das nochmal dividiert, sodass man auf >einen
Prescaler von 64 kommt."
Also liegt es am fremdländischen Englisch.
Der Satz heißt:
Beachte, daß jeder Wert in die clkps-Bits geschrieben werden kann, ohne
Beachtung der/Rücksicht auf die Fuse-Einstellung.
Das bedeutet, daß die Fuse überschrieben werden kann. Sie stellt nur
einen Anfangswert beim Start dar, der durch das Programm jederzeit
geändert werden kann. Man kann es auch so verstehen, wie Du oben
geschrieben hast. Das wäre eigentlich naheliegend, entspricht aber nicht
dem Wortlaut des Autors.
MfG
spess53 schrieb:> Nein. Es gibt nur einen Prescaler. Beim setzen der CKDIV8-Fuse wird> dieser auf einen Teiler von 8 gestellt. Mit dem Setzen eines anderen> Prescalers wird das überschrieben.
Hallo, ich arbeite mich auch gerade in die Clock/Timer-Geschichten ein
und habe in der Docu gefunden, dass neben dem System-Clock-Prescaler
Timer0/1 und Timer2 jeweils noch einen "eigenen" Prescaler haben
(können). Verstehe ich das richtig?
Gruß Rainer
Der ADC UART TWI SPI haben auch noch Teiler!
Gibt also Mengen davon.
Alle diese hängen (meist) am Systemtakt.
Sind also dem CLKPS untergeordnet.
Rainer V. schrieb:> dass neben dem System-Clock-Prescaler
Nicht neben, sondern unter, in der Hierarchie.
Hallo,
ich bin gerade dabei den PID Regler einzubinden. Er funktioniert
halbwegs, aber der Integrierer ist zu fleissig. Wie kann ich das
Anti-Wind-Up einprogrammieren?
In der AVR221 AppNote
(https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591227)
ist der Quellcode für den PID Regler. Wo sollte ich jetzt dem Integrator
einen Strich durch die Rechnung machen?
1
2
// Calculate Iterm and limit integral runaway
3
temp=pid_st->sumError+errors;
4
if(temp>pid_st->255){//maxSumError;
5
i_term=255;//MAX_I_TERM;
6
pid_st->sumError=pid_st->255;//maxSumError;
7
}elseif(temp<-pid_st->0){//maxSumError;
8
i_term=0;//-MAX_I_TERM;
9
pid_st->sumError=-pid_st->0;//maxSumError;
10
}else{
11
pid_st->sumError=temp;
12
i_term=pid_st->I_Factor*pid_st->sumError;
13
}
Die auskommentierten Werte sind die aus dem originalen Code und die 0
und 255 kommt von mir.
Was mache ich falsch? Weil so funktioniert es nicht. Der C++ Code ist
mir bisher noch nicht geläufig.
Ich will ja den Ausgang vom Regler auf 256 skalieren, weil es auf einem
PWM Ausgang geht.
Grüße
Jch
Oliver S. schrieb:> Tust du, das hat aber mit dem Thema des Threads wenig zu tun.
Ja, ich weiss, aber der TO hat die Timer-Prescaler wohl nicht auf dem
Schirm und ich habe mich eben gefragt, ob ich da mit meinen
"Erkenntnissen" ganz falsch liege. Sorry und danke :-)
Rainer