Bascom BASCOM ; Erste Schritte zum Ausprobieren

Frage zwischendurch:
Ich hatte einen Code mit Getadc wobei ich die Pwm mittels Pori verändern kann. Der Poti geht an Vcc und GND und der Schleifer an einen ADC Pin.
Wenn ich einen Lichtempfindlichen Sensor (LDR) nehme, der seinen Widerstand durch die Helligkeit ändert aber nur zwei Anschlüsse hat, wie wird diese geschalten?
 
Ja, die Sub Main ansich muss drin bleiben, nur der Inhalt nicht*.

Also 9mA, das kommt hin. Angegeben sind typisch 11mA (ATmega8).
Die Main Loop läuft ja trotzdem kontinuierlich. Das ändern wir jetzt.

Dazu braucht man etwas Hintergrundwissen.
Die AVRs haben mehrere Sleep Modes. Je nachdem welche Hardware man nutzt - oder eben nicht - kann man den Controller tiefer schlafen legen. Je tiefer desto weniger Stromverbrauch. Was du nutzt weißt du ja. INT0, Timer1 und Uart. Vielleicht später noch ADC.
Hier ein Beispiel aus dem Datenblatt des ATmega8:
8069

Hier zu sehen, es gibt 5 Sleep Modes. INTx weckt immer auf. ADC würde nur noch im ADC Noise Reduction und im Idle Mode laufen. Nutzt man diesen also, fallen schon 3 der 5 raus. Da du den Timer nutzt fallen Power Down und Standby raus. Da aber der Uart verwendet wird kommt nur noch der Idle Mode in Frage.
Die "Kollegen" haben es auch recht schön beschrieben:

Also. Jetzt muss man den Controller sagen wie tief er schlafen darf.


CodeBox BascomAVR
Config Powermode = Idle

Genaue Befehlsreferenz:

Technisch gesehen sagt man ihm das eigentlich (in Assembler und C) in der Init Phase und dann wenn er schlafen darf (also in der Main Loop) mittels Sleep Befehl.
Bascom sieht das scheinbar etwas anders. Da ist der Config Befehl gleichzeitig der Sleep Befehl. Sprich: Die Config Powermode ist jetzt die einzige Zeile in deiner Main Loop. Die CPU läuft dann nur noch bei Bedarf, also wenn eine der Interrupt Routinen läuft.

Im Idle ist er angegeben mit typisch 4,5mA, also immerhin rund ein Drittel.
Im PowerDown Mode wären es sogar unter 30µA, ohne Watchdog unter 3µA.
Klingt nicht nach viel, ist aber für Batteriebetriebene Anwendungen sehr wichtig.
Sollte man sich generell angewöhnen ;)


Zum Lichtsensor, es kommt auf den Typ drauf an und wie du ihn verwenden möchtest. Ich verweise hier mal wieder auf die "Kollegen", da ich sowas noch nie selber gemacht habe. Vielleicht jemand anders hier?


*) Es gibt natürlich Situationen wo es durchaus sinnvoll ist Code in der Main abzuarbeiten, vor allem wenn man Routinen hat die Wartezeiten voraussetzen, wie das Beschreiben eines LCDs. Haben wir hier aber nicht.
 
Lichtempfindlichen Sensor (LDR) nehme, der seinen Widerstand durch die Helligkeit ändert aber nur zwei Anschlüsse hat, wie wird diese geschalten?i
LDR steht für: Light Dependent Resistor, also wie Du selbst gesagt hast: ein Widerstand, dessen Wert lichtabhängig ist. Der ADC kann nur Spannungen messen, also baust Du mit dem LDR und einem festen Widerstand einen Spannungsteiler auf (dessen Spannung somit die lichtabhängigkeit des LDR erbt.) Je nach Situation läßt sich dabei der interne Pullup des ADC-Beines verwenden.
 
Diese Zeile
Config Powermode = Idle
Main-Schleife eingesetzt. Gemessen wurden 0,004A (es sind nur 3 Stellen nach dem Komma).
 
Kommt ja hin, also Stromverbrauch etwas mehr als halbiert, geht also. Meine Werte waren ja jetzt auch von einem Mega8.
Würdest du auf Uart verzichten können wäre noch mehr drin, vermutlich bis in einen nicht mehr messbaren Bereich. ;)

