April 25, 2024, 02:06:16 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


A datalogger that requires very little extra hardware.

Started by Andre, May 26, 2008, 05:33:38 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andre

My first project in Ebasic.

Here it is:

**** Please check the improved version attached to a post below**** -edited in june 9 2008


'------------------------------------------------
' Program:
' FREEDATALOGGER
'
' This code is writen in EMERGENGE BASIC (freeware) and is in the PUBLIC DOMAIN  - May 2008
' By Andre T.
'------------------------------------------------
/*  This software is a data logger that can record the changes in a variable resistance like
an LDR, a photodiode or a thermistor, and plot it in a graph. It works with a minimum of
extra hardware, just a cable, the variable resistor, one extra resistor to make a voltage
divider and two diodes to protect the sound card from overloads.

A tone (a sinusoidal wave, it can be heard if the speakers are connected) is generated by the
software and should be applied to the voltage divider and then to the microphone input.
The voltage divider is made with the variable resistor and the fixed one. As the variable
resistance changes, so does the values of the input.

The input line should be protected by two opposite diodes. If you
don't know what I am talking about, don't built the circuit, because it's very likely that
you will damage your computer.

The software reads the level of the input from the microphone every "interval" milliseconds.
The recording routine is not elegant at all, and involves recording the "sound" to a file and
then analysing it. I'm still looking for a better way to obtain data directly from the
sound card. But it's not half as ugly as my help routine though...

A freeware osciloscope should be useful to make sure your signal is beeing nicely modulated by
the variation of the electrical resistance. As the resistance changes, the sinewave should change
amplitude without any 'clipping'. If clipping occurs, try to lower your system volume on the
Windows' 'Control Panel'.

A good freeware osciloscope is Winscope, which is available at
http://www.mitedu.freeserve.co.uk/Prac/winscope.htm among other places

The raw data is processed by a polynomial curve fitting. This websites can help you to
find the best parameters for your data:

http://www.xuru.org/rt/PR.asp
http://zunzun.com/
http://www.softintegration.com/chhtml/lang/lib/libch/numeric/CGI_Curvefit.html

I found out the hard way that, at least in my computer, the microphone input uses just one
of the channels. Beware.

Both data and configuration are saved as text files. The data file can be imported by
spreadsheets and manipulated there.

This program is provided "as is", no garantees. Use only if you understand the electronics
and the programming involved. If you can inprove it, please do so, and post it at the Ionic Wind forum
http://www.ionicwind.com/forums/index.php .

Thanks Paul Turley for EBASIC in general and specifically for the DATA to WAV routines.


*/

DECLARE "winmm",mciSendStringA(lpszCommand:STRING,lpszReturnString:STRING,cchReturn:INT,hwndCallback:INT),INT

WINDOW w,screen,helpwindow
FILE myfile
BFILE samplewav
MEMORY sound1
INT seconds[10000], value[10000]
SWORD sampledata[2000]
SWORD ScaleTop, ScaleBottom, loc
SWORD divisions[9]
INT run, band, wid, hgt, i, j, CurrentVal, meanx, meany, sdev, c, x,y, Interval,pos, posi, posf
INT rbits, rrate, sndlength, SamplingTime, InitialTime,SampleAverage,SampleNum
CHAR ZoomFactor, snddata
WORD PixelZero
FLOAT  Add, Multiplyx, Multiplyx2, PixelValue
STRING savename, input$


CONST ButtonStart  = 1
CONST ButtonPause  = 2
CONST ButtonReset  = 3
CONST ButtonOpen   = 4
CONST ButtonSave   = 5
CONST ButtonPrint  = 6
CONST ButtonHelp = 7
CONST ButtonSConfig = 8
CONST ButtonLConfig = 9
CONST EditboxCurrentVal = 10
CONST EditboxInterval   = 11
CONST EditboxAdd        = 12
CONST EditboxMultiplyx   = 13
CONST EditboxMultiplyx2   = 14
CONST EditboxZoomFactor = 15
CONST CheckSimetric = 16
CONST ComboScale =17

AUTODEFINE "OFF"
SETPRECISION(3)

