In my case, I am creating a controller to make a rotor turn at ~ 300rad/s which is approximately 50rev/s or 1 rev per 20ms.
For my control system it was desirable to have a high resolution reading, and a fast reading rate. Using an interval of one revolution I got a fast reading rate, but a low resolution. With a rolling average over 10 laps I got the same reading rate, but with a higher resolution.
The same reasoning applies to why I didn't use the fixed time interval; If I used a small time interval I would get a fast reading rate, low resolution. If I used a long time interval I would get a slow reading rate but high resolution.
Well, thanks for your work. It's been very helpful to me. I adapted the code to use a rolling average over 10 cycles to increase the speed reading frequency, but like the initial code, this has the problem of given a speed reading which is on average 5 cycles old.
Now i've switched to reading the microseconds taken for just 1 cycle for a good resolution, high frequency and low delay.
Rolling average:
Code:
void speedcalc() { if (revcount > 0) { time = (lap0-lap10); //(ms) w = 20000*pi/time; //Calculating rad/sec by number of revolutions in a time sample Serial.print(millis(),DEC); Serial.print(","); Serial.println(w,DEC); revcount = 0; //Reset rev count } }
Thanks for the suggestions. The speed code appears to work with no hiccups now that the calculations code have been placed in the loop rather than the interrupt.
Code:
//AOA sweep //David Browne
//Arduino nano pwm ports // 3,5,6,9,10,11
#include <Servo.h> #include "math.h"
Servo rear; // create servo object to control a servo Servo right; Servo left; Servo esc;
int aoa = 0; // variable to store the aoa int angleright; int angleleft; int anglerear;
if (revcount>= 10) { //Update RPM every 20 counts, increase this for better RPM resolution, decrease for faster update w = 2000*pi*(revcount/nomags)/(millis() - timeold); //Calculating rad/sec by number of revolutions in a time sample timeold = millis(); //Reset timeold for revcount = 0 revcount = 0; //Reset rev count Serial.print("Speed = "); Serial.print(w,DEC); //Print most recent speed value to serial Serial.println(" RAD/s"); }
if (revcount>= 10) { //Update RPM every 20 counts, increase this for better RPM resolution, decrease for faster update w = 2000*pi*(revcount/nomags)/(millis() - timeold); //Calculating rad/sec by number of revolutions in a time sample timeold = millis(); //Reset timeold for revcount = 0 revcount = 0; //Reset rev count Serial.print("Speed = "); Serial.print(w,DEC); //Print most recent speed value to serial Serial.println(" RAD/s"); }
volatile byte revcount; unsigned int w; unsigned long timeold; unsigned int nomags; float pi;
Servo ESC; //Creates servo object int pos; //ESC throttle position (0-180)
void setup(){ Serial.begin(9600);
//Some ESC initialization - temperemental but seems to work ESC.attach(9); //Attach esc to pin 9 as a "servo" pos = 150; ESC.write(pos); delay(5000); pos = 50; ESC.write(pos);
attachInterrupt(0, rev_fun, RISING); //Run rev_fun every time the hall switch rises from low to high (interupt 0 = pin 2)
revcount = 0; pi = 3.14; timeold = 0; //Initial time value nomags = 1; //Number of magnets around circumference }
void loop() { for(pos = 50; pos < 150; pos += 1) // goes from 0 degrees to 180 degrees { // in steps of 1 degree ESC.write(pos); // tell servo to go to position in variable 'pos delay(1500); // waits 15ms for the servo to reach the position } for(pos = 150; pos>=50; pos-=1) // goes from 180 degrees to 0 degrees { ESC.write(pos); // tell servo to go to position in variable 'pos' delay(1500); // waits 15ms for the servo to reach the position } }
void rev_fun() { revcount++; //Increase revolution count by 1 //Serial.println("blip");
if (revcount>= 10) { //Update RPM every 20 counts, increase this for better RPM resolution, decrease for faster update w = 2000*pi*(revcount/nomags)/(millis() - timeold); //Calculating rad/sec by number of revolutions in a time sample timeold = millis(); //Reset timeold for revcount = 0 revcount = 0; //Reset rev count Serial.print("Speed = "); Serial.print(w,DEC); //Print most recent speed value to serial Serial.println(" RAD/s"); } }
If you watch the video, you can see and hear that occasionally the motor will decelerate. I believe this is because the signal to the ESC is not being sent due to the interrupt function. I'm welcome to any other suggestions to what might be happening though.
Unmanned Air System, although I do like the starship abbreviation.
Sorted out the servo control now. I have attempted to sync the rear, front and left servo so that they all raise the swashplate by the same amount throughout a sweep.
My intention is to initially mount the helicopter onto the end of a cantilever, therefore restricting it to 1 degree of freedom. The helicopter will then be able to stabilize itself against any disturbances to cantilever angle as well as navigate itself to user defined cantilever angles with high precision.
There are 2 control systems used; 1 to govern the speed of the motor, 1 to control the angle of attack of the blades through the swash-plate servo motors. I plan to maintain a constant speed by varying the voltage to the motor and control the lift through the blade angle of attack. I have already designed the control laws for both of these systems. I am now in the process of implementing what I have designed into the hardware.
My most recent progress was building a speed sensor to monitor the speed of the blades. This was achieved using a similar method to the demo code found here; http://www.arduino.cc/playground/Main/ReadingRPM. I am having some problems due to the interrupt technique that it uses. I plan to fix this by changing the code to use an alternative technique yet to be decided! The video below demonstrates the sensor in operation.
Thank you for the advice. Could you please clarify what 'network' you are referring to when you suggest I need to match them? What about the LMP2021 makes it suitable to my application?
I am currently trying to interface a MR rotation sensor to my arduino.
The sensor has 2 analog outputs of 2.5V+/- 0.1V. That is to say; if one output is 2.6V, the other is 2.4V.
I would like to take this output and manipulate it using an omp amp so that it is roughly in the range of 0-5V for use in the arduino's ADC.
I have been experimenting with a range of set ups and checking the results with a multimeter. Without the op amp plugged in, I have verified the sensor behaves as expected.
If I set up the opamp to provide an expected amplification of 10X, and plug in the sensor, the sensor output drops to 0.7V and the opamp output is 4.0V. However, at the point, the sensor does not seem to operate, as the output does not change in the presence of a magnetic field.
I believe my problem might be the Vcc and grounding I have used. Currently I have linked the 5V output and GND of the arduino to a breadboard, and linked all the required voltage inputs (from sensor and opamp) to this. Can anyone else suggest the problem and how to solve it?
I am using the HMC1512 which has the larger angular range. Does the diagram below indicate that the sensor contains the circuit or that I should wire up the chip legs into the circuit shown? If the latter, where do I input power and output a signal?
In case any one stumbles upon this thread looking for a solution themselves, the problem was that the sensor required a resistor to be placed between the Vin and Vcc ports. With this in place, the sensor is functional.
Thankyou for your help anyway. With regards to your edit I already thought to try a different LED output pin, and the same results occur.
I guess I'll wait and see if Jd.steinberger has anything to suggest if he had a similar problem.
If there is no resolve, I still have reason to suspect I may of been sent an incorrect sensor model and I may return it. If you still have yours available could you let me know what markings it had on it?