Ah zählt zu schnell hoch bei 0,328A sind es 1mA pro Sekunde

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Ah zählt zu schnell hoch bei 0,328A sind es 1mA pro Sekunde

      Hallo,

      ich hab mal wieder mißt gebaut.
      Ich hab mir ein kleines Meßgerät zum messen von Batteriekapazitäten gebastelt.
      Leider zählt das ding zu schnell hoch.
      Bei einem Strom von 0,328A der auch richtig angezeigt wird zählt er um 1mAh pro Sekunde hoch.
      Eigendlich müssten es viel weniger sein und ich finde den Fehler einfach nicht.

      Source Code

      1. '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      2. 'Mikrocontroller Konfigurieren
      3. $regfile = "m48def.dat" ' specify the used micro
      4. $crystal = 1000000 ' used crystal frequency
      5. $hwstack = 32 ' default use 32 for the hardware stack
      6. $swstack = 10 ' default use 10 for the SW stack
      7. $framesize = 40 ' default use 40 for the frame space
      8. 'Ende Mikrocontroller Konfigurieren
      9. '=============================================================
      10. '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      11. 'Ports für Display Konfigurieren PortD,
      12. Config Portd = Output 'LCD Display Datenbits
      13. 'LCD Datenbits im 8BIT Mod
      14. Config Portb.0 = Output 'LCD E
      15. 'LCD Enable
      16. Config Portb.1 = Output 'LCD Rs
      17. 'LCD Reset
      18. Config Portc.5 = Input
      19. Config Portc.3 = Input
      20. Config Portc.1 = Input
      21. 'Ende Ports für Display Konfigurieren PortD
      22. '=============================================================
      23. '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      24. 'LCD Displayö Konfigurieren PORTD, PortB.6, PortB.7
      25. Waitms 100
      26. Config Lcdpin = Pin , Port = Portd , E = Portb.0 , Rs = Portb.1
      27. Config Lcdbus = 8 ' LCD arbeitet über 8-Bit
      28. Config Lcd = 16 * 2
      29. Initlcd
      30. 'Ende LCD Display Konfigurieren PORTD, PortB.6, PortB.7
      31. '=============================================================
      32. '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      33. 'Spannung Messen Anfang
      34. Config Adc = Single , Prescaler = Auto , Reference = Internal
      35. Start Adc
      36. 'Ende Spannung Messen
      37. '=============================================================
      38. '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      39. 'Datum Konfigurieren
      40. Enable Interrupts
      41. Config Date = Dmy , Separator = .
      42. Config Clock = Soft
      43. 'Ende Datum Konfigurieren
      44. '=============================================================
      45. '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      46. 'Variablen
      47. Dim Var_old_sec As Byte
      48. Dim Var_adc_ampere As Word
      49. Dim Var_adc_volt_batterie As Word
      50. Dim Var_adc_volt_eigenver As Word
      51. Dim Var_ampere As Single
      52. Dim Var_ampere_tmp As Single
      53. Dim Var_volt_batterie As Single
      54. Dim Var_volt_eigenver As Single
      55. Dim Var_ampere_hour As Single
      56. Dim Var_zeile(2) As String * 16
      57. Dim Var_eram_ampere_hour As Single
      58. Dim Var_eram As Bit
      59. 'Ende Variablen
      60. '=============================================================
      61. '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      62. 'Konstanten
      63. Const Cons_2_1v = 0.001973876953125
      64. 'Spannungsteiler 2,1Volt
      65. Const Cons_5_8v = 0.0056640625
      66. 'Spannungsteiler für Eigenversorgung
      67. Const Cons_ampere = 0.0020131106321
      68. 'Strom an 0,5Ohm
      69. 'Ende Konstanten
      70. '=============================================================
      71. '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      72. 'Hauptprogramm
      73. 'Var_ampere_hour = Var_eram_ampere_hour
      74. Do
      75. Waitms 5
      76. Var_adc_ampere = Getadc(5)
      77. Waitms 15
      78. Var_adc_volt_batterie = Getadc(3)
      79. Waitms 15
      80. Var_adc_volt_eigenver = Getadc(1)
      81. Waitms 5
      82. Var_ampere = Var_adc_ampere * Cons_ampere
      83. Var_volt_batterie = Var_adc_volt_batterie * Cons_2_1v
      84. Var_volt_eigenver = Var_adc_volt_eigenver * Cons_5_8v
      85. If _sec <> Var_old_sec Then
      86. Var_old_sec = _sec
      87. Var_ampere_tmp = Var_ampere / 3600
      88. Var_ampere_hour = Var_ampere_hour + Var_ampere_tmp
      89. End If
      90. Locate 1 , 1
      91. Var_zeile(1) = "A:" + Fusing(var_ampere , "#.###") + "|Ah:" + Fusing(var_ampere_hour , "#.###")
      92. Lcd Var_zeile(1)
      93. Var_zeile(1) = ""
      94. Locate 2 , 1
      95. Var_zeile(2) = "VB:" + Fusing(var_volt_batterie , "#.##") + "|VV:" + Fusing(var_volt_eigenver , "#.##")
      96. Lcd Var_zeile(2)
      97. Cursor Off
      98. If Var_volt_eigenver < 2.7 Then
      99. 'If Var_eram = 0 Then
      100. ' Var_eram = 1
      101. ' Var_eram_ampere_hour = Var_ampere_hour
      102. 'End If
      103. Goto Ende
      104. End If
      105. Loop
      106. Ende:
      107. Portd = 0
      108. Portb.0 = 0
      109. Portb.1 = 0
      110. Powerdown
      111. 'Ende Hauptprogramm
      112. '=============================================================
      Display All
      Grüße & Danke!
      Alex
    • Ich würde mal vor dem Anzeigen der Werte, die Zeile des displays mit Leerzeichen 'löschen' und dann den string mit den Ampere und Ah zusammenbasteln und anzeigen. Sonst sehe ich jetzt auch keinen Fehler, dein fusing rundet, vielleicht führt das zu 1mA/h. Wenn's länger läuft, was wird angezeigt und was sollte handrechnerisch angezeigt werden?
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Alex_T wrote:

      Bei einem Strom von 0,328A der auch richtig angezeigt wird zählt er um 1mAh pro Sekunde hoch.
      Dass der Strom richtig angezeigt wird, wundert mich, denn ich komme auf einen etwas anderen Wert für Cons_ampere:

      Bei einem Strom von genau 1 Ampere fallen am 0,5 Ohm-Widerstand 0,5 Volt ab. Mit der internen Referenz von 1,1V ergibt sich bei einem Ampere ein ADC-Wert von (0,5V/1,1V)*1023, also 465. Damit ergibt sich für Cons_ampere ein Wert von 1/465, also 0,00215053. Dieser Wert liegt allerdings sehr nahe bei Deinem, und diese 5% Unterschied können ja nicht das einzige Problem sein. Ich frage mich halt nur, wie Du zu Deinem Wert für Const_ampere gekommen bist.

      Irgendwo muss aber noch ein zweiter Fehler drinstecken, der ziemlich genau der Faktor 10 ins Spiel bringt: Ein Strom von 0,328 A ergibt über eine Stunde eine Ladung von 328 mAh, und über eine Sekunde dementsprechend (fast) genau 0,1 mAh, also 1/10 von dem, was Dein Controller ausrechnet. Für mich sieht das also so aus, als wärde irgendwo ein Komma nicht ganz an der richtigen Stelle.
    • Einzeller wrote:

      Alex_T wrote:

      Bei einem Strom von 0,328A der auch richtig angezeigt wird zählt er um 1mAh pro Sekunde hoch.
      Dass der Strom richtig angezeigt wird, wundert mich, denn ich komme auf einen etwas anderen Wert für Cons_ampere:
      Bei einem Strom von genau 1 Ampere fallen am 0,5 Ohm-Widerstand 0,5 Volt ab. Mit der internen Referenz von 1,1V ergibt sich bei einem Ampere ein ADC-Wert von (0,5V/1,1V)*1023, also 465. Damit ergibt sich für Cons_ampere ein Wert von 1/465, also 0,00215053. Dieser Wert liegt allerdings sehr nahe bei Deinem, und diese 5% Unterschied können ja nicht das einzige Problem sein. Ich frage mich halt nur, wie Du zu Deinem Wert für Const_ampere gekommen bist.

      Irgendwo muss aber noch ein zweiter Fehler drinstecken, der ziemlich genau der Faktor 10 ins Spiel bringt: Ein Strom von 0,328 A ergibt über eine Stunde eine Ladung von 328 mAh, und über eine Sekunde dementsprechend (fast) genau 0,1 mAh, also 1/10 von dem, was Dein Controller ausrechnet. Für mich sieht das also so aus, als wärde irgendwo ein Komma nicht ganz an der richtigen Stelle.
      Die Werte hab ich manuell nchjustiert.
      Die errechneten Werte waren anders, da aber die Widertände entsprechende Toleranzen hatten stimmten sie mit den Referenzmessungen nicht überein. Dann hab ich die Werte entsprechend angepasst.
      Meine Widerstände haben eine Toleranz von 5%.

      Der Fehler muss irgendwo am Mikrochip liegen. In der Sim mit entkernter Software und manueller werteingabe funktioniert das ganze wunderbar. Trotz mehrfacher suche finde ich einfach nichts. Wahrscheinlich sehe ich den Wald vor lauter Bäumen nicht.

      Als schnelle und schmutzige Lösung fällt mir nur ein den Teilfaktor auf 36000 zu erhöhen. Mal schauen ob das was bringt.

      Grüße
      Alex
    • tschoeatsch wrote:

      Ich würde mal vor dem Anzeigen der Werte, die Zeile des displays mit Leerzeichen 'löschen' und dann den string mit den Ampere und Ah zusammenbasteln und anzeigen. Sonst sehe ich jetzt auch keinen Fehler, dein fusing rundet, vielleicht führt das zu 1mA/h. Wenn's länger läuft, was wird angezeigt und was sollte handrechnerisch angezeigt werden?
      Ich wollte bei jeden 40 oder 80 mal ein cls machen lassen.
      Das mit dem Display ist aber erstmal nicht so wichtig.
      Viel wichtiger ist es das ich diesen Fehler finde.

      Der Fehler ist da und irgendwie muss man den auch finden können...
      Wahrscheinlich ist er dermaßen einfach das ich ihn erst nach Wochen sehe...

      Grüße
      Alex
    • Update:

      Ich habe mir gerade per Time$ die Uhrzeit anzeigen lassen und hab festgestellt das die Minuten etwa wie Sekunden durchlaufen und die Sekunden in einem Tempo das man sie kaum erkennen kann.

      Kann das am Quarz liegen? Ich habe einen 8Mhz Quarz drin und den Teiler in den Fuse auf 8 gestellt. Im Programm steht bei mir $crystal = 1000000 - kann es sein das ich das hier auf 8000000 stellen muss?


      Ergibt aber immer noch keinen Sinn. Da das Programm nicht 8 mal so schnell läuft sondern 10,03 mal so schnell.


      Grüße

      Alex
    • Hallo Alex,
      du verwendest den falschen Quarz. Bei der internen Uhr wird ein Quarz mit 32,768kHz gebraucht.
      Auszug aus dem Datenblatt.
      6.10 Timer/Counter OscillatorThe device can operate its Timer/Counter2 from an external 32.768kHz watch crystal or a external clock source. TheTimer/Counter oscillator pins (TOSC1 and TOSC2) are shared with XTAL1 and XTAL2. This means that the Timer/Counteroscillator can only be used when an internal RC oscillator is selected as system clock source.

      Du könntest den Prozessor auch mit den internen Takt laufen lassen und den Uhrenquarz anstelle des 8Mhz Quarzes einsetzen oder verwende doch einfach eine externe Uhr die du über denI²C Bus ansteuerst.
      Versuch macht klug !

      The post was edited 3 times, last by Cable ().

    • Cable wrote:

      Hallo Alex,
      du verwendest den falschen Quarz. Bei der internen Uhr wird ein Quarz mit 32,768kHz gebraucht.
      Auszug aus dem Datenblatt.
      6.10 Timer/Counter OscillatorThe device can operate its Timer/Counter2 from an external 32.768kHz watch crystal or a external clock source. TheTimer/Counter oscillator pins (TOSC1 and TOSC2) are shared with XTAL1 and XTAL2. This means that the Timer/Counteroscillator can only be used when an internal RC oscillator is selected as system clock source.

      Du könntest den Prozessor auch mit den internen Takt laufen lassen und den Uhrenquarz anstelle des 8Mhz Quarzes einsetzen oder verwende doch einfach eine externe Uhr die du über denI²C Bus ansteuerst.
      Gibts keine irgendwie geartete Möglichkeit das doch mit dem 8 Mhz Quarz hin zu bekommen?
      Bei meiner dcf77 Uhr hab ich einen 16Mhz Quarz drin und da funktioniert das recht präzise.
      Ahaaaaaaaaaa - Vielleicht mal versuchen von config clock auf config dcf77 umsteigen?

      Das mit dem 32khz ding ist doch eigendlich kontraproduktiv oder? Ich mein je höher die Frequenz des Quarzes desto höher die Präzision, oder? Außerdem dürften dann kleinere Produktionabweichungen kaum eine Rolle spielen...

      tschoeatsch wrote:

      @Alex_T Wenn du nur den Sekundentakt brauchst, dann tut's ein timer-int auch.
      Also, dann kann der 8Mhz Quarz bleiben? Kannst du mir kurz ein paar Code zeilen tippen?
      config clock = soft fällt dann raus?

      Grüße & Danke!
      Alex
    • @Alex_T schau mal hier Tool für Timerberechnung
      dieses tool erzeugt gleich den passenden code samt Erklärungen dazu. Finde ich ganz nett.
      Damit kannst du eine isr einrichten, die alle Sekunde aufgerufen wird, in der setzt du nur ein flag. Im main wartest du, bis das flag gesetzt wird, machst deine Berechnungen und setzt das flag zurück. Fast genau so, wie du es mit den _sec gemacht hast.
      der code, der erzeugt wird, schaut dann so aus

      BASCOM Source Code

      1. const Timer1Reload = 31250
      2. config timer1=timer,prescale = 256
      3. load timer1 , Timer1Reload
      4. on ovf1 Timer1_isr
      5. enable timer1
      6. start timer1
      7. enable interrupts
      8. 'Add your code here
      9. Timer1_ISR:
      10. load timer1, Timer1Reload
      11. 'Add your ISR code here
      12. return
      13. 'Timer value explination
      14. ' The timer is a 16Bit timer, it overflows when the timer reaches 65536
      15. ' The AVR is running at 8000000Hz, the prescaler is 256
      16. ' Each tick is 0,032 ms - (1 / CPUSpeed in KHz ) * Prescaler
      17. ' The timer needs 31250 ticks to reach the required time ( 31250 * 0,032 = 1000ms)
      18. ' The start value for the timer must be set to 34286 so that it will overflow at 65536 after 31250 ticks
      19. ' NOTE: The load command does the inversion for you (256-value or 65536-value)
      Display All

      oder, bei 1 Mhz

      BASCOM Source Code

      1. const Timer1Reload = 15625
      2. config timer1=timer,prescale = 64
      3. load timer1 , Timer1Reload
      4. on ovf1 Timer1_isr
      5. enable timer1
      6. start timer1
      7. enable interrupts
      8. 'Add your code here
      9. Timer1_ISR:
      10. load timer1, Timer1Reload
      11. 'Add your ISR code here
      12. return
      13. 'Timer value explination
      14. ' The timer is a 16Bit timer, it overflows when the timer reaches 65536
      15. ' The AVR is running at 1000000Hz, the prescaler is 64
      16. ' Each tick is 0,064 ms - (1 / CPUSpeed in KHz ) * Prescaler
      17. ' The timer needs 15625 ticks to reach the required time ( 15625 * 0,064 = 1000ms)
      18. ' The start value for the timer must be set to 49911 so that it will overflow at 65536 after 15625 ticks
      19. ' NOTE: The load command does the inversion for you (256-value or 65536-value)
      Display All
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------

      The post was edited 1 time, last by tschoeatsch ().

    • tschoeatsch wrote:

      @Alex_T schau mal hier Tool für Timerberechnung
      dieses tool erzeugt gleich den passenden code samt Erklärungen dazu. Finde ich ganz nett.
      Damit kannst du eine isr einrichten, die alle Sekunde aufgerufen wird, in der setzt du nur ein flag. Im main wartest du, bis das flag gesetzt wird, machst deine Berechnungen und setzt das flag zurück. Fast genau so, wie du es mit den _sec gemacht hast.
      der code, der erzeugt wird, schaut dann so aus

      BASCOM Source Code

      1. const Timer1Reload = 31250
      2. config timer1=timer,prescale = 256
      3. load timer1 , Timer1Reload
      4. on ovf1 Timer1_isr
      5. enable timer1
      6. start timer1
      7. enable interrupts
      8. 'Add your code here
      9. Timer1_ISR:
      10. load timer1, Timer1Reload
      11. 'Add your ISR code here
      12. return
      13. 'Timer value explination
      14. ' The timer is a 16Bit timer, it overflows when the timer reaches 65536
      15. ' The AVR is running at 8000000Hz, the prescaler is 256
      16. ' Each tick is 0,032 ms - (1 / CPUSpeed in KHz ) * Prescaler
      17. ' The timer needs 31250 ticks to reach the required time ( 31250 * 0,032 = 1000ms)
      18. ' The start value for the timer must be set to 34286 so that it will overflow at 65536 after 31250 ticks
      19. ' NOTE: The load command does the inversion for you (256-value or 65536-value)
      Display All
      oder, bei 1 Mhz

      BASCOM Source Code

      1. const Timer1Reload = 15625
      2. config timer1=timer,prescale = 64
      3. load timer1 , Timer1Reload
      4. on ovf1 Timer1_isr
      5. enable timer1
      6. start timer1
      7. enable interrupts
      8. 'Add your code here
      9. Timer1_ISR:
      10. load timer1, Timer1Reload
      11. 'Add your ISR code here
      12. return
      13. 'Timer value explination
      14. ' The timer is a 16Bit timer, it overflows when the timer reaches 65536
      15. ' The AVR is running at 1000000Hz, the prescaler is 64
      16. ' Each tick is 0,064 ms - (1 / CPUSpeed in KHz ) * Prescaler
      17. ' The timer needs 15625 ticks to reach the required time ( 15625 * 0,064 = 1000ms)
      18. ' The start value for the timer must be set to 49911 so that it will overflow at 65536 after 15625 ticks
      19. ' NOTE: The load command does the inversion for you (256-value or 65536-value)
      Display All
      Herzlichen Dank!
      Werd es morgen gleich mal testen.

      Hab bis jetzt config dcf77 drin was auch wunderbar funzt.
      Braucht mir nur etwas zuviel Speicher am MC.

      Aktuell teste ich mit meiner Schaltung gerade eine Monozelle auf seine Kapazität.

      Grüße
      Alex
    • Mitch64 wrote:

      Die Uhr läuft mit Preload in der ISR bestimmt zu langsam.
      Ob das auffällt, ist die Frage. Prescaler 64 (bei 1Mhz), das heißt doch, dass das Laden der Werte weniger lang dauert, als ein timertick. 15625 ticks braucht der für 1 Sekunde, 1 tick hin oder her, da ist doch die Widerstandstoleranz vom shunt größer und produziert mehr Messfehler, als eine fette Sekunde. Man könnte auch die vom tool berechneten Werte für den ctc-Modus verwenden.


      Alex_T wrote:

      Das mit dem 32khz ding ist doch eigendlich kontraproduktiv oder? Ich mein je höher die Frequenz des Quarzes desto höher die Präzision, oder? Außerdem dürften dann kleinere Produktionabweichungen kaum eine Rolle spielen...
      das stimmt nicht. In Datenblättern wirst du bei der Genauigkeit einen Wert 'soundsoviel ppm' finden, da kann ein Uhrenquarz genauer sein, als ein 16Mhz Quarz. die 32khz haben halt den Vorteil, dass man mit einfachen Frequenzteilern in wenigen Schritten auf 1Hz kommt, beim AVR mit einem 8bit-timer und einem passenden prescaler auch. Mit mehreren Mhz als Ausgangsfrequenz ist der Aufwand auf 1 Sekunde zu kommen höher und es bleiben zum Teil Reste beim Teilen.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------

      The post was edited 1 time, last by tschoeatsch ().

    • tschoeatsch wrote:

      Man könnte auch die vom tool berechneten Werte für den ctc-Modus verwenden.
      Das wäre definitiv die bessere Wahl, vom berechneten Wert aber Wert-1 in das Register schreiben.

      tschoeatsch wrote:

      Ob das auffällt, ist die Frage. Prescaler 64 (bei 1Mhz), das heißt doch, dass das Laden der Werte weniger lang dauert, als ein timertick.
      Ja, aber du vegrisst die ganzen Register, die Bascom automatisch sichert. Die kommen noch On-Top.

      tschoeatsch wrote:

      In Datenblättern wirst du bei der Genauigkeit einen Wert 'soundsoviel ppm' finden, da kann ein Uhrenquarz genauer sein
      Wenn man bei Reichelt die Quarze durchsieht, haben die alle eine Toleranz von +/-30ppm.
      Die Uhrenquarze alle +/-20ppm. Sind also etwas genauer.

      Die Angabe "ppm" bedeutet "Parts per Million". Also bei 1Mio Takten kann der Quarz +/- 30 Takte mehr/weniger haben.
      Egal wieviel Hz der Quarz hat.
      Ein 16MHz Quarz kann somit 16 x +/-30ppm haben, also +/-480Hz Abweichung. Ein 2MHz Quarz 2 x 30ppm, also +/-60Hz.
    • Mitch64 wrote:

      bestimmt zu langsam
      Vom errechneten Preload Wert 2 abziehen dann paßts besser. ca 120 braucht die isr. Dann könnte noch die Abweichung nach einem Tag festgestellt werden um es mit ein paar nop ganz genau zu bekommen. Die Quartzabweichung ist konstant. Wenn er heute 20 zu langsam ist ist er es auch in drei Wochen noch. Somit wäre eine Armbanduhrgenauigkeit hin zu bekommen.
    • Klar, wenn in der isr der timer mit preload gesetzt wird, dann läuft während dieses Befehls der timer weiter und auch in der Zeit, wo die Register gesichert werden. Ich behaupte aber, dass geschied innerhalb von 64 Systemtakten, also einem timertakt. Das ist der eigentliche Grund, warum dadurch die Sekunde etwas länger dauert. Im ctc entfällt dieser Befehl, dadurch wird die isr auch genau nach den vorgegebenen timerticks aufgerufen und das Registersichern verzögert auch nix.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------