'------------------------------------------------
' Main window setup
'------------------------------------------------
wid = 666
hgt = 490
OPENWINDOW w, 0, 0, wid, hgt, 0x80C80080, 0, "Data Logger", &msghandler
RECT w, 0, 0, wid, hgt, RGB(212,208,200), RGB(212,208,200)
CONTROL w, @BUTTON, "Start",     20, 347,  60,  25, 0x50000000, ButtonStart
CONTROL w, @BUTTON, "Pause",     90, 347,  60,  25, 0x50000000, ButtonPause
CONTROL w, @BUTTON, "Reset",    160, 347,  60,  25, 0x50000000, ButtonReset
CONTROL w, @BUTTON, "Open",      20,  12,  60,  25, 0x50000000, ButtonOpen
CONTROL w, @BUTTON, "Save",      90,  12,  60,  25, 0x50000000, ButtonSave
CONTROL w, @BUTTON, "Print",    160,  12,  60,  25, 0x50000000, ButtonPrint
CONTROL w, @BUTTON, "Help",     230,  12,  60,  25, 0x50000000, ButtonHelp
CONTROL w, @BUTTON, "Save Config. ",  250, 347,  100,  22, 0x50000000, ButtonSConfig
CONTROL w, @BUTTON, "Load Config. ",  250, 371,  100,  22, 0x50000000, ButtonLConfig

CONTROL w, @EDIT,   STR$(CurrentVal), 520,  12,  65,  25, @CTEDITRO,EditboxCurrentVal   
CONTROL w, @EDIT,   STR$(Interval),   520, 347,  65,  22, @CTEDITNUMBER,EditboxInterval
CONTROL w, @EDIT,   STR$(Add),        370, 410,  55,  25, @CTEDITRIGHT,EditboxAdd
CONTROL w, @EDIT,   STR$(Multiplyx),  448, 410,  55,  25, @CTEDITRIGHT,EditboxMultiplyx
CONTROL w, @EDIT,   STR$(Multiplyx2), 530, 410,  55,  25, @CTEDITRIGHT,EditboxMultiplyx2

CONTROL w,@CHECKBOX,"+/-",590,377,50,20,0x50000003,CheckSimetric
SETCONTROLCOLOR w,CheckSimetric,RGB(0,0,0), RGB(212,208,200)
CONTROL w,@COMBOBOX,"",520,372,65,300,   0x50800603,ComboScale

AddString w,ComboScale,"120"
AddString w,ComboScale,"160"
AddString w,ComboScale,"200"
AddString w,ComboScale,"280"
AddString w,ComboScale,"400"
AddString w,ComboScale,"600"
AddString w,ComboScale,"800"
AddString w,ComboScale,"1000"

SETCONTROLNOTIFY(w,EditboxInterval,0,1)
SETCONTROLNOTIFY(w,EditboxAdd,0,1)
SETCONTROLNOTIFY(w,EditboxMultiplyx,0,1)
SETCONTROLNOTIFY(w,EditboxMultiplyx2,0,1)

BACKPEN w, RGB(212,208,200)
RECT w, 242,340,400,105, RGB(100,100,100)
MOVE w, 419,17 : PRINT w, "Current Value :"
MOVE w, 363,350 : PRINT w, "Interval (milliseconds) :"
MOVE w, 425,377 : PRINT w, "Top of Scale :"
MOVE w, 260,415 : PRINT w, "Adjust function: "
MOVE w, 430,415 : PRINT w, " +"
MOVE w, 506,415 : PRINT w, "X +"
MOVE w, 590,415 : PRINT w, "X^2"

'------------------------------------------------
' Initialize variables and settings
'------------------------------------------------

rbits=16
rrate=16000
SamplingTime = 260      /*the smaller working value on my machine is 260. Smaller values simply
don't give enough time to write the files to disk. As this number grows,
the sample.wav file grows in 8 kbytes increments. */
savename = "samplewav.wav"
GOSUB Reset

'------------------------------------------------
' Screen window setup
'------------------------------------------------

OPENWINDOW screen,15,52,wid-35,278,@NOCAPTION|@BORDER,w,"Screen",&screenhandler
SETFONT screen, "Arial", 7, 400
SETSCROLLRANGE screen, -1,0,100
SETSCROLLPOS screen,-1,100
GOSUB RedrawDivisions
GOSUB QuickRedraw

'------------------------------------------------
' Load wavefile from data to to memory and play it
'------------------------------------------------
' Clever way of playing a wav file without accessing the disk

GETDATA wave,sndlength
ALLOCMEM sound1,1,sndlength
FOR x = 0 to sndlength-1
    GETDATA wave,snddata
    WRITEMEM sound1,x+1,snddata
NEXT x

playwave sound1,@SNDASYNC|@SNDLOOP     'plays on and on

'------------------------------------------------
' Main
'------------------------------------------------

run = 1
WAITUNTIL run = 0
IF sound1 <> NULL THEN FREEMEM sound1
STOPTIMER w,1
CLOSEWINDOW w
END

'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
' Within the two "%%%" lines are the code used for the sampling routines
' I can see lots of improvements to be made here.
' All the rest of the code is window sizing, drawing and plotting routines.
' If you want to costumize or improve the code, you probably want to start with
' the routines enclosed here
'------------------------------------------------

