Inhoudstafel

2150:

Acceleratiesensors: toepassingsvoorbeelden:

Het EI van Godfried...

Axe3-interface (2007)

Inleiding:

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

 

Stap1:

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