Von PWM zu sauberen Ausgang

Ups, hatte irgendwie die Minuten weggelassen - aber generell bleibts gleich...
Mit'ner RTC wird das natürlich wesentlich interessanter. Da kann man das Register-Uhrwerk auch an den Frequenz-Ausgang der RTC hängen (hmm... und den dann als Wakeup & IRQ verwenden?)
Das Problem mit dem Integrieren ist, daß Du eventuell keinen ganzzahligen Step herausbekommst. Wenn der stupide addiert wird, drifte Dir die zeit weg. Mit'nem Nachkomma-Byte reduzierst Du dieses driften auf ein 256stel zulasten einer weiteren ADC/SBC pro Addition/Subtraktion. Und da das ein ganzes Byte ist, braucht vor dem kopieren ins OC-Register auch nix geschoben werden.
Zweimal am Tag das ganze auf Null syncen...
Nach einem Reset dann die Zeit aus dem RTC auslesen, da mußte dann halt einmal multiplizieren (entweder "richtig", oder auf die "TommyB-Methode").

P.S.: zum Stellen der RTC würde ich von Dir(!!) jetzt allerdings irgendwas erwarten wie: RTC (via µC) an'n USB gesteckt, und die RTC synct mit irgend'nem Internet-Zeit-Dingens...
 
Nun ja, mir schwebte erst dcf vor, aber … nee. Lohnt sich nicht. Allzu leicht ist es auch nicht mit dem PC zu kommunizieren, außer man schraubt sich dafür auch noch ne Software für und verbaut n USB RS2323 Adapter. Wär etwas der Overkill. Zumal ich jetzt nicht weiß ob der ggf. durch Schutzdioden aktiv gehalten wird wenn kein USB angeschlossen ist. Das wäre denn etwas suboptimal.
 
Ich meinte eher, Du stöpselst 'n USB-Kabel mit drangebasteltem FTDI oder so zwischen RTC und PC, und Dein VB-Programm synct die RTC. Die können doch auch irgendwie SPI oder I²C ausgeben. Danach sollte die ja dann jahrelang richtig gehen.
(Ich (!!) habe FTDIs bisher nur als virtuellen Comport gehabt - aber PC-seitig bist Du ja ehr der Profi...)

P.S.: Wenn ich was (hoffentlich(!) halbwegs(!)) verständliches zur Multiplikation von Words usw schreiben soll, sag bescheid...
 
Achso meinst du, das war n Missverständnis :)
Ne, mir wars wichtig dass es auch ohne Strom weiter läuft. Daher interner LiIO Akku und der Batteriegepufferte RTC :)
Aber sonst wäre das auch eine gute Idee. Einzige Problem was ich da für mich sehe (und auch für den Empfänger des Präsentes): Wenn man schon zig verschiedene virtuelle COM Ports hat (Gerät 1..10, womöglich noch 4 oder 6 weitere dank Bluetooth…) kommt man fix durcheinander. Zumal Windows gerne mal Probleme bekommt wenn die (automatisch vergebene) Nummer > 20 wird.

Wegen Multiplikation, ich lass da mal n bissl den Kammerjäger laufen, ich glaube das Prinzip habe ich so in etwa verstanden.
Aber mal schaun :)

Ich melde mich
 
