A simple PCB connected each inductor and capacitor in parallel, which in turn were connected to a PIC i/o pin:
Here's the board all made up and connected to the PIC (ok, we only soldered four out of a possible eight squares, but it's just a prototype to prove a concept, so we're not too worried about that!)
We quickly knocked up some code to test the board. We're using XOR to detect which pins have gone high/low. This kind of thing often throws up some queries, so here's a quick explanation:
First we get the PORB input.
Let's assume it's 00011000
Now we XOR it with a previous read.
Let's pretend that previously the input was 00001000
So 00011000 XOR'd with 00001000 give us 00010000
This result tells us that PORB.5 has changed. Just by looking at the "before" and "after" port states, we can see that this is correct. So we've identified which pin has changed - but has it gone high or low?
If we AND the result with the "new" read data, we should get a pattern telling us which pins have just gone HIGH: 00010000 AND 00011000 gives us 00010000
Incidentally, if we AND the result with the "old" read data, we get a pattern telling us which pins have just gone low. We're not interested in this information right now, but it's a handy technique to know!
Now we've a way of telling, very quickly, which pins from an entire port have just gone high, we can use this to track how long it take for the oscillating LC part of the circuit to go from high, to low, and back to high again. Here's the code we used:
Define CONF_WORD = 0x3f32
Define CLOCK_FREQUENCY = 20
AllDigital
Config PORTB = Output
Dim i As Byte 'declare a variable
Dim portb_input As Byte
Dim portb_last As Byte
Dim portb_change As Byte
Dim portb_rising As Byte
Dim portb_response(8) As Word
Dim portb_final As Byte
Dim read_count As Word
High PORTB.0
Hseropen 9600 'open hardware uart port for baud rate 9600
WaitMs 1000 'this delay should be used in a real device
Low PORTB.0
i = 0
Hserout "Starting PIC: ", CrLf 'send formatted output to serial port
WaitMs 1000 'this delay should be used in a real device
loop:
'switch on timer 1
T1CON.TMR1CS = 0 '(use fosc/4 as time base)
T1CON.T1OSCEN = 1 '(enable timer1 oscillator)
T1CON.TMR1ON = 1 '(turn the timer1 on)
'make all of PORTB an output
TRISB = 0x00
'wait a sec
WaitMs 100
'make all PORTB inputs
TRISB = 0xff
'wait for the inputs to trail off to zero
portb_input = 0xff
While portb_input > 0
portb_input = PORTB And 15
Wend
'now reset the timer
TMR1H = 0
TMR1L = 0
'get the input from the port
portb_input = 0
portb_last = 0
portb_final = 0
read_count = 0
While portb_final < 15 And read_count < 1000
portb_input = PORTB And 15
portb_change = portb_input Xor portb_last
portb_rising = portb_change And portb_input
portb_final = portb_final Or portb_input
read_count = read_count + 1
If portb_rising.0 = 1 Then
If portb_response(0) = 0 Then
portb_response(0) = (TMR1H * 256) + TMR1L
Endif
Endif
If portb_rising.1 = 1 Then
If portb_response(1) = 0 Then
portb_response(1) = (TMR1H * 256) + TMR1L
Endif
Endif
If portb_rising.2 = 1 Then
If portb_response(2) = 0 Then
portb_response(2) = (TMR1H * 256) + TMR1L
Endif
Endif
If portb_rising.3 = 1 Then
If portb_response(3) = 0 Then
portb_response(3) = (TMR1H * 256) + TMR1L
Endif
Endif
portb_last = portb_input
Wend
'now write your results out over serial
Hserout "Read count ", #read_count, " "
For i = 0 To 3
Hserout "R", #i, ":", #portb_response(i), " "
Next i
Hserout CrLf
WaitMs 1000
Goto loop 'loop forever
Define CLOCK_FREQUENCY = 20
AllDigital
Config PORTB = Output
Dim i As Byte 'declare a variable
Dim portb_input As Byte
Dim portb_last As Byte
Dim portb_change As Byte
Dim portb_rising As Byte
Dim portb_response(8) As Word
Dim portb_final As Byte
Dim read_count As Word
High PORTB.0
Hseropen 9600 'open hardware uart port for baud rate 9600
WaitMs 1000 'this delay should be used in a real device
Low PORTB.0
i = 0
Hserout "Starting PIC: ", CrLf 'send formatted output to serial port
WaitMs 1000 'this delay should be used in a real device
loop:
'switch on timer 1
T1CON.TMR1CS = 0 '(use fosc/4 as time base)
T1CON.T1OSCEN = 1 '(enable timer1 oscillator)
T1CON.TMR1ON = 1 '(turn the timer1 on)
'make all of PORTB an output
TRISB = 0x00
'wait a sec
WaitMs 100
'make all PORTB inputs
TRISB = 0xff
'wait for the inputs to trail off to zero
portb_input = 0xff
While portb_input > 0
portb_input = PORTB And 15
Wend
'now reset the timer
TMR1H = 0
TMR1L = 0
'get the input from the port
portb_input = 0
portb_last = 0
portb_final = 0
read_count = 0
While portb_final < 15 And read_count < 1000
portb_input = PORTB And 15
portb_change = portb_input Xor portb_last
portb_rising = portb_change And portb_input
portb_final = portb_final Or portb_input
read_count = read_count + 1
If portb_rising.0 = 1 Then
If portb_response(0) = 0 Then
portb_response(0) = (TMR1H * 256) + TMR1L
Endif
Endif
If portb_rising.1 = 1 Then
If portb_response(1) = 0 Then
portb_response(1) = (TMR1H * 256) + TMR1L
Endif
Endif
If portb_rising.2 = 1 Then
If portb_response(2) = 0 Then
portb_response(2) = (TMR1H * 256) + TMR1L
Endif
Endif
If portb_rising.3 = 1 Then
If portb_response(3) = 0 Then
portb_response(3) = (TMR1H * 256) + TMR1L
Endif
Endif
portb_last = portb_input
Wend
'now write your results out over serial
Hserout "Read count ", #read_count, " "
For i = 0 To 3
Hserout "R", #i, ":", #portb_response(i), " "
Next i
Hserout CrLf
WaitMs 1000
Goto loop 'loop forever
The idea here is that we send the output pin high, charging the LC circuit. We then turn the pin to an input, wait for the LC/input to drop to 0v, then time how long it takes before the oscillator takes the input high again. The results were quite unexpected:
Using an inductor of 1.5mH and a capacitor of 3.3uF, we calculated that the oscillator should be running at about 71khz. But different input pins were returning different timing values. Something didn't look right! We took the board off the PIC and re-ran the code and the results were pretty much the same; the input pins were reading as if they were just floating!
One way to eliminate false reads from floating input pins is to add a pull-down resistor on each one. We did this and re-ran the code:
As expected (except, for some reason, the input on PORTB.1) once the input has gone to zero, it never comes back up to a positive value - any current in the circuit from the LC oscillator is being pulled straight to ground through the resistor.
Conclusion? Epic Fail :(
In fact it's not quite as bad as all that.
It's not a roaring success.
But for a while it was nice just to get back to making stuff and trying ideas out!
No comments:
Post a Comment