Measuring light energy using multiple TSL230's
RichardF
Posts: 168
Fellow Spinners,
My application requires reading 8 TSL230 light to frequency converters as rapidly as possible and with as much dynamic light energy range as possible. There·will··be a compromise because it takes more time to measure lower frequencies.·I want to do this in Spin first, then go on to assembly later.· I have come up with the following method as a starting point:
PUB start
cognew(measFreq, @stack2)
'do something with freq[noparse][[/noparse]pinx]
····
PUB measFreq
ctra[noparse][[/noparse]30..26] := %01010························· · 'counter module set·to pos edge detect
repeat···················································'continuous light energy meaurement
· repeat pinx from 0 to 7···················· ···· ·'select TSL230 input pin to read·
··· ctra[noparse][[/noparse]5..0] := pinx
··· frqa := 1············································'add 1 to ·phsa·with each pos edge detect
··· phsa~···············································'clear phsa
··· waitcnt(clkfreq/10+cnt)·················· ·· · 'count detects for 1/10 sec period
··· freq[noparse][[/noparse]pinx] := phsa*10·························· 'save frequency measured
I should be able to measure and save values for all 8 detectors in less than a second. My lower frequency range·should be limited to ~15 hz. In my application I don't think I will need to go near as low as 20 hz, so I can keep reducing the count period and increase the number of reads per second as my application proceeds in development. Basically, I·want to be able to detect a flashbulb going off in daylight conditions and tell in what direction it is coming from. I don't need true values of frequency for comparison, only changes·in relative values between the converters. I will need to experiment with different ranges and look at the dynamic changes in frequency that occur.
I would appreciate any comments on this, especialy ways·to speed up the reads and increase dynamic range.
Thanks,
Richard·
My application requires reading 8 TSL230 light to frequency converters as rapidly as possible and with as much dynamic light energy range as possible. There·will··be a compromise because it takes more time to measure lower frequencies.·I want to do this in Spin first, then go on to assembly later.· I have come up with the following method as a starting point:
PUB start
cognew(measFreq, @stack2)
'do something with freq[noparse][[/noparse]pinx]
····
PUB measFreq
ctra[noparse][[/noparse]30..26] := %01010························· · 'counter module set·to pos edge detect
repeat···················································'continuous light energy meaurement
· repeat pinx from 0 to 7···················· ···· ·'select TSL230 input pin to read·
··· ctra[noparse][[/noparse]5..0] := pinx
··· frqa := 1············································'add 1 to ·phsa·with each pos edge detect
··· phsa~···············································'clear phsa
··· waitcnt(clkfreq/10+cnt)·················· ·· · 'count detects for 1/10 sec period
··· freq[noparse][[/noparse]pinx] := phsa*10·························· 'save frequency measured
I should be able to measure and save values for all 8 detectors in less than a second. My lower frequency range·should be limited to ~15 hz. In my application I don't think I will need to go near as low as 20 hz, so I can keep reducing the count period and increase the number of reads per second as my application proceeds in development. Basically, I·want to be able to detect a flashbulb going off in daylight conditions and tell in what direction it is coming from. I don't need true values of frequency for comparison, only changes·in relative values between the converters. I will need to experiment with different ranges and look at the dynamic changes in frequency that occur.
I would appreciate any comments on this, especialy ways·to speed up the reads and increase dynamic range.
Thanks,
Richard·
Comments
This is an interesting app! Please keep us tuned in!
-Phil
Correct me if I am missing something, but isn't the duration of a flashbulb flash less than 0.1 second, in which case the sampling would have to be much faster. The TSL230 does have frequency and sensitivity scaling.
To measure period, it might be possible to do all channels in parallel in assembly, using a waitpne mask. Every time there is a transition, update the period of the sensor that changed state, update the mask, and loop. That would take a cog. The 8 element data array could be passed to other objects in a producer/consumer scheme.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
To get an idea what you'd be looking at, I took an old TCS230 board without the lens or LEDs, programmed it to read the "clear" channel, and hooked the output to a scope. (The TCS230 is similar to a TSL230, but with color filters.) The scope was set to trigger on a pulse width less than 5µS, so I could capture the flash event. Then I took a flash picture of the setup. The resulting photo and the scope trace are shown in the photos below.
As you can see, the flash event lasted only 160µS, but it does cause a significant change in the output period during that time.
-Phil
I did not try the following code, but it should be not far from Tracy's idea. It has to be assmebler of course....
The current period of all (upto 32!) I/Os is readily available through vector "periodV".
A change of frequency has to be detected by other means which needs much more code! Note that this mainloop must not be disturbed by conditional code
(Corrected a bug :- )
Post Edited (deSilva) : 6/26/2007 6:41:51 PM GMT
Please bring it down about ten notches. You are in areas way over my head! Maybe a year from now, but for now... thanks.
In my further testing of how high a frequency I can count in the minimum period of time using just Spin, the following is the best I can do so far:
Note: pin 15 and 16 are jumpered together.
PUB freqOut
dira[noparse][[/noparse]15]~~
repeat
waitcnt(400 + cnt) 'around 100 khz?
!outa[noparse][[/noparse]15]
PUB measFreq
ctra[noparse][[/noparse]30..26] := %01010
ctra[noparse][[/noparse]5..0] := 16
frqa := 1
phsa~
waitcnt(clkfreq/1000 + cnt) 'around 1 ms measurement time
dc := phsa
dc comes out to be 22 on the Lcd. If I multiply frequency by ten I get register overflow; if I reduce measurement time by ten I get zero in phsa.
The lowest frequency I can measure with a 1 ms measurement period is around 10 khz. That gives me a value of 7 in phsa.
Phil,
Based on your scope results with a flash and TSL230 I may still get enough of a change in converter output to see a measurable difference from the other converters. I am thinking the 230 converter output takes a while to revover after the flash, so there is a longer period than 5us that a change in output frequency can be noted.
Richard
Post Edited (RichardF) : 6/26/2007 8:34:19 PM GMT
The repeat-loop will take approx. 20 mys
Adding a wait delay of 5 mys is minimal
Thus you get 50 mys for a full cycle which results in your reading of around 20 in 1ms.
Reducing the wait delay will bring you a desaster, as 200 or 300 are minimum wait times in SPIN, and "cnt" will probably overflow, as you described.
A delay of 50 mys = 4000+cnt will result in a 140 mys cycle which explains your reading of "7"
Post Edited (deSilva) : 6/26/2007 9:41:05 PM GMT
What the scope trace shows is that you have no more than 160uS (possibly less, depending on the flash duration) to read all eight sensors; otherwise you could miss the flash. You can't do this in Spin. You will have to write an assembly routine, as Tracy suggested, to read the sensors and determine if a flash has occurred and from which direction.
The TSL230 recovery time is one output cycle, by the way. There's no latency beyond that. The 5 uS pulse width I mentioned was a threshold I used to trigger the scope. You could do something similar in your assembly program. If any pulse is less than X uS wide, there's been a flash. The direction will correspond to the sensor that produced the narrowest pulse.
-Phil
I understand what you are saying.
PushingSpin as much as I can for now:
PUB freqOut
ctra[noparse][[/noparse]30..26] := %00100
ctra[noparse][[/noparse]5..0] := 15
frqa := 112_367 'by formula for freq in NCO mode -> freq ~ 2,093
dira[noparse][[/noparse]15]~~
PUB measFreq
repeat
ctra[noparse][[/noparse]30..26] := %01010
ctra[noparse][[/noparse]5..0] := 16
frqa := 1
phsa~
waitcnt(clkfreq/100 + cnt) '1/100 sec measure period
dc := phsa
This yielded a phsa 0f 21
Richard
This runs the accumulation in a loop; each loop execution will be roughly the same amount of
time (and probably on the order of 100us or something each). Note we don't reset phs because
doing so may mean we miss the pulse that just caused it to bump up a lot! This gives you a bit
more time to fire off the flash and see how many pulses you can get max. Compare it with the
same thing when you *don't* fire off the flash. They should be *very* different.
I like your idea of accumulating phsa as opposed to a reset. I now have a single TSL 230 up and running using the following Spin method to measure light energy into the 230:
PUB measFreq
repeat
ctra[noparse][[/noparse]30..26] := %01010
ctra[noparse][[/noparse]5..0] := 16 'TSJ230 input
frqa := 1
phsa~
waitcnt(clkfreq/100 + cnt) '1/100 sec measure period
dc := phsa 'freq = dc*100
I have the 230 set on highest sensitivity and divide-by 100 scale. I am going to get a full set of light readings as the day progresses and then into the night and adjust my scale accordingly. I also will try and capture a flash today.
Richard
Note, read time is set at 1 ms.
PUB measFreq
freq[noparse][[/noparse]0] := 0
repeat
ctra[noparse][[/noparse]30..26] := %01010
ctra[noparse][[/noparse]5..0] := 16
frqa := 1
phsa~
waitcnt(clkfreq/1000 + cnt)···················· '1/1000 sec measure period
if phsa > freq[noparse][[/noparse]0]
· freq[noparse][[/noparse]0] := phsa····································'freq[noparse][[/noparse]0] sent to LCD readout
The first test used low ambient light conditions giving a freq[noparse][[/noparse]0] of 7. The flash from my camera was capured at freq[noparse][[/noparse]0] = 175.
The second test was with an ambient reading of 903 (turned the reading lamp on). I was able to capture that flah with a reading of 1327. Pretty encouraging so far, but I realize I have a long way to go to monitor 8 230's for a flash. I like the idea of using 4 cogs and 8 counter modules. Rokicki's idea of not reseting phsa will be tried next.
Thanks again,
Richard
Post Edited (RichardF) : 6/27/2007 11:19:16 AM GMT
PUB measFreq | curphs, newphs, delta
freq[noparse][[/noparse]0] := 0
ctra[noparse][[/noparse]30..26] := %01010
ctra[noparse][[/noparse]5..0] := 16
frqa := 1
curphs := phsa
repeat
· newphs := phsa
· delta := newphs - curphs
· if delta > freq[noparse][[/noparse]0]
··· freq[noparse][[/noparse]0] := delta
· curphs := newphs
It worked giving me results of 64 flash in 9 ambient and 64 flash in 32 ambient. How long does the loop take and how much time in the loop is dead (non-capture) time?
Thanks,
Richard
p.s. this is why a microcontroller hobby is some much better than programming games on a PC!
Post Edited (RichardF) : 6/27/2007 11:43:22 AM GMT
PUB measFreq | curphsa, curphsb, newphs, delta
freq[noparse][[/noparse]0] := 0
freq := 0
ctra[noparse][[/noparse]30..26] := %01010
ctrb[noparse][[/noparse]30..26] := %01010
ctra[noparse][[/noparse]5..0] := 16
ctrb[noparse][[/noparse]5..0] := 17
frqa := 1
frqb := 1
curphsa := phsa
curphsb := phsb
repeat
· newphs := phsa
· delta := newphs - curphsa
· if delta > freq[noparse][[/noparse]0]··········································· 'increase due to incoming light pulses
··· freq[noparse][[/noparse]0] := delta
· curphsa := newphs
· newphs := phsb
· delta := newphs - curphsb
· if delta > freq················································'increase due to incoming light pulses
··· freq := delta
· curphsb := newphs
Does this look correct to you? I am going to go ahead and get the second 230 wired up and I can see how this works with two sensors detecting a flash and indicationg from what sensor it came from. I can then expand out two at a time until it doesn't work any more. Then it is time for assembly code!
Richard
Ambient light max reading 300·phsx units
Flash·going off 8 ft from sensor 11,400 phsx units
A soon as I get the other 7 TSL230's hooked up I will publish the results.
I am putting the 8 sensors in a radial configuration so that a flash going off from any 45 deg segment can be detected and it's approximate direction calculated.
For those who have helped, thank you.
Richard
Post Edited (RichardF) : 6/27/2007 3:54:09 PM GMT
Wow, looked at your code, you're doing great!
I'd use a single subroutine and pass parameters to distinguish them, but other than that,
things look really good.
Thank you. Don't know if Phil and DeSilva have been around. I hope I didn't upset them when I said they were getting over my head. Don't think so. I still have to add a method to come up with dynamic average ambient levels, and then a means of setting a triggering detection threshold above that level. I keep thinking how much harder all this would be if it weren't for the Propeller chip.
regards,
Richard
I'm still following this thread with interest, and I'm impressed with what you've done so far. Using four cogs overcomes the "it can't be done in Spin" admonition nicely!
-Phil