Ohne jetzt weiter auf Körper und Ringe usw einzugehen:
Multiplikation und Addition sind je kommutativ, d.h. die Reihenfolge der Operanden ist egal ("a+b=b+a","a*b=b*a")
Multiplikation und Addition sind je assoziativ, d.h. die Reihenfolge gleicher(!) Operationen ist egal ("(a+b)+c=a+(b+c)","(a*b)*c=a*(b*c)")
Es gilt das Distributivgesetz:
Zerlegst Du in einem Produkt einen Faktor un eine Summe zweier Summanden, ist es egal ob man den anderen Faktor mit der Summe multipliziert, oder mit jedem(!) Summanden ("a*(b+c)=(a*b)+(a*c)")
(Der andere Fall mit dem ersten Faktor als Summe folgt aus dem Kommutativgesetz)
Ok, Du hast jetzt also zwei Words - sagen wir a und b. Beide bestehen aus je zwei Bytes (High(a), Low(a), High(b), und Low(b))
a*b ist also dasselbe wie
((High(a)*256)+Low(a))*((High(b)*256)+Low(b))
Das ist ein Produkt (rot) aus zwei Summen (blau, grün)
((High(a)*256)+Low(a))*((High(b)*256)+Low(b))
Mit dem Distributivgesetz (blaue Summe) kannst Du also genauso schreiben:
((High(a)*256)*((High(b)*256)+Low(b))+(Low(a)*((High(b)*256)+Low(b)))
Und dasselbe mit Grün:
((High(a)*256)*(High(b)*256))+((High(a)*256)*Low(b))+((Low(a)*(High(b)*256))+(Low(a)*Low(b)))
Damit hat man 'ne Summe aus vier Produkten, die man mit Kommutativgesetz und Assoziativgesetz umsortieren kann:
(High(a)*High(b)*256*256)
+(High(a)*Low(b)*256)+(Low(a)*High(b)*256)+(Low(a)*Low(b))
Jetzt kannst Du bei den mittleren beiden Summanden die 256 ausklammern (Distributivgesetz), und erhälst:
(High(a)*High(b)*256*256)+((High(a)*Low(b))+(Low(a)*High(b))*256)+(Low(a)*Low(b))

Nach dem Assoziativgesetz kannst Du vorn ausklammern, die vier Produkte (rot) bestehen nun alle aus 8bit-Faktoren:
((High(a)*High(b))*256*256)+((High(a)*Low(b))+((Low(a)*High(b))*256)+(Low(a)*Low(b))
Die 8bit-Multiplikation kann MUL, wobei das Ergebnis dann 'ne 16bit-Zahl ist und in R1:R0 abgelegt wird.
Die fehlenden Multiplikationen mit 256 berechnest Du natürlich nicht, die werden auch nicht geschoben, sondern Du berücksichtigst die beim Zusammenrechnen der Summe.
Im folgenden sind High(a), Low(a), High(b), Low(b) die Register, wo die entsprechenden Bytes abgelegt sind; E3..E0 die 4 Register, die das Produkt aufnehmen sollen (wobei High und Low in aufeinanderfolgenden Registern stehen). Dann gehts so:


CodeBox Assembler
MUL Low(a), Low(b) ;berechnet das letzte Produkt (Ergebnis in R1:R0)
MOVW E1:E0, R1:R0 ;kopiert die beiden Bytes in die unteren Ergebnisregister
MUL High(a), High(b) ;berechnet das erste Produkt, Ergebnis in R1:R0
MOVW E3:E2, R1:R0 ;Kopie in die obersten beiden Bytes, womit auch die beiden "*256" erledigt sind
MUL High(a), Low(b) ;2tes Produkt
ADD E1, R0 ;addiert das lowbyte (wegen den *256 auf E1 statt E0)
ADC E2, R1 ;addiert das highbyte mit Carry
;jetzt müßte das eventuelle Carry auf E3 addiert werden, da's kein "ADD/Subtract Immediate with Carry" oder so gibt, muß man entweder mit 'nem Conditional Branch ein INC E3 überspringen, oder ein Null-Register mit Carry addieren
ADC E3, Nullregister
MUL Low(a), High(b) ; drittes Produkt
ADD E1, R0
ADC E2, R1
ADC E3, Nullregister ;wie eben
 
Also wäre es vom Prinzip genau so wie man dank der (wie damals vermutet) sadomasochistischen Ader des Mathelehrers der die Taschenrechner verbot, multiplizierte?

Zumindest habe ich das gerade mal versucht durchzuspielen:
upload_2015-12-22_7-48-45.png

Dezimal ist nur per forma da.
x markiert nicht berücksichtigte Stellen.

Gegeben ist Eingang 1: 16 Bit (folgend E1H und E1L), Eingang 2 8 Bit (E2), Ausgang 16 Bit. Overflow braucht nicht, weil kann nicht passieren. (klar wären hier 24 richtig).

Also:
• E1H * E2 --> Low Byte vom Result in Cache High Byte
• E1L * E2 --> Komplettes Result in Cache (unverändert)
• Beide Caches addieren, Overflow ignorieren

Zu 16x16=16 Bit komm ich bissl später, brauch als erstes das, wobei da E2 tatsächlich eine Konstante ist (60dec).


Herrjeh, ich und Mathe ^^'
 
Also auf den ersten Blick scheint meine abgespeckte Version gut zu funktionieren.
So Gans trau ich den Braten aber noch nicht ;D

Z Register ist Eingang 1 (16 Bit)
Y Register ist der Ausgang (16 Bit)
TEMP1 ist Eingang 2 (8 Bit) und typisch "nutz mich und verwirf mich" Register.



CodeBox Assembler
    ; Multiply increment value by 60 (16x8 bit, ignore 16 bit overflows)
    LDI        TEMP1     ,    60               ; Load multiplicator (low byte)
    MUL        ZL        ,    TEMP1            ; Mult. low byte (=base)
    MOVW       YH:YL     ,    MULRESH:MULRESL  ; Copy result to output register
    MUL        ZH        ,    TEMP1            ; Mult. high byte (low byte needed)
    ;LDI       TEMP1     ,    0                ; Load multiplicator (high byte)
    ;ADD       YL        ,    MULRESL          ; Add high byte result to result
    ;ADC       YH        ,    TEMP1            ; Add carry (if any)
    ADD        YH        ,    MULRESL          ; Add low byte result to result high byte


Edit:
Quatsch... Weg kommentiertes war falsch. Da hat wer gepennt ^^
 
Zuletzt bearbeitet:
(High(a)*High(b)*256*256)+(High(a)*Low(b)*256)+(Low(a)*High(b)*256)+(Low(a)*Low(b))
Deine 60dez seien b, da nur 8bit (eigentlich nur 6bit), ist High(b)=0. Somit sind auch alle Produkte mit High(b) als Faktor null (und Fallen raus)
(die Null ist das sogenannte "absorbierende Element" der Multiplikation im Ring der Natürlichen Zahlen mit "+" und "*" (TeerAusWeich))
somit bleibt:
(High(a)*Low(b)*256)+(Low(a)*Low(b))
Beide Produkte (MUL) liefern Dir je 16bit-Ergebnisse.
Der 256-Faktor verschiebt das eine Produkt um acht Stellen (ein Byte), deswegen hast Du eigentlich drei Bytes als Ergebnis.
Du addierst von diesem Produkt aber nur das untere Byte auf das Highbyte des Ergebnisses.
Das dabei eventuell fallende Carry und das HighByte des Produktes vergißt Du.
Ab a=1093 (0x0445) reichen zwei Ergebnisbytes nicht mehr aus (0x0445*0x003C=0x01002C)

(2^16)/60=1092,2666666...
 
Zuletzt bearbeitet:
Das dabei eventuell fallende Carry und das HighByte des Produktes vergißt Du.
Ab a=1093 (0x0445) reichen zwei Ergebnisbytes nicht mehr aus (0x0445*0x003C=0x01002C)

(2^16)/60=1092,2666666...
Nein, das vergesse ich nicht, das ignoriere ich, mit brutaler Absichtlichkeit, weil es in diesem Anwendungsfall einfach nicht vorkommen kann, außer die ALU verrechnet sich. Dann ist aber die Hardware defekt. ;)

p.s.: …und damit mein ich nicht meinen Dickschädel :D
 
außer die ALU verrechnet sich. Dann ist aber die Hardware defekt. ;)

