Sciencemadness Discussion Board
Not logged in [Login ]
Go To Bottom

Printable Version  
 Pages:  1  ..  6    8  
Author: Subject: Building a polarimeter
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 31-5-2015 at 14:45


Woohoo !

Nice one smaerd.




View user's profile View All Posts By User
m1tanker78
National Hazard
****




Posts: 685
Registered: 5-1-2011
Member Is Offline

Mood: No Mood

[*] posted on 1-6-2015 at 18:20


Quote: Originally posted by smaerd  
So I did some work on this today. First things first. Thank you M1Tanker. You were right the red laser pointer does have a significant source polarization. I removed a polarizing film from the optical path and swapped my detector for the source as suggested. Now I have clean sinuisoids without filtering.

So I added a constant voltage power supply for the laser pointer, so glad I did, now my FFT filter has a constant setting!



Anyways, now I took some results as the instrument stood without fine tuning the soft-ware for the new alignment. It's pretty buggy still, but now I have eliminated two or three huge issues. So again thank your M1Tanker. I can see polarization!



Here are the results:
Without a sample here are the observed rotations: 0.52*, -0.60*,0.22*,-0.27*(Average: 0.033, STDEV = 0.5)
With a 20% sucrose solution: : +7.83*, +9.67*, +9.36*, +8.08*, (Average: 8.74, STDEV = 0.9)

The mean value gives me a specific rotation of 43.7 (+/-4.5)*, which is reasonable.

The instrument is obviously not consistent but now that I have a consistent sinuisoid I can do curve fitting rather then my calculus based approaches to finding peak locations.

As suspected the variance of the orientation is 2X that of measurements, because the routine is run twice to take a measurement. So it is my algorithm that is off.

[Edited on 31-5-2015 by smaerd]

Edit - also I got the green laser pointer but when I shorted the switch on the circuit and subjected it to the 3.3V source. I'd subjectively say it's 100-200 times brighter then the red laser, but knowing the human eye is ~5-10x more sensitive to green then red, this is probably a 50mW laser. It too is polarized. It is bright enough that I would be concerned for my eyes if it were to be shined there. I'm afraid to even try it on my amplification circuit, it would likely saturate it and I'd need to use a 50kOhm trimmer pot on the second stage, too finicky for my blood knowing how the ideal FFT filter is.

[Edited on 31-5-2015 by smaerd]


Looking good smeard! Can you elaborate a little on the sampling parameters? I read the thread in bits and pieces so forgive me if you already mentioned it.

Specifically:

1. How many samples per full polarizer rotation? (Ballpark, I know it depends on motor RPM). Are we talking dozens, hundreds, thousands??

2. Are you writing the sampled data to a file or processing it on the fly?

3. If writing to file, in what format? Not file format, data format.. Complex real? Absolute floats, signed, unsigned, etc. Also, are you 'packing' or compressing the data before sending over serial?

If the sinusoid amplitude was centered around zero, finding the peaks and, more importantly, phase shift would be trivial with a zero-crossing algorithm. I think this is where your peak-finding headaches originate. Is that about right or am I missing a piece of the puzzle? Directly modifying the offset would probably introduce all kinds of bugs. I'll give this some thought and see if I can come up with anything.

Oh and to the green laser intensity.... can't do much about eye safety without goggles and/or a reliable enclosure but to the sensor saturating... couldn't you just adjust the stationary pol with respect to the laser to trim down the intensity, take another background scan, proceed with sample scan?

You're running a Linux box, right?




Chemical CURIOSITY KILLED THE CATalyst.
View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 1-6-2015 at 19:07


Actually I don't think I ever elaborated on this piece of information so these are great questions.