Der Wachhund ist ähnlich leicht einzubinden. Mit dem Lichtsensor muss ich aber eher passen, da wäre LotadaC wieder der Lehrer und ich der Sitznachbar :)
 
Ok, du hast also 2 Möglichkeiten den zu nutzen, digital (Schwellwert einstellbar auf dem Board), sprich wie einen Taster, oder Analog. Der Spannungsteiler ist schon on-board, du musst also nur noch die Spannung messen, welche sich im Extremfall zwischen VCC und GND bewegen könnte (aber nicht wird).
 
Würdest du auf Uart verzichten können wäre noch mehr drin, vermutlich bis in einen nicht mehr messbaren Bereich. ;)
Aber TWI, Timer0, Timer2 und SPI können abgeschaltet werden (Power Reduction Register). Und der Comperator (ACD in ACSR).
Wirkt sich nicht nur auf den Sleep aus, sondern auch auf den active mode...
Wie Thomas schon sagte: der fixe Widerstand für den Spannungsteiler ist bereits drin (10kOhm). Pin1=AO (analog out) könnte also durch den ADC gemessen werden.
Auf der Platine ist aber außerdem ein Dual-Comperator enthalten (LM393, quasi ein Operationsverstärker mit unendlicher Verstärkung), der diese analoge Spannung mit der eines Potentiometers vergleicht, und entsprechend seinen Ausgang umschaltet (Du kannst also mit dem Poti einen Schwellwert festlegen, die die Helligkeit bestimmt, bei der der Comperator kippt. Das (digitale) Signal des Comperators kannn an Pin=out durch ein beliebiges Controllerbein erfaßt werden.

Der 393 besitzt zwei Gatter. Laut Schaltplan wird das zweite Gatter nicht verwendet UND dessen Eingänge hängen in der Luft. Die gehören auf feste Pegel gelegt (weil die sonst irgendwas einfangen, und der Ausgang wild rumschalten kann...).

Wenn Strom gespart werden soll, stören natürlich auch die LEDs - um das zu begrenzen könnte man das Modul durch einen Controllerpin versorgen, und zwar nur immer kurz, wenn man nach der Helligkeit schauen will...

Also zum testen ok - in einer finalen Schaltung könnte man sich auf einen der beiden Wege festlegen, und dabei bei der analogen Variante ggf die internen Pullups verwenden; bei der digitalen Variante den internen Comperator des Controllers... Da reicht also in beiden Fällen der eigentliche LDR allein am Controller aus.
Als Bauteil-Spar-Variante würde ich aber immer noch die LED als Lichtsensor bevorzugen...
 
Das stimmt, die nicht benötigten Teile kann man noch deaktivieren, PRR und ACD.
Aber: Scheinbar nicht beim Mega8. Zumindest fehlen passende Infos dazu komplett im Datenblatt.

Mit der LED als Lichtsensor, da muss ich auch mal mit rum spielen. Messgeräte hab ich ja genug ;)
 
Das LDR-Modul habe ich nur zufällig entdeckt (48 Cent/Stück) und bestellt, weil hier
Unter Ausnutzung des ADC könnte man stattdessen/zusätzlich auch auf die Helligkeit reagieren...
mal dese Rede davon war. Ja, ich habe das so aufgenommen, dass man das ein- und ausschalten mittels LDR vornehmen kann.
Der Link Sleep Mode ist sehr verständlich, auch weil er auf Deutsch geschrieben ist. Nur die Beispiel-Code's, die kenne ich noch vom Arduino.
Ansonsten ist die Stromeinsparung eine interessante Sache.
 
Scheinbar nicht beim Mega8
Asche auf men Haupt...
Gibts nicht beim Mega8 und beim Tiny13. Der Tiny13A besitzt ein PRR, wo ADC und Timer0 nochmal extra abgeregelt werden können.

Für Mega8 und Tiny13 gilt also nur (wenn nicht verwendet):
ADC disablen (default off, ADCE in ADCSRA)
AC disablen (default on, ACD in ACSR)
Brown Out Detector abschalten (Fusebit)

Hintergrund: Der AC bleibt nur im Idle und ADC-Noise-Reduction-Mode aktiv, sonst wird er beim Sleep abgeschaltet - aber alle drei Units können die Interne Referenz verwenden - die dann auch im Sleep anbleibt.

