'!basic stamp2 by parallax ' ' ev_log4.bs2 Event Logger w/ external 8kbyte memory ' 2^24s = 4660 hr = 194 day max interval ' dave forrest 7/16/97 ' ' this program uses the parallax http://www.parallaxinc.com basic stamp 2 ' microcomputer controller to monitor a set of open contacts on a CNC machine ' ' the dumped output is then used to analyze downtime and machine utilization ' ' Please forgive the roughness of the code -- I've spent a few long nights ' just hacking it together. ' ' ' This program uses these fine routines from: '**************************************************************************** '* I2C SUBROUTINES * '**************************************************************************** 'Author: Jordan Haralampopoulos 'E-mail: jordanis@ix.netcom.com ' 'Version: 0.1 (more to come) ' ' which I downloaded from parallax's mailing list archives ' - search on "24C65" ' '========================================================================== ' ---------------- 'DB9#2>-------|SOUT Vin|-----+9vdc 'DB9#3>-------|SIN Vss|----- 'DB9#4>--X X--|ATN ~Reset|----- 'DB9#5>-------|Vss Vdd|--C--- 'P-R220-LED---|P0 P15|--R--- '----------R--|P1 P14|--R--- 'TERM<>----R--|P2 p13|--R--- 'G-PBNO----R--|P3 p12|--R--- 'BCD~1-----R--|P4 p11|--R--- 'BCD~2-----R--|P5 P10|--R--- 'BCD~4-----R--|P6 $50 P9|--R--- 'BCD~8-----R--|P7 BS2 P8|--R--- ' Vdd---C ---------------- ' 'G-----terminal terminal------>TERM<> contacts ' ' ---------------------- ' G-----|A0 Microchip Vcc|------P ' G-----|A1 24C65 NC|--- ' G-----|A0 $3.00 SCL|----- ' G-----|Vss SDA|----- ' ---------------------- ' ' G = ground P = Vdd from BS2 ' R220 = 220 ohm resistor ' ' RRRRRRRRC is a inline resistor pack 10kohm ' the common of the BCD switch attaches to ground ' ' maxaddress con 8190 ' 0-8191 -1 looptime con 991 ' adjust for calibrating time 'looptime con 0 ' for testing maxsecs con 253 ' symbol for large # of seconds twobyte con 255 threebyte con 254 ' | byten | byten+1 |.... ' for secs 0-253 | xxx | | ' for secs in { 254 - 65535} | 255 | Secs.byte1 | secs.byte0 ' for secs in { 65536 - 2^32) | 254 | secs.byte2 | secs.byte1 | byte0 ' note: no allowance for secs > 2^32 saveReading data 0(2) 'non volitile storage saveSecs data 0(3) ' 3 bytes of storage saveLast1 data 1(1) reading var word 'sample location x var word y var word w var bit full var bit ' flag for memory full condition secs var word ' state-time in seconds secs2 var byte ' 3rd byte (byte2) of seconds last1 var bit ' old state of contacts new1 var bit ' new state of contacts light con 0 ' a led to show it it alive databit con 2 ' the contacts data1 var ins.bit2 ' input bit watched 1 = open 0 = closed confirm var ins.bit3 command var ins.nib1 ' bcd input switch bcddecoder con $f 'command^xor to deal with 'inverse logic BCD switches ' = $0 for BCD(~1,~2,~4,~8) ' = $f for BCD(1,2,4,8) 'I2C variables ' i2addr var word '16 bit mem address i2addr1 var i2addr.highbyte '8 MSBs of mem address i2addr0 var i2addr.lowbyte '8 LSBs of mem address temp1 var byte 'temporary byte variable temp2 var nib ' temporary nibble variable i2data var byte 'byte for I2C I/O i2ack var bit 'I2C acknowledge bit i2dt con 15 'I2C data pin i2clk con 9 'I2C clock pin i2memWR con %10100000 'I2C mem write control byte chip address 000 ' 1010aaa0 where aaa = A2, A2, A0 of the 24C65 i2memRD con %10100001 'I2C mem read control byte chip address 000 ' 1010aaa1 where aaa = A2, A2, A0 of the 24C65 memtop con 8191 'I2C EEPROM memory top ' bcd codes for commands logCmd con 0 ' enable logging dumpCmd con 1 ' dipswitch 1 data dump dumpallCmd con 2 ' dump all the data space clearCmd con 3 ' restart count (reset works better) saveCmd con 4 ' save registers checkmemCmd con 5 ' testing area clearallcmd con 6 maxcmd con 6 open con 1 ' input bit status from pullup closed con 0 initialState con 1 ' End of variables, constants and definitions dirs = $FF03 secs = 0 secs2 = 0 last1 = initialState high light initialize: read saveReading,reading.byte1 read savereading + 1, reading.byte0 read saveSecs , secs2 read saveSecs + 1, secs.byte1 read savesecs + 2, secs.byte0 read saveLast1,last1 main: ' main loop ******************************** if not command^bcddecoder = logCmd then nolog new1 = data1 if not full = 1 then spaceleft nap 7 debug "F" nap 4 pulsout light, 100 return spaceleft: if new1 = last1 then nochange gosub logdata last1 = new1 nochange: if not confirm = closed then nowrite gosub saveregs nowrite: gosub advance goto main nolog: pulsout light,100 nap 7 pulsout light,100 nap 4 debug "." if not (confirm = closed) then endloop debug "cmd", dec command ^bcddecoder,cr if not ( command^bcddecoder > maxcmd ) then noinfo gosub info noinfo: if not (command^bcddecoder = clearCmd) then noclear gosub clear noclear: if not (command^bcddecoder = checkmemcmd) then nodebug gosub check24c65 nodebug if not ( command^bcddecoder = dumpallCmd) then nodumpall gosub dumpall nodumpall: if not (command^bcddecoder = saveCmd) then nosave gosub saveregs nosave: if not (command^bcddecoder = dumpCmd) then nodump gosub dump nodump: if not (command^bcddecoder = clearallcmd) then noclearall gosub clearall noclearall endloop: goto main stop '*************************** logdata: '****************** logdata pulsout light,5000 debug cr,"#",dec reading, ": ",dec secs,"s ",bin last1,">",bin new1," " if reading >= maxaddress - 3 then full_ if not secs2 = 0 then writethreebyte ' three byte data if secs <= maxsecs then writeonebyte ' 1 byte data goto writetwobyte ' 2 byte data writethreebyte: i2addr = reading temp1 = threebyte gosub wrmem i2addr = reading +1 temp1 = secs2 gosub wrmem reading = reading +1 secs2 = 0 goto xx_writetwobyte writetwobyte: i2addr = reading temp1 = twobyte gosub wrmem xx_writetwobyte: 'dual entrance for threebyte i2addr = reading +1 temp1 = secs.byte1 gosub wrmem reading = reading + 2 writeonebyte: i2addr = reading temp1 = secs.byte0 gosub wrmem reading = reading + 1 donelog: secs = 0 return full_: gosub saveregs full = 1 return saveregs: write saveReading,reading.byte1 write savereading + 1, reading.byte0 write saveSecs, secs2 write saveSecs +1 , secs.byte1 write savesecs + 2, secs.byte0 write saveLast1,last1 debug bin ? last1 debug "saved",cr temp1 = 4: gosub pulser ret: return 'dump: '****************************** dump ' if reading > 0 then dumpit ' debug "no data",cr,cr ' gosub info' ' temp1 = 2 ' gosub pulser 'ret: return dump: '****************************** dump dumpit: debug cls, "#drf 7/9/97 dump of IATs",cr,"#cycle, closed, open",cr if reading > 0 then notempty x = maxaddress goto moredump notempty: x = reading moredump: y = 0 w = InitialState for i2addr = 0 to x -1 gosub rdmem secs = temp1 secs2 = 0 if secs <= maxsecs then printit i2addr = i2addr+1 if secs = twobyte then readtwobyte if secs = threebyte then readthreebyte readthreebyte: gosub rdmem secs2 = temp1 i2addr = i2addr +1 readtwobyte: gosub rdmem secs.byte1 = temp1 i2addr = i2addr +1 gosub rdmem secs.byte0 = temp1 printit: if w = open then popen debug cr,dec y,", " y = y+1 goto psecs popen: debug ", " psecs: debug dec secs w = w ^ 1 if secs2 = 0 then nxt debug "+2^16*",dec secs2 nxt: next done_dump: temp1 = 1 :gosub pulser return ' dumpall read & displays sequentialy all the values from the starting ' address that you supply to the end of memory (memtop) dumpall: debug "#dump all of memory",cr pause 5000 i2addr=0 'start from the beginning 'max value is 8190 gosub rdmemsq 'do the sequential read return ' This is the dosomething routines. In this case it displays ' the memory values trough debug. It could be a serial output ' to something else. dosomething: 'pause 50 'give some time to see the value debug dec temp1,cr return ' clearall writes 255s throut memory ' clearall low light for i2addr = 0 to memtop temp1 = 255 gosub wrmem debug dec ?i2addr next high light temp1 = 6 gosub pulser gosub clear return ' advance moves the clock forward during logging ************************** ' advance: if data1 = closed then pa_closed debug ":" goto delay pa_closed: debug "+" delay: pause looptime secs = secs + 1 pulsout light,500 if not secs = 0 then ret secs2 = secs2 +1 return ' clear clears the non-volitile registers and restarts the system clear: '****************** clear debug "clearing...",cr reading = 0 secs = 0 secs2 = 0 last1 = initialState gosub saveregs return info: '****************** info debug "Event logger ev_log3.bs2 7/17/97 drf5n@virginia.edu",CR debug dec logCmd^bcddecoder," logs up to ",dec maxaddress, " cycles",cr debug dec dumpCmd^bcddecoder, " dumps about ",dec reading/2, " cycles",CR debug dec dumpallCmd^bcddecoder," dumps all",cr debug dec clearCmd^bcddecoder," clears and ",dec savecmd^bcddecoder," saves",cr debug dec checkmemcmd^bcddecoder," for debugging",cr return ' check24c65 writes a value to the 24C65 EEPROM and then reads back ' to verify check24c65 debug "debugmem..133 > 125" i2addr=125 'pick an address 0-8191 temp1=133 'pick a value 0-255 gosub wrmem 'go write debug bin ? i2ack,cr 'got ack=%0 (aknowledged) if i2ack=%1 then check24c65 'if not do it again temp1=0 'clear temp1 i2addr=125 'go to the same address gosub rdmem 'read and verify debug dec ? temp1,cr temp1 = 5 gosub pulser return ' pulser flashes the light temp1 times ' pulser: if temp1 = 0 then ret pulsout light,5000 nap 5 temp1 = temp1 -1 goto pulser return '**************************** '* I2C Routines begin here * '**************************** '********************************************** '* (wrmem) write a byte to I2C memory routine * '********************************************** 'Before you call wrmem 'Load i2addr with memory address word 'Load temp1 with variable byte to store '********************************************** wrmem: gosub i2start 'send start contition i2data=i2memWR 'send wr command gosub i2tx gosub ackrx i2data=i2addr1 'send high address gosub i2tx gosub ackrx i2data=i2addr0 'send low address gosub i2tx gosub ackrx i2data=temp1 'send data byte gosub i2tx gosub ackrx gosub i2stop 'send stop condition return '*********************************************** '* (rdmem) read a byte from I2C memory routine * '*********************************************** 'Before you call rdmem 'Load i2addr with memory address word to retrieve from 'Returns the value from address in temp1 '****************************************************** rdmem: gosub i2start 'send start condition i2data=i2memWR 'send wr command gosub i2tx gosub ackrx i2data=i2addr1 'send high address gosub i2tx gosub ackrx i2data=i2addr0 'send low address gosub i2tx gosub ackrx gosub i2start 'again start condition i2data=i2memRD 'send rd command now gosub i2tx gosub ackrx gosub i2rx 'get byte temp1=i2data 'put it in temp1 gosub i2stop 'send stop condition return '************************************* '* (rdmemsq) Sequential I2C mem read * '************************************* 'Before you call rdmemsq: 'Load i2addr with starting memory address word 'Gets constant memtop (top of memory) 'Returns value from memory in temp1 in the subroutine dosemething 'Example: 'This is used to upload data stored in the EEPROM to a PC 'through the serial port. Much faster than the single byte read '***************************************************************** rdmemsq: gosub i2start 'send start condition i2data=i2memWR 'send wr command gosub i2tx gosub ackrx i2data=i2addr1 'send high address gosub i2tx gosub ackrx i2data=i2addr0 'send low address gosub i2tx gosub ackrx gosub i2start 'send start condition again i2data=i2memRD gosub i2tx gosub ackrx for i2addr=i2addr to memtop-1 'loop to memtop-1 shiftin i2dt,i2clk,0,[i2data] 'get data 'shifin instead of gosub 'to i2rx speeds up things shiftout i2dt,i2clk,1,[%0\1] 'send ack temp1=i2data 'put data in temp1 gosub dosomething 'do something with the data next shiftin i2dt,i2clk,0,[i2data] 'get the last byte gosub i2stop 'send stop condition temp1=i2data 'put last byte in temp gosub dosomething 'do something with the data return '********************************* '* (i2start) I2C start contition * '********************************* i2start: high i2dt 'I2C data line high high i2clk 'I2C clock line high low i2dt 'I2C data line low return '******************************* '* (i2stop) I2C stop contition * '******************************* i2stop: low i2dt 'I2C data line low high i2clk 'I2C clock line high high i2dt 'I2C data line high return '******************************************** '* (i2tx & i2rx) I2C byte tensmit & receive * '******************************************** i2tx: shiftout i2dt,i2clk,1,[i2data] 'shift out byte to I2C return i2rx: shiftin i2dt,i2clk,0,[i2data] 'shift in byte from I2C return '****************************************************** '* (acktx & ackrx) I2C acknowledge transmit & receive * '****************************************************** acktx: shiftout i2dt,i2clk,1,[%0\1] 'send acknowledge to I2C return ackrx: shiftin i2dt,i2clk,0,[i2ack\1] 'receive acknowledge from I2C if i2ack = 0 then ret debug "ack failed " debug bin ?i2ack debug hex ?i2data nap 7 return