SUB TimerTick         'every "interval" this routine records some data

    mciSendStringA("open new type waveaudio alias capture","",0,0)
    mciSendStringA("set capture alignment 1 bytespersec 8000","",0,0)
    mciSendStringA("set capture time format ms bitspersample "+str$(rbits),"",0,0)
    mciSendStringA("set capture channels 1 samplespersec "+str$(rrate),"",0,0)
    mciSendStringA("record capture","",0,0)

'this is the second timer, the one that determines how much we record
    STARTTIMER w,SamplingTime,2     
'SamplingTime is the actual data recording time

ENDSUB
'------------------------------------------------

SUB StopRecord            'after 260 milisseconds (SamplingTime) of recording, we analyse what we recorded...

' the recorded data is saved to disk as "sample.wav". This is a huge waste of time and processing power,
' but it's the best I could come up with so far.

    STOPTIMER w,2
    mciSendStringA("stop capture","",0,0)
    mciSendStringA("save capture " + chr$(34) + savename + chr$(34),"",0,0)
    mciSendStringA("close capture ","",0,0)

    IF OPENFILE(samplewav, "samplewav.wav", "R") = 0
        IF READ (samplewav, sampledata[0])=0
            CLOSEFILE samplewav
            j=0
            SampleAverage=0

'now we average all the positive values recorded
            FOR i=46 to 2000
                IF sampledata[i]>0 THEN
                SampleAverage = SampleAverage+sampledata[i]
                j++
                ENDIF
            NEXT i
            IF j=0 THEN j=1
            SampleAverage=SampleAverage/j
        ENDIF
    ENDIF                                 

' if you remove the comment "'" from the next line, you will obtain a sinusoidal wave on your graph.
' this was useful for me for debugging

  '  SampleAverage=50*SIND(SampleNum*10)   

    SampleAverage=  (SampleAverage * Multiplyx)+(SampleAverage^2* Multiplyx2)+ Add
    seconds[SampleNum]= MILLISECS()-InitialTime
    value[SampleNum]= Sampleaverage
    SETCONTROLTEXT w, EditBoxCurrentVal, STR$(value[SampleNum])
    GOSUB QuickRedraw   
    SampleNum++
ENDSUB

'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


'------------------------------------------------
' Subrotines
'------------------------------------------------

SUB msghandler
    SELECT @MESSAGE
        CASE @IDCLOSEWINDOW : run = 0
        CASE @IDCREATE  : centerwindow w
        CASE @IDTIMER
            SELECT @CODE
                CASE 1  : gosub TimerTick
                CASE 2  : gosub StopRecord
            ENDSELECT
        CASE @IDCONTROL           
            IF (@CONTROLID = ButtonStart)  THEN
                STARTTIMER w,Interval,1
                InitialTime = MILLISECS()
            ENDIF
            IF (@CONTROLID = ButtonPause)    THEN STOPTIMER w,1             
            IF (@CONTROLID = ButtonReset)    THEN GOSUB Reset                           
            IF (@CONTROLID = ButtonOpen)     THEN GOSUB Open                         
            IF (@CONTROLID = ButtonSave)     THEN GOSUB Save
            IF (@CONTROLID = ButtonPrint)    THEN GOSUB PrintClicked
            IF (@CONTROLID = ButtonHelp)     THEN GOSUB Help
            IF (@CONTROLID = ButtonSConfig)  THEN GOSUB SaveConfig
            IF (@CONTROLID = ButtonLConfig)  THEN GOSUB LoadConfig
            IF (@CONTROLID = EditboxInterval)THEN GOSUB IntervalChange
            IF (@CONTROLID = EditboxAdd)     THEN GOSUB AddChange
            IF (@CONTROLID = EditboxMultiplyx) THEN GOSUB MultiplyxChange
            IF (@CONTROLID = EditboxMultiplyx2)THEN GOSUB Multiplyx2Change
            IF (@CONTROLID = CheckSimetric) THEN GOSUB CheckSimetricChange
            IF (@CONTROLID = ComboScale) THEN GOSUB ComboScaleChange
        CASE @idchar  : IF (@wparam = 27) THEN CLOSEWINDOW w
    ENDSELECT
    RETURN
ENDSUB

'------------------------------------------------

