Forum: Mikrocontroller und Digitale Elektronik Hilfe bei C-Programm Problem gesucht


von Paul Baumann (Gast)


Lesenswert?

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


von jack (Gast)


Lesenswert?

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.

von Paul Baumann (Gast)


Angehängte Dateien:

Lesenswert?

@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

von Rahul, der Trollige (Gast)


Lesenswert?

Die 2004er-Version enthält noch eine ganze Menge Zeug, das nicht mehr 
AVRgcc-aktuell ist...

von Rahul, der Trollige (Gast)


Angehängte Dateien:

Lesenswert?

Ich häng mal die untested-Version an.

von jack (Gast)


Lesenswert?

@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.

von Rahul, der Trollige (Gast)


Lesenswert?

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...)

von Rahul, der Trollige (Gast)


Angehängte Dateien:

Lesenswert?

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

von jack (Gast)


Lesenswert?

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?

von Paul Baumann (Gast)


Lesenswert?

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



von Paul Baumann (Gast)


Lesenswert?

@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

von Rahul, der Trollige (Gast)


Lesenswert?

>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).

von Rahul, der Trollige (Gast)


Lesenswert?

oder an der Schaltfrequenz...

von Paul Baumann (Gast)


Lesenswert?

@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

von Rahul, der Trollige (Gast)


Lesenswert?

>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

von Rahul, der Trollige (Gast)


Lesenswert?

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.

von Paul Baumann (Gast)


Angehängte Dateien:

Lesenswert?

@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
Noch kein Account? Hier anmelden.