Hallo, ich habe ein kleines Problem mit einem C-Programm. Dazu muß ich etwas weiter ausholen. auf der Seite: http://www.opend.co.za/hardware/nimh1/nimh1.htm ist ein NIMH-Lader mit Atmega8 veröffentlicht, den ich nachgebaut habe und der auch ganz prima funktioniert. Es war schon einmal jemand so freundlich, mir den Quelltext davon zu assemblieren, so daß ich das Gerät aufbauen konnte. (Winavr kann ich mittels Modem nicht herladen, da zu groß). Jetzt zu meinem Problem: Der Lader läßt sich nur bis minimal 100mA herunter einstellen. Das ist offenbar in der Software so festgelegt. Wenn ich nun aber z.B. einen 9V-Blockakku mit 150 mAh Kapazität laden will, muß ich aber herunter bis auf 15mA einstellen können. Da ich von der Sprache C nichts verstehe, ist es mir nicht möglich, die Stelle in der Datei Main.c zu finden, wo der Autor des Beitrages den unteren "Anschlag" der PWM festgelegt hat. Ich hatte ihn im November schon mal angeschrieben und auf einen anderen Fehler aufmerksam gemacht, den er auch behob, aber jetzt höre ich nichts mehr von ihm. Deshalb die Frage: Kann sich mal ein "C-Kundiger" die Quellen laden und sehen, wo die untere Begrenzung programmiert ist, sie nach unten hin korrigieren und dann die geänderte .hex-Datei posten? Es ist die getestete Version von 2004. MfG Paul
Hallo Paul, ich hab mir mal die main.c (version 2006) angesehen. Im Unterprogramm pwm_control ist ein Wert min_duty von 4 und ein Wert max_duty von 100 eingetragen. Probehalber könnte man min_duty auf 2 oder 1 setzen. Aber um das Programm genau zu verstehen, müßte man schon einige Zeit investieren.
@Jack Ich danke Dir für Deine Mühe. Könntest Du mir bitte in der Version von 2004 (die ist getestet; die 2006er nicht) den min_duty Wert auf 1 setzen und mir dann die compilierte Datei im .hex-Format senden? Unabhängig davon, ob das die ganze Lösung des Problems darstellt. MfG Paul
Die 2004er-Version enthält noch eine ganze Menge Zeug, das nicht mehr AVRgcc-aktuell ist...
@Rahul Na das war ja fix, hast Du Dir den Code mal genauer angesehen? Würde mich mal interessieren, wo man da noch was drehen kann.
Nee, habe ich noch nicht. Ich habe erst mal nur "outp" und "inp" übersetzt... Das alte Ding will mein Compiler immer noch nicht (und irgendwie ist mal wieder mein Output-Fenster des Programmer's Notepad verschwunden...)
Mist! Irgendwie lässt sich das alte Programm bei mir nicht /mehr) compilieren. Ich hätte gerne geholfen. Anbei die ungetestete 2006er-Variante mit geändertem min_duty
Ich wollte mal das 2004er Programm compilieren und hab mir das neueste WinAvr runtergeladen. Anscheinend kennt er inp und outp nicht mehr. Muß man da jetzt ein neues Makro schreiben?
Menschenskinder! ;-) Schönen Dank. Da freue ich mich, daß ihr mir geholfen habt. Ich lade das heute abend mal rein und schreibe Euch dann, wie sich die Änderung geäußert hat. MfG Paul
@Rahul So, jetzt habe ich beide Versionen, die Du gesandt hast ausprobiert. Die erste (von 20:47 Uhr) funktioniert, läßt aber als Minimum nur 120mA einstellen. Die zweite Version geht besser; sie läßt minimal 68mA einstellen. Auf welchen Wert hast Du "min_Duty" gesetzt? Wenn der jetzt auf 1 steht, dann geht es prinzipbedingt nicht weiter runter und ich muß für das Laden der Blockakkus einen anderen Apparat benutzen. Danke Dir noch einmal! :-) MfG Paul
>Auf welchen Wert hast Du "min_Duty" gesetzt? Wenn der jetzt >auf 1 steht, dann geht es prinzipbedingt nicht weiter runter und ich muß >für das Laden der Blockakkus einen anderen Apparat benutzen. Die erste habe ich einfach so compiliert. Dann ist mit das mit "min_duty=1" noch eingefallen... Das wurde dann das 2.Posting. Scheinbar geht es wirklich nicht kleiner... Da müsste man vermutlich an der Hardware drehen (habe ich mir noch nicht näher angesehen).
@Rahul ...da ist mir das Ergebnis mit dem ersten .hex-File klar.:-)) Das war das Gleiche, was ich schon drin hatte. (Habe ich mit dem Hexeditor vergleichen lassen) Eben fiel mir noch ein, daß ja der fließende Strom über den AD-Wandler als proportionale Spannung wieder eingelesen wird und er damit den Ladestromkonstant hält. Vielleicht fragt das Programm den irgendwo auf seinen minimalen Wert hin ab und es hängt daran. C ist so unübersichtlich. (Jaul!):-) MfG Paul
>Vielleicht fragt das Programm den irgendwo auf seinen minimalen Wert hin >ab und es hängt daran. Wenn ich dazu komme, schaue ich mir den Code noch mal genauer an. Eigentlich wird sich das Programm nur um den Regler drehen (wer hätte das gedacht?!), und eine gewisse Anzahl von Impulsen zählen bis die Zeit um ist. >C ist so unübersichtlich. Um dem entgegenzuwirken gibt es die Möglichkeit, Programme mit Kommentaren zu versehen...Das gilt nämlich für jede Programmiersprache
Ich hab mir mal den Code angeguckt. Der Regler sieht so aus:
1 | //------------------------------------------------------
|
2 | // the soft implementation of the SMPSU control
|
3 | //------------------------------------------------------
|
4 | void control_pwm(void) |
5 | {
|
6 | //#define max_duty 127
|
7 | //#define min_duty 0
|
8 | |
9 | #define max_duty 100
|
10 | #define min_duty 4
|
11 | |
12 | static uint8_t dutycycle = min_duty; |
13 | static uint32_t adc_ave = 0; |
14 | |
15 | static uint8_t pre = 0; |
16 | static uint32_t adc_ave_tmp; |
17 | uint16_t adcv; |
18 | |
19 | if (ADC_DataInBuffer()) // only if there is data waiting for me |
20 | {
|
21 | //------------------------------------------------------
|
22 | // the adc sample collection
|
23 | // average a number of samples out to get a smoothed average
|
24 | //------------------------------------------------------
|
25 | adcv = ADC_get(); |
26 | |
27 | adc_ave = adc_ave + adcv; |
28 | //------------------
|
29 | // a prescaler used in the averaging of the adc
|
30 | if (pre >= 16) |
31 | pre = 0; |
32 | pre +=1; |
33 | |
34 | if (1 == pre) |
35 | {
|
36 | adc_ave = adc_ave >> 3; |
37 | |
38 | adc_ave_tmp = adc_ave; |
39 | while ((adc_ave_tmp < setpnt) && (dutycycle < max_duty)) |
40 | {
|
41 | dutycycle += 1; |
42 | adc_ave_tmp = adc_ave_tmp + (adc_ave_tmp >> 3); // exponential duty cycle control for fast accurate responce |
43 | }
|
44 | |
45 | adc_ave_tmp = adc_ave; |
46 | while ((adc_ave_tmp > setpnt) && (dutycycle > min_duty)) |
47 | {
|
48 | dutycycle -= 1; |
49 | adc_ave_tmp = adc_ave_tmp - (adc_ave_tmp >> 3); // exponential duty cycle control for fast accurate responce |
50 | }
|
51 | pwm_duty_cycle(dutycycle); |
52 | |
53 | adc_ave = 0; // flush the averaging accumulator |
54 | }
|
55 | }
|
56 | //------------------------------------------------------
|
57 | }
|
So wie ich den Code verstehe, mittelt er 16 Messwerte (wobei es bei der ersten Messung Probleme geben könnte, da dort nur ein einziger vorhanden sein könnte). Dann berechnet er auf Grundlage des "Mittelwerts" (>>3 ist doch eigentlich nur ein Teilen durch 8...) den Tastgrad seiner PWM. setpnt ist der eingestellte Ladestrom, der durch
1 | temp_16 = ADC_get(); |
2 | if (voltage_100 <= temp_16) |
3 | {
|
4 | temp_32 = temp_16 - voltage_100; |
5 | temp_32 = temp_32 * (pwm_300-pwm_100); |
6 | temp_32 = temp_32 / (voltage_300-voltage_100); |
7 | temp_32 = pwm_100 + temp_32; |
8 | }
|
9 | else
|
10 | {
|
11 | temp_32 = voltage_100 - temp_16; |
12 | temp_32 = temp_32 * (pwm_300-pwm_100); |
13 | temp_32 = temp_32 / (voltage_300-voltage_100); |
14 | temp_32 = pwm_100 - temp_32; |
15 | }
|
16 | setpnt = temp_32; |
berechnet wird. Der ADC arbeitet voller Auflösung. voltage_300, voltage_100, pwm_300 und pwm_100 sind Konstanten, die beim Kalibrieren im EEPROM gespeichert und dann wieder ausgelesen werden.
@Rahul Du hast mir jetzt einige Details klarer gemacht. Danke dafür! Ich werde mal ein kleines Programm mit Bascom schreiben, was mir nur die PWM mittels Poti ansteuerbar macht. Dann kann ich sehen, ob ich den Strom _überhaupt_ so weit runterkriege, wie ich es brauche. Denn ob ich mit der Drossel von 500 uH den Bereich von 10-300mA überhaupt erwische, habe ich noch nicht probiert. Ich hänge Dir mal mein Programm an. (Achtung, ist so noch nicht komplett!!) MfG Paul
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.