SUB screenhandler

    SELECT @MESSAGE
        CASE @IDHSCROLL
        SELECT @CODE
            CASE @SBTHUMBPOS: CASE @SBTHUMBTRACK
                SETSCROLLPOS screen,-1,GETTHUMBPOS(screen,-1)
            CASE @SBLINELEFT
                setscrollpos screen,-1,(getscrollpos(screen,-1)-1)
            case @SBLINERIGHT
                setscrollpos screen,-1,(getscrollpos(screen,-1)+1)
            case @SBPAGELEFT
                setscrollpos screen,-1,(getscrollpos(screen,-1)-10)
            case @SBPAGERIGHT
                setscrollpos screen,-1,(getscrollpos(screen,-1)+10)
        ENDSELECT
        GOSUB QuickRedraw

    ENDSELECT
    RETURN

ENDSUB

'------------------------------------------------

SUB IntervalChange
    IF @NOTIFYCODE = @ENENTERKEY THEN
        i=VAL(GETCONTROLTEXT(w,EditboxInterval))
        if i>120000 then i = 120000
        Interval=i
        STOPTIMER w,1
        STARTTIMER w,Interval,1
        SETCONTROLTEXT(w,EditboxInterval,STR$(Interval))
        GOSUB RedrawDivisions
        GOSUB QuickRedraw
        SETFOCUS w
    ENDIF
ENDSUB

'------------------------------------------------

SUB AddChange
    IF (@NOTIFYCODE = @ENENTERKEY) OR (@NOTIFYCODE = @ENKILLFOCUS) THEN
        Add=Val(GETCONTROLTEXT(w,EditboxAdd))
        SETCONTROLTEXT(w,EditboxAdd,STR$(Add))
        SETFOCUS w
        GOSUB RedrawDivisions
        GOSUB QuickRedraw
    ENDIF
ENDSUB

'------------------------------------------------

SUB MultiplyxChange
    IF (@NOTIFYCODE = @ENENTERKEY) OR (@NOTIFYCODE = @ENKILLFOCUS) THEN
        input$= GETCONTROLTEXT(w,EditboxMultiplyx)
        i=INSTR(input$,",")
        REPLACE$ input$,i,1,"."
        Multiplyx=VAL(input$)
        SETCONTROLTEXT(w,EditboxMultiplyx,STR$(Multiplyx))
        SETFOCUS w
        GOSUB RedrawDivisions
        GOSUB QuickRedraw
    ENDIF
ENDSUB

'------------------------------------------------

SUB Multiplyx2Change
    IF (@NOTIFYCODE = @ENENTERKEY) OR (@NOTIFYCODE = @ENKILLFOCUS) THEN
        input$= GETCONTROLTEXT(w,EditboxMultiplyx2)
        i=INSTR(input$,",")
        REPLACE$ input$,i,1,"."
        Multiplyx2=VAL(input$)
        SETCONTROLTEXT(w,EditboxMultiplyx2,STR$(Multiplyx2))
        SETFOCUS w
        GOSUB RedrawDivisions
        GOSUB QuickRedraw
    ENDIF
ENDSUB

'------------------------------------------------

SUB CheckSimetricChange

    IF (GETSTATE w, CheckSimetric) THEN
        ScaleBottom=-ScaleTop
        PixelValue=120.0/ScaleTop
        PixelZero=130
    ELSE
        ScaleBottom=0
        PixelValue=240.0/ScaleTop
        PixelZero=250
    ENDIF
    GOSUB RedrawDivisions
    GOSUB QuickRedraw
ENDSUB

'------------------------------------------------

SUB ComboScaleChange

    SELECT GETSELECTED w,ComboScale
        CASE 0 : ScaleTop = 120
        CASE 1 : ScaleTop = 160
        CASE 2 : ScaleTop = 200
        CASE 3 : ScaleTop = 280
        CASE 4 : ScaleTop = 400
        CASE 5 : ScaleTop = 600
        CASE 6 : ScaleTop = 800
        CASE 7 : ScaleTop = 1000
    ENDSELECT
    IF (GETSTATE w, CheckSimetric) THEN
        ScaleBottom=-ScaleTop
        PixelValue=120.0/ScaleTop
        PixelZero=130
    ELSE
        ScaleBottom=0
        PixelValue=240.0/ScaleTop
        PixelZero=250
    ENDIF
    GOSUB RedrawDivisions
    GOSUB QuickRedraw
ENDSUB

'------------------------------------------------