Den Watchdog hatten wir ja bereits genannt - wenn der aber aktiviert ist, muß man sich im Sleep ja eh drum kümmern, wenn der Controller da nicht immer in den Reset gehen soll.

Beim Tiny13 können (sollten) außerdem bei analog verwendeten Beinen die digitalen Input Buffer abgeschaltet werden (DIDRn). Im Sleep geschieht dies teilweise automatisch (Ausnahme: IRQs und so), aber im Active Mode müssen die auch nicht wild rumschwingen...

Zumindest fehlen passende Infos dazu komplett im Datenblatt.
Am Ende vom Power Management Kapitel, direkt vor dem Reset Kapitel.
 
Hm, wegen dem Wachhund. Ist ja eigentlich egal. Der Timer läuft ja und generiert Interrupts, folglich springt er wieder in die Main rein. So zumindest wenn er läuft (=die 8 Stunden). Wenn nicht könnte man den Timer ja auch komplett deaktivieren. Dann würde zwar der Hund zubeisen weil man ihn nicht mehr tritt, aber aus bleibt aus. So mache ich es in meinen Taschenlampen auch, klappt ganz gut.

Also, die nächsten Punkte: Wachhund (geht schnell) und ADC. :)

Wachhund ist nur ein Befehl in der Init wo du ihn scharf stellst, und einen in der Main Loop um ihn zurück zu setzen. Die Befehle rauszusuchen überlasse ich vorerst mal dir ;)
Ohne Reset (testweise auskommentieren) sollte das Licht ständig wieder ausgehen (Zustand wie nach dem Anschalten). Mit sollte er weiter laufen.
 
Ohne Reset meckert Bascom die Main-Schleife an.


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 C As Byte
Dim Fla As Byte
Dim Pause As Byte
Dim Pausex2 As Byte
Dim Tov1cnt As Byte
Dim Countdown As Word
Ddrc = &B_11_1111                       '1 ist Ausgang 0 ist Eingang
Portc = &B00_0000                       'auf Hi oder Low setzen
Ddrd = &B_1111_1011
Portd = &B0000_0100
Rot Alias Portd.7
Blau Alias Portd.6
Gruen Alias Portc.3
Key1 Alias Pind.2
'Phasenkorrekter 8-Bit-PWM, PWM-Frequenz=245Hz
Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
Config Watchdog = 2048
Start Watchdog
On Urxc Onuartrx
Enable Urxc
On Timer1 Ontimer1overflow
Enable Timer1
On Int0 Onkey1pressed
Enable Int0
Enable Interrupts
Main:
   Reset Watchdog
'Config Powermode = Idle
   'If Ischarwaiting() = 1 Then Gosub Onuartrx
   'If Tifr.tov1 = 1 Then Gosub Ontimer1overflow
   'If Key1 = 0 Then Gosub Onkey1pressed
   Goto Main
Onuartrx:
   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                   'Dann wenn Led aus ist...
         Print "Led ist aus"
      Elseif Rot = 1 Then               'sonst wenn Led an ist...
         Print "Led ist an"
      End If
   Elseif Zeichen = 0 Then              'bei 0x00 PWM deaktivieren
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect
   Elseif Zeichen = 255 Then            'bei 0xFF PWM aktivieren
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
   Else
      Countdown = Zeichen * 60
      Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
   End If
Return
Ontimer1overflow:
   Set Tifr.tov1                        'Überlaufflag zurücksetzen
   Incr Tov1cnt                         'überlaufzähler inkrementieren
   If Pause = Tov1cnt Then              'entspricht dem 2ten "waitms pause"
      Fla = Rnd(200)
      Fla = Fla + 55
      Pwm1a = Fla
   End If
   If Pausex2 = Tov1cnt Then            'entspricht dem ersten "waitms pause"
      Pwm1b = 255 - Fla
      Pause = Rnd(10)
      Pause = Pause * 6
      Pausex2 = Pause
      Shift Pausex2 , Left              'pausex2=pause*2
      Tov1cnt = 0
   End If
   Incr C
   If C = 245 Then                      'Überläufe zählen (245)
      C = 0                             'Zähler zurücksetzen
      Toggle Gruen                      'LED toggeln
      If Countdown = 0 Then
         Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Disconnect , Compare B Pwm = Disconnect
      Else
         Decr Countdown
      End If
   End If