p.s.: …und damit mein ich nicht meinen Dickschädel :D

:D Der war gut!

Durch die zweite Multiplikation und die darauffolgende Addition berücksichtigt Tommy doch das Highbyte. Und wenn er die beiden Faktoren entsprechend begrenzt, kommt es nicht zum 16Bit Überlauf.
 
Wie gesagt... bis 1092dez gehts so, wenn das reicht (offensichtlich ja), ist mein "vergißt" das falsche Wort gewesen...
 
Ihr habt bestimmt noch nie n Typen gesehen der mit Geodreieck am Monitor gearbeitet hat.
Ich auch nicht. Aber ich habe es getan ^^'

Man glaubt nicht wie schwer es eigentlich ist etwas am PC präzise zu zeichnen, vor allem wenn es um Winkel und Bögen etcpp geht...

Aber ich habe es geschafft :)

Das wäre der erste Entwurf für die Skala/Legende/WieAuchImmerDasDingHeißt.
Blau und pink sind Hilfslinien.

upload_2015-12-23_21-35-24.png

upload_2015-12-23_21-35-44.png

Happy bashing :D
 
Man glaubt nicht wie schwer es eigentlich ist etwas am PC präzise zu zeichnen, vor allem wenn es um Winkel und Bögen etcpp geht...
Du hast doch Eagle, damit kannste doch dann auch Kreisbögen etc... als Hilfslinien zeichnen... so hab ich das schon gemacht
Oder die Zielposition berechnen, und das Element dann über die Eigenschaften dorthin setzen/moven

P.S.: gut schauts aus
 
Ja, daran hatte ich auch schon gedacht, aber dazu reichen meine Kenntnisse in Eagle bei Weitem nicht aus.
Außerdem das optisch auch noch einigermaßen hübsch hin zu bekommen... Die Eagle Schriftarten sind ja doch recht … verbesserungsfähig.

Dann lieber mit Geodreieck am Monitor ^^
 
Sodelle, die Anzeigen sind fertig umgebaut :)

