I’ve done some experimenting in order to determine why I can’t get stable numbers with it sitting on a table while I simulate high RPM (120 RPM +/- 40). 60 – 90 RPM seem acceptably stable at 0 watts, but at 200 RPM it could erroneously read high, up to 26 watts I’ve seen. 26 watts error is flat out unacceptable!
So I’m back to basics. Read out the samples as fast as the fake serial port can allow and I come up with a few graphs. So what I am doing is summing up so many samples and then dividing them by the count, so averaging out over so many samples. This will be referred to as Samples/Report.
At 2000 samples/report things look very good! Less than 1 bit of appreciable noise getting though this crude filtering technique. But things quickly go bleak.
At 200 samples/report we have about 3 LSB of noise almost. My 16bit ADC is now barely a 13 bit ADC.
At 20 samples / report things just get very very very bad. We are at 4 – 5 LSB of noise! This means I’m down to MCP3201 territory with 11-12 bit.
This wouldn’t be so bad, but with so much time spent doing floating point math, at 160 RPM the code is struggling to make 200 samples before it has to update the calculations. This is skewed because I’m slowing it down a lot by sending data over USB. However it’s much slower than I can actually read out. Keep in mind that this is reading two sets of data.
So what is the problem? It’s now ratiometric so it should be more tolerant of voltage fluctuations. I’ve tested to see if I am causing any spikes in voltage due to magnets passing over it, that’s proven to not be a problem. I think it’s one of two things, the voltage regulator isn’t great causing some additional noise, or a higher quality ADC with more bits is needed.
Let’s look at one of the other problems mentioned, time calculating versus time reading. I’ve had the serial output tell me the running time before the zeroL and before and after zeroR. This is seen below.
Speed | Time (Absolute) | ||
Start | Zero L | Zero R | |
4mhz | 8017 | 8914 | 9699 |
2mhz | 8019 | 9037 | 9943 |
1mhz | 8017 | 9277 | 10424 |
Speed | Time (relative) | Time Reading | Time Calculating | |||
Zero L | Zero R | Zero L | Zero R | |||
4mhz | 897 | 785 | 121 | 776 | 664 | |
2mhz | 1018 | 906 | 242 | 776 | 664 | |
1mhz | 1260 | 1147 | 484 | 776 | 663 |
At 2 Mhz I’m spending 3 times as long to calculate as I am to read! So what is my code! Below is the zero command. I am summing to a “Long” from a short and then after 20000 reads it averages it out.
short zeroadcL() { long adcl = 0; //initialize a long variable for (int i=0; i < 20000; i++){adcl += long(readadcL());} // Serial.print(adcl); // Serial.print(","); // Serial.println(i);} //Read 1000 times return (short((adcl/20000))); //Output the average }
I think this is a limitation of two things 8 bit and 8 Mhz microcontrollers. However, it puts me back on another issue; I need the microcontroller to spend more time sleeping. If I have to bump to 16Mhz on an 8 bit AVR type chip then I might as well hold off until I can move to the nRF51 which is 32bit and shouldn’t require so many commands to sum.
A lot to think about.
No comments:
Post a Comment