|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The story in text:
The objective of this project is to resize the average workbench. David mentioned that it is interesting to make something of greater simplicity from to objects of higher order, equivalent complexity. I agree! We are building an oscilliscope, with each of the fifteen of us working on a particular aspect of the design. Organization is reasonably free-form, which seems to me to add a third degree of equivalent complexity (our degree of understanding) to the puzzle. I like it a lot! I am developing a device to determine capacitance, because the ability to collect charge is highly interesting to me, so something I would like to measure. (Super capacitors, here we come?) Of all of the units so far, this is the one that is farthest from my base of knowledge, but should our individual efforts come together also something that I will rebuild on my own and put in our student shop. I ordered a copy of the Roland Mill yesterday, and am exceedingly excited to get going.
The Thought Process :
1. Of course, every project begins with ideas, but this one more than usual because I know less than is common. I began by milling and stuffing the Hello3 board, and just looking down on it believe that the new device denoted by a 1$ on the schematic looks like an ideal input / output location. Perhaps I will add leads here that can attach to whatever it might be that I am trying to measure (me?)! |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The Potential Input Point |
|
Some Text from the Manual |
|
|
2. Next step here involved looking at the base code adn reading through it:
;
; hello3.step.asm
; step response measurement
; Neil Gershenfeld CBA MIT 10/29/05
;
; definitions
;
.include "tn13def.inc"
.equ chargepin = PB1 ; charging pin
.equ txpin = PB4 ; serial transmit pin
.def bitcnt = R16 ; bit counter
.def temp = R17 ; temporary storage
.def txbyte = R18 ; data byte
.def delaycnt = R19 ; delay counter
.def uplo = R20 ; up low byte
.def uphi = R21 ; up hi byte
;
; start of code
;
.cseg
.org 0
rjmp reset ; jump to reset routine
;
; putchar routine
; assumes no line driver (doesn't invert bits)
;
.equ sb = 1 ; number of stop bits
putchar:
ldi bitcnt, 9+sb ; 1+8+sb
com txbyte ; invert everything
sec ; set start bit
putchar0:
brcc putchar1 ; if carry set
sbi PORTB, txpin ; send a '0'
rjmp putchar2 ; else
putchar1:
cbi PORTB, txpin ; send a '1'
nop
putchar2:
rcall bitdelay ; one bit delay
rcall bitdelay
lsr txbyte ; get next bit
dec bitcnt ; if not all bits sent
brne putchar0 ; send next
ret ; else return
;
; serial bit delay routine
;
.equ b = 17 ; 9600 bps
bitdelay:
ldi temp, b
bitloop:
dec temp
brne bitloop
ret
;
; routine to wait for sample to settle
;
.equ delay = 255
settle:
ldi temp, delay
settleloop:
dec temp
brne settleloop
ret
;
; main program
;
reset:
ldi temp, low(RAMEND) ; set stack pointer to top of RAM
out SPL, temp ;
;
; init output pins
;
sbi PORTB, txpin ; comm
sbi DDRB, txpin ; "
sbi PORTB, chargepin ; charging
sbi DDRB, chargepin ; "
;
; init A/D
;
cbi ADMUX, REFS0 ; use Vcc as reference
cbi ADMUX, ADLAR ; right-adjust result
sbi ADCSRA, ADEN ; enable A/D
cbi ADCSRA, ADATE ; disable auto-trigger
cbi ADCSRA, ADPS2 ; set prescaler for /2
cbi ADCSRA, ADPS1 ; "
cbi ADCSRA, ADPS0 ; "
cbi ADMUX, MUX1 ; input on ADC1
sbi ADMUX, MUX0 ; "
;
; infinite main loop
;
loop:
;
; loop over delays
;
ldi delaycnt, 254
delayloop:
;
; settle sample and start upward step response
;
cbi PORTB, chargepin
rcall settle
mov temp, delaycnt
sbi PORTB, chargepin
;
; wait for delay
;
addelayup:
dec temp
brne addelayup
;
; read response
;
sbi ADCSRA, ADSC ; start conversion
adloopup:
sbic ADCSRA, ADSC ; loop until complete
rjmp adloopup
;
; save conversion
;
in uplo, ADCL ; get low byte
in uphi, ADCH ; get high byte
;
; settle sample and start downward step response
;
rcall settle
mov temp, delaycnt
cbi PORTB, chargepin
;
; wait for delay
;
addelaydown:
dec temp
brne addelaydown
;
; read response
;
sbi ADCSRA, ADSC ; start conversion
adloopdown:
sbic ADCSRA, ADSC ; loop until complete
rjmp adloopdown
;
; send conversions
;
in txbyte, ADCL ; low down byte
rcall putchar
in txbyte, ADCH ; hi down byte
rcall putchar
mov txbyte, uplo ; low up byte
rcall putchar
mov txbyte, uphi ; hi up byte
rcall putchar
dec delaycnt
dec delaycnt
brne delayloop
;
; send 1 2 3 4 for framing
;
ldi txbyte, 1
rcall putchar
ldi txbyte, 2
rcall putchar
ldi txbyte, 3
rcall putchar
ldi txbyte, 4
rcall putchar
rjmp loop
This will become a link, but for now everything is here so I can scroll through it easily while reading over the manual for ATiny13 to determine what exactly needs to be changed to allow for capacitance to be read. Notes from reading over the manual include:
Perhaps most importantly, what the pins do!
• Bit 7 – I: Global Interrupt Enable
The Global Interrupt Enable bit must be set for the interrupts to be enabled. The individ-
ual interrupt enable control is then performed in separate control registers. If the Global
Interrupt Enable Register is cleared, none of the interrupts are enabled independent of
the individual interrupt enable settings. The I-bit is cleared by hardware after an interrupt
has occurred, and is set by the RETI instruction to enable subsequent interrupts. The I-
bit can also be set and cleared by the application with the SEI and CLI instructions, as
described in the instruction set reference.
• Bit 6 – T: Bit Copy Storage
The Bit Copy instructions BLD (Bit LoaD) and BST (Bit STore) use the T-bit as source or destination for the operated bit. A bit from a register in the Register File can be copied
into T by the BST instruction, and a bit in T can be copied into a bit in a register in the
Register File by the BLD instruction.
• Bit 5 – H: Half Carry Flag
The Half Carry Flag H indicates a Half Carry in some arithmetic operations. Half Carry is useful in BCD arithmetic. See the “Instruction Set Description” for detailed information.
• Bit 4 – S: Sign Bit, S = N ⊕ V
The S-bit is always an exclusive or between the Negative Flag N and the Two’s Comple- ment Overflow Flag V. See the “Instruction Set Description” for detailed information.
• Bit 3 – V: Two’s Complement Overflow Flag
The Two’s Complement Overflow Flag V supports two’s complement arithmetics. See
the “Instruction Set Description” for detailed information.
• Bit 2 – N: Negative Flag
The Negative Flag N indicates a negative result in an arithmetic or logic operation. See
the “Instruction Set Description” for detailed information.
• Bit 1 – Z: Zero Flag
The Zero Flag Z indicates a zero result in an arithmetic or logic operation. See the
“Instruction Set Description” for detailed information.
• Bit 0 – C: Carry Flag
The Carry Flag C indicates a carry in an arithmetic or logic operation. See the “Instruc-
tion Set Description” for detailed information.
The stack pointer stores temporary data. In reading over the code, I have yet to assimilate what is being measured, or where exactly I want to process the data I gather. But I do know how to find capacitance! I need to determine the dv/dt and current, which means I have a device to measure all three! if I so choose. Or maybe there is an easier way to go about it, though in searching through all manuals capacitance as a word only appears twice!, so this path seems unlikely to result in success.
|
|
|
|
|
|
|
|
|
|
|
|
|
Computer Used for Programming |
|
Command Line Prompt . |
|
|
|
|
|
|
|
|
|
|
Now that the code is written to get capacitance, we are interested in how this is displayed to the world, and so want to develop a GUI. As a beginning point, I read over the tkinter and looked at the following code in python:
#
# hello3.step.py
# receive and plot step response
# Neil Gershenfeld CBA MIT
# 10/29/05
#
from Tkinter import *
import serial
WINDOW = 600
NSAMPLES = 254
MAX = 1040
eps = .9
saveflag = 0
index = 0
path = []
step = []
path_filt = []
step_filt = []
baseline = []
def idle(parent,canvas):
global index, channel, baseline, path, path_filt, step, step_filt, saveflag
#
# idle routine
#
eps = float(sfilter.get())
lo_dn = ord(ser.read())
hi_dn = ord(ser.read())
lo_up = ord(ser.read())
hi_up = ord(ser.read())
if ((lo_dn == 1) & (hi_dn == 2) & (lo_up == 3) & (hi_up == 4)):
if (path_filt == []):
path_filt = path
step_filt = step
else:
for i in range(len(path_filt)):
path_filt[i] = (1-eps)*path_filt[i] + eps*path[i]
for i in range(len(step_filt)):
step_filt[i] = (1-eps)*step_filt[i] + eps*step[i]
canvas.delete("path")
canvas.create_line(path_filt,tag="path",width=3,fill="#00b000")
if (baseline != []):
canvas.delete("baseline_path")
canvas.create_line(baseline,tag="baseline_path",width=3,fill="#b00000")
canvas.itemconfigure("y0",text="y[0]: %.2f"%step_filt[0])
canvas.itemconfigure("y1",text="y[1]: %.2f"%step_filt[1])
canvas.itemconfigure("y-1",text="y[-1]: %.2f"%step_filt[-1])
canvas.coords('x0',0,.95*WINDOW,step_filt[0],WINDOW)
if (saveflag == 1):
file = open(soutfile.get(),"w")
for i in range(len(step_filt)):
file.write("%f\n"%(step_filt[i]))
file.close()
print 'saved to '+soutfile.get()
saveflag = 0
index = 0
path = []
step = []
else:
value_up = 256*hi_up + lo_up
value_dn = 256*hi_dn + lo_dn
value = (value_up + (1023-value_dn))/2.0
index += 2
step.insert(0,value)
path.insert(0,WINDOW-value*WINDOW/float(MAX))
path.insert(0,WINDOW-index*WINDOW/float(NSAMPLES))
parent.after_idle(idle,parent,canvas)
def save_data(parent):
global saveflag
saveflag = 1
def store_baseline(parent):
global path_filt, baseline
baseline = []
for i in range(len(path_filt)):
baseline.append(path_filt[i])
#
# open serial port
#
#ser = serial.Serial('/dev/ttyUSB0',9600)
ser = serial.Serial('/dev/ttyS0',9600)
#ser = serial.Serial('COM6',9600)
ser.setDTR()
#
# find framing
#
print "finding framing ..."
byte2 = 0
byte3 = 0
byte4 = 0
while 1:
byte1 = byte2
byte2 = byte3
byte3 = byte4
byte4 = ord(ser.read())
if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)):
print "start plotting"
break
#
# start plotting
#
root = Tk()
root.title('hello3.step.py')
root.bind('q','exit')
canvas = Canvas(root, width=WINDOW, height=WINDOW, background='white')
canvas.create_text(.2*WINDOW,.9*WINDOW,font=("Helvetica", 24),tags="y0",fill="#0000b0")
canvas.create_text(.5*WINDOW,.9*WINDOW,font=("Helvetica", 24),tags="y1",fill="#0000b0")
canvas.create_text(.8*WINDOW,.9*WINDOW,font=("Helvetica", 24),tags="y-1",fill="#0000b0")
canvas.create_rectangle(0,.95*WINDOW,0,WINDOW, tags='x0', fill='#b00000')
canvas.pack()
ioframe = Frame(root)
Label(ioframe, text=" filter (0-1):").pack(side="left")
sfilter = StringVar()
sfilter.set(str(eps))
Entry(ioframe, width=5, textvariable=sfilter).pack(side="left")
Label(ioframe, text=" ").pack(side="left")
basebtn = Button(ioframe, text="store baseline")
basebtn.bind('<Button-1>',store_baseline)
basebtn.pack(side="left")
Label(ioframe, text=" ").pack(side="left")
savebtn = Button(ioframe, text="save data")
savebtn.bind('<Button-1>',save_data)
savebtn.pack(side="left")
Label(ioframe, text=" output file:").pack(side="left")
soutfile = StringVar()
soutfile.set("out.dat")
Entry(ioframe, width=10, textvariable=soutfile).pack(side="left")
Label(ioframe, text=" ").pack(side="left")
quitbtn = Button(ioframe, text="quit")
quitbtn.bind('<Button-1>','exit')
quitbtn.pack(side="left")
ioframe.pack()
root.after(100,idle,root,canvas)
root.mainloop() |
|
|