SUB Reset

    STOPTIMER w,1
    STOPTIMER w,2
    FOR i = 0 TO 9999
    seconds[i]=0
    value[i]=0
    NEXT i
    SETCONTROLTEXT(w, CurrentVal,"")
    Add=0 :SETCONTROLTEXT(w,EditboxAdd,STR$(Add))
    Multiplyx=0.01 :SETCONTROLTEXT(w,EditboxMultiplyx,STR$(Multiplyx))
    Multiplyx2=0 :SETCONTROLTEXT(w,EditboxMultiplyx2,STR$(Multiplyx2))
    ScaleTop=120
    ScaleBottom=0
    Interval=700 :SETCONTROLTEXT(w,EditboxInterval,STR$(Interval))
    SampleNum=0
    ScaleTop=120
    ScaleBottom=0
    SETSTATE w, CheckSimetric, 0
    SETSELECTED w,ComboScale,7
    GOSUB ComboScaleChange

ENDSUB


'------------------------------------------------

SUB SaveConfig
    STRING filter$,  filename$
    filter$ = "All Files (*.*)|*.*|Text Files (*.txt)|*.txt||"
    filename$ = FILEREQUEST("Save configuration file",0,0,filter$,"txt",null, "C:\\")
    IF OPENFILE(myfile, filename$,"W") = 0 THEN
        WRITE myfile, Str$(Interval)
        WRITE myfile, Str$(Add)
        WRITE myfile, Str$(Multiplyx)
        WRITE myfile, Str$(multiplyx2)
        WRITE myfile, Str$( GETSELECTED w, ComboScale)
        WRITE myfile, Str$( GETSTATE w, CheckSimetric)
        CLOSEFILE myfile
    ENDIF
ENDSUB

'------------------------------------------------

SUB LoadConfig

    STRING filter$, fileinput$, filename$
    filter$ = "All Files (*.*)|*.*|Text Files (*.txt)|*.txt||"
    filename$ = FILEREQUEST("Open configuration file",0,1,filter$,"txt",null, "C:\\")
    IF OPENFILE(myfile, filename$,"R") = 0 THEN
        READ myfile, fileinput$
        Interval=VAL(fileinput$)
        SETCONTROLTEXT w, EditboxInterval, fileinput$
        READ myfile, fileinput$
        Add = VAL(fileinput$)
        SETCONTROLTEXT w, EditboxAdd, fileinput$
        READ myfile, fileinput$
        Multiplyx= VAL(fileinput$)
        SETCONTROLTEXT w, EditboxMultiplyx, fileinput$
        READ myfile, fileinput$
        Multiplyx2= VAL(fileinput$)
        SETCONTROLTEXT w, EditboxMultiplyx2, fileinput$
        READ myfile, fileinput$
        SETSELECTED w, ComboScale, VAL(fileinput$)
        READ myfile, fileinput$
        SETSTATE w, CheckSimetric, VAL(fileinput$)
        CLOSEFILE myfile
        GOSUB RedrawDivisions
        GOSUB QuickRedraw
    ENDIF
ENDSUB

'------------------------------------------------

SUB Save

    STRING filter$,  filename$
    filter$ = "All Files (*.*)|*.*|Text Files (*.txt)|*.txt||"
    filename$ = FILEREQUEST("Save data file",0,0,filter$,"txt",null, "C:\\")
    IF OPENFILE(myfile, filename$,"W") = 0 THEN
        WRITE myfile, Str$(Interval)
        WRITE myfile, Str$(Add)
        WRITE myfile, Str$(Multiplyx)
        WRITE myfile, Str$(multiplyx2)
        WRITE myfile, Str$( GETSELECTED w, ComboScale)
        WRITE myfile, Str$( GETSTATE w, CheckSimetric)
        j = SampleNum
        WRITE myfile, Str$(j)
        FOR i = 0 TO j
            WRITE myfile, seconds[i]
            WRITE myfile, Str$(value[i])
        NEXT i
        CLOSEFILE myfile
    ENDIF
ENDSUB

'------------------------------------------------
SUB Open

    STRING filter$, fileinput$, filename$
    filter$ = "All Files (*.*)|*.*|Text Files (*.txt)|*.txt||"
    filename$ = FILEREQUEST("Open data file",0,1,filter$,"txt",null, "C:\\")
    IF OPENFILE(myfile, filename$,"R") = 0 THEN
        READ myfile, fileinput$ : Interval = VAL(fileinput$)
        READ myfile, fileinput$ : Add = VAL(fileinput$)
        READ myfile, fileinput$ : Multiplyx = VAL(fileinput$)
        READ myfile, fileinput$ : Multiplyx2 =VAL(fileinput$)
        READ myfile, fileinput$: SETSELECTED w, ComboScale,VAL(fileinput$)
        GOSUB ComboScaleChange
        READ myfile, fileinput$
        SETSTATE w, CheckSimetric, VAL(fileinput$)
        READ myfile, fileinput$: j = VAL(fileinput$)
        SampleNum=j
        FOR i = 0 TO j
            READ myfile, seconds[i]
            READ myfile, fileinput$ : value[i]=  VAL(fileinput$)
        NEXT i
        CLOSEFILE myfile
        GOSUB ComboScaleChange
        GOSUB RedrawDivisions
        GOSUB QuickRedraw
    ENDIF

