Bascom BASCOM ; Erste Schritte zum Ausprobieren

Danke für die Auflösung.
Aber, dieses hatte ich heut Vormittag auch in einen meiner Versuchsreihe gehabt, leider haben die Led's keine Veränderung gezeigt (jetzt auch nicht).
Was muss ich machen, dass die weißen Led''s, also Pwm1a und Pwm1b sich verändern?
 
Zuletzt bearbeitet:
Also beim ersten (Variante *2*) reagiert die PWM-LED auch auf die Zeichen, die die rote LED ansteuern/auswerten. Wenn also die Ausgabe im Terminal kommt, reagiert auch die PWM-LED.
Wie Thomas bereits meinte:
aber die (dezimal gesehen) Werte sind so eng beieinander dass man kaum einen Unterschied sehen wird
deswegen brauchst Du die ganze Bandbreite des Bytes, also von 0..255 - und es macht doch 'nen Unterschied, ob Du ALT+0 oder ALT+0000 eingibst.
 
Also die Rote LED reagiert bei Eingabe ohne Null mit 0, 1 oder 63.
Wenn ich aber Alt+0111 eingebe, werden die weißen LED's dunkler und bei Alt+0011 heller.
Ist das richtig, soll das so sein?
 
Also die Rote LED reagiert bei Eingabe ohne Null mit 0, 1 oder 63.
Bei 48, 49, 63 und 116
Wenn ich aber Alt+0111 eingebe, werden die weißen LED's dunkler und bei Alt+0011 heller.
Nur die an OC1B, eine kleinere Zahl läßt sie heller leuchten, bei (ALT+0001) ist sie ganz an - eine größere Zahl läßt sie dunkler leuchten, bei (ALT+0254) leuchtet sie gerade noch so, bei (ALT+0255) ist sie aus.
Die LED an OC1A sollte konstant leuchten.
Bei Variante *2* beeinflussen 0, 1, 63 und 116 (eben "0", "1", "?" und "t") neben der roten auch die PWM-LED. In Variante *3* nicht mehr.
P.S.: Die Eingabe ALT+0000 klappt bei mir nicht - aber über Terminal->Send ASCII Character geht's.

Wie gesagt, die LED am letzten Bein, OC1A sollte konstant leuchten. Für die Benötigen wir in der nächsten Aufgabe jetzt ein Potentiometer (10kOhm oder so).
 
Es ist alles so, wie Du es angegeben hast, je kleiner die Zahl desto heller und je größer die Zahl desto dunkler.
Die Led an OC1A leuchtet konstant.
Keine Ahnung, was ich vorhin beobachtet habe. Ich habe alles umstecken müssen, weil ich den USB RS232 bekommen habe. Den USBasp hatte ich schon. Somit kann ich jetzt am Desktop PC arbeiten.
Auf jeden Fall funktioniert es so, wie es sollte.
Zeile 20 und 21 könnten doch weggelassen werden? Hab ich getestet und funktioniert trotzdem.

10K hab ich.
 
Zuletzt bearbeitet:
:good:
Zeile 20 und 21 könnten doch weggelassen werden? Hab ich getestet und funktioniert trotzdem.
Die beiden Zeilen legen den Startzustand der beiden Kanäle fest.
Bei Kanal B, bis er zum ersten mal geändert wird.
Bei Kanal A bisher dauerhaft.
Ohne diese Zeilen würden beide Kanäle den wert 0 als Ausgangszustand haben - wegen PWM=clear down entspräche das der maximalen Intensität.

So, zu Kanal A.

Der Mega8 besitzt einen 10-Bit-Analog-Digital-Converter. Dieser kann eine Spannung mit einer vorgegebenen Referenz vergleichen. 10 Bit erlauben 210=1024 unterscheidbare Werte. 0..1023. Die Referenzspannung entspricht also 1023, 0V entspricht 0. Dreisatz aus der Schul-Mathematik.
Wir schalten also ein 10K-Potentiometer zwischen Vcc und Gnd, und legen den Mittelabgriff (sicherheitshalber über einen 10K-Serienwiderstand) auf... sagen wir mal C0.
Außerdem puffern wir (falls noch nicht geschehen) den Aref-Pin mit einem 100nF-Kerko.

