Hallo liebes Forum.
Ich wollte ein altes Volume-Pedal um eine MIDI-Funktionalität erweitern.
Leider habe ich nach der Entwicklung auf dem Steckbrett mit einem Poti,
welches den vollen Weg fahren kann, festgestellt dass das Pedal das
nicht tut.
Bislang sieht mein Code so aus:
1
loop_adc:
2
;Referenzspannung AVCC - Ergebnis Linksbündig - Kanal 0
;Und Schleife neu starten falls noch nicht fertig konvertiert
23
jmp loop_adc_load_wait
24
;Das Low-Byte muss immer zuerst ausgelesen werden. Da drin stehen die 2 niederwertigsten Bits der Ergebnisses
25
in TMP3, ADCL
26
;Jetzt kommt das High-Byte. Das Low-Byte wird überschrieben um ein Zittern zu vermeiden. Wir haben also nur noch 8bit
27
in TMP3, ADCH
28
;Linksschieben, da wir nur 7 bit verarbeiten können
29
lsr TMP3
30
;Speichern des Ergebnisses und inkrementieren des Zeigers
31
st X+, TMP3
32
;Dekrementieren des Zählers
33
dec TMP2
34
;Inkrementieren des ADMUX-Registers
35
inc TMP1
36
out ADMUX, TMP1
37
;Schleife von neu beginnen
38
jmp loop_adc_check
39
40
loop_btn_right:
Den Befehl
1
;Linksschieben, da wir nur 7 bit verarbeiten können
2
lsr TMP3
muss ich nun durch eine Routine ersetzen, welche mir einem Eingangs-Wert
von, sagen wir mal, 60 bis 150 in einen Wert von 0 bis 127 umrechnet.
Wie stelle ich das am besten an? Ich stehe da ein bissl aufm Schlauch.
Entwickelt wurde und wird das ganze auf einem ATMEGA32. Später soll
alles auf einen Tiny25/45/85 portiert werden. Da hätte ich auch keinen
Hardware-Multiplizierer.
Danke für Antworten und ein schönes Wochenende.
Nimm C, BASCOM, Arduino oder sonstwas, da macht der Compiler die
Multiplikation für dich. Oder frag den "8 Bit MSR Optimalspezialisten"
Moby, ob er das für dich programmiert ;-)
TBI schrieb:> Später soll alles auf einen Tiny25/45/85 portiert werden. Da hätte ich> auch keinen Hardware-Multiplizierer.
Aber genug Speicher: ich würde eine Tabelle mit 256 Einträgen anlegen
und dort direkt mit dem AD-Wert den "umgerechneten" Midi-Wert abholen.
Dann könntest du sogar irgendwelche Nichtlinearitäten ganz einfach
geradebiegen...
@ TBI (Gast)
>Ich will hier keinen Thread über C vs. ASM vs. Bascom vs. was weiss ich.
Will auch keiner.
>Lediglich einen Denkanstoß, damit ich weiterkomme.
Nimm eine Softwarefunktion zur Multiplikation, die läuft auch auf den
Tinys.
Die gibt es in einer App-Note von Atmel, musst du mal suchen.
Lothar M. schrieb:> Aber genug Speicher: ich würde eine Tabelle mit 256 Einträgen anlegen> und dort direkt mit dem AD-Wert den "umgerechneten" Midi-Wert abholen.
Ich wollte einen Kalibrierungstaster anbringen um die Minimalen und
Maximalen Werte zu erhalten. Daher geht das leider nicht ohne weiteres.
Hallo,
hier würde ich auch eine Tabelle nehmen.
Tabellenstart in Z rein, ADC-Wert dazu addeiren und den MIDI-Wert
abholen.
Kann man vor allem genau passend basteln oder in Excel berechnen oder
wie auch immern. Macht man ja nur einmal.
Wenn man den Tiny85 nimmt kann man das vermutlich auch beim Start
berechnen und im Ram anlegen, dann spielt hinterher Laufzeit auch keine
Rolle mehr.
Gruß aus Berlin
Michael
Ich bräuchte 256 * 256 (Minimaler Wert) * 256 (Maximaler Wert) = 16MByte
Selbst bei 7 bit wären das noch 2MByte. Das packt auch der größte Mega
nicht...
TBI schrieb:> Wie stelle ich das am besten an?
Ob es am besten für dich ist, weiss ich nicht, aber üblicherweise würde
man eine lineare Umrechnung der Form y =x * m + b machen. In deinem Fall
also als Ganzzahlrechnung mit y = x * m1 / m2 + b mit z.B. m1=361,
m2=256 und b=-84. Das spart dir schon mal Float-Rechnung und Division.
> Da hätte ich auch keinen Hardware-Multiplizierer.
Dann wirst du die Multiplikation wohl in Software, ggf. hart kodiert mit
Addieren und Schieben machen müssen, also
Du müsstest, wenn du kalibrieren musst, die Geradengleichung im
Controller bestimmen.
Wie im Bild zu sehen wären die Werte 60 und 150 beispielhaft die
Ergebnisse aus der Kalibrierroutine. Diese musst du im Gleichungssystem
benutzen, um die Faktoren für die Gerade zu erhalten.
Noch einer schrieb:> Jeder Tiny dürfte die Skalierung schneller berechnen, als dein Kabel die> Midi-Pakete transportieren kann.
Genau das denke ich jetzt auch.
Erneut... Vielen Dank
Servus,
in meinem alten picalic-Projekt benutze ich eine lineare Interpolation,
um den Y-Wert einer Geraden für einen bestimmten X-Wert (im Bereich
X=0..X2) zu bestimmen. Einen Offset auf die X-Werte (wenn X1 nicht Null
sein soll) kann man ja leicht durch Addition erschlagen.
Ist zwar PIC-Assembler, aber vielleicht als Denkanstoss...:
1
;================ Linear Interpolation
2
;computes Y-value for given X-val.
3
;input:
4
;y1 = Y-value for X=0
5
;y2 = Y-value for X=x2
6
;x2 = X-value: length of interval
7
;x = x input value (1 ... x2-1)
8
;output:
9
;y = Y-value for given x
10
11
interpolate
12
clrf x1
13
btfsc x2,7
14
goto interp_loop ;x2 >= 0x80
15
16
bcf STATUS,C
17
interp_max
18
rlf x2,F ;maximize for higher precision
19
rlf x,F
20
btfss x2,7
21
goto interp_max
22
23
interp_loop
24
movf y1,W
25
addwf y2,W
26
movwf y
27
rrf y,F ;= mean val. of y1, y2
28
29
movf x1,W
30
addwf x2,W
31
movwf temp
32
rrf temp,F ;= mean val. of x1, x2
33
movf temp,W
34
subwf x,W
35
btfsc STATUS,Z
36
return ;exact match -> iteration complete
37
38
movf y,W
39
xorwf y1,W
40
btfsc STATUS,Z ;y == y1?
41
goto interp_exit ;Y: result is y1 or y2
42
43
movf y,W
44
xorwf y2,W
45
btfsc STATUS,Z ;y == y2?
46
goto interp_exit ;Y: result is y1 or y2
47
48
movf temp,W ;mean(x1,x2) -> W
49
btfss STATUS,C
50
goto interp_less ;C=0 => x < mean(x1,x2)
51
;x > mean(x1,x2):
52
movwf x1 ;new interval = mean..x2
53
movf y,W
54
movwf y1 ;new y within y..y2
55
goto interp_loop
56
57
;x < mean(x1,x2):
58
interp_less
59
movwf x2 ;new interval = x1..mean
60
movf y,W
61
movwf y2 ;new y within y1..y
62
goto interp_loop
63
64
;difference(y1,y2) <= 1, use y1 or y2 depending on x < or > mean(x1,x2)
Bei Werten von 60 bis 150 würde ich zunächst die 60 abziehen.
Bleibt 0 - 90
Dies würde ich mit 182 multiplizieren und vom Ergebnis die Bits 7-14
benutzen.
Natürlich kannst Dur diese Werte auch nachträglich kalibrieren.
Unterster Wert ist derjenige, der abgezogen wird.
Und 16352 geteilt durch das was nach Abzug vom obersten Wert übrig
bleibt ist die Zahl, mit der multipliziert werden muss.
Gruß
Jobst
Ich würde schauen, dass ich das Poti im Pedal so verdrehe, dass es 0-90
Verstellweg hat und eine ext. ADC-Referenz erzeugen, welche dem
Spannungswert bei 90 entspricht. Dann hast du von 0-90 den vollen
ADC-Bereich von 0-255, machst einen Rechtsshift und hast 0-127.
Ich werde die Routine neu schreiben und dabei den jeweiligen MIDI-Wert
aus dem ADC-Wert live berechnen. Selbst ein Tiny25 hat dazu genug Kraft.
Den im Ursprungspost geposteten Quellcode habe ich auf einen Kanal
reduziert und das Linksschieben verworfen. Jetzt bekomme ich zwar im
Moment nur Blödsinn, aber morgen werde ich mich mal in die
SW-Multiplikation und Division einlesen. Dann sollte das auch ganz
schnell klappen.
Ich habe das erstmal so vor:
TMP1 = ADC - Kalibrierung(Min)
TMP1 = TMP1 * 127
TMP2 = Kalibrierung(Max) - Kalibrierung(Min)
TMP1 = TMP1 / TMP2 (Rest wird verworfen)
Ob die Register gerade in Benutzung (bzgl. des geposteten SC) sind, oder
ob ich nachher noch den Rest der Division nutzen muss stelle ich fest
während/wenn ich das gecoded und ausprobiert habe. Aber erst morgen. Ein
Problem nach dem anderen...
Ich bedanke mich für alle Antworten und wünsche einen schönen restlichen
Sonntag.