ENDSUB

'------------------------------------------------

SUB PrintClicked   'we can print a screenshot of the graph.

'first we redraw the screen with white background to save ink or toner:

    RECT screen, 0, 0, 600,260, RGB(0,0,0),RGB(255,255,255)
    RECT screen, 600, 0,616,260, RGB(230,230,230),RGB(230,230,230)
    LINE screen, 0,10,600,10, RGB(200,200,200)
    LINE screen, 0,40,600,40, RGB(200,200,200)
    LINE screen, 0,70,600,70, RGB(200,200,200)
    LINE screen, 0,100,600,100, RGB(200,200,200)
    LINE screen, 0,130,600,130, RGB(200,200,200)
    LINE screen, 0,160,600,160, RGB(200,200,200)
    LINE screen, 0,190,600,190, RGB(200,200,200)
    LINE screen, 0,220,600,220, RGB(200,200,200)
    LINE screen, 0,250,600,250, RGB(200,200,200)
    IF (GETSTATE w, CheckSimetric) then LINE screen, 0,130,600,130, RGB(0,0,0) _
         else LINE screen, 0,250,600,250, RGB(0,0,0)

    pos=100-getscrollpos(screen,-1)

    IF SampleNum > 100 THEN
            SETSCROLLRANGE screen, -1,0, SampleNum
            SETSCROLLPOS screen, -1, (getscrollpos(screen,-1)+1)
            pos = SampleNum - getscrollpos(screen,-1)
        ELSE
            pos=100-getscrollpos(screen,-1)
    ENDIF


    FOR i= 1 TO SampleNum
        posi = SampleNum-i-pos
        posf = SampleNum-(i-1)-pos
        IF (posi >=0) AND (posi <= SampleNum) AND (posf >=0) AND (posf <= SampleNum) THEN
            LINE screen,600-(i*5),PixelZero-(value[posi])*PixelValue ,600-((i-1)*5), PixelZero-value[posf]*PixelValue,RGB(0,120,0)
        ENDIF
    NEXT i

    GOSUB RedrawDivisions

    PRINTWINDOW(screen)
    GOSUB QuickRedraw     'turn the screen black again
ENDSUB

'------------------------------------------------

SUB Help              'very limited help routine.
    INT left,top,width,height, helplength,x
    STRING helpline$
    OPENWINDOW helpwindow,0,0,600,450,null,NULL,"Datalogger Help",&helpwindowhandler
    CENTERWINDOW helpwindow
    getclientsize helpwindow,left,top,width,height
    control helpwindow,@LISTBOX,"",left,top,width,height, @CTLISTEXTENDED|@VSCROLL,1
    RESTORE help
    GETDATA help,helplength

    FOR x = 1 to helplength
        GETDATA help,helpline$
        ADDSTRING helpwindow,1,helpline$
    NEXT x

    WAITUNTIL helpwindow = 0

ENDSUB

'------------------------------------------------

SUB helpwindowhandler
    IF @MESSAGE = @IDCLOSEWINDOW
        REM closes the window and sets helpwindow = 0
        CLOSEWINDOW helpwindow
    ENDIF
    RETURN
ENDSUB

'------------------------------------------------

SUB RedrawDivisions

    for i = 0 to 8
    divisions[i]=ScaleTop- (((ScaleTop-ScaleBottom)/8)*i)
    next i
    RECT screen, 600, 0,616,260, RGB(255,255,255),RGB(255,255,255)
    MOVE screen,604,5: PRINT screen, divisions[0]
    MOVE screen,604,35: PRINT screen, divisions[1]
    MOVE screen,604,65: PRINT screen, divisions[2]
    MOVE screen,604,95: PRINT screen, divisions[3]
    MOVE screen,604,125: PRINT screen, divisions[4]
    MOVE screen,604,155: PRINT screen, divisions[5]
    MOVE screen,604,185: PRINT screen, divisions[6]
    MOVE screen,604,215: PRINT screen, divisions[7]
    MOVE screen,604,245: PRINT screen, divisions[8]


