Versnelling is in de mechanika een uiterst belangrijk begrip. Of een massa al dan niet in beweging is, kan niet in absolute zin worden uitgemaakt, maar waar verandering van snelheid optreedt, moet energie aan die massa worden toegevoerd. Exakter uitgedrukt: er moet een kracht op de massa inwerken. De versnelling, of, de snelheidsverandering van een massa in de tijd, is dan ook een rechtstreeks meetbare grootheid die een maat vormt voor de grootte van de kracht. In de mate waarin we akkoord gaan om te stellen dat de door een mens uitgeoefende kracht, een expressief relevant gegeven kan zijn, zullen we ook geinteresseerd zijn in meetmetodes om deze kracht zo rechtstreeks en precies mogelijk te meten. De in de fysika meest gebruikte metode bestaat erin gebruik te maken van de inertie (de traagheid). Wanneer aan de massa waarop een kracht werkt (bijvoorbeeld onze hand, bewogen door onze spierkracht) een tweede kleine massa vrij beweeglijk wordt vastgehecht, dan zal die tweede massa zich pogen te verzetten tegen die kracht (aktie = - reaktie uit de fyzika van Isaac Newton). Dit verzet is een kracht die via een sensor kan gemeten worden.
De modernste uitvoeringen van acceleratiesensors zijn uitgevoerd als een in chipvorm geintegreerde kondensator, bestaande uit een vaste 'plaat' en een met een kleine massa verzwaard beweeglijk daartegenover geplaatst membraan. In principe dus niet verschillend van de kondensatormikrofoon, maar wel zowat een faktor 1000 kleiner! Wanneer de kondensator met een bekende spanning wordt geladen dan zullen de variaties in kapaciteit van de kondensator onder invloed van het bij versnelling bewegend membraan, een verschuiving van de lading teweegbrengen: er vloeit een elektrische stroom. De variaties van deze stroom nu zijn een goede maat voor de versnelling die de sensor ondervindt. Er kleeft aan dit opzet weliswaar een belangrijke konditie: de meting zal alleen dan korrekt zijn wanneer de krachtvektor samenvalt of evenwijdig is met de loodlijn op de as van het membraan. Draaien we de sensor 90 graden dan heeft dezelfde kracht geen enkel effekt meer. Wiskundig kunnen we afleiden dat de sensor een signaal aflevert dat evenredig is met het produkt van de versnelling en de cosinus van de hoek gevormd door de aslijn van de sensor en de krachtvektor.
Willen we de 'absolute' versnelling van een in de ruimte bewegende massa kennen, dan kunnen we er niet onderuit een 3-dimensionele sensor te gebruiken . Dit is niets meer dan een kombinatie van 3 in een Cartesiaans assenstelsel opgestelde sensoren. De absolute versnelling van de massa kan dan worden afgeleid uit de berekening van de vektortiele som van de signalen van de drie sensoren. Dit gebeurt door de kwadraten van de grootte der individuele signalen op te tellen en uit deze som de wortel te trekken.
De versnelling wordt uitgedrukt in m/s^2. Maar, aangezien wij aardbewoners zijn, vergelijken wij haar als grootheid vaak met de elk van ons goed bekende valversnelling: 9.81 m/s^2. Dit is de versnelling die een massa ondervindt onder invloed van de zwaartekracht wanneer zij in vrije val is. De valversnelling wordt meestal aangeduid met g. Merk op dat versnelling een vektoriele grootheid is en dus een teken heeft (+ of -). Vertraging is immers niet anders dan een negatieve versnelling. Om een idee te krijgen van deze grootheid: een auto die tegen 110km/u tegen een muur knalt, ondervindt een versnelling van -50g. Voor het meten van menselijke motoriek is een meetbereik van -10 tot +10g algemeen genomen voldoende.
1. Hardware:
Voor de praktische opbouw van de sensor werd gebruik gemaakt van 3 chips van Analog Devices, ontwikkeld voor gebruik in air-bag systemen in autos. Het elektronische schema is niet veel meer dan een letterlijke toepassing van de application notes zelf. Erg belangrijk is de opstelling van de sensorchips op cartesische koordinaten, zodat we rechstreeks de vektoriele versnelling in X,Y en X kunnen verkrijgen. Het spreekt vanzelf dat de precisie van de rechthoekigheid hier beter moet zijn dan de resolutie van de sensors zelf: dus ca. 0.25%.
De 3 uitgangen worden verbonden met drie afzonderlijke kanalen van een ADC konversiekaart voor de ISA-bus in een IBM-achtige PC. Wij pasten hiervoor de overigens uitstekende Contec 16 kanaals 12 bits kaart toe, waardoor we tevens konden gebruik maken van de bijgeleverde libraries voor de softwarematige aansturing.
De technische specifikaties van de chip bepalen een meetbereik van -50 tot + 50g (g is de valversnelling, ca. 10m/s^2 ). Dit meetbereik is eigenlijk niet helemaal geschikt voor het opnemen van menselijke versnellingen, maar op het ogenblik waarop we het <Ei> ontwierpen was er geen andere keuze op de markt. Chips met een bereik van -2 tot + 2g worden aangekondigd, maar die zijn zeer waarschijnlijk veel te gevoelig. Eigen metingen leverden ons voor de bewegingen van de menselijke hand waarden op in het bereik -20 tot + 10g. De assymmetrie is het gevolg van het feit dat we ook botsingen met objekten (slaan, m.a.w.) wilden mogelijk maken.
Dit heeft uiteraard zijn gevolgen voor de haalbare resolutie met de door ons opgebouwde schakeling. De chip zelf heeft een resolutie van 7bit (ca. 1% precisie). Aangezien we van het gehele meetbereik evenwel slechts een vierde gebruiken, dienen we de praktische resolutie voor het door de mens haalbare bereik te verminderen tot 5 bits (bipolair dus: -32 tot + 31). Uit mijn eigen experimenteel werk met het interface, bleek evenwel dat deze waarde nog steeds iets groter is dan wat wij zelf repeteerbaar kunnen motorisch kontroleren.
Wie zelf met dit soort chips aan de slag wil, moet ik wel verwittigen voor hun relatief hoge prijs: ik betaalde zo'n 5.600 fr per stuk! Natuurlijk, wanneer we deze prijs vergelijken met die van driedimensionele muizen, dan zitten we beslist in een overeenkomstige prijsklasse... Wie een en ander graag op een eenvoudiger (lees: goedkopere) wijze wil beproeven, raad ik aan uit de gaan van goedkope piezoschijfjes voorzien van een inertiegewichtje en gebufferd met een stabiele op-amp. Zo'n opzet zal wel wat groter uitvallen maar kan voor zo'n 500 fr. worden opgebouwd.
(gebruik een TL074 quad opamp (inverterend) en drie stukjes piezo-materiaal, of, voor een heel wat gevoeliger uitvoering, 3 stukjes kynar-film).
In december 1995 bracht Motorola eveneens een accelerometer in chip vorm uit onder het typenummer MMAS40G. Deze chip heeft een meetbereik van -40g tot +40g en bevat onder meer de analoge elektronika voor een 4-polig uitgangsfilter. Prijsgegevens zijn ons (nog) niet bekend. Info: Motorola Inc., 5005 E.McDowell Road, Phoenix, Arizona, AZ85008. Tel.: [00-1]- (800)-273-6731.
De schakeling zoals we die opbouwden met de chips van analog devices ziet eruit alsvolgt
2. Software voorbeeld
Ter gelegenheid van de 11e week van de Hedendaagse Muziek aan het Konservatorium, zette ik een koncert op touw gewijd aan de mogelijkheden van de automatische player piano (cfr. het betreffende hoofdstuk in deze kursus). Een van de zaken die we daarbij voorstelden was een afstandsbestuurde piano. De bespeling maakte daarbij gebruik van wat ik mijn <Ei> heb gedoopt. De naam is niet zomaar gratuit gekozen: gezien het vektorieel karakter van de sensor en gezien de opmerkelijke assymetrie van de anatomie van onze handspieren, speelt het een belangrijke rol hoe we de sensor juist in de hand houden. Om die positie goed taktiel te kunnen aanvoelen en korrigeren, bouwde ik de sensoren in de vorm van een klein ei.
De kode zelf voert volgende taken uit:
1.- Initialisatie van de hardware (ADC-kaart, referentienivos van de XYZ acceleratiesensors...)
2. Data acquisition en informatieververwerving
3.- Mapping op muzikale parameters
4.- Interaktiviteit via de komputer
Bijzonder aan deze kode is het gebruik van twee tijdsvensters (timeframes): een eerste, heel klein venster vanwaaruit de momentane waarden van de input worden bepaald en een tweede, de grootte ervan is bepaald door de afmetingen van de ring-buffer, vanwaaruit globale gegevens over een groter tijdssegment kunnen worden afgeleid: bvb. de piek waarden van de versnelling in een tijdsvenster van 0.4s. Alleen op deze wijze kan op een intelligente wijze informatie uit de ingangssignalen afgeleid worden. Verdere uitbreiding van deze aanpak door nog meer tijdsvensters in te voeren is mogelijk, hoewel het vanuit geheugen-motorische optiek wellicht niet veel zin heeft vensters groter dan 5 a 10 sekonden te gaan bewerken.
Van fundamenteel belang bij het opzetten van dit soort interaktieve programmas is een juiste bepaling van de data-acquisitie parameters: sampling rate, aantal samples waarover uitgemiddeld wordt. Wanneer de sampling rate te laag is, krijgen we een al te geringe responsiviteit. Wordt zij te hoog genomen dan krijgen we te maken met onkontroleerbaarheid wegens motorische en elektronische ruis. Vaste wetten zijn in deze niet te geven, hoewel nooit uit het oog mag worden verloren wat de beperkingen zijn van onze menselijke motoriek: de kleinste kontroleerbare tijdsintervallen hebben een grootteorde van 10 a 30 ms. Dit interval moeten we in elk geval met een zo goed mogelijke resolutie weten te dekken.
3. Pianomuziek
Muzikale resultaten kunnen met dit ei alleen worden verkregen wanneer expressief zinnige 'mappings' worden toegepast om de versnellingsparameters af te beelden op eigenschappen van muzikale konstellaties. Voor het koncert programmeerden we een twaalftal verschillende mappings binnen een multitasker: notenreeksen waarvan de intervalvolgorde, de dynamiek (aanslag) en uiteraard de timing via het ei kunnen worden gespeeld, georganiseerd notenmateriaal waaruit muzikale zinnen gestueel kunnen worden geformuleerd, kwazi patogenetische clusteraggregaten die zelfs een wildebras als Fred Van Hove zouden doen watertanden, additieve strukturen over grotere tijdsintervallen met resetmogelijkheid vanuit bewegingseigenschappen zoals gedetekteerd door het ei ...
Weze tot slot opgemerkt dat deze sensor, net zoals overigens het <holosound> systeem zoals ik het ontwikkelde en toepaste in <A Book of Moves> en in <Songbook> , geen positionele informatie kan leveren. Een alternatieve traditionele bespeling van de piano kan er dan ook niet mee worden gerealiseerd. Louter teoretisch gesproken is het weliswaar mogelijk uit de vektoriele versnelling en de tijd, de snelheid af te leiden en vandaaruit de afgelegde weg, maar in de praktijk stapelen de meet- en rekenfouten zich dermate snel op, dat de numerieke resultaten zo goed als onbruikbaar worden. Wat expressieve direktheid betreft echter, is het uitstekend bruikbaar, mits de bespeler over een goede en beheerste motorische kontrole beschikt. In een latere faze hopen we de sensor verder te ontwikkelen tot een 'dirigeer'-sensor voor gebruik bij muzikale interaktieve uitvoeringen van komputermuziek. Daarvoor is evenwel nog heel wat wiskundige analyse nodig...
' *************************************************************************
' * < EGG > *
' * Programma voor de CONTEC ADC kaart type : AD12-16U(PC)E *
' * Dr.Godfried-Willem RAES *
' * Start up as: QBX /L H306BC7.QLB *
' *************************************************************************
' 14.10.95: for history on library development cfr. contec.bas
' de te gebruiken library files zijn nu:
' H306BC7.QLB (voor de interpreter)
' H306BC7.LIB (voor kompilatie)
' H306.BI (include file met procedures)
' HARDWARE-DATA:
' I/O adres jumpered to &H300 (SW1,2,3)
' Input range set to UNIPOLAR 0 - +5V (JP7,8,9,10)
' Analog output set to -10 to +10V (JP11,12)
' Digital output 3 (D3) CN2-pin10 (JP1)
' Gate control signal timer internal (JP2)
' Clock signal from counter 0 (JP3)
' Channel 0-7 start on 0 , 8-16 on &H0FFF: inversed sign on - input?
REM $DYNAMIC
' declaration of constants, arrays and variables
' **********************************************
CONST Adr = &H300 ' I/O address - must match jumpers
' Must be integer type!
CONST Dp% = &H330 ' Midi-card adres
CONST DAC5Volt = &HC40 ' = 3136 for 5Volt output
CONST DAC0Volt = &H800 ' = 2048 for 0 volt output.
CONST Xchannel = 13 ' adc channel used for X-vector
CONST Ychannel = 14 ' adc channel used for Y-vector
CONST Zchannel = 15 ' adc channel used for Z-vector
' this must match the hardware wiring
CONST False = 0
CONST True = NOT False
CONST Htes = 88 ' highest note on player piano
CONST Ltes = 24 ' lowest note on player piano
COMMON SHARED Buf%() ' buffer for converted data
' this buffer is filled using
' a single DMA-cycle if DMA
' is enabled in the corresponding
' function.
COMMON SHARED ErrFlg% ' Errorflag
COMMON SHARED IntCnt%
COMMON SHARED NrCh% ' number of channels
COMMON SHARED Rdata% ' for single ADC conversions
COMMON SHARED res% ' resolution
COMMON SHARED NrSamp%
COMMON SHARED SampFreq& ' sampling interval
COMMON SHARED Samprate#
COMMON SHARED Scanrate!
COMMON SHARED Acc%() ' acceleration values X,Y,Z,abs
COMMON SHARED OldAcc%()
COMMON SHARED V%() ' velocity values X,Y,Z,abs
COMMON SHARED S%() ' travel values X,Y,Z,abs
COMMON SHARED Ref0%() ' zero-acceleration references
COMMON SHARED RefMin%() ' -50g acceleration values
COMMON SHARED FactorX!, FactorY!, FactorZ!
COMMON SHARED CircBuf%()
COMMON SHARED MinMax%() ' positive and negative peak-values
COMMON SHARED Bufsize% ' determines time-slot for
' peak-values calculation.
COMMON SHARED DeltaT!
COMMON SHARED TimeSlot!
COMMON SHARED Ruis%
COMMON SHARED Ladder%() ' dim1 = 0-127
' dim2 = voices 0-2
COMMON SHARED oldnoot%()
' Procedures in external library :
' ***********************************
REM $INCLUDE: 'H306.BI'
' Functions and Subs for this Module:
' ***********************************
DECLARE SUB ContecIni (modus%) ' initializes Contec board
' modus%=0 sample channels 0-15
' modus%=1 sample single channel once
' modus%=2 sample many from single channel
' this is the mode used here!
' modus%=3 sample many from 0-15 channels
DECLARE FUNCTION ADC% (byte%) ' returns ADC from channel byte%
' should be compatible with BOM-code
DECLARE SUB MultiADC () ' fills Buf%() with one sample/channel
DECLARE SUB Samp (byte%) ' returns NrSamp% samples from channel byte%
' sampling rate= rate% as frequency
DECLARE SUB DAC (byte%) ' procedure for analog output used here
' for calibration routines.
DECLARE SUB Uit (byte%)
DECLARE SUB Mpuuart ()
DECLARE SUB Recalibrate () ' recalibration procedure
DECLARE SUB GetMinMax () ' calculates peak-values
DECLARE SUB MakeLadders () ' remapping for scales
DECLARE SUB DacqWindow () ' shows data acquisition parameters
DECLARE SUB Algomenu () ' shows mapping algorithm names
' Initialisation of variables:
' ****************************
NrSamp% = 10 ' default number of samples to take (10)
NrCh% = 16 ' default number of channels to scan
Samprate# = 16000 ' default sampling rate (nanoseconds)
' 16000 is maximum for 16 channel sampling.
' This results in a periodic sampling rate of 62.5ks/s
SampFreq& = 1000 ' max. default Sampling rate 62.5ks/s
Scanrate! = Samprate# / NrCh% ' channel scanning rate in nanoseconds.
' This is the minimal value!
Bufsize% = &HF ' size for circular buffer
DIM SHARED Buf%(NrCh% - 1, NrSamp% - 1)
' size of bufferarray must match amount
' of data from sample commands.
DIM SHARED Acc%(0 TO 3)
DIM SHARED V%(0 TO 3)
DIM SHARED S%(0 TO 3)
DIM SHARED OldAcc%(0 TO 3)
DIM SHARED Ref0%(0 TO 16)
DIM SHARED RefMin%(0 TO 16)
DIM SHARED MinMax%(0 TO 3, 0 TO 1) ' MinMax%(0,0)= Minimum Xacc
' MinMax%(0,1)= Maximum Xacc
' MinMax%(1,0)= Minimum Yacc
' MinMax%(1,1)= Maximum Yacc
' MinMax%(2,0)= Minimum Zacc
' MinMax%(2,1)= Maximum Zacc
' Minmax%(3,0)= Minimum AccAbs
' MinMax%(3,1)= Maximum AccAbs
DIM SHARED CircBuf%(0 TO Bufsize%, 0 TO 3)
DIM SHARED oldnoot%(0 TO 3)
DIM Toets%(0 TO 127) ' for player-piano
Cnote% = 64 ' default central note at start
oldnoot%(0) = 60
oldnoot%(1) = 60
oldnoot%(2) = 60
oldnoot%(3) = 60
Ruis% = 2 ' should be calculated
Algo% = 10 ' do nothing algorithm
SCREEN 12: WIDTH 80, 30
' *********************initial calibration ****************************
dummy% = InitBoard%(Adr) ' initialize Contec board
Mpuuart ' initialize midi-card
' get ZERO-references:
' set tst-pins low:
DAC DAC0Volt
COLOR 11: LOCATE 1, 10
PRINT "dr.Godfried-Willem RAES < EGG > - controller software";
COLOR 9: LOCATE 2, 10
PRINT "********************************************************";
COLOR 12: LOCATE 3, 2
PRINT " Dont move egg now ... ";
' take a series of samples from channels Xchannel,Ychannel,Zchannel:
NrSamp% = 256: ' aantal samples
SampFreq& = 500: ' in Hz (Samples per second)
FOR k% = Xchannel TO Zchannel
ContecIni 2
REDIM SHARED Buf%(0 TO NrSamp%, 0)
Samp k%
' calculation of weighted sum:
FOR i% = 1 TO NrSamp%
Ref0%(k%) = (Ref0%(k%) * .75) + (Buf%(i%, 0) * .25)
NEXT i%
Ref0%(k%) = Ref0%(k%) / 16: ' reduce from 12 to 8 bit
NEXT k%
COLOR 2: LOCATE 4, 2
PRINT "Integrated Zero-references:";
COLOR 10: LOCATE 5, 10
PRINT "X-ref="; Ref0%(Xchannel), "Y-ref="; Ref0%(Ychannel), "Z-ref="; Ref0%(Zchannel)
' **** get range-references:
' test nu de output bij -50g
DAC DAC5Volt
' read the values again now:
NrSamp% = 256: ' aantal samples
SampFreq& = 500: ' in Hz
FOR k% = Xchannel TO Zchannel
ContecIni 2
REDIM SHARED Buf%(0 TO NrSamp%, 0)
Samp k%
' again we use the weighted sum algorithm
FOR i% = 1 TO NrSamp%
RefMin%(k%) = (RefMin%(k%) * .75) + (Buf%(i%, 0) * .25)
NEXT i%
RefMin%(k%) = RefMin%(k%) / 16
NEXT k%
COLOR 2: LOCATE 6, 2
PRINT "Integrated Range-references at -50g";
COLOR 10: LOCATE 7, 10:
PRINT "X-min="; RefMin%(Xchannel), "Y-min="; RefMin%(Ychannel), "Z-ref="; RefMin%(Zchannel)
' note: this returns positive values, so
' the acceleration sign is inversed!
' berekening van de schaalfactoren
' - voor +/- 6 bit, of, 7-bit resolutie:
FactorX! = (2 ^ 6) / (RefMin%(Xchannel) - Ref0%(Xchannel))
FactorY! = (2 ^ 6) / (RefMin%(Ychannel) - Ref0%(Ychannel))
FactorZ! = (2 ^ 6) / (RefMin%(Zchannel) - Ref0%(Zchannel))
' berekening van de vector-offset error:
' NOT really tested yet:
VectorSumError = (Ref0%(Xchannel) ^ 2) + (Ref0%(Ychannel) ^ 2) + (Ref0%(Zchannel) ^ 2)
IF VectorSum >= 0 THEN
VectorSumError = SQR(VectorSum)
ELSE
VectorSumError = NOT (SQR(ABS(VectorSum))) + 1
END IF
COLOR 2: LOCATE 8, 2
PRINT "Err="; INT(VectorSumError); " ";
COLOR 10: LOCATE 3, 2:
PRINT "Initialisation done. Free for movement input...";
DIM SHARED Ladder%(0 TO 127, 0 TO 2)
MakeLadders ' get remapping-data
Algomenu
' ******************* measurement code running status ***************
DAC DAC0Volt
NrSamp% = 32 ' 16 samples @ 2ms per sample= 32ms per vector
SampFreq& = 2000 ' for 3 vectors at 500Hz this yields 96ms
pointer% = 0
DacqWindow
DO
ContecIni 2 ' must be in the loop!
REDIM SHARED Buf%(0 TO NrSamp%, 0)
Samp Xchannel
' calculation of weighted sum X-vector:
FOR i% = 1 TO NrSamp%
AccelX! = (AccelX! * .75) + (Buf%(i%, 0) * .25)
NEXT i%
AccelX! = AccelX! / 16: ' reduce to 8 bit
REDIM SHARED Buf%(0 TO NrSamp%, 0)
Samp Ychannel
' calculation of weighted sum Y-vector:
FOR i% = 1 TO NrSamp%
AccelY! = (AccelY! * .75) + (Buf%(i%, 0) * .25)
NEXT i%
AccelY! = AccelY! / 16: ' reduce to 8 bit
REDIM SHARED Buf%(0 TO NrSamp%, 0)
Samp Zchannel
' calculation of weighted sum Z-vector:
FOR i% = 1 TO NrSamp%
AccelZ! = (AccelZ! * .75) + (Buf%(i%, 0) * .25)
NEXT i%
AccelZ! = AccelZ! / 16: ' reduce to 8 bit
' scaling to 7-bit bi-polar:
' + polariteitskorrektie:
AccelX! = -(AccelX! - Ref0%(Xchannel)) * FactorX!
AccelY! = -(AccelY! - Ref0%(Ychannel)) * FactorY!
AccelZ! = -(AccelZ! - Ref0%(Zchannel)) * FactorZ!
VectorSum = (AccelX! ^ 2) + (AccelY! ^ 2) + (AccelZ! ^ 2)
Sum% = AccelX! + AccelY! + AccelZ!
IF Sum% < 0 THEN VectorSum = -SQR(VectorSum) ELSE VectorSum = SQR(VectorSum)
' derive velocities:
' for scaling we add:
VScalefactor! = 1 / DeltaT!
V%(0) = V%(0) + (AccelX! * VScalefactor!): IF V%(0) < 0 THEN V%(0) = 0
V%(1) = V%(1) + (AccelY! * VScalefactor!): IF V%(1) < 0 THEN V%(1) = 0
V%(2) = V%(2) + (AccelZ! * VScalefactor!): IF V%(2) < 0 THEN V%(2) = 0
V%(3) = V%(3) + (VectorSum * VScalefactor!): IF V%(3) < 0 THEN V%(3) = 0
' reset velocities on standstill:
IF ABS(AccelX!) <= Ruis% THEN V%(0) = 0
IF ABS(AccelY!) <= Ruis% THEN V%(1) = 0
IF ABS(AccelZ!) <= Ruis% THEN V%(2) = 0
IF ABS(VectorSum) <= Ruis% THEN V%(3) = 0
' limit velocities to 127 maximum value:
IF V%(0) > 127 THEN V%(0) = 127
IF V%(1) > 127 THEN V%(1) = 127
IF V%(2) > 127 THEN V%(2) = 127
IF V%(3) > 127 THEN V%(3) = 127
' derive trajects:
' these can be used as counters
IF V%(0) THEN S%(0) = (S%(0) + (V%(0) * DeltaT!)) AND &H7FFF
IF V%(1) THEN S%(1) = (S%(1) + (V%(1) * DeltaT!)) AND &H7FFF
IF V%(2) THEN S%(2) = (S%(2) + (V%(2) * DeltaT!)) AND &H7FFF
IF V%(3) THEN S%(3) = (S%(3) + (V%(3) * DeltaT!)) AND &H7FFF
' copy data into Acc% array:
Acc%(0) = INT(AccelX!)
Acc%(1) = INT(AccelY!)
Acc%(2) = INT(AccelZ!)
Acc%(3) = INT(VectorSum)
' copy data into circular buffer:
CircBuf%(pointer%, 0) = Acc%(0)
CircBuf%(pointer%, 1) = Acc%(1)
CircBuf%(pointer%, 2) = Acc%(2)
CircBuf%(pointer%, 3) = Acc%(3)
pointer% = (pointer% + 1) AND Bufsize%
' calculate acceleration peak-values
' within time-slot DeltaT! * BufSize%
GetMinMax
' display results:
COLOR 14: ' fel geel
LOCATE 10, 1:
PRINT " X ="; Acc%(0), "Min="; MinMax%(0, 0), "Max="; MinMax%(0, 1),
PRINT " Vx ="; V%(0), " Sx ="; S%(0);
LOCATE 11, 1:
PRINT " Y ="; Acc%(1), "Min="; MinMax%(1, 0), "Max="; MinMax%(1, 1),
PRINT " Vy ="; V%(1), " Sy ="; S%(1);
LOCATE 12, 1:
PRINT " Z ="; Acc%(2), "Min="; MinMax%(2, 0), "Max="; MinMax%(2, 1),
PRINT " Vz ="; V%(2), " Sz ="; S%(2);
LOCATE 13, 1:
PRINT " Abs="; Acc%(3), "Min="; MinMax%(3, 0), "Max="; MinMax%(3, 1),
PRINT " Va ="; V%(3), " Sa ="; S%(3);
' ************************* Instrumentale Kode ***************************
SELECT CASE Algo%
CASE 0
' recalibration on command
NrSamp% = 32: ' aantal samples
SampFreq& = 2000: ' in Hz (Samples per second)
REDIM SHARED Buf%(0 TO NrSamp%, 0)
Recalibrate
Algo% = -1
DacqWindow
CASE 1
' Mapping1: - X-Y-Z
' linear mapping on pitch
Velo% = (ABS(Acc%(0)) + ABS(Acc%(1)) + ABS(Acc%(2)))
IF Velo% > 127 THEN Velo% = 127
IF Velo% < 0 THEN Velo% = 0
FOR j% = 0 TO 2
IF ABS(Acc%(j%) - OldAcc%(j%)) > Ruis% THEN
IF Toets%(oldnoot%(0)) THEN
Uit 144: Uit oldnoot%(j%): Uit 0
END IF
oldnoot%(j%) = Cnote% + Acc%(j%)
IF oldnoot%(j%) > Htes THEN oldnoot%(j%) = Htes
IF oldnoot%(j%) <= Ltes THEN oldnoot%(j%) = Ltes
Uit 144: Uit oldnoot%(j%): Uit Velo%
OldAcc%(j%) = Acc%(j%)
Toets%(oldnoot%(j%)) = Velo%
END IF
NEXT j%
IF ABS(Acc%(3) - OldAcc%(3)) > Ruis% THEN
Cnote% = 64 + Acc%(3)
OldAcc%(3) = Acc%(3)
END IF
CASE 2
' mapping 2: additive!
' velocity mapped on
' non-vectorial acceleration:
IF Acc%(3) <> OldAcc%(3) THEN
Velo% = ABS(Acc%(3)) * 3
IF Velo% > 127 THEN Velo% = 127
OldAcc%(3) = Acc%(3)
END IF
FOR j% = 0 TO 2
IF ABS(Acc%(j%) - OldAcc%(j%)) > Ruis% THEN
IF Toets%(oldnoot%(j%)) THEN
Uit 144: Uit oldnoot%(j%): Uit 0
Toets%(oldnoot%(j%)) = False
END IF
oldnoot%(j%) = oldnoot%(j%) + Acc%(j%)
IF oldnoot%(j%) > Htes THEN oldnoot%(j%) = Htes
IF oldnoot%(j%) <= Ltes THEN oldnoot%(j%) = Ltes
Uit 144: Uit oldnoot%(j%): Uit Velo%
OldAcc%(j%) = Acc%(j%)
Toets%(oldnoot%(j%)) = Velo%
END IF
' reset when Minimum-peak equals maximum-peak
IF ABS(MinMax%(j%, 1) - MinMax%(j%, 0)) <= Ruis% THEN
IF Toets%(oldnoot%(j%)) THEN
Uit 144: Uit oldnoot%(j%): Uit 0
Toets%(oldnoot%(j%)) = False
END IF
oldnoot%(j%) = 48 + (j% * 12)
END IF
NEXT j%
CASE 3
' algo using peak-values:
Velo% = ABS(MinMax%(3, 0)) + MinMax%(3, 1)
IF Velo% > 127 THEN Velo% = 127
IF Velo% < 0 THEN Velo% = 0
FOR j% = 0 TO 2
Cnote% = 60 + MinMax%(j%, 0) + MinMax%(j%, 1)
IF ABS(Acc%(j%) - OldAcc%(j%)) > Ruis% THEN
IF Toets%(oldnoot%(j%)) THEN
Uit 144: Uit oldnoot%(j%): Uit 0
END IF
oldnoot%(j%) = Cnote% + Acc%(j%)
IF oldnoot%(j%) > Htes THEN oldnoot%(j%) = Htes
IF oldnoot%(j%) <= Ltes THEN oldnoot%(j%) = Ltes
Uit 144: Uit oldnoot%(j%): Uit Velo%
OldAcc%(j%) = Acc%(j%)
Toets%(oldnoot%(j%)) = Velo%
END IF
NEXT j%
CASE 4
' using remapping of scales with different Tc% for each voice:
' Tc X = 0 = 60
' Tc Y = 4 = 64
' Tc Z = 8 = 68
' algo using peak-values:
Velo% = ABS(MinMax%(3, 0)) + MinMax%(3, 1)
IF Velo% > 127 THEN Velo% = 127
IF Velo% < 0 THEN Velo% = 0
FOR j% = 0 TO 2
IF j% = 0 THEN Cnote% = 0: ' of: (MinMax%(0, 0) + MinMax%(0, 1)) MOD 12
IF j% = 1 THEN Cnote% = 4: ' of: (4+ MinMax%(1, 0) + MinMax%(1, 1)) MOD 12
IF j% = 2 THEN Cnote% = 8: ' of: (8+ MinMax%(2, 0) + MinMax%(2, 1)) MOD 12
IF ABS(Acc%(j%) - OldAcc%(j%)) > Ruis% THEN
IF Toets%(oldnoot%(j%)) THEN
Uit 144: Uit oldnoot%(j%): Uit 0
Toets%(oldnoot%(j%)) = False
END IF
oldnoot%(j%) = Cnote% + Ladder%(60 + Acc%(j%), j%)
IF oldnoot%(j%) > Htes THEN oldnoot%(j%) = Htes
IF oldnoot%(j%) <= Ltes THEN oldnoot%(j%) = Ltes
Uit 144: Uit oldnoot%(j%): Uit Velo%
OldAcc%(j%) = Acc%(j%)
Toets%(oldnoot%(j%)) = Velo%
END IF
NEXT j%
CASE 5
' using remapping of scales with varying Tc% for each voice:
' algo using peak-values:
Velo% = ABS(MinMax%(3, 0)) + MinMax%(3, 1)
IF Velo% > 127 THEN Velo% = 127
IF Velo% < 0 THEN Velo% = 0
FOR j% = 0 TO 2
Cnote% = ((j% * 4) + (MinMax%(j%, 0) + MinMax%(j%, 1))) MOD 12
IF ABS(Acc%(j%) - OldAcc%(j%)) > Ruis% THEN
IF Toets%(oldnoot%(j%)) THEN
Uit 144: Uit oldnoot%(j%): Uit 0
END IF
oldnoot%(j%) = Cnote% + Ladder%(60 + Acc%(j%), j%)
IF oldnoot%(j%) > Htes THEN oldnoot%(j%) = Htes
IF oldnoot%(j%) <= Ltes THEN oldnoot%(j%) = Ltes
Uit 144: Uit oldnoot%(j%): Uit Velo%
OldAcc%(j%) = Acc%(j%)
Toets%(oldnoot%(j%)) = Velo%
END IF
NEXT j%
CASE 6
' use velocity to controll
' midi-velocity:
' using remapping of scales with varying Tc% for each voice:
' algo using peak-values:
FOR j% = 0 TO 2
Cnote% = ((j% * 4) + (MinMax%(j%, 0) + MinMax%(j%, 1))) MOD 12
IF V%(j%) THEN
IF Toets%(oldnoot%(j%)) THEN
Uit 144: Uit oldnoot%(j%): Uit 0
Toets%(oldnoot%(j%)) = False
END IF
oldnoot%(j%) = Cnote% + Ladder%(60 + Acc%(j%), j%)
IF oldnoot%(j%) > Htes THEN oldnoot%(j%) = Htes
IF oldnoot%(j%) <= Ltes THEN oldnoot%(j%) = Ltes
Uit 144: Uit oldnoot%(j%): Uit V%(j%)
OldAcc%(j%) = Acc%(j%)
Toets%(oldnoot%(j%)) = V%(j%)
END IF
NEXT j%
END SELECT
' select different mappings with number-keys:
k$ = INKEY$
SELECT CASE k$
CASE ""
CASE CHR$(27)
EXIT DO
CASE " "
' CHR$(32)
k$ = ""
SLEEP 1
CASE ELSE
Ask% = ASC(UCASE$(k$))
' numerieke toetsen:
IF Ask% > 47 AND Ask% < 58 THEN
Algo% = Ask% - 48
k$ = ""
' initialize parameters:
IF Algo% = 1 THEN Cnote% = 60
IF Algo% = 2 THEN oldnoot%(0) = 60: oldnoot%(1) = 60: oldnoot%(2) = 60
COLOR 12: LOCATE 15, 10
PRINT "Playing Algo nr="; Algo%; " ";
END IF
' alfabet toetsen:
IF Ask% > 64 AND Ask% < 94 THEN
Algo% = Ask% - 55
k$ = ""
END IF
IF LEN(k$) = 2 THEN
' get 2-byte keyboard codes:
' these control data-acquisition parameters
Kpcode% = ASC(RIGHT$(k$, 1))
SELECT CASE Kpcode%
CASE 80
' cursor down key (sens up)
' smaller number of samples
NrSamp% = NrSamp% - 1
IF NrSamp% < 1 THEN NrSamp% = 1
CASE 72
' cursor up key (sens down)
' larger number of samples
NrSamp% = NrSamp% + 1
CASE 75
' cursor left (slower)
' control sampling rate
SampFreq& = SampFreq& / 2
IF SampFreq& < 9 THEN SampFreq& = 9
CASE 77
' cursor right (faster)
' control sampling rate
SampFreq& = SampFreq& * 2
IF SampFreq& > 5000 THEN SampFreq& = 5000
CASE 73
' page up (faster)
' control buffersize window: smaller
Bufsize% = (Bufsize% \ 2) OR 1
REDIM SHARED CircBuf%(0 TO Bufsize%, 0 TO 3)
pointer% = 0
CASE 81
' page down (slower)
' control buffersize window: larger
Bufsize% = (Bufsize% * 2) + 1
IF Bufsize% > &HFFF THEN Bufsize% = &HFFF
REDIM SHARED CircBuf%(0 TO Bufsize%, 0 TO 3)
pointer% = 0
END SELECT
DacqWindow
END IF
END SELECT
LOOP
END
REM $STATIC
FUNCTION ADC% (byte%)
' deze funktie levert de uitgelezen waarde van het overgedragen kanaal op
' Sampling rate > 1000S/s
dummy% = StartAI%(Adr, byte%) ' start conversion on channel byte%
' dummy% = StopAI%(Adr)
' stops analog input
' only needed of no limit
' was set in SetAIfunction%
DO
dummy% = GetStatus%(Adr, VARPTR(Sts%), VARSEG(Sts%)) ' get sampling status
LOOP WHILE Sts% AND &H1 ' test busy status
IF (Sts% AND &H80) <> 0 THEN ErrFlg% = 1 ' test sampling error
dummy% = GetAIData%(Adr, VARPTR(Rdata%), VARSEG(Rdata%))
SELECT CASE res%
CASE 16
ADC% = Rdata% * 16 ' voor 16-bit getal
CASE 15
ADC% = Rdata% * 8 ' voor 15-bit getal
CASE 14
ADC% = Rdata% * 4 ' voor 14-bit getal
CASE 13
ADC% = Rdata% * 2 ' voor 13-bit getal
CASE 12
ADC% = Rdata% ' voor 12 bit resolutie
CASE 11
ADC% = Rdata% \ 2 ' voor 11-bit resolutie
CASE 10
ADC% = Rdata% \ 4 ' voor 10-bit resolutie
CASE 9
ADC% = Rdata% \ 8 ' voor 9-bit resolutie
CASE 8
ADC% = Rdata% \ 16: ' voor 8-bit resolutie
CASE 7
ADC% = Rdata% \ 32: ' voor 7-bit resolutie
CASE 6
ADC% = Rdata% \ 64: ' voor 6-bit resolutie
CASE 5
ADC% = Rdata% \ 128: ' voor 5-bit resolutie
CASE 4
ADC% = Rdata% \ 256: ' voor 4-bit resolutie
CASE ELSE
ADC% = 0
END SELECT
END FUNCTION
SUB Algomenu
COLOR 4
LOCATE 17, 5: PRINT "<0> = Recalibrate ";
LOCATE 18, 5: PRINT "<1> = XYZ-linear ";
LOCATE 19, 5: PRINT "<2> = XYZ-additive";
LOCATE 20, 5: PRINT "<3> = XYZ-peak ";
LOCATE 21, 5: PRINT "<4> = ";
LOCATE 22, 5: PRINT "<5> = ";
LOCATE 17, 25: PRINT "<6> = ";
LOCATE 18, 25: PRINT "<7> = ";
LOCATE 19, 25: PRINT "<8> = ";
LOCATE 20, 25: PRINT "<9> = ";
LOCATE 21, 25: PRINT "<A> = ";
LOCATE 22, 25: PRINT "<B> = ";
LOCATE 17, 45: PRINT "<C> = ";
LOCATE 18, 45: PRINT "<D> = ";
LOCATE 19, 45: PRINT "<E> = ";
LOCATE 20, 45: PRINT "<F> = ";
LOCATE 21, 45: PRINT "<G> = ";
LOCATE 22, 45: PRINT "<H> = ";
END SUB
SUB ContecIni (modus%)
SELECT CASE modus%
CASE 0
' take one sample from each channel (0-15)
dummy% = SetAIFunction%(Adr, &H280) ' set function 101
'&H00 = 0000 0010 1000 0000
' = software sampling (D0, D1 = 0)
' = sampling stop on end of storage (D2, D3 = 0)
' = Internal period clock for sampling (D4, D5 = 0)
' = D6 = 0 not used
' = Input channel = multi channel (D7 = 1)
' = select use of on board memory= FIFO (D8 = 0)
' = Repeat mode limited number (=D9 = 1)
' = D10 = 0 not used
' = DMA transfer mode not used (= D11 = 0)
' = Simultaneous sampling not used (=D12 = 0)
' = Converted data type= Offset straight binary (=D13=0)
' 2's complement binary (=D13=1)
' other bits are not used (=D14, D15 = 0)
FOR i% = 0 TO 15
dummy% = SetAIChannel%(Adr, i%, i%)
' set input channel scanning sequence
' This remaps the channels - should be done once only
NEXT i%
dummy% = SetAIScanClk%(Adr, 1000)
' long integer type...
' 1000& =set to 1 microsecond -cfr. p.35
' default is 25ns (settling time)
dummy% = SetAISmpClk%(Adr, 16384)
' set sampling clock: must be > 1000! * 16 ns
dummy% = SetAISmpNum%(Adr, 0, 16, 0)
' set number of samples to store: long integers
' 0& = number of samples to take before storing
' 16& = number of samples to store
' 0& = number of samples to take afterwards and stored
CASE 1
' take a single sample from a single channel
dummy% = SetAIFunction%(Adr, &H200) ' set function 101
'&H00 = 0000 0010 0000 0000
' = software sampling (D0-D1)
' = sampling stop on end of storage (D2, D3)
' = Internal period clock for sampling (D4,D5)
' = D6=0 not used
' = Input channel = single channel (D7= 0)
' = select use of on board memory= FIFO (D8)
' = Repeat mode limited number of times (=D9 = 1)
' = D10=0 not used
' = DMA transfer mode not used (=D11)
' = Simultaneous sampling not used (=D12)
' = Converted data type= Offset straight binary (=D13/0)
' 2's complement binary (=D13/1)
' other bits are not used
dummy% = SetAIScanClk%(Adr, 25)
' 1000&=set to 1 microsecond -cfr. p.35
' default is 25ns (settling time)
dummy% = SetAISmpClk%(Adr, 1000)
' set sampling clock
' must be > 1000! ns
dummy% = SetAISmpNum%(Adr, 0&, 1&, 0&):
' set number of samples to store
' 0& = number of samples to take before storing
' 1& = number of samples to store
' 0& = number of samples to take afterwards and stored
CASE 2
' single channel - many samples (1-dim. array)
dummy% = SetAIFunction%(Adr, &H10) ' set function 101
'&H00 = 0000 0000 0001 0000
' = software sampling (D0, D1 = 00)
' = sampling stop on end of storage (D2, D3 = 00)
' = Internal frequency clock for sampling (D4, D5 = 01)
' = D6=0 not used
' = Input channel = single channel (D7 = 0)
' = select use of on board memory= FIFO (D8 = 0)
' = Repeat mode limited fixed number (D9 = 0)
' = D10=0 not used
' = DMA transfer mode not used (D11= 0)
' = Simultaneous sampling not used (D12= 0)
' = Converted data type
' Offset straight binary (D13= 0)
' 2's complement binary (D13= 1)
' other bits are not used
dummy% = SetAIScanClk%(Adr, 900)
' 1000&=set to 1 microsecond -cfr. p.35
' default is 25ns (settling time)
dummy% = SetAISmpFrq%(Adr, SampFreq&)
' set sampling frequency
' must be < 1.000.000 Hz
dummy% = SetAISmpNum%(Adr, 0&, NrSamp%, 0&):
' set number of samples to store
' 0& = number of samples to take before storing
' 1& = number of samples to store
' 0& = number of samples to take afterwards and stored
CASE 3
' multichannel - multisample (2-dim array)
dummy% = SetAIFunction%(Adr, &H80) ' set function 101
'&H00 = 0000 0000 1000 0000
' = software sampling (D0, D1 = 00)
' = sampling stop on end of storage (D2, D3 = 00)
' = Internal period clock for sampling (D4, D5 = 00)
' = D6 = 0 not used (D6 = 0)
' = Input channel = multi channel (D7 = 1)
' = select use of on board memory= FIFO (D8 = 0)
' = Repeat mode limited or no limit (D9 = 0)
' D9=0 = limited times
' D9=1 = no limit
' = D10 = 0 not used (D10 = 0)
' = DMA transfer mode not used (D11 = 0)
' = Simultaneous sampling not used (D12 = 0)
' = Converted data type (D13 = 0)
' Offset straight binary (=D13=0)
' 2's complement binary (=D13=1)
' other bits are not used (D14,D15= 00)
FOR i% = 0 TO NrCh% - 1
dummy% = SetAIChannel%(Adr, i%, i%) ' set input channel
' scanning sequence
' This remaps the channels
NEXT i%
dummy% = SetAIScanClk%(Adr, Scanrate!) ' set scan clock
dummy% = SetAISmpClk%(Adr, Samprate#) ' set sampling clock
dummy% = SetAISmpNum%(Adr, 0, NrSamp%, 0) ' set number of samples
' first sample is unreliable!
but setting some trow away samples does not seem to help us out...
END SELECT
END SUB
SUB DAC (byte%)
' ***Use analog out to set the -50g reference for the range***********
' "Hardware set to range -10V to +10V";
' "To output 5V on ADC-channel 16, the value"
' "3136 should be given. (HEX: &H0C40)";
' "Values below &H800 (2048) are negative voltage!";
' "To output exactly 0V: give &H800 or 2048 as value";
' This is required for normal operation of the egg.
' Dat% = 2048 ' 0Volt
' Dat% = 3136 ' +5Volt
dummy% = SetAOData%(Adr, byte%)
END SUB
SUB DacqWindow
' redraws the window with data-acquisition parameters
DeltaT! = 3 * NrSamp% / SampFreq&
TimeSlot! = DeltaT! * Bufsize%
COLOR 11
LOCATE 24, 1: PRINT "Data Acquisition Real Time Parameters:";
COLOR 9
LOCATE 25, 1: PRINT "**************************************";
COLOR 5
LOCATE 26, 5: PRINT "NrSamp =";
COLOR 13: PRINT NrSamp%,
COLOR 5: PRINT "Samplingrate=";
COLOR 13: PRINT SampFreq&; " ";
COLOR 5
LOCATE 27, 5: PRINT "Bufsize=";
COLOR 13: PRINT Bufsize%,
COLOR 5: PRINT "TimeSlot =";
COLOR 13: PRINT TimeSlot!; " ";
COLOR 5: LOCATE 28, 5:
PRINT "Noise =";
COLOR 13: PRINT Ruis%,
COLOR 5: PRINT "Delta-T=";
COLOR 13: PRINT DeltaT!; " ";
COLOR 2
LOCATE 29, 1: PRINT "<- ->= Samplingrate", "Up/Down= NrSamp", "PgUp/PgDn= Bufsize";
' rescale on exit:
DeltaT! = DeltaT! * 10
COLOR 14
END SUB
SUB GetMinMax
' the time-slot windows wherin the peak values are calculated is
' a function of BufSize%. This parameter may be changed in real-time.
' MinMax%(0,0)= Minimum Xacc
' MinMax%(0,1)= Maximum Xacc
' MinMax%(1,0)= Minimum Yacc
' MinMax%(1,1)= Maximum Yacc
' MinMax%(2,0)= Minimum Zacc
' MinMax%(2,1)= Maximum Zacc
' Minmax%(3,0)= Minimum AccAbs
' MinMax%(3,1)= Maximum AccAbs
' step1: reset MinMax%
MinMax%(0, 0) = 64
MinMax%(0, 1) = -64
MinMax%(1, 0) = 64
MinMax%(1, 1) = -64
MinMax%(2, 0) = 64
MinMax%(2, 1) = -64
MinMax%(3, 0) = 64
MinMax%(3, 1) = -64
' step2: get new min and max values from the circular buffer
' its size determines the time-slot.
FOR i% = Bufsize% TO 0 STEP -1
' find minimum peak's:
IF CircBuf%(i%, 0) < MinMax%(0, 0) THEN MinMax%(0, 0) = CircBuf%(i%, 0)
IF CircBuf%(i%, 1) < MinMax%(1, 0) THEN MinMax%(1, 0) = CircBuf%(i%, 1)
IF CircBuf%(i%, 2) < MinMax%(2, 0) THEN MinMax%(2, 0) = CircBuf%(i%, 2)
IF CircBuf%(i%, 3) < MinMax%(3, 0) THEN MinMax%(3, 0) = CircBuf%(i%, 3)
' find maximum peak's:
IF CircBuf%(i%, 0) > MinMax%(0, 1) THEN MinMax%(0, 1) = CircBuf%(i%, 0)
IF CircBuf%(i%, 1) > MinMax%(1, 1) THEN MinMax%(1, 1) = CircBuf%(i%, 1)
IF CircBuf%(i%, 2) > MinMax%(2, 1) THEN MinMax%(2, 1) = CircBuf%(i%, 2)
IF CircBuf%(i%, 3) > MinMax%(3, 1) THEN MinMax%(3, 1) = CircBuf%(i%, 3)
NEXT i%
END SUB
SUB MakeLadders
FOR j% = 0 TO 2
Tc% = 60
Increm% = 0
Ladder%(60, j%) = Tc%
FOR i% = 61 TO 120
' stijgende toonladder in vergrotende intervallen:
Increm% = Increm% + 1
Ladder%(i%, j%) = Tc% + Increm%
IF Ladder%(i%, j%) > Htes THEN Ladder%(i%, j%) = (((Htes \ 12) * 12) - 1) + (Ladder%(i%, j%) MOD 12)
' dalend in vergrotende intervallen:
' memo: 120= Tc% * 2
Ladder%(120 - i%, j%) = Tc% - Increm%
IF Ladder%(120 - i%, j%) < Ltes THEN Ladder%(120 - i%, j%) = (((Ltes \ 12) * 12) + 1) + (Ladder%(120 - i%, j%) MOD 12)
NEXT i%
NEXT j%
END SUB
SUB Mpuuart
IF Dp% <> &H330 THEN EXIT SUB
Uart% = &H3F ' = 0011 1111 (63) =UART-command
Rst% = &HFF: ' = 1111 1111 (255)= Reset-command
Cp% = Dp% + 1
INITUART:
' als bit 7 1 is, is er geen te lezen byte:
IF INP(Cp%) AND 128 THEN
WAIT Cp%, 64, 64: ' check bit 6 - must be 0
OUT Cp%, Uart%
ELSE
' als bit 7 0 is moet er een byte ingelezen worden:
DO
dummy% = INP(Dp%)
LOOP UNTIL INP(Cp%) AND 128
GOTO INITUART
END IF
END SUB
SUB MultiADC
' this function returns a single sample from each channel in Buf%()
dummy% = StartAI%(Adr, 15)
' start conversion from channel 0 to 15
' dummy% = StopAI%(Adr)
' stops analog input - only needed if no limit
' was set in SetAIfunction%
DO
dummy% = GetStatus%(Adr, VARPTR(Sts%), VARSEG(Sts%)) ' get sampling status
LOOP WHILE Sts% AND &H1 ' test busy status
IF (Sts% AND &H80) <> 0 THEN ErrFlg% = 1 ' test sampling error
'--- Get converted data ---
dummy% = GetAIArray%(Adr, VARPTR(Buf%(0, 0)), VARSEG(Buf%(0, 0)), 16)
' de data worden nu geretourneerd in het shared array Buf%()
END SUB
SUB Recalibrate
dummy% = InitBoard%(Adr) ' initialize Contec board
' get ZERO-references:
' set tst-pins low:
DAC DAC0Volt
COLOR 12: LOCATE 3, 2:
PRINT " Dont move egg now ... ";
' take a series of samples
' from channels Xchannel,Ychannel,Zchannel:
FOR k% = Xchannel TO Zchannel
ContecIni 2
REDIM Buf%(0 TO NrSamp%, 0)
Samp k%
' calculation of weighted sum:
FOR i% = 1 TO NrSamp%
Ref0%(k%) = (Ref0%(k%) * .75) + (Buf%(i%, 0) * .25)
NEXT i%
Ref0%(k%) = Ref0%(k%) / 16: ' reduce to 8 bit
NEXT k%
COLOR 2: LOCATE 4, 2
PRINT "Integrated Zero references:";
COLOR 10: LOCATE 5, 10
PRINT "X-ref="; Ref0%(Xchannel), "Y-ref="; Ref0%(Ychannel), "Z-ref="; Ref0%(Zchannel)
' **** get range-references:
' test nu de output bij -50g
DAC DAC5Volt
' read the values again now:
FOR k% = Xchannel TO Zchannel
ContecIni 2
REDIM Buf%(0 TO NrSamp%, 0)
Samp k%
' weighted sum algorithm
FOR i% = 1 TO NrSamp%
RefMin%(k%) = (RefMin%(k%) * .75) + (Buf%(i%, 0) * .25)
NEXT i%
RefMin%(k%) = RefMin%(k%) / 16
NEXT k%
DAC DAC0Volt ' reset the test-pin
COLOR 2: LOCATE 6, 2
PRINT "Integrated Range-references at -50g";
COLOR 10: LOCATE 7, 10
PRINT "X-min="; RefMin%(Xchannel), "Y-min="; RefMin%(Ychannel), "Z-ref="; RefMin%(Zchannel)
' note: this returns positive values, so
' the acceleration sign is inversed!
' berekening van de schaalfactoren -
' voor +/- 6 bit, of, 7-bit resolutie:
FactorX! = (2 ^ 6) / (RefMin%(Xchannel) - Ref0%(Xchannel))
FactorY! = (2 ^ 6) / (RefMin%(Ychannel) - Ref0%(Ychannel))
FactorZ! = (2 ^ 6) / (RefMin%(Zchannel) - Ref0%(Zchannel))
COLOR 10: LOCATE 3, 2:
PRINT "Recalibration done. Free for playing... ";
END SUB
SUB Samp (byte%)
' should be called after initialisation by ContecIni 2
' This function returns n samples from a channel byte%
' sampling at a sampling rate determined by Sampfreq&
' the data are returned in the shared array Buf%()
dummy% = StartAI%(Adr, byte%)
DO
dummy% = GetStatus%(Adr, VARPTR(Sts%), VARSEG(Sts%)) ' get sampling status
LOOP WHILE Sts% AND &H1 ' test busy status
IF (Sts% AND &H80) <> 0 THEN ErrFlg% = 1 ' test sampling error
dummy% = GetAIArray%(Adr, VARPTR(Buf%(0, 0)), VARSEG(Buf%(0, 0)), NrSamp%)
END SUB
SUB Uit (byte%)
SELECT CASE Dp%
CASE &H330
IF INP(&H331) AND 128 THEN
WAIT &H331, 64, 64: OUT &H330, byte%: EXIT SUB
ELSE
WHILE INP(&H331) < 128: dummy% = INP(&H330): WEND
WAIT &H331, 64, 64: OUT &H330, byte%: EXIT SUB
END IF
CASE &H2FA
' Logotronics interfaces:
OUT &H2FA, byte%: DO: LOOP UNTIL INP(&H2FB) AND 64: EXIT SUB
WHILE INP(&H2FB) < 64: WEND: ' werkt ook zonder op de T1000 !
CASE &H378
' this is for the Halikan Notebook 80386SX + 80486DX (not tested yet)
OUT &H378, byte%: OUT &H37A, 0: ZZ# = ZZ# ^ ZZ#: OUT &H37A, 1
WHILE INP(&H379) AND 128: WEND
CASE &H320
' this is for Abulafia
OUT &H320, byte%: OUT &H322, 0: ZZ# = TIMER
DO: LOOP UNTIL TIMER - ZZ# > .00001
OUT &H322, 1
WHILE INP(&H321) AND 128: WEND
CASE 0
EXIT SUB
CASE ELSE
OUT Dp%, byte%: OUT Dp% + 2, 0: t$ = "_": OUT Dp% + 2, 1
WHILE INP(Dp% + 1) AND 128: WEND
END SELECT
END SUB
Terug naar inhoudtafel kursus: <Index kursus>
Naar homepage dr.Godfried-Willem RAES