Return
Onkey1pressed:
   Config Timer1 = Pwm , Prescale = 64 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
   Countdown = 60
Return
 
Gut möglich dass Bascom da etwas Intelligenz hat, weil es wäre ja auch ein Fehler den Watchdog zu aktivieren, aber nie zu resetten.
Sieht auf jeden Fall so richtig aus.

Um den Hund zu ärgern und zu überprüfen ob er funktioniert könnte man jetzt das Reset Watchdog direkt unter die Main Loop setzen.
Das dient jetzt aber nur dem Funktionstest des Hundes, sonst ist es komplett unsinnig. Du hast es schon richtig gemacht, sollte so gehen.
 
Hm, eigentlich müsste denn nach den eingestellten Wert (2 Sekunden) den selben Zustand haben wie nach einem Power Cycle...
Vielleicht eine Bascom Eigenheit? @LotadaC

Ist ja aber egal. Jetzt der ADC.
Hast du schon eine Idee?
 
ne Idee hab ich nicht. Damit werden zB. LDR oder auch Poti Werte ausgelesen und umgewandelt. So etwas wird dann mit Getadc (x) irgendwie gestartet. Hatten wir schon einmal, als ich die Pwm mittels Poti gesteuert und über UART ausgegeben habe.
 
Jupp.

Also, der ADC ist eine interne Komponente, ähnlich wie UART und die Timer, die unabhängig von der CPU weiter arbeiten.
Den ADC selbst kann, grob gesagt, in 2 Modis betreiben. Single shot, also du musst jedes Mal die Messung anstoßen, oder der Running Mode wo er fortlaufend weiter misst, ohne dass man etwas tun muss.
Da der ADC nicht grade der schnellste ist (~100khz im Durchschnitt) bietet es sich hier stark an ihn per Interrupts zu verwenden. Also ein weiteres Teilprogramm (OnADC). Die wird dann aufgerufen wenn:
1.: Der ADC Interrupt scharf gestellt ist.
2.: Interrupts generell scharf sind.
3.: Der ADC selbst initialisiert ist.

Vom Prinzip kaum anders als der Timer, nur hier halt für den ADC.
Der Einfachheit halber starten wir erst mal mit der reinen Ausgabe des ADC Wertes in der OnADC Routine. Ausgabe per Uart. Kann jetzt Poti oder schon dein Lichtsensor sein, wie früher.

Später könnte man dann abfragen, wenn Wert > x ist (x ist herauszufinden) dann schalte die Kerze aus, weil zu hell. Oder auch wenn Wert < x ist schalte sie ein.

Rein theoretisch könntest du natürlich auch den digitalen Ausgang des Sensors nutzen. x würde dann per Poti definiert werden.
 
Ich verstehe bestimmt etwas falsch, wenn ich
Also ein weiteres Teilprogramm (OnADC). Die wird dann aufgerufen wenn:
wir aber schon

CodeBox BascomAVR
On Urxc Onuartrx
Enable Urxc
On Timer1 Ontimer1overflow
Enable Timer1
On Int0 Onkey1pressed
Enable Int0
Enable Interrupts
haben und der Interrupt auch schon scharf gestellt ist, habe ich bis jetzt die

CodeBox BascomAVR
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
hinzugefügt. Also müsste ich dann
On ADC
Enable ADC

als viertes Programm hinzufügen.
 
Du hattest mir in #393 diese Vorgabe geschrieben
Für den Uart wäre es:
On Urxc OnUartRx
Enable Urxc

Für den Timer1 wäre es:
On Timer1 OnTimer1Overflow
Enable Timer1

Für den Taster (angeschlossen an INT0):
On INT0 OnKey1Pressed
Enable INT0

Und wegen Punkt 4:
Enable Interrupts
Da wäre ich selbst nicht drauf gekommen. Ich sagte auch irgendwo einmal, dass es so auch geht und fragen kann ich dann immer noch.
Frage: Die Bezeichnung On Urxc OnUartRx ist diese bestimmte vorgeschriebene Ausdrucksweise oder könnte es auch irgend eine andere sein?
 

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