ENDSUB
'------------------------------------------------
SUB QuickRedraw

    RECT screen, 0, 0, 600,260, RGB(0,0,0),RGB(0,0,0)
    LINE screen, 0,10,600,10, RGB(50,50,50)
    LINE screen, 0,40,600,40, RGB(50,50,50)
    LINE screen, 0,70,600,70, RGB(50,50,50)
    LINE screen, 0,100,600,100, RGB(50,50,50)
    LINE screen, 0,130,600,130, RGB(50,50,50)
    LINE screen, 0,160,600,160, RGB(50,50,50)
    LINE screen, 0,190,600,190, RGB(50,50,50)
    LINE screen, 0,220,600,220, RGB(50,50,50)
    LINE screen, 0,250,600,250, RGB(50,50,50)
    IF (GETSTATE w, CheckSimetric) then LINE screen, 0,130,600,130, RGB(130,130,130) _
        ELSE LINE screen, 0,250,600,250, RGB(130,130,130)

    pos=100-getscrollpos(screen,-1)

    IF SampleNum > 100 THEN
            SETSCROLLRANGE screen, -1,0, SampleNum
            SETSCROLLPOS screen, -1, (getscrollpos(screen,-1)+1)
            pos = SampleNum - getscrollpos(screen,-1)
        ELSE
            pos=100-getscrollpos(screen,-1)
    ENDIF

'here is the function that really draws the graph every time a sample is taken
    FOR i= 1 TO SampleNum
        posi = SampleNum-i-pos
        posf = SampleNum-(i-1)-pos
        IF (posi >=0) AND (posi <= SampleNum) AND (posf >=0) AND (posf <= SampleNum) THEN
        LINE screen,600-(i*5),PixelZero-(value[posi])*PixelValue ,600-((i-1)*5), PixelZero-value[posf]*PixelValue,RGB(0,255,0)
        ENDIF
    NEXT i

ENDSUB
'------------------------------------------------
DATABEGIN wave   

'This is a sinusoidal wave. I used a square wave for a while, but its easier to detect
' clipping of the signal on a sinusoidal shape.
DATA 364
DATA 82,73,70,70,100,1,0,0,87,65,86,69,102,109,116,32,16,0,0,0,1,0,1,0,128,62
DATA 0,0,0,125,0,0,2,0,16,0,100,97,116,97,64,1,0,0,4,0,2,5,17,10,6
DATA 15,10,20,245,24,229,29,188,34,145,39,72,44,2,49,144,53,35,58,132,62,233,66,21,71
DATA 66,75,60,79,33,83,228,86,131,90,251,93,89,97,131,100,142,103,112,106,32,109,176,111,12
DATA 114,61,116,69,118,18,120,192,121,48,123,118,124,142,125,104,126,31,127,155,127,229,127,255,127
DATA 229,127,155,127,29,127,108,126,141,125,115,124,54,123,182,121,28,120,64,118,63,116,11,114,174
DATA 111,36,109,107,106,147,103,130,100,84,97,3,94,123,90,233,86,30,83,64,79,61,75,27,71
DATA 227,66,137,62,31,58,148,53,254,48,77,44,143,39,188,34,226,29,251,24,3,20,15,15,8
DATA 10,5,5,5,0,244,250,251,245,238,240,0,236,2,231,34,226,63,221,116,216,178,211,4,207
DATA 107,202,225,197,118,193,32,189,225,184,200,180,188,176,225,172,31,169,121,165,10,162,161,158,130
DATA 155,110,152,148,149,220,146,83,144,242,141,196,139,188,137,236,135,64,134,210,132,133,131,123,130
DATA 142,129,233,128,94,128,31,128,0,128,28,128,99,128,228,128,147,129,120,130,132,131,212,132,64
DATA 134,235,135,192,137,189,139,250,141,75,144,228,146,140,149,120,152,118,155,174,158,2,162,124,165
DATA 30,169,222,172,195,176,196,180,225,184,33,189,115,193,230,197,103,202,7,207,175,211,118,216,63
DATA 221,32,226,6,231,250,235,245,240,246,245,249,250
DATAEND


DATABEGIN help   
DATA 20

DATA "   ABOUT DATALOGGER"
DATA ""
DATA "   DATALOGGER is an open source software that generates a sound and records changes "
DATA "   in the level of the input from the microphone. "
DATA ""
DATA "   HOW TO USE IT "
DATA ""
DATA "   Some basic knowledge of electronics is required."
DATA "   First you must make a cable that plugs in the speaker output, passes through a "
DATA "   voltage divider that includes a variable resistance (a thermistor or an LDR for "
DATA "   example), and plugs in the microphone input."
DATA "   The input of the microphone should be protected by two diodes in opposition to"
DATA "   prevent damage to the sound card, in case of accidental overload."
DATA "   The changes in the variable resistance will be shown in the graph. The values will"   
DATA "   be corrected by the polinomial formula in the lower right of the screen. To obtain"
DATA "   the best curve fitting parameters, do a web search on 'curve fitting'. There are "
DATA "   websites that calculate them for you online."
DATA ""
DATA ""
DATAEND




