today on Applied
Science I'm going to
describe how I built an image capture
system for this vintage scanning
electron microscope this allows me to
connect a modern computer to it and
capture images directly but first let's
take a look at an animation that I made
today using this system this is a two
millimeter drill bit drilling into some
lead metal and I chose lead just because
it's soft I can't get a hold real press
inside the scanning electron microscope
so I'm basically using a makeshift drill
press inside there so the basic idea of
this image capture system is to start
with an analog video signal that the SEM
is outputting and then digitize that
using a microcontroller and send the
digital values over USB to the computer
and then on the computer I'm running a
processing org script that just displays
the image in real time and optionally
allows me to save the frames so this way
I can just with you know two keystrokes
see an image and then save it and then
advance the sound so I can get an easy
sort of animation going okay so let's
talk about that analog signal this
microscope is capable of capturing
images in real time so if I move the
drill bit inside the microscope you can
see in the on the screen it's updating
it at full speed it's about 30 to 60
frames a second but if you want a really
high-resolution image we have to slow
the scan way down so the scope comes
with this setting and as you can see
it's building up the image line by line
and the whole thing takes about 10
seconds so back in the day the way that
you would actually make an image out of
that is to hook up a Polaroid camera to
this and then mount the camera to the
front of the screen and let it expose
the film the line at a time but of
course we have better technology than
that now so let's talk about today's
solution since the designers of the
microscope thought that you'd be using a
camera to capture this slow scan image
unfortunately there's no port on the
side of the scope that has a signal we
can use so I had to go probing around on
the circuit board with the oscilloscope
and with the help of this schematic here
found a signal that will work just fine
it's actually quite a large range signal
it goes from negative 12 to 12 the
reason being that the scope uses plus
and minus 15 volt rails for its op amps
so that when the op amp is railed all
the way it puts out about negative 12 or
these in this case the signal is
composite so basically it's a raster
scan it's left to right top to bottom
just like you saw on the screen and when
it gets to the end of the horizontal
line there's a sync pulse in this case
it's about 126 microseconds long and
during the sync pulse the voltage is as
far negative as it can go about negative
12 volts then there's analog data for
eleven point two milliseconds and this
repeats for every horizontal line and
when we get to the bottom of the frame
there's a much longer pulse of about 10
milliseconds so if we know what the
pulses are supposed to be and we're
listening to this signal we can figure
out everything we need to to reconstruct
the frame and that this comes out to
about a thousand lines per frame and so
the whole thing takes about 11 seconds
so if we want to get this into a
microcontroller the first step is to
voltage translate it into something that
won't destroy the microcontroller in
this case I'm using the teensy LLC which
is a 3.3 volt microcontroller so what we
want to do is translate this negative 12
to 12 volt signal into zero to 3.3 and
we also want to do something else
these sync pulses don't really carry any
information about the image itself I
mean its timing information but it's not
visual information so if we were to
compress this whole negative 12 to 12
range down to 0 to 3.3 a lot of our
dynamic range would be wasted on this
pulse so what I'm going to do is
separate the signal into just video and
then just sync so let's talk about the
video first I just ended up using two op
amps this could have been done with one
but with two we invert the signal then
invert it back so that the sense of the
signal is the same not that it makes a
huge difference whatever
so this first op-amp is set up as a
reducer usually you configure op amp
circuits to amplify signals but in this
case we're actually attenuating and then
the second op amp is an offset so if we
put it the positive input on a
potentiometer from negative 15 to plus
15 we can dial up where
want the offset to be so after these two
we get a signal that is just the video
data hopefully taking up as much dynamic
range as possible zero to three point
three and the sync pulse is not really
there anymore then to recover the sync
pulse I have another op-amp set up as a
comparator so it's negative input as a
fixed voltage between negative fifteen
and fifteen and then there's a little
bit of positive feedback so that when
the signal goes below the threshold and
I set the threshold to be something like
you know negative eleven so as soon as
this thing gets down to its most
negative voltage we know we have a sync
pulse and this comparator quickly snaps
over now remember that this this
comparator is still using plus and minus
fifteen volt rails but we want to get
the signal to be zero to three point
three so what I did is I used a 74 Hz
series inverter and the datasheet even
says that this thing is set up with
protection diodes specifically to
convert high voltage systems into low
voltage systems so I powered the
inverter with the 3.3 volt rail from the
microcontroller and then put a resistor
here to limit the current so that even
though this thing is snapping around
from negative 15 to 15 almost when we
get through the inverter we're down to
just zero 23.3 so now we have our
digital sync signal which we can put
into a digital pen on the
microcontroller and then we have our
analog signal which we put into an
analog pin and like I said I'm using the
teensy LLC which gives us a bunch of
options here here's a flow chart showing
what the firmware it does we have our
two signals in the video analog signal
and the digital sync signal and we want
to go through all this and have USB data
ours so the way this is set up the ADC
is in freerunning mode and it's running
at about a hundred forty two kilohertz
actually it's averaging for samples but
we're getting a result from it one
hundred forty two thousand times a
second and what we want to do is stop
the ADC at the start of a sync pulse so
that when we restart the ADC it will be
nice and lined up with that falling edge
of the sync pulse originally I had the
ADC free running all the time and I
tried to sync it up at the beginning of
the pulse but it didn't work
very well because at certain stages of
the IDC's function you can't stop and
restart it with a deterministic amount
of time however you if you stop the
system here then what we can do is just
measure the pulse width using a timer
function in the microcontroller and then
we'll know how long the pulse was and we
can restart the ADC and get very
deterministic timing another trick I ran
into is it since we have data coming
from the ADC so fast if we just filled
up a buffer from the ADC and then sent
that out over USB we would end up with
some contention there eventually because
the USB would be wanting to send the
same data that's being written in by the
ADC and I think you could implement this
with a loop buffer but I still couldn't
quite figure it out since they're both
reading and writing so quickly you end
up with some weirdness there and another
nice thing is that we'd like to fill up
a buffer of at least 64 bytes before we
actually do the USB transaction it's
super inefficient to collect a sample
and then send that one byte and then
collect another sample and send that
next byte so the code that operates the
USB transaction would much prefer to
have a 64 byte buffer or larger to work
with so the way that I solved this
problem is to use ping pong buffers so
the ADC is currently filling buffer a
while buffer B is being drained by the
USB command and then it with interrupts
disabled snaps over so it ping pongs to
the other side and this seems to work
really well I don't know if there's an
even sneakier way to do it but the code
is actually quite compact and I'll post
a link in the description so you can
take a look and then the last bit is
just to figure out how long this pulse
was and I used the elapsed micros
variable that is included in the teensy
libraries and if it's over a certain
amount like if it's big enough to be a
vertical sync pulse then it dumps a
different byte into the buffer whereas
it's a short one then it dumps you know
a horizontal pipe basically the ADC is
running in 8-bit mode and all of the
values except 0 & 1 are valid data
values I retain 0 & 1 to
differentiate
between the types of sinc pulses and
probably eventually later I'll have
other
bits of encoding but this just keeps
things really simple so it's one sample
one bite just sent right over the USB
and then there's two special bites for
the sink
here's a couple other things to keep in
mind if you're doing a similar project
USB HID is limited to about 64 kilobytes
per second now it is guaranteed
bandwidth so a thousand times a second
you can send a 64 byte packet but in
this case we're going a bit faster we're
already up to 142 kilobytes per second
so we can't use hid and if we use an
emulated serial port that's fine it's
not guaranteed bandwidth so if you plug
a bunch of other stuff onto that same
USB you may run out of bandwidth but in
this case we're totally fine and it's
running at about 142 KB per second I
originally started using the independent
ADC cloth that the teensy has or that
the freescale microcontroller has and it
says oh you should use this alternative
clock if you're worried about noise
coming from the system clock and I
thought oh great well that's that's just
what I want but as it turns out this is
actually probably an RC timer inside the
microcontroller and it drifts like crazy
so I couldn't use that I switched back
to the system clock also if you search
around on the net about using the teensy
for projects like this like audio
projects and things like that you'll
find that people are talking about this
pdb the programmable delay block which I
had never heard of before reading about
this in the freescale controller I
thought well if you want something with
accurate timing you would just set up a
timer and use an interrupt and then put
your code in there but if you need
something that's really deterministic I
mean really accurate you can't trust the
interrupts because there could be you
know it delay an undetermined delay when
the interrupt fires and so it you know
leads to variable timing so apparently
this pdb is something that you can set
up in the microcontroller that really
runs very deterministically and it
triggers the ADC without really any code
happening and the teensy three-point-one
has this but the teensy LC doesn't so
when I started this project I thought I
had a 3.1 on the shelf but I didn't I
had an LLC and then I started coding it
and thought oh well now it's a challenge
I get to make it work without the PD
be so by playing with interrupt
priorities and writing the code as
efficiently as I could I actually got it
to be very very consistent it's it's
performing as well as it possibly could
it's not dropping samples so I thought
that was a bit of a win the ping pong
buffer I described like I say I don't
know if a circular buffer would be more
elegant or whatever but you can check it
out and see what you think of my
implementation there and then finally
why am I not using DNA most of the
resources about teen CDMA refer to the
three point one and the DMA controller
on the LC is different and I didn't
really feel like learning about it and I
got enough performance out of the code
the way it's written now so I just went
with that here's the setup we've got the
composite video signal coming in from
the SEM here and we have the USB
connection going out here and then to
power the board I've actually just
tapped on to the circuit board that's
part of the salmon we're getting ground
plus and minus 15 volts out of it as you
can see the thing is completely probed
up so let's take a look at it on the
scope here we can see everything on the
oscilloscope so the two analog channels
video and sync are the two analog inputs
to the microcontroller and then we have
USB on the top here and the scope is
actually decoding the USB data in real
time and then we also have debug 1 2
& 3
down here which are digital signals that
are generated by the microcontroller so
if you're really interested in this you
can download the code that I posted and
the comments actually indicate what
debug 1 2 & 3 are so briefly debug 3
is
the interrupt service routine that
handles the sync pulse developed 1 is
the interrupt service routine that
handles the analog digital converter and
debug 2 is the main loop of the program
where we actually send the data out USB
so it's needs that we can use the scope
to measure the duty cycle and see how
much time is being spent by the
microcontroller in each of these places
so as you can see debug one is a has a
duty cycle of about 32 percent which
means that the processor is spending 32
percent of its time in the
analog/digital converter interrupt
service routine which is kind of high I
mean that's that's a lot of time luckily
the job of this processor is just to
digitize stuff and send it to the
computer so it's not too surprising that
it's you know spending a lot of time
there we're also measuring the frequency
and so we can see that that interrupt
routine for the analog/digital converter
fires at about 142 kilohertz which is
the sample rate of this system these
measurements are also being made just
between the cursors so you can see as I
was describing when the sync pulse comes
we actually stop the ADC here and then
restarted at the end of the pulse or at
U so that we have a good sync up here so
let me show you what happens if we don't
have good sync up this is an image that
shows this jaggies problem you know the
image is sort of jagged up there and the
reason is that on some lines the ADC
would be restarted like a few pixels too
early or too late depending how you look
at it and it's kind of a small image
problem but I got to the point where I
realized I could fix it and so then I
had to and syncing up or stopping the
ADC and then starting it at the end of
the sync pulse solved the problem very
well let's take a look at some of the
data that's flowing through USB so we
just do a single acquisition here the
blue areas are data so if we zoom in we
can scroll over to those transactions
and then if we look in here each one of
these is one of the bytes that are being
sent through the USB pipe if we ever see
a zero in here then we know that's the
sync pulse of course there's only one
and so it's very hard to see and the
scope has the ability to be triggered
off of data that's flowing through the
USB so you can tell it trigger when you
see a zero in one of these but actually
haven't got that to work so I have to
ask a tech expert how to set this up or
it seems like I've got it but it's just
not triggering another thing that's
helpful for debugging is if we get a
single acquisition we want to look
through the data but we don't want to
use the magnifier so this is actually
pretty handy if
what you're looking for is sort of
time-sensitive so I can use this job
wheel to scroll through and I can say oh
yeah that's you know the value that
corresponds to the thing and since we're
also recording the analog value you can
kind of look for a blip that might have
happened in the analog Channel and look
for it in the digital but alternatively
what we can do is pull up the event
table and this is just sort of a listing
of all the data that's gone through that
USB pipe in this particular acquisition
we're sending individual bytes so half
of each one of these nibbles here is a
sample and we can look through here and
look for a zero and that sort of thing
you'll also notice there's a lot of
these nak packets remember that USB is
kintyre lis controlled by the host so
the the client the microcontroller can't
tell the host that it wants to send data
it has to wait for the host to ask so in
this case since the host is pulling in
the data as quickly as possible it keeps
sending requests to the microcontroller
saying you know do you have any data do
you have any data and all of these
knacks are the microcontroller
responding no my buffer is not full and
I don't have any data to send and then
eventually the computer asked and the
microcontroller responds yeah the day of
the buffer is full so I can send you all
this stuff
which is why it's helpful to have the
buffer always filled up too close to the
64 byte maximum that way one transaction
is full whereas if you send each byte
all by themselves you end up wasting
lots of transactions that are just
carrying one byte when they could have
been carrying up to 64 so here's the
whole set up you can see the computer
tracks right along with the SEM in terms
of the scan out and the update rate is
truly real-time so that you can see
exactly what the SEM is transmitting
because the transfer rate isn't really
that high so after all that you might be
wondering why didn't I just use the
microcontroller to actually generate the
scan rate instead of just you know
passively taking this slow 10 seconds
per frame scan yeah that's definitely
kind of a phase 2 type thing so using
the analog outputs of the
microcontroller to generate the X&Y;
scan
would actually be helpful but at this
point I'm mostly just interested in
making
innovations and if I can get away with
just using the existing scan rate and
that's okay but I would like to
experiment with high-speed acquisition
and we'll have to generate my own scan
rates for that okay see you next time
byeTop Search Keyword : online earning, , make money online, earn money online, online earning, online earning sites, make money online free, online money income, earn money online free, money online, best way to earn money online, online income site, money earning websites, best online earning sites, easiest way to earn money online, earn money payment bkash, online money income site

No comments:
Post a Comment