1. For a complete polarizer rotation there are 13,132 measurements (weird number I know, but it was experimentally found). So 360*/13132 = 0.027* per encoder count.I can actually double the encoder count number by running in quadrature (but it isn't worth it right now), or by expanding the gear size/tooth count.

2. Here's how the data is transferred/dealt with currently.

Motor encoder detects position change -> photodiode take a measurement (with-in 20μs) -> Data is sent over USB to soft-ware -> software stores information until analysis is completed.
->Soft-ware then FFT filters -> Calculates maxima locations -> Phase shift -> interpolates the next minima to rotate too -> etc

Scans can take from 20s-120s depending on how fast I PWM the motor. I'm preferring 40s scans just for 'safety' even though I had no difference in results with 30s scans.

3. The transferred value is based on a 1024 count (no decimals 0-1023) which the ADC reads as a voltage (0-5V). So all real values. There is no packing the value is recorded as an integer(2bytes), individual bytes are chucked sequentially down the serial pipe.

I'm not manipulating the data on the fly, I could by creating another thread for the application, but I really don't like multi-threaded applications for stability purposes.

Sinuisoid amplitude - I had never heard of a zero crossing algorithm before. Funnily that was one approach I considered, monitor the first derivative for greatest and smallest changes. That was a portion of the algorithm I was using which gave me 0-3 encoder count errors (0-0.08* off).

I think the best method would be to go back to a harmonic regression algorithm, because the 'artificial' sinuisoid will have an absolute maximum rather then an imperfect plateau. Then again, I'm open to suggestions :).

Green laser - That sounds like a good idea, but remember I removed the stationary polarizer :P. It seemed like when I had the stationary polarizer and a polarized light source I was not able to get polarization measurements of the sample cell. It also gave me a 'biased'/off-set waveform for a result. I found that counter intuitive but I am going to accept it for now as that was the only change of the instrument/soft-ware.

With batteries the source was not as ridiculously intense, but I think the intensity is limited by current not voltage (my supply can offer 1A). I didn't analyze the driver circuit too much other then how to short the switch(which was trickier then one might assume). I could try it once I stabilize the algorithm but for now I think I am happy with the Red laser, even though the green laser may give an extra significant decimal for some samples. I could also implement a filter to reduce it's intensity, which funnily enough sounds easier then current regulating the circuit.

Linux -
Yes I am running a linux operating system :). My USB ports are ACM0-5, but the soft-ware includes COM and whatever the hell Mac's use.

[Edited on 2-6-2015 by smaerd]




View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 3-6-2015 at 12:06


The harmonic regression was a bust. At it's optimized form(it was quite slow) it was capable of giving me 0.09-0.90* error. I think I'm going to revisit the FFT phase-shift method because it is horrendously fast compared to a residual square error calculation. Test it's accuracy.

If not, I'm going to have to revisit the convoluted algorithm I was using before which required a lot of tuning.




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 3-6-2015 at 12:53


Why do you need to FFT a series of measurements of the observed polarity (by intensity) ?

Am i missing something enormously obvious ?




View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 3-6-2015 at 14:15


In the frequency domain phase angle can be very easily extrapolated by the arctangent of the imaginary component over the real component.

I wasn't able to use that before because my additional polarizer gave me an improper band shape and the FFT decomposed the sinuisoid into two or more harmonic functions.

This isn't about intensity. I need to figure out how a sample's phase shift differs from a blank. Otherwise no measurement can be made.

This is one of those problems that is incredibly easy on paper, or in your mind, but when applied to real results is becoming a lot more difficult then anything else in the project.

I'm really not sure where a lot of these inconsistencies arise from with my previous approaches but its definitely frustrating.

Edit -FFT phase angle is a bust too. It's giving me 0.1-1.5* errors. Bummer.
Think I might try gaussian curve fitting next.

[Edited on 3-6-2015 by smaerd]




View user's profile View All Posts By User
m1tanker78
National Hazard
****




Posts: 685
Registered: 5-1-2011
Member Is Offline

Mood: No Mood

[*] posted on 3-6-2015 at 16:47


Smeard, I'm confused as to how you derive the imaginary ( i or j ) component of the signal when as far as I can tell, you don't have complex samples to begin with. Are you applying a Hilbert transform or something?

Again, if your amplitude measurements were relative to zero, it'd be an enormous shoe in for measuring the zero-crossing points and hence, your phase shift. The accuracy would be limited only by the usual factors like sample rate, sample depth, mechanical jitter, electrical noise, etc... Rather than trying to measure the peaks where you have an ocean of similar-valued amplitudes, you'd be looking at a sharp transition through the zero 'point'. The trick to knowing if it's a positive or negative-going zero crossing is to compare the current sample with the previous one(s). The zero point doesn't necessarily have to be zero-valued. My memory fails me ATM with the terminology, sorry.

Anyway, no brain-busting calculus or trig needed to find zero crossings and it's incredibly easy on resources. ;)