Barney

Very nice! I felt like I was back in high school while I was assembling the necessary circuitry and while trying it out later.

Thank you for sharing. :)

Barney

Andre

Wow!
I know the circuitry is simple, but I am surprised that you managed to built it and test it in about 45 minutes after I posted the code!
Thank YOU, not only for demonstrating the simplicity of it, but for your work posted here:http://www.ionicwind.com/forums/index.php/topic,1986.0.html . By the way, the latest version of the Port.dll (for Windows XP) can be found here: http://www.b-kainka.de/download.htm (Update der Port.DLL fÃÆ'Ã,¼r Windows XP- port.zip), but I could not make the SOUNDIN() function work with Ebasic. That's my next step.

I used a thermistor (9k at room temp.) to do my tests. The line is a bit jagged but it clearly shows the temperature variations as sharp slopes as I dip the thermistor in hot or cold water. I covered the thermistor with epoxy to waterproof it.

The jagged lines are due to fluctuations in the readings that don't seem to have anything to do with the algorithm. I tried different routines to sample and average the readings and they all resulted in jagged lines. No big deal. Maybe it's my hardware.


aurelCB

If it posible conect small oscilator in microphone input and see wave?

aurelCB

I try cinect and i got vertical line,i think that working something.
My question is ,do you heard for Osciloscopedll ?

Andre

A vertical line? That is strange. When nothing is connected it should generate a horizontal line (zero).

Quote from: aurelCB on May 27, 2008, 12:59:50 PM
If it posible conect small oscilator in microphone input and see wave?

No, the smallest interval between samples is 500ms, that is half a second, quite a long time. You cannot make it smaller because the recording routine takes at least 260 ms to work. To watch waves I suggest that you download the "Winscope" freeware.
The idea of the datalogger is to record slow events over a long period of time, like changes in ambient temperature or humidity.

Yes, I read about the osciloscope.dll but have not tried it yet. Does it have a simple function to read values from the sound card input?

aurelCB

I think that have..
When you download it has source code written in VB and other languages.
Maby you can convert something.

Andre

Thank you aurelCB, I'll try it in the near future. For now, thanks to the help of other members of this forum, I figured out how to use the SOUNDIN() function from port.dll. Here: http://www.ionicwind.com/forums/index.php/topic,2484.0.html

Hopefully I'll soon post a new, more elegant and fast, version of the datalogger.

Another technical note: The datalogger does not work if a USB microphone, such as those in modern webcams, is connected to the computer.

dossic

Hi!

I think your solution is quite elegant. 

I do not know the frequency you are generating; maybe this is the reasons for the fluctuations you experience.  Using a frequency uncorrelated to line frequency (here 50 Hz in Europe) may generate noise and spikes. You may try to use directly 50 Hz for feeding your themistor-based dividing network.


I am considering to buy a low-cost data acquisition kit from EMANT, I'll keep you informed.  Another low-cost alternative is using UBW from Brian Schmalz, it is a PIC 18F2550 based circuit with analog 10-bit ADC's and digital input/output ports.  UBW is interfaced to your PC via USB.

Yours   carlo

Andre

Thank you dossic,

I tried many different frequencies with square and sinusoidal shapes. They all fluctuate. It seem to be intrinsic to the design. I hope to fix that with faster sampling routines that can be averaged.

It's a good idea to use the mains 50hz (60 in my case) as a source of stable AC reference, but the insulation has to be very well done. Maybe a small customized transformer...  Any mistake may ruin the sound card though. The two diodes in oposition keep the input voltage under about 0,3V, but they may fail in many different ways.

Microprocessors are always a good idea. I'm an old fashioned 8051's family fan, but my aim with this project is to give those with very little electronic skills a tool for projects that require datalogging. All dataloggers I've seen so far require more or less sofisticated extra electronic circuitry.


czoran

Thank you for program.
I started similar project years ago but never have it finished.

Regards.

Andre

Here it is! A new and improved version of the Datalogger, packed in a zip file for distribution.
It uses the PORT.DLL for quicker (down to 200ms), more elegant measurements. The improved sampling routines generate less fluctuation and the screen can be stretched to 900 pixels. The "Help" is now a compiled file, quite nice, with a mini-tutorial and an image of the circuit.

The PORT.DLL for windows XP is in the zip file, with the permission of Burkhard Kainka [http://www.b-kainka.de/] . Barney's include file for this DLL is also included (thanks Barney) along with a translated reference text for the DLL.

There is also a screenshot in the zip file, so you can see what the program looks like without compiling it.
Its open source and free.