Dreistellige BCD Ausgabe für Nixies

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

    • Dreistellige BCD Ausgabe für Nixies

      Guten Tag Zusammen,

      bin noch relativ neu hier und hab bisher mehr oder weniger nur gelesen. Bitte steinigt mich nicht gleich, falls es dazu schon einen Beitrag gibt, bin mit der SuFu noch nicht so Firm.

      Zum Projekt:

      Für einen Röhrenverstärker soll über zwei Dreh-Encoder zum einen ein Digitaler Hifi-Poti angesteuert werden (PGA2310 über SPI) und parallel der Wert über insgesamt fünf Nixies (Vorzeichen +/-, zwei Ziffern 0-9, Nachkommastelle nur 0 oder 5 , ein dB-Zeichen, aber das ist statisch) ausgegeben werden.
      Der zweite Dreh-Encoder ist nur für die Kanal-Auswahl und Stand-by gedacht.

      Auf meinem Experimentierboard hab ich einen ATMega8 (kann aber auch ein anderer werden) und programmieren tu ich mit der Freeware, bin also auf 4k beschränkt.

      Der PGA2310 bekommt den Wert seriell mit jeweils 8Bit pro Kanal, also 0-255 und arbeitet von +31.5 bis -95.5dB. Die Mathematik für die Anzeige wollte ich im Controller machen, also mit der Formel 315 - [5 * (255 - N)] eine dreistellige Zahl aus meinem Binärwert machen und diese als Binärwert über die IOs ausgeben. Der Einfachheit halber wollte ich einfach mit ganzzahligen Werten arbeiten und das Komma nur statisch bei der Röhre einblenden, daher 315 bis -955.

      Problem aktuell, mit Makebcd kann ich nur ein Byte verarbeiten und die Hunderterstelle bekomme ich nicht umgesetzt. Da das ganze ja auch negativ werden kann, brauche ich wohl einen Integer und den kann Makebcd ja auch nicht, so wie ich das verstanden habe.

      Gibt es da einen fertigen Bascom Befehl/-weg, oder muss ich da selbst was stricken?
      Ich bin hier schon über den Binär zu BCD Wettbewerb gestolpert, aber da versteh ich ehrlich gesagt nur Bahnhof. Mein letzter Kontakt mit Assembler war 2004...

      Kann mir vielleicht einer einen kleinen gedanklichen Schubs in die richtige Richtung geben?

      Gruß,

      Flo
    • BlackTigraC20XE wrote:

      eine dreistellige Zahl aus meinem Binärwert machen und diese als Binärwert über die IOs ausgeben.
      Wie sind denn die Röhren an den Ports angeschlossen, über einen BCD-zu-Dezimal-Decoder?

      BlackTigraC20XE wrote:

      Gibt es da einen fertigen Bascom Befehl/-weg, oder muss ich da selbst was stricken?
      Da gibt es leider nichts fertiges, das musst du schon selber bauen.
      Die Zahl kannst du aber sehr einfach in die einzelnen Teile zerlegen und über eine Datentabelle die passende BCD-Information dazu raussuchen.
      Falls zwei Röhren an einem Port hängen sollten kannst du eine Byte-Variable mit zwei Mal BCD am Port ausgeben.
      Eine solche Datentabelle könnte für einen Port so aussehen:

      BASCOM Source Code

      1. 'Erste Stelle von links 100er
      2. First_digit:
      3. Data &B0000_0000 '0
      4. Date &B0001_0000 '1
      5. Data &B0010_0000 '2
      6. Data &B0011_0000 '3
      7. Data &B0100_0000 '4
      8. Data &B0101_0000 '5
      9. Data &B0110_0000 '6
      10. Data &B0111_0000 '7
      11. Data &B1000_0000 '8
      12. Data &B1001_0000 '9
      13. 'Zweite Stelle von links 10er
      14. Second_digit:
      15. Data &B0000_0000 '0
      16. Data &B0000_0001 '1
      17. Data &B0000_0010 '2
      18. Data &B0000_0011 '3
      19. Data &B0000_0100 '4
      20. Data &B0000_0101 '5
      21. Data &B0000_0110 '6
      22. Data &B0000_0111 '7
      23. Data &B0000_1000 '8
      24. Data &B0000_1001 '9
      Display All

      und zusammenführen kannst du die beiden BCD-Zahlen so:

      BASCOM Source Code

      1. Dim Hunderter As Byte , Zehner As Byte , Einer As Byte
      2. Hunderter = Lookup(3 , First_digit)
      3. Zehner = Lookup(1 , Second_digit)
      4. Ausgabe_port1 = Hunderter Or Zehner
      5. Einer = Lookup(5 , First_digit) 'oder
      6. Einer = Lookup(5 , Second_digit) 'je nachdem auf welche 4 Portpinns die letzte Stelle liegt
      7. Ausgabe_port2 = Einer
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • Zum zerlegen der Zahl kannst du folgendermaßen vorgehen:

      BASCOM Source Code

      1. Dim Db_wert As Word , 1er As Byte , 10er As Byte , 100er As Byte
      2. Db_wert = 315
      3. 1er = Db_wert Mod 10 '5
      4. 10er = Db_wert Mod 100 '15
      5. 100er = Db_wert - 10er '300
      6. 10er = 10er - 1er '15 - 5 = 10
      7. 10er = 10er / 10 '10 / 10 = 1
      8. 100er = 100er / 100 '300 / 100 = 3
      Bleibt am Ende nur noch das Herausfinden der negativen Werte.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • Danke für die schnelle Hilfe, habs nun am Laufen, auch wenn da ganz sicher noch Luft für Optimierung ist.

      Es zählt sauber von -95.5 in 0,5er Schritten bis 31,5. Die Vorzeichen +/- geb ich über zwei LEDs aus, Mute wird ebenfalls über eine LED ausgegeben.

      Ich hab aktuell noch meinen makebcd Part drinne, wäre die Wertetabelle effektiver?

      Hier mal mein Code, bin bei 22% Flash. Zeigt Bascom mit eigentlich 22% von den vollen 8k an, oder berücksichtigt es schon das Limit bei 4k?

      Gruß,

      Flo

      BASCOM Source Code

      1. $Regfile="m8def.dat"
      2. $Crystal=4000000
      3. $hwstack=40
      4. $swstack=16
      5. $framesize=32
      6. dim Enc as Byte
      7. On int0 Taster
      8. On int1 _Encoder
      9. config int0=falling
      10. config int1=falling
      11. enable int0
      12. enable int1
      13. enable interrupts
      14. Config Portb = Output
      15. Config Portc = Output
      16. Enc_A alias Pind.3
      17. Enc_B alias PIND.4
      18. Led1 Alias PortB.0
      19. Led2 Alias Portb.1
      20. Led3 Alias Portb.2
      21. Led4 Alias Portb.3
      22. Led5 Alias PortB.4
      23. Led6 Alias Portb.5
      24. Led7 Alias Portb.6
      25. Led8 Alias Portb.7
      26. Led9 Alias PortC.0
      27. Led10 Alias PortC.1
      28. Led11 Alias PortC.2
      29. Led12 Alias PortC.3
      30. Plus alias Portc.4
      31. Minus alias Portc.5
      32. Mute ALias PortD.1
      33. Config Mute = Output
      34. 'Variablen BCD
      35. Dim A As Byte
      36. Dim B As Byte
      37. Dim C As Byte
      38. Dim A1bcd As Bit
      39. Dim B1bcd As Bit
      40. Dim C1bcd As Bit
      41. Dim D1bcd As Bit
      42. Dim A10bcd As Bit
      43. Dim B10bcd As Bit
      44. Dim C10bcd As Bit
      45. Dim D10bcd As Bit
      46. Dim A100bcd As Bit
      47. Dim B100bcd As Bit
      48. Dim C100bcd As Bit
      49. Dim D100bcd As Bit
      50. dim 1er as Integer
      51. dim 10er as Integer
      52. dim 100er as Integer
      53. dim 1er_bcd as Byte
      54. dim 10er_bcd as Byte
      55. dim 100er_bcd as Byte
      56. 'Variablen Mathe
      57. dim Wert as Integer
      58. dim dBWert as Integer
      59. dim sub1 as Integer
      60. dim sub2 as Integer
      61. dim 10erI as Integer
      62. dim maxw as Integer
      63. 'Grundwert festlegen
      64. dim Grundwert as Byte
      65. Grundwert = 192
      66. enc = Grundwert
      67. 'Hauptschleife
      68. do
      69. 'Mathe & Zwischenwerte
      70. maxw = 315
      71. Wert = Enc
      72. sub1 = 255 - Wert
      73. sub2 = sub1 * 5
      74. dBWert = maxw - sub2
      75. 'Vorzeichenauswertung
      76. if dbwert < 0 then Minus = 1 else Minus = 0
      77. if dbwert > 0 then Plus = 1 else plus = 0
      78. 'Mathe für BCD
      79. 1er = dBWert Mod 10
      80. 10er = dBWert Mod 100
      81. 100er = dBWert - 10er
      82. 10er = 10er - 1er
      83. 10er = 10er / 10
      84. 100er = 100er / 100
      85. 'negative zu positiven Werten; Integer zu Byte
      86. 1er_bcd = 1er ^ 2
      87. 1er_bcd = sqr(1er_bcd)
      88. 10er_bcd = 10er ^ 2
      89. 10er_bcd = sqr(10er_bcd)
      90. 100er_bcd = 100er ^ 2
      91. 100er_bcd = sqr(100er_bcd)
      92. 'BCD Auswertung
      93. A = Makebcd(1er_bcd)
      94. A1bcd = A.0
      95. B1bcd = A.1
      96. C1bcd = A.2
      97. D1bcd = A.3
      98. Led1 = A1bcd
      99. Led2 = B1bcd
      100. Led3 = C1bcd
      101. Led4 = D1bcd
      102. B = Makebcd(10er_bcd)
      103. A10bcd = B.0
      104. B10bcd = B.1
      105. C10bcd = B.2
      106. D10bcd = B.3
      107. LED5 = A10bcd
      108. LED6 = B10bcd
      109. LED7 = C10bcd
      110. LED8 = D10bcd
      111. C = Makebcd(100er_bcd)
      112. A100bcd = C.0
      113. B100bcd = C.1
      114. C100bcd = C.2
      115. D100bcd = C.3
      116. LED9 = A100bcd
      117. LED10 = B100bcd
      118. LED11 = C100bcd
      119. LED12 = D100bcd
      120. loop
      121. 'Taster für Mute
      122. Taster:
      123. toggle Mute
      124. return
      125. _Encoder:
      126. if enc>1 and Enc_a=1 and Enc_b=0 then Enc=Enc-1
      127. if enc>1 and Enc_a=0 and Enc_b=1 then Enc=Enc-1
      128. if enc<255 and Enc_b=1 and Enc_a=1 then Enc=Enc+1
      129. if enc<255 and Enc_b=0 and Enc_a=0 then Enc=Enc+1
      130. return
      Display All
    • BlackTigraC20XE wrote:

      Zeigt Bascom mit eigentlich 22% von den vollen 8k an, oder berücksichtigt es schon das Limit bei 4k?
      Wenn die 4Kb-Grenze überschritten wird zeigt Bascom unten einen Fehler an. Also es zeigt bei Compilieren die volle Größe an. Nur wenn die 4Kb überschritten werden gibt es einen fehlermeldung und es wird nicht mehr compilliert.

      BlackTigraC20XE wrote:

      Ich hab aktuell noch meinen makebcd Part drinne, wäre die Wertetabelle effektiver?
      Wenn es so funktioniert, dann lass es drin. Ich nehme allerdings lieber die Datentabellen :)
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • So, die SPI läuft auch, am Ende der SPI Subroutine schreibe ich nochmal den gesendeten Wert in eine Variable, am Anfang der Hauptschleife wird abgefragt, ob der Wert sich geändert hat und nur im Falle einer Änderung die SPI Subroutine aufgerufen. Bin jetzt bei 24% Flash, muss aber erstmal auf neue Hardware wechseln, mir gehen die I/O Pins aus und ich muss noch einen zweiten Drehregler und eine Relaissteuerung einfügen :)

      Hat jemand vielleicht Tips, was ich optimieren könnte?

      Gruß,

      Flo

      BASCOM Source Code

      1. $Regfile="m8def.dat"
      2. $Crystal=4000000
      3. $hwstack=40
      4. $swstack=16
      5. $framesize=32
      6. dim Enc as Byte
      7. dim Enc_SPI_sent as Byte
      8. dim Enc_SPI as Word
      9. dim Enc_SPIL as Word
      10. dim Enc_SPIR as Word
      11. On int0 Taster
      12. On int1 _Encoder
      13. config int0=falling
      14. config int1=falling
      15. enable int0
      16. enable int1
      17. enable interrupts
      18. Config Portb = Output
      19. Config Portc = Output
      20. Enc_A alias Pind.3
      21. Enc_B alias PIND.4
      22. Led1 Alias PortB.0
      23. Led2 Alias Portb.1
      24. Led3 Alias Portb.2
      25. Led4 Alias Portb.3
      26. Led5 Alias PortB.4
      27. Led6 Alias Portb.5
      28. Led7 Alias Portb.6
      29. Led8 Alias Portb.7
      30. Led9 Alias PortC.0
      31. Led10 Alias PortC.1
      32. Led11 Alias PortC.2
      33. Led12 Alias PortC.3
      34. Plus alias Portc.4
      35. Minus alias Portc.5
      36. Mute ALias PortD.1
      37. Config Mute = Output
      38. 'Variablen BCD
      39. Dim A As Byte
      40. Dim B As Byte
      41. Dim C As Byte
      42. Dim A1bcd As Bit
      43. Dim B1bcd As Bit
      44. Dim C1bcd As Bit
      45. Dim D1bcd As Bit
      46. Dim A10bcd As Bit
      47. Dim B10bcd As Bit
      48. Dim C10bcd As Bit
      49. Dim D10bcd As Bit
      50. Dim A100bcd As Bit
      51. Dim B100bcd As Bit
      52. Dim C100bcd As Bit
      53. Dim D100bcd As Bit
      54. dim 1er as Integer
      55. dim 10er as Integer
      56. dim 100er as Integer
      57. dim 1er_bcd as Byte
      58. dim 10er_bcd as Byte
      59. dim 100er_bcd as Byte
      60. 'Variablen Mathe
      61. dim Wert as Integer
      62. dim dBWert as Integer
      63. dim sub1 as Integer
      64. dim sub2 as Integer
      65. dim 10erI as Integer
      66. dim maxw as Integer
      67. 'Grundwert festlegen
      68. dim Grundwert as Byte
      69. Grundwert = 192
      70. enc = Grundwert
      71. 'SPI
      72. Config Spi = Soft , Dout = PortD.7 , Ss = Portd.6 , Clock = Portd.5
      73. SPIINIT
      74. 'Hauptschleife
      75. do
      76. IF Enc <> Enc_SPI_sent then gosub Send_SPI
      77. 'Mathe & Zwischenwerte
      78. maxw = 315
      79. Wert = Enc
      80. sub1 = 255 - Wert
      81. sub2 = sub1 * 5
      82. dBWert = maxw - sub2
      83. 'Vorzeichenauswertung
      84. if dbwert < 0 then Minus = 1 else Minus = 0
      85. if dbwert > 0 then Plus = 1 else plus = 0
      86. 'Mathe für BCD
      87. 1er = dBWert Mod 10
      88. 10er = dBWert Mod 100
      89. 100er = dBWert - 10er
      90. 10er = 10er - 1er
      91. 10er = 10er / 10
      92. 100er = 100er / 100
      93. 'negative zu positiven Werten; Integer zu Byte
      94. 1er_bcd = 1er ^ 2
      95. 1er_bcd = sqr(1er_bcd)
      96. 10er_bcd = 10er ^ 2
      97. 10er_bcd = sqr(10er_bcd)
      98. 100er_bcd = 100er ^ 2
      99. 100er_bcd = sqr(100er_bcd)
      100. 'BCD Auswertung
      101. A = Makebcd(1er_bcd)
      102. A1bcd = A.0
      103. B1bcd = A.1
      104. C1bcd = A.2
      105. D1bcd = A.3
      106. Led1 = A1bcd
      107. Led2 = B1bcd
      108. Led3 = C1bcd
      109. Led4 = D1bcd
      110. B = Makebcd(10er_bcd)
      111. A10bcd = B.0
      112. B10bcd = B.1
      113. C10bcd = B.2
      114. D10bcd = B.3
      115. LED5 = A10bcd
      116. LED6 = B10bcd
      117. LED7 = C10bcd
      118. LED8 = D10bcd
      119. C = Makebcd(100er_bcd)
      120. A100bcd = C.0
      121. B100bcd = C.1
      122. C100bcd = C.2
      123. D100bcd = C.3
      124. LED9 = A100bcd
      125. LED10 = B100bcd
      126. LED11 = C100bcd
      127. LED12 = D100bcd
      128. loop
      129. Send_SPI:
      130. 'Word aus 2 Bytes bilden
      131. Enc_SPIL = Enc
      132. Shift Enc_SPIL, left, 8
      133. Enc_SPIR = Enc
      134. Enc_SPI = Enc_SPIL + Enc_SPIR
      135. 'Word über SPI senden
      136. SPIOUT enc_SPI , 2
      137. Enc_SPI_sent = Enc 'gesendeten Wert speichern
      138. return
      139. 'Taster für Mute
      140. Taster:
      141. toggle Mute
      142. return
      143. _Encoder:
      144. if enc>1 and Enc_a=1 and Enc_b=0 then Enc=Enc-1
      145. if enc>1 and Enc_a=0 and Enc_b=1 then Enc=Enc-1
      146. if enc<255 and Enc_b=1 and Enc_a=1 then Enc=Enc+1
      147. if enc<255 and Enc_b=0 and Enc_a=0 then Enc=Enc+1
      148. return
      Display All
    • Wäre es nicht erheblich einfacher der _Encoder die komplette BCD/Vorzeichenarbeit aufzuhalsen. Ählich wie eine Uhr: anstelle Enc=Enc+1
      (evt bei der Kommastelle beginnen
      If Komma =5 then
      Komma=0 )
      incr Einer
      if Einer>9 then
      Einer=0
      incr Zehner
      ...u.s.w.
      Das kann auch negative Werte mitnehmen sowie Grenzwerte erfassen.

      Im Port D sind noch Pins frei? Zwei Drehgeber können sich einen Int teilen.
    • Bin jetzt noch nicht so der Experte, aber hab gelesen, dass der Interrupt möglichst kurz gehalten werden sollte, da während der Ausführung nix anderes passiert, daher liegt die Recherei in der Hauptschleife. Außerdem benötige ich den Encoder werd einmal doppelt als 16Bit Word für den Poti-IC und einmal als BCD für die Nixies.

      Es wird allgemein etwas knapp mit den Pins, da ich noch ne komplette Relaissteuerung unterbekommen muss, außerdem werden die beiden Encoder räumlich getrennt voneinander auf separaten Leiterplatten im Gehäuse verbaut.

      Ich bin parallel schon die Leiterplatte am zeichnen, da komme ich auch an die Limits der Freeware
      Target 3001 macht bei 250Pins dicht, zum Glück kann man das hier und da etwas austricksen. Trotzdem muss ich die ganze Schaltung noch etwas eindampfen, evtl. bekomme ich so viele Hardware Pins eingespart, das ich wirklich mit dem 8er hinkomme. Das würde mir auch bei den Max. Pins in Target noch Punkte gut machen.

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

    • Ich hab das gestern nochmal durchdacht, egal wie ichs drehe und wende, ich hab entweder zu wenig Ports am ATMega, oder eine externe Lösung verbraucht zu viele Pins bei Target. Die Reise geht jetzt zum 16er, da hab ich ausreichend Ressourcen. Werd zwar wahrscheinlich noch etwas in Target tricksen müssen, damit ich mehr Pins frei bekomme, aber das sollte kein Problem sein, da ist noch etwas Luft.



      Gruß,
      Flo
      Files
      • N_dB_MB.jpg

        (222.62 kB, downloaded 25 times, last: )
    • BlackTigraC20XE wrote:

      ich hab entweder zu wenig Ports am ATMega, oder eine externe Lösung verbraucht zu viele Pins bei Target.
      Die beiden SN74141 könntest du über ein zusätzliches Schieberegister (74HC595) steuern. Dann hättest du schon mal wieder 5 Pins mehr frei :)
      Wenn Target nicht mehr reicht kannst du auch auf KiCad umsteigen. Ist kostenlos, ohne Einschränkungen und relativ einfach zu erlernen.

      PS: mit einem zweiten 74HC595 in Reihe könntest du sogar nochmal 8 Pins sparen.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • BlackTigraC20XE wrote:

      zu viele Pins bei Target
      Ja, sehr nevig.
      Deshalb bin ich vor ein paar Jahren weg von Target.
      KiCad ist zwar frickeliger zu bedienen, aber ohne Beschränkung.
      Ich meine, man konnte bei Target Pins sparen, wenn man die GND-Symbole weggespart hat und Leitungen für GND gezogen hat. (und Vcc etc)
      Sieht nicht schön aus, aber wenn nur ein paar Pins fehlen...
    • Ich bin jetzt seit ca. 2005 bei Target, da werd ich jetzt auch bleiben. Bin in der Bedienung inzwischen ziemlich fit und wenn man zum Beispiel die Gehäuse und Symbole so anpasst, dass nur die benötigten Pins auch eine Anschlussnummer zugewiesen haben, dann kann man gut sparen.

      Bin jetzt beim Atmega16, der hat fast genug Pins, hab nur einen von der Programmierschnittstelle doppelt belegt. Bei Target bin ich bei 247/250 Pins und fast fertig mit Routen

      Hab zur Optimierung des Layouts die Pins ziemlich über den ganzen Chip verteilt. Bevor ich die Leiterplatte bestelle wer's ich nochmal alles am Demo Board aufbauen, die Ports anpassen und schauen ob alles geht.

      Gruß,

      Flo
    • BlackTigraC20XE wrote:

      Ich bin jetzt seit ca. 2005 bei Target, da werd ich jetzt auch bleiben.
      Aber die Anspüche werden steigen und dann reicht Target nicht mehr aus ergo wirst du dir entweder die teure Version von Target kaufen oder auf ein kostenloses Programm wie KiCad umsteigen. Warum nicht gleich umsteigen?
      Ich denke wir haben alle Programme die wir lange benutzt haben und später umgesteigen mussten, weil die geliebten Programme nicht mehr ausgereicht haben oder einfach nicht weiter entwickelt wurden.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • Das war jetzt seit langem das erste Projekt, wo ich die 250 geknackt habe. Die meisten Sachen die ich entwickel sind aktuell Röhrentechnik und ich plane eigentlich immer alles modular, sprich Netzteil eine LP, Endstufe eine eigene LP, ... Mit 250Pins bin ich da in der Regel immer gut dabei. Ich sehe aktuell da einfach keinen wirklichen Grund zu wechseln.
    • Das Projekt ist inzwischen übrigens quasi auf der Zielgeraden, heute war ein erster Testlauf mit der kompletten Peripherie und von kleineren Fehlern in der Schaltung mal abgesehen funktioniert alles. Jetzt geht's noch an die Details und etwas debuggen.