Quote:
(aga: Why do you need to FFT a series of measurements of the observed polarity (by intensity) ?

Am i missing something enormously obvious ?


I'm with aga here... As I understand, your samples are already ordered in the time domain which is good for finding the phase offset. I don't see a good use for applying a FT when your signals have the same frequency, no? If you violate the Nyquist rules, you'll have aliasing issues to contend with. Keep that in mind when designing your filters and functions.

[Edited on 6-4-2015 by m1tanker78]




Chemical CURIOSITY KILLED THE CATalyst.
View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 3-6-2015 at 17:17


@m1tanker - The fourier transform creates imaginary components in things called 'bins'. So say I put in an array with 10 elements in to the FFT. The FFT will spit out a 20 element array with alternating Real, 'Complex' values. It's just the nature of the beast. Each bin corresponds to one 'item' in the frequency domain.

Well M1, I don't have a definite 0 point. I could artificially create one though which it sounds like you are suggesting. The amplitude remains pretty constant and I've already got an algorithm to find that 'offset' value. I see what you're saying though. Basically get the 'slope' of points and traverse the line. If the point/line intersects the "zero" line then mark its position. I see I see, because there is only one such point where that will happen(well two for a given positive peak). That's really clever. I'll experiment with that tomorrow.




View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 4-6-2015 at 11:07


Just tried the zero crossing algorithm. It's about the same as the others. There's some other source of error here. I'm not 100% where it is just yet, but I am about to do some digging...

I'm starting to wonder if the arduino is gargling up the motor positioning routine. I have no idea how, but I am truly at a loss. I'm noticing that my positioning algorithm is off, probably by a degree or so (with variance). I don't believe it was doing this before.

Thinking of switching to a raspberry pi.

[Edited on 4-6-2015 by smaerd]




View user's profile View All Posts By User
m1tanker78
National Hazard
****




Posts: 685
Registered: 5-1-2011
Member Is Offline

Mood: No Mood

[*] posted on 4-6-2015 at 19:11


I've never used an arduino so I can't comment on the internal hardware workings. As a matter of isolating the problem, why don't you replace your encoder with a single 'tick' connected to a direct interrupt pin (??) and have the motor free-running on a stable-ish supply (not PWM) at a reasonable rate. Use a dedicated hardware counter (??) to cycle the ADC at a reasonable interval. Observe reference crossing or peak locations if that works better for you and use the tick location as a global absolute reference. Sampling at least 2 'tick' intervals continuously will guarantee that you have 2+ positive-going and negative-going reference crossings (or 2+ pos/neg peaks if you prefer).

If the readings are off by ~1 degree, that translates to ~20 counts per half rotation (or 40 counts per full rotation) that are being missed, right?





Chemical CURIOSITY KILLED THE CATalyst.
View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 4-6-2015 at 20:19


m1tanker - I decided that the next phase is going from the ground up in the arduino and debugging. It's a tricky environment to navigate because it is not 'low-level' so processes do things that are not explicit. Example: I've discovered the serial functions are a 'threaded'/interrupt process, so it can interrupt other operations at indiscernible times. So I am switching to an external SPI RAM chip (23LC1024) which supports 5V logic levels. Digital write operations only take about 10 nSec (using low level commands) and do not poll back or hault or any nonsense. I estimate I'll be storing data to transfer later ~100x faster then calling serial.

Actually what you suggest is interesting m1tanker. I had to abandon 'interrupts' because of the serial writing process, instead I was polling the digital pins in a loop. So once I switch to external ram I may be able to get away with using digital write using low level commands in an interrupt (IDEAL). Without that I am likely missing encoder counts, or other things.

I am currently over-clocking the ADC in a reproducible range so I can at least eliminate that. The arduino platform does not utilize it's full or even quarter potential. Even though the documentation even states it can be exceeded significantly without a noteworthy loss of resolution. Peculiar...

Your math checks out. 20-40 counts missing depending on the mood. I've discerned that I cannot reproduce a rotation. Meaning I rotate once, create a graph. Then tell the motor to rotate another 180* (accounting for the motor drift) and the second graph's phase shift is slightly off. It looks like 1-2* but hard/impossible to measure in my current set up. So I am starting to look back and think, maybe a lot of these algorithms were working, but the basis for the microcontroller has been off the entire time.

So, it's kind of a trial by fire time to get reproducibility there, but once that's done, I should have a bank of algorithms to pick and choose from to complete the rest of the project without any serious issues. Using stepper motor would have been so much easier, but lacks the really fine positioning that I want.

I'm going to take your advice for debugging after I try 2-3 of my initial ideas. Getting the motor off PWM could only help.




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 5-6-2015 at 07:55


Stepper motor resolution can be magnified greatly by the use of simple gearing, and are pretty much spot on if you always rotate in the same direction.

That ensures that the gears are always well meshed, and you don't have to worry about any 'play'.

Edit:

Some more polarised film arrived today, so i'll fit my rig up with a full circle of film and see what happens.

[Edited on 5-6-2015 by aga]




View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 5-6-2015 at 09:32


For sure aga I am just limited by gears. I have a 96 tooth object gear and a 16 tooth drive gear, that's it. So 1.7 degree step wouldn't cut it for me. Could get me down to ~0.3* resolution though which isn't bad at all. Well with half-steps that 0.15* which is pretty good. If all else fails, I'll go that route, but I really think I can hone this in.

I'm excited to see your results.

Edit - I think I've found where the error is. It seems to be in counting the encoder counts for the drift of the motor. I am scheming something up...

[Edited on 5-6-2015 by smaerd]




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 5-6-2015 at 11:41


New film fitted, so now there's an actual disc of un-scratched film, and a static piece as well.

The results with no test tube in place are a bit random, due (i think) to the direct laser light saturating everything.

With an empty test tube i now get this on the arduino's TFT shield :-

Sine.JPG - 193kB

Edit:

I initially got 4 peaks, then realised that only 180* rotation really counts.

[Edited on 5-6-2015 by aga]




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 5-6-2015 at 12:54


it should be said that the graph is a plot of just 64 samples over the 180* rotation with the points interpolated.



View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 5-6-2015 at 12:57


aga you should only be getting 1 peak for 180* of rotation.

Looks good though, increase that resolution and smooth it out! Not sure how you got a negative value though.




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 5-6-2015 at 13:03


The graphing routines are pretty crude, so don't rely on them too much !

I just wanted a graph on the TFT shield so did it quick and dirty.

Decreasing the steps/sample will probably help.

Edit :

1 Peak ! Of course, if you start from the position where the light is fully blocked (blush)



[Edited on 5-6-2015 by aga]

[Edited on 6-6-2015 by aga]




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 6-6-2015 at 04:44


Been kicking this around a bit today, and came across a couple of references that seem to work, and easily (maths isn't my strong point).
http://stackoverflow.com/questions/26714410/partial-sine-dat...

The interesting bit starts with :-

float cog = 0f;

Using that method on a data set after taking a moving average seems to work well for this application, although i always end up with the calculated peak being x10, and can't see why.

Attachment: calcs1.xlsx (15kB)
This file has been downloaded 397 times

edit:

had to remove the code segment as the board html all goes potty.

[Edited on 6-6-2015 by aga]




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 6-6-2015 at 12:08


Nope.

The moving average works, but the other 'cog' thing doesn't seem to.

Edit :

any chance of some assistance smaerd ?

[Edited on 6-6-2015 by aga]




View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 6-6-2015 at 15:19


You're averaging looks pretty good.

What do you mean by moving cog? Can you explain with a bit more detail. I'll be happy to help if I can.




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 6-6-2015 at 22:36


Moving average smooths the data OK.

Calculating the best fit sine and then the peak is boggling the mind.

The 'cog' thing doesn't work - the idea is to regard it as a 'centre of gravity' task (ref: stackoverflow link above).

Edit:

Hold on. At 1024 steps per 180*, that's an accuracy of 0.176*

Isn't that close enough for an amateur built instrument ?

[Edited on 7-6-2015 by aga]




View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 7-6-2015 at 06:33


Yea aga if that's what you want then thats good enough for general purposes :). I just want at most 0.10* or ideally 0.05*.

Back to your center of gravity thing. I think that could work. Assume your sine function follows the general form of a sine function(Amplitude * Sin(inside terms) + Amplitude). What it requires is that there is only 1 peak or location above the offset or the + amplitude term. So you must carefully select half of the phase(90*) of the data in that way. Other-wise you're likely going to be finding the point of inflection between the peak and the valley.

I tried going through your excel sheet but I'm a little confused by it. I see some minor errors in the D6 & D7 cells (not the right formula?) and in the G7-G34 cells (no dividing by ten there?). Also why divide by ten, unless that's the moving average script inwhich case ignore this comment.

One way to find such a value would be to use your smoothed function. Find the set of points that are greater then the + amplitude term. Then implement the CoG algorithm there. I could be wrong but I think in this case you might have to add a subtraction term in the for next loop to account for any offset of those values. IE: if your peaks start at say 100 counts you might have to subtract 100 from the I * term so it would be (I-100) * samples. Also this script will not work if your peak shape is split meaning you have half a sine peak then the valley then the other half of the sine peak.

Why not try the zero crossing algorithm, it's really really easy! Here's the simple zero cross I wrote

Quote:

//First lets try to find the first UPWARDS zero crossing value
//Then use that to associate the phase of the data/interpolate a minima
public void findRisingZeroCross(double amplitude, int motorDrift){
int dataSize = recievedData.size();//store this to save some time
double tmpVal = 0.0, lstVal = (double) recievedData.get(0),
val = 0.0, one = 0.0, two = 0.0;
int zero = -1;
int i = 0, nullV = 0;
while(zero == -1){
tmpVal = (double) recievedData.get(i);
if(tmpVal > 100){
if(tmpVal > lstVal){//We are going upwards
//Did we JUST cross a threshold travelling upwards
if(tmpVal >= offset+amplitude && lstVal < offset+amplitude){
zero = i;
}
}
lstVal = tmpVal;
}
i++;
if(i==dataSize-1){zero = 10;System.out.println("No zero found");}
}
System.out.println("Zero: " + ((double)zero/(double)halfRotationPulseCount)*180.0);
}





View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 7-6-2015 at 07:47


Cheers smaerd.

I can see now why the data needs to be smooth and have no lumps !

The complexity of the maths required to fit even a smoothed dataset to a sine function, and then derive a maxima, is quite some way over my head.

The last FFT function i tried gave a graph that looked like a squiggle with legs on, so i'll stick with the moving average function for now.
(i don't understand Fourier Transforms at all).

Trying 1024 sample points didn't work - the repeatability was way out (+/- 12*) presumably because of noise in the system.




View user's profile View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 7-6-2015 at 08:23


Aga, I think we're at roughly the same spot right now. If you need some code for finding peaks let me know. Personally the zero crossing algorithm is my new favorite because you don't even need a maximum you just need to find the same "spot" which in the algo I gave you is the left wall of the rising sine wave.

FFT - Basically this turns time domain values into frequency domain values. So say you have 1 sine wave and it's oscillating at 50 hertz. After a FFT you will see one peak at 50Hz rather then a wave form. So high frequency values/ripples in data are easily separated from low frequency(the signal we want).

The current issue is repeatability but you have a definite advantage right now. Your stepper is pretty much rock solid (chances of missing a step with a decent driver is incredibly low). My DC motor encoder approach might actually be impossible via arduino. I'm not 100% sure yet, but I'm edging towards 80%. I just spent ~2 hours trying to nail down this motor drift error and it's um awful. There are maybe 8-9 variables going on bouncing between hard-ware, firmware and soft-ware.

I have to take a break and wait until I get this SPI RAM and if I can't make it work with that then it's the encoder. If it's the encoder I'm just going to buy a stepper and a stepper driver board. I can't afford another $40 on a bad motor-encoder bundle. But at this point I've tried every logical permutation I can fathom, and cannot do any more testing without an oscilloscope.

[Edited on 7-6-2015 by smaerd]




View user's profile View All Posts By User
aga
Forum Drunkard
*****




Posts: 7030
Registered: 25-3-2014
Member Is Offline


[*] posted on 7-6-2015 at 10:25


Thanks for the explanation of FFT - i get it now !

Oh i can put the stepper anywhere i want, just that after doing so, it detects the peak anywhere in a window of about 22* !

Pretty sure my 'design' is totally flawed at this point, with light getting in everywhere, the test tube skewing the laser out of alignment, unknown path length etc etc.

If you're on arduino, as i am, then you have to remember that it's got other interrupts going off in the background (time keeping for example) so you're not guaranteed to get your interrupt from the encoder wheel when you expect it, and could even have a few masked out without you knowing.

Offer still stands re a stepper motor & driver - just U2U the address.




View user's profile View All Posts By User
 Pages:  1  ..  6    8  

  Go To Top