8054
Die Spannung an C0 soll also regelmäßig durch den ADC bestimmt werden (besser gesagt nicht die Spannung, sondern ihr Anteil an AVcc als Referenz.
Die oberen acht Bit des Ergebnisses sollen dann die Intensität von PWM-Kanal A festlegen.
 
Ich hab die Schaltung erweitert, aber mit dem ADC und Referenzspannung habe ich bisher noch nie etwas zu tun gehabt.
Wenn ich das richtig verstehe, müsste die Spannung abgefragt, verglichen und ausgewertet werden.
Aber wie?
 
Hintergrundinformationen zum Analog Digital Konverter:
Der hat natürlich auch 'n eigenes Kapitel im Datenblatt (in der aktuellen Version ab Seite 189), und da am Anfang auch ein Blockschema.
Wie alle Peripheriemodule kann Dein Programm nur über I/O-Register (über den Datenbus) auf den ADC zugreifen - der ADC besitzt drei Register (eines davon als Doppelregister bzw 16bit-Register)
Das ADC Multiplexer Select Register (ADMUX), das ADC Control and Status Register (ADCSRA) und das ADC Data Register (ADC).

Links siehst Du zwei Multiplexer, einen kleinen für die Wahl der Referenzspannung, und einen größeren für die Wahl des zu messenden Kanals.
Gemessen werden können die Spannungen an den Beinen C0..C5 (ADC0..ADC5), an den Beinen ADC6 und ADC7 (gibt's nur in SMD-Packages, nicht beim PDIP), die interne 1,1V-Bandgap-Referenz und Gnd (die letzten beiden eher zu Kalibrationszwecken).
In ADMUX wird also gewählt, welchen Kanal der Multiplexer durchlegen soll.
Bei der Referenzspannung hast Du die Wahl, ob die interne 2,56V-Referenz verwendet werden soll, oder die (interne) analoge Versorgungsspannung (AVcc) - beide liegen dann auch am Aref-Bein an, und sollten dort mit einem Kerko gestützt werden. Alternativ kann man den Multiplexer dort auch abkoppeln (REFS0), und dann (nur dann) eine externe Vergleichsspannung an Aref einspeisen.
Auch diese Wahl wird im ADMUX festgelegt.

Wir haben also den zu messenden Kanal und die Referenz festgelegt, was nun?
Das Arbeitsprinzip des ADC ist schrittweise Approximation - er leitet aus der Referenz Spannungen ab, die er an die zu messende Spannung angleicht.
Dazu steht ihm ein 10-Bit-Analog-Digital-Konverter und ein Komperator zur Verfügung.
Wenn eine Messung angestoßen wird, beginnt die Kontrolllogik mit dem höchsten Bit, es wird vereinfacht gesagt das höchste Bit gesetzt, der DAC liefert die halbe Referenzspannung, diese wird mit der zu bestimmenden Spannung "verglichen" (der Komparator liefert 'ne 0 wenn der DAC-Ausgang größer ist, und 'ne 1 wenn er kleiner ist). Der Ausgang des Komparators hat damit das erste Ergebnisbit festgelegt, Schrittweise geht's mit den restlichen Bits weiter (dieses Bit bleibt also auch im DAC stehen, weiter geht's mit dem 2ten...3ten... … 10ten Bit)

Wenn so alle 10 Bits bestimmt sind, werden diese in das Ergebnisregister übertragen - da zehn Bit nicht in ein Byte passen, besteht das Ergebnisregister aus zwei Byte Registern. Dem ADCH und dem ADCL. Außerdem wird im ADCSRA gemeldet, daß der ADC fertig ist; mit dem Flag ADIF (ADC Interrupt Flag). An ADIF könnte(!!) auch ein Interrupt gekoppelt werden.

"Schrittweise" bedeutet, daß das ganze irgendwie getaktet werden muß, empfohlen sind (bei voller 10bit-Auflösung) höchstens 200kHz. Da der Takt aus dem Systemtakt abgeleitet wird, muß der Takt (im allgemeinen) über einen Vorteiler reduziert werden. Dieser wird konsequenterweise im ADCSRA gewählt. Eine normale Konversion benötigt etwa 13 Takte dieser Takte.

Und in Bascom?
natürlich kannst Du auch hier selbst in ADMUX die Multiplexer einstellen, in ADCSRA den Prescaler festlegen, den ADC überhaupt erst aktivieren, und 'ne Messung starten - aber natürlich bietet Bascom Dir auch 'nen komfortablen Konfigurationsbefehl an (wie wir ja auch schon beim Timer1 verwendet haben.

Für den ADC ist das (nicht sonderlich überraschend): Config ADC
Als erster Parameter ist der Running Mode anzugeben. Wir wollen jede Messung einzeln anstoßen (single), hier könnte man den ADC auch im Dauerlauf betreiben.
Parameter zwei legt den Prescaler fest, man kann hier einen festen Vorteiler festlegen, oder Bascom den kleinsten (schnellsten) Vorteiler unter Beachtung der maximalen 200kHz selbst bestimmen lassen (Auto).
Parameter drei legt die zu verwendende Referenz fest. In der Tabelle fehlt der Mega8 - es gilt trotzdem die letzte Zeile: ADC-Referenzmodel-8.
Erlaubt sind hier AREF bzw OFF (also interne Referenzen abgekoppelt, eine extern an Aref angeschlossene Spannung liefert die Referenz), oder AVcc (die analoge Spannungsversorgung vom AVcc-Bein wird intern über den Multiplexer als Referenz verwendet, liegt dabei aber zusätzlich am Aref-Bein an und sollte dort gestützt werden), oder INTERNAL bzw INTERNAL_2.56 (hier wird die interne 2.56V-Referenz über den Multiplexer geschaltet. auch sie liegt dann am Aref-Bein an und ist dort zu stützen).
Obacht: bei einigen Experimentierplatinen ('n Klassiker mit diesem Fauxpas war meiner Erinnerung nach irgendein Pollin-Board) liegen am Aref-Bein immer extern Vcc (5V) an. Schaltet man da auf 'ne interne Referenz auf, ist diese gegen Vcc geschlossen...
(bei AVcc vs. Vcc passiert sicher nicht viel, bei 1,1V vs. 5V siehts sicher anders aus...)

So, wir Initialisieren den ADC also im Single-Mode, lassen Bascom den Prescaler automatisch festlegen, und wählen als Referenz die interne analoge Versorgungsspannung (da unser Poti ja irgendwas zwischen Gnd und (A)Vcc liefert:


CodeBox BascomAVR
Config ADC = Single , Prescaler = Auto , Reference = Avcc

Die Zeile würde ich direkt vor dem "Config Timer1" platzieren, also in Zeile 17.

Der ADC liefert als Ergebnis wie gesagt 'ne 10-Bit-Ganzzahl - wir benötigen also eine Wordvariable. In Zeile 10 wird also eine weitere Variable dimensioniert:


CodeBox BascomAVR
Dim Poti As Word     'ADC-Messergebnis


Für eine single-Messung bietet Bascom die Funktion getadc() an. Sie erwartet als Parameter den zu messenden Kanal, startet die Messung, wartet(!!) das Ergebnis ab, und liefert das Ergebnis als Word zurück. Wir wollen ADC0=C0 messen (Kanal 0 ) und das Ergebnis in "Poti haben, also:


CodeBox BascomAVR
Poti = Getadc(0)


Für einen ersten Test platzieren wir diese Zeile im zweiten Teilprogramm direkt nach dem toggeln von "grün". Dadurch wird jede Sekunde 'ne Messung durchgeführt (und der Variable zugewiesen). Anschließend soll das Ergebnis einfach mal seriell ausgegeben werden:


CodeBox BascomAVR
Print "Poti: ", Poti
 
Fehlermeldung in Zeile 57 (Numeric parameter expected ["Poti: "])

CodeBox BascomAVR
$regfile = "m8def.dat"                  'Controllerdefinitionsdatei einbinden
$crystal = 8000000                      'Systemtakt angeben (Baudrate)
$hwstack = 40                           'Stacks
$swstack = 16
$framesize = 32
$baud = 19200                           'Baudrate UART

Dim Zeichen As Byte                     'UART-Empfang
Dim Z As Byte                           'Timerüberlaufzähler
Dim Poti As Word

Rot Alias Portd.7                       'Namen für LED-Beine
Gruen Alias Portc.3
Config Rot = Output                     'Ausgänge
Config Gruen = Output
Rot = 1                                 'LEDs erstmal an
Gruen = 1

Config Adc = Single , Prescaler = Auto , Reference = Avcc
'Phasenkorrekter 8-Bit-PWM, PWM-Frequenz=245Hz
Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
'Pwm1a = 250
'Pwm1b = 100

Do                                      'Hauptschleife Begin
'erstes Teilprogramm - UART Empfang und auswerten
   If Ischarwaiting() = 1 Then          'Wenn Zeichen Empfangen
      Zeichen = Inkey()                 'dann Zeichen aus Puffer lesen
      If Zeichen = "1" Then             'Wenn Zeichen = "1"
         Rot = 1                        '...
         Print "Led An"
      Elseif Zeichen = "0" Then         'Wenn Zeichen = "0"
         Rot = 0                        '...
         Print "Led Aus"
      Elseif Zeichen = "t" Then         'Wenn Zeichen = "t"
         Toggle Rot                     '...
         Print "Toggle Led"
      Elseif Zeichen = "?" Then         'Wenn Zeichen = "?"
         If Rot = 0 Then                'sonst wenn Led aus ist...
            Print "Led ist aus"
         Elseif Rot = 1 Then            'Dann wenn Led an ist...
            Print "Led ist an"
         End If
      Else
         Pwm1a = Zeichen
      End If
   End If

'zweites Teilprogramm - LED durch timer blinken lassen
   If Tifr.tov1 = 1 Then                'wenn Timer übergelaufen ist
      Tifr.tov1 = 1                     'Überlaufflag zurücksetzen
      Incr Z
      If Z = 245 Then                   'Überläufe zählen (245)
         Z = 0                          'Zähler zurücksetzen
         Toggle Gruen                   'LED toggeln
         Poti = Getadc(0)
         Print "Poti: " , Poti
      End If
   End If

Loop                                    'Hauptschleife Ende

Was muss ich im Terminal tun, damit ich irgend eine Veränderung sehen kann?
 
OK, das Semikolon war's.
Das Terminal zeigt im Sekundentakt, je nach Einstellung des Poti, die Werte 0 bis 1023 an.

Mir ist aufgefallen, dass Du das RS232 Modul nur mit GND verbunden hast. Hab ich auch probiert und es geht auch ganz ohne VCC un GND. Im Prinzp bezieht es ja Strom über USB.
Frage: Muss das GND angeschlossen sein?8058
 
Zuletzt bearbeitet:
Im Prinzp bezieht es ja Strom über USB
Der FTDI-Chip wird über USB versorgt, richtig. Außerdem ist ein 3,3V-Regler enthalten. Meist kannst Du auf der Unterseite mit'ner Lötbrücke festlegen, ob 5V oder 3V3 bereitgestellt werden sollen - damit könnte eine Zielschaltung versorgt werden. Nutzen wir aber nicht.

ABER: an RXI wird eine Spannung erwartet/gemessen, an TXO wird eine Spannung ausgegeben. Was ist eine Spannung? Ein Potential, welches sich irgendworauf beziehen muß. Auf Ground.

Also Ground sollte angeschlossen sein (damit sich die Signale auf dieselbe Masse beziehen, und nicht nur zufällig schweben), Vcc hingegen nicht (da wir ja 'ne eigene Spannungsquelle haben).

Das Terminal zeigt im Sekundentakt, je nach Einstellung des Poti, die Werte 0 bis 1023 an.
Richtig, es sind zehn Bit.
Letztendlich soll der Wert ja PWM1A zugewiesen werden, da passen aber nur acht Bit (0..255). 'Ne Idee?
 
Der ADC liefert 'ne 10-Bit-Zahl, die in einem Word abgespeichert wurde. PWM1A sollen aber nur die obersten acht Bit dieser Zahl zugewiesen werden. Du mußt also vorher durch vier teilen, bzw das Word zweimal nach rechts schieben lassen.
 
Nicht ganz.
Du bekommst Werte 0..1023. Zuweisen kannst du aber nur 0..255.
Man könnte jetzt über Dreisatz gehen. Das wäre vielleicht leichter zu lesen, aber stark vom Nachteil. Mehr dazu später.
Auch könnte man sich einen Schritt sparen und einfach durch 4 teilen. Nicht von jedem nachvollziehbar, etwas besser als oben, aber immer noch von Nachteil.
Oder man schubst einfach die Bits um 2 nach rechts. Damit erreichst du eine Division /4.

Wegen den Nachteilen:
Die kleinen Käfer können von Haus aus nicht dividieren, multiplizieren können nur einige. Also die Hardware. Fazit: wenn du es trotzdem machst setzt (hier Bascom) das in Software um. Das frisst CPU Zeit und Flash Speicher ohne Ende, was hier komplett unnötig ist.

Zum Bits schubsen:
Der Einfachheit halber sage ich jetzt dass ein Byte 4 Bit hat (es sind natürlich 8).
Wie rechnet ein Chip? Erhöhen wir mal einen Wert um 1 und sehen uns die Bits an:
Code:
0 0 0 0 = 0
0 0 0 1 = 1
0 0 1 0 = 2
0 0 1 1 = 3
0 1 0 0 = 4
0 1 0 1 = 5
0 1 1 0 = 6
0 1 1 1 = 7
Die Liste kannst du jetzt weiter führen. Aber zu sehen ist hier schon, wenn du etwas durch 2 teilen möchtest musst du eigentlich nur die Bits um 1 nach rechts schieben, für /4 halt 2x, /8 3x, /16 4x...
Klar, der Rest fällt so weg, den brauchen wir jetzt aber nicht.

In Basic ist es normalerweise (meine Bascom Zeit ist ewig her, sorry)


CodeBox BascomAVR
Wert = Wert >> 2 ' Bits aus Wert um 2 nach rechts schieben
' Bascom scheint dafür einen extra Befehl zu haben
Shift Wert, Right, 2

Das wäre die Division /4 die du brauchst. Multiplizieren könntest du so auch, dann halt mit << (Left). Geht aber nur mit Werten 2, 4, 8, 16, 32, ... das Zweifache halt.
 
Shift Wert, Right, 2
So etwas habe ich schon einmal in einem Code gesehen. Konnte aber nichts damit anfangen.
Jetzt verstehe ich natürlich, was damit gemeint ist. Allerdings muss ich mich mit diesen Befehl erst einmal auseinandersetzen. Kann ein bisschen dauern, bis Wochenende.
 
Zuletzt bearbeitet:
Ich habe in Zeile 11 eine Variable "Wert als Byte" hinzugefügt und im zweitem Teilprogramm die Zeile 59 "Shift Wert , Right , 2".
Zeile 58 musste ich auskommentieren, da Bascom wieder eine Fehlermeldung bringt.
Allerdings kann ich keine Änderung erkennen.
Ich habe zwar gesagt, dass ich das "Shift Wert, Right, 2" schon einmal gesehen habe, aber finde es nicht mehr oder habe es mir auch gar nicht erst abgespeichert, weil ich eh nichts damit anfangen konnte.


CodeBox BascomAVR
$regfile = "m8def.dat"                  'Controllerdefinitionsdatei einbinden
$crystal = 8000000                      'Systemtakt angeben (Baudrate)
$hwstack = 40                           'Stacks
$swstack = 16
$framesize = 32
$baud = 19200                           'Baudrate UART

Dim Zeichen As Byte                     'UART-Empfang
Dim Z As Byte                           'Timerüberlaufzähler
Dim Poti As Word
Dim Wert As Byte

Rot Alias Portd.7                       'Namen für LED-Beine
Gruen Alias Portc.3
Config Rot = Output                     'Ausgänge
Config Gruen = Output
Rot = 1                                 'LEDs erstmal an
Gruen = 1

Config Adc = Single , Prescaler = Auto , Reference = Avcc
'Phasenkorrekter 8-Bit-PWM, PWM-Frequenz=245Hz
Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
'Pwm1a = 250
'Pwm1b = 100

Do                                      'Hauptschleife Begin
'erstes Teilprogramm - UART Empfang und auswerten
   If Ischarwaiting() = 1 Then          'Wenn Zeichen Empfangen
      Zeichen = Inkey()                 'dann Zeichen aus Puffer lesen
      If Zeichen = "1" Then             'Wenn Zeichen = "1"
         Rot = 1                        '...
         Print "Led An"
      Elseif Zeichen = "0" Then         'Wenn Zeichen = "0"
         Rot = 0                        '...
         Print "Led Aus"
      Elseif Zeichen = "t" Then         'Wenn Zeichen = "t"
         Toggle Rot                     '...
         Print "Toggle Led"
      Elseif Zeichen = "?" Then         'Wenn Zeichen = "?"
         If Rot = 0 Then                'sonst wenn Led aus ist...
            Print "Led ist aus"
         Elseif Rot = 1 Then            'Dann wenn Led an ist...
            Print "Led ist an"
         End If
      Else
         Pwm1a = Zeichen
      End If
   End If

'zweites Teilprogramm - LED durch timer blinken lassen
   If Tifr.tov1 = 1 Then                'wenn Timer übergelaufen ist
      Tifr.tov1 = 1                     'Überlaufflag zurücksetzen
      Incr Z
      If Z = 245 Then                   'Überläufe zählen (245)
         Z = 0                          'Zähler zurücksetzen
         Toggle Gruen                   'LED toggeln
         Poti = Getadc(0)
         'Wert = Wert >> 2
         Shift Wert , Right , 2
         Print "Poti: " ; Poti
      End If
   End If

Loop                                    'Hauptschleife Ende
 
58 ist die gängige Basic Schreibweise. Bascom erkennt die nicht, hat dafür seinen eigenen Befehl (59). Beide Zeilen bewirken das Selbe.
Die Ausgabe von Print müsste doch jetzt statt von 0..1024 halt 0..255 sein. Oder übersehe ich jetzt was, @LotadaC?
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)