IMAG0595.jpg

Bild stammt auf die Schnelle von der Handy Cam, reicht aber eigentlich :)
 
  • Like
Reaktionen: Dirk
Sodelle, habs endlich fehlerfrei hinbekommen :)
Vielleicht noch mit Optimierungspotential, aber so läuft es 1a :)



CodeBox Assembler
PWM_SetHours:

    ; Load increment value
    LDI        TEMP1    ,    EE_HoursPWM + 2    ; Get address of inc. value (low)
    RCALL    EE_Read                        ; Read from eeprom
    MOV        ZL        ,     TEMP1            ; Store received byte in ZL
    LDI        TEMP1    ,    EE_HoursPWM + 3    ; Get address of inc. value (high)
    RCALL    EE_Read                        ; Read from eeprom
    MOV        ZH        ,     TEMP1            ; Store received byte in ZH

    ; Multiply increment value by current minute (16x8=16 bit,ignore overfl.)
    MUL        ZL        ,    MINUTES            ; Mult. low byte (=base)
    MOVW    LTEMPH:LTEMPL    ,    MULRESH:MULRESL    ; Copy result to output
    MUL        ZH        ,    MINUTES            ; Mult. high byte (low byte needed)
    ADD        LTEMPH    ,    MULRESL            ; Add high byte result to result
   
    ; Multiply increment value by 60. (16x8=16 bit, ignore overflows)
    LDI        TEMP1    ,    60                ; Load minutes multiplicator (low)
    MUL        ZL        ,    TEMP1            ; Mult. low byte (=base)
    MOVW    XH:XL    ,    MULRESH:MULRESL    ; Copy result to output
    MUL        ZH        ,    TEMP1            ; Mult. high byte (low byte needed)
    ADD        XH        ,    MULRESL            ; Add high byte result to result

    ; Multiply increment value by current hour (16x8=16 bit, ignore overfl.)
    MUL        XL        ,    HOURS            ; Mult. low byte (=base)
    MOVW    YH:YL    ,    MULRESH:MULRESL    ; Copy result to output
    MUL        XH        ,    HOURS            ; Mult. high byte (low byte needed)
    ADD        YH        ,    MULRESL            ; Add high byte result to result

    ; Load start value (=minimum)
    LDI        TEMP1    ,    EE_HoursPWM + 0    ; Get address of start value (low)
    RCALL    EE_Read                        ; Read from eeprom
    MOV        ZL        ,     TEMP1            ; Store received byte in ZL
    LDI        TEMP1    ,    EE_HoursPWM + 1    ; Get address of start value (high)
    RCALL    EE_Read                        ; Read from eeprom
    MOV        ZH        ,     TEMP1            ; Store received byte in ZH

    ; Add start value (=minimum)
    ADD        YL        ,    ZL                ; Low byte
    ADC        YH        ,    ZH                ; High byte

    ; Add minutes value
    ADD        YL        ,    LTEMPL            ; Low byte
    ADC        YH        ,    LTEMPH            ; High byte

    ; Apply new value to the timer
    OUTX    OCR1AH    ,    YH
    OUTX    OCR1AL    ,    YL

RET
 
Hi Tommy,

Ihr habt bestimmt noch nie n Typen gesehen der mit Geodreieck am Monitor gearbeitet hat.
Ich auch nicht. Aber ich habe es getan ^^

und wie dann weiter? Mit Edding oder mit Bleistift (2H-Mine) eingeritzt? ;)

Ist schon teilweise recht kompliziert die Seitenverhältnisse und Proportionen auf dem Bildschirm mit der Wirklichkeit in Einklang zu bringen.
Entweder einiges an Testdrucken oder mit Geodreieck. Dann darf man aber keines dieser neumodisch gebogenen LCDs haben :D

Gruß
Dino
 
Nun ja, die Spezies Mensch, zu der ich mich gelegentlich auch zähle, hat ja 2 Hände.
Und so Geodreiecke sind idR transparent.

Dran halten mit einer Hand und Maus in die Andere und Linie zeichnen ;)
 
Dann nur noch abfotografieren, Film entwickeln, Abzug machen, ausschneiden und aufkleben. Ratzfatz professionelle Skalen! Schaut gut aus! Echt!
 
Naja, ich hab die Original Skala eingescannt (primär wegen den Maßen), da ich die Original Skala nicht verwenden konnte (falsche Einteilung).
Dann neue Skala gezeichnet, auf Fotopapier (matt) ausgedruckt, mit nem scharfen Messer ausgeschnitten und das statt dem original Blech genommen. Geht auch :)
 

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