Go Down

Topic: POV LED-ARDUINO UNO-HELP (Read 1 time) previous topic - next topic

Naruto128

hello, I'm trying to make a POV (Persistence Of Vision), for my bike, I'm painting a circle, and works well with constant speeds.
the problem is that when the velocity is decreasing, or stopped pedaling
the circle is not closed, is there any way to solve this?

thank you!


Code: [Select]

volatile unsigned long timeold;
volatile unsigned long new_time = 0;
volatile unsigned long refreshEnd = 0;
volatile  unsigned long Refresh = 0;
volatile unsigned long milliperrevolution = 0;


volatile unsigned long revolutions=0;
volatile boolean interruptHit = false;
void setup() {
  Serial.begin(9600);
pinMode(2, INPUT); //
  attachInterrupt(0, rpm, FALLING);//    attachInterrupt(0, rpm, FALLING) pin 2 Arduino----     : hall sensor
pinMode(13, OUTPUT);     
digitalWrite(13, 0);   // set the LED off

}
int c=0;
void loop() {
 
  if( interruptHit ==true){
                   interruptHit =false;

      digitalWrite(13, HIGH);   // set the LED
    new_time = millis();
    refreshEnd=new_time;
   
   
    while((millis() - refreshEnd)<= (Refresh  ) ) {;}
 
  }else{
        digitalWrite(13, LOW);   // set the LED

 
  } 

}


void rpm(){
revolutions++;
interruptHit=true;

if (revolutions == 2)                                     // RPM gets updated for every two complete rotations
    {
     new_time=millis();
      milliperrevolution = (( new_time - timeold)/2);
     
      timeold =  new_time;
     revolutions = 0;
      Refresh = milliperrevolution/1;  //number the  slice
    }


}

johnwasser

Averaging duration two revolutions will only help if the speed is constant.  If you are speeding up the average duration will be too high and if you are slowing down the average duration will be too low.  Try using just one revolution and using microseconds for measurement to get more accuracy.

Code: [Select]

volatile unsigned long microsecondsPerRevolution = 0;
volatile boolean interruptHit = false;

void setup() {
 pinMode(2, INPUT); //
 attachInterrupt(0, rpm, FALLING);  // hall sensor

 pinMode(13, OUTPUT);    
 digitalWrite(13, LOW);   // set the LED off
}

void loop() {
 static unsigned long start_time;

 if (interruptHit) {
   digitalWrite(13, HIGH);   // LED on
   start_time = micros();
   interruptHit = false;
 }

 unsigned long mpr;

 // Copy the microsecondsPerRevolution value with interrupts disabled, otherwise we might be
 // half way through copying the value and the ISR will change it!
 noInterrupts();
 mpr = microsecondsPerRevolution;
 interrupts();

 if(micros() - start_time > mpr)
   digitalWrite(13, LOW);   // LED off
}


void rpm() {
 static unsigned long old_time;
 unsigned long new_time = micros();

 microsecondsPerRevolution = new_time - old_time;

 interruptHit = true;
 old_time =  new_time;
}
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Naruto128


Averaging duration two revolutions will only help if the speed is constant.  If you are speeding up the average duration will be too high and if you are slowing down the average duration will be too low.  Try using just one revolution and using microseconds for measurement to get more accuracy.

Code: [Select]

volatile unsigned long microsecondsPerRevolution = 0;
volatile boolean interruptHit = false;

void setup() {
 pinMode(2, INPUT); //
 attachInterrupt(0, rpm, FALLING);  // hall sensor

 pinMode(13, OUTPUT);    
 digitalWrite(13, LOW);   // set the LED off
}

void loop() {
 static unsigned long start_time;

 if (interruptHit) {
   digitalWrite(13, HIGH);   // LED on
   start_time = micros();
   interruptHit = false;
 }

 unsigned long mpr;

 // Copy the microsecondsPerRevolution value with interrupts disabled, otherwise we might be
 // half way through copying the value and the ISR will change it!
 noInterrupts();
 mpr = microsecondsPerRevolution;
 interrupts();

 if(micros() - start_time > mpr)
   digitalWrite(13, LOW);   // LED off
}


void rpm() {
 static unsigned long old_time;
 unsigned long new_time = micros();

 microsecondsPerRevolution = new_time - old_time;

 interruptHit = true;
 old_time =  new_time;
}



hello, thanks for your help ........... but
the problem remains the same  =(
I tried to take a picture but I have 4 hands-


johnwasser

You can't use the time of the previous revolution as the length of the current revolution if the speed is changing.  You might get closer if you track the difference between the last two revolutions and add that to the previous revolution:
Code: [Select]

volatile unsigned long microsecondsPerRevolution = 0;
volatile boolean interruptHit = false;

void setup() {
  pinMode(2, INPUT); //
  attachInterrupt(0, rpm, FALLING);  // hall sensor

  pinMode(13, OUTPUT);     
  digitalWrite(13, LOW);   // set the LED off
}

void loop() {
  static unsigned long start_time;

  if (interruptHit) {
    digitalWrite(13, HIGH);   // LED on
    start_time = micros();
    interruptHit = false;
  }

  unsigned long mpr;

  // Copy the microsecondsPerRevolution value with interrupts disabled, otherwise we might be
  // half way through copying the value and the ISR will change it!
  noInterrupts();
  mpr = microsecondsPerRevolution;
  interrupts();

  if(micros() - start_time > mpr)
    digitalWrite(13, LOW);   // LED off
}

void rpm() {
  static unsigned long old_time;
  unsigned long new_time = micros();
  static unsigned long lastMPR = microsecondsPerRevolution;
  microsecondsPerRevolution = new_time - old_time;
  long deltaMPR = microsecondsPerRevolution - lastMPR;
 
  // Adjust the current microsecond count to better anticipate the
  // time for the NEXT revolution.
  microsecondsPerRevolution += deltaMPR;

  interruptHit = true;
  old_time =  new_time;
}
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Naruto128


You can't use the time of the previous revolution as the length of the current revolution if the speed is changing.  You might get closer if you track the difference between the last two revolutions and add that to the previous revolution:
Code: [Select]

volatile unsigned long microsecondsPerRevolution = 0;
volatile boolean interruptHit = false;

void setup() {
  pinMode(2, INPUT); //
  attachInterrupt(0, rpm, FALLING);  // hall sensor

  pinMode(13, OUTPUT);     
  digitalWrite(13, LOW);   // set the LED off
}

void loop() {
  static unsigned long start_time;

  if (interruptHit) {
    digitalWrite(13, HIGH);   // LED on
    start_time = micros();
    interruptHit = false;
  }

  unsigned long mpr;

  // Copy the microsecondsPerRevolution value with interrupts disabled, otherwise we might be
  // half way through copying the value and the ISR will change it!
  noInterrupts();
  mpr = microsecondsPerRevolution;
  interrupts();

  if(micros() - start_time > mpr)
    digitalWrite(13, LOW);   // LED off
}

void rpm() {
  static unsigned long old_time;
  unsigned long new_time = micros();
  static unsigned long lastMPR = microsecondsPerRevolution;
  microsecondsPerRevolution = new_time - old_time;
  long deltaMPR = microsecondsPerRevolution - lastMPR;
 
  // Adjust the current microsecond count to better anticipate the
  // time for the NEXT revolution.
  microsecondsPerRevolution += deltaMPR;

  interruptHit = true;
  old_time =  new_time;
}





hello, I have bad news, does not work.
This exceeded the time code, ie removing an time for two laps, because if I divide by 2. mpr = (microsecondsPerRevolution / 2);
should only paint half a circle, and it is not, paints almost full circle, I mean is the same effect, an open circle.

johnwasser greetings, sorry for the inconvenience.


PaulS

Quote
any ideas?

Just the obvious ones - post your current code and a description of the (current) problem(s).

Naruto128


Quote
any ideas?

Just the obvious ones - post your current code and a description of the (current) problem(s).


obvious what is already published

GoForSmoke

Add a gyro and know the speed 100 to 1000x a second.
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Naruto128


Add a gyro and know the speed 100 to 1000x a second.



Add a gyro and know the speed 100 to 1000x to second.

LOl, as I do that?, I have a gyroscope out of a WII

GoForSmoke

Solid state gyro modules weigh far less and have much lower power requirements. An accelerometer turning in the vertical will be affected by gravity but a gyro may give only angular change which on a turning bicycle wheel can translate directly to movement speed.

Imagine trying to put your ancient gyro into a cellphone or tablet where the solid state gyro goes mostly unnoticed?

http://www.ebay.com/itm/MPU-6050-Triple-Axis-Accelerometer-Gyro-Breakout-Module-/251132720300?pt=LH_DefaultDomain_0&hash=item3a78ad34ac

Be sure to check the buy more and save prices, 3 for $10.04 ea, etc, does add to shipping.
http://dx.com/p/gy-50-l3g4200d-3-axis-digital-gyro-sensor-module-for-arduino-148731

I have bought direct from factory here and gotten lower prices but since I asked them and got a quote that is the price I get (less than $10) and you have to ask for your own. Caveat, there is a small, probably subsidized, shipping charge so I don't order just one thing at a time.
So far my only problem module from there has been the VS1053 MP3 module that came set up for voice recognition. Badji here was able to do the fix, a credit to his soldering skill.
I have not tackled the gyro-accelerometer yet as wrapping up an MP3 module has consumed most of my gumption (frustration will do that, especially in old people) for quite a while.

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Naruto128


Solid state gyro modules weigh far less and have much lower power requirements. An accelerometer turning in the vertical will be affected by gravity but a gyro may give only angular change which on a turning bicycle wheel can translate directly to movement speed.

Imagine trying to put your ancient gyro into a cellphone or tablet where the solid state gyro goes mostly unnoticed?

http://www.ebay.com/itm/MPU-6050-Triple-Axis-Accelerometer-Gyro-Breakout-Module-/251132720300?pt=LH_DefaultDomain_0&hash=item3a78ad34ac

Be sure to check the buy more and save prices, 3 for $10.04 ea, etc, does add to shipping.
http://dx.com/p/gy-50-l3g4200d-3-axis-digital-gyro-sensor-module-for-arduino-148731

I have bought direct from factory here and gotten lower prices but since I asked them and got a quote that is the price I get (less than $10) and you have to ask for your own. Caveat, there is a small, probably subsidized, shipping charge so I don't order just one thing at a time.
So far my only problem module from there has been the VS1053 MP3 module that came set up for voice recognition. Badji here was able to do the fix, a credit to his soldering skill.
I have not tackled the gyro-accelerometer yet as wrapping up an MP3 module has consumed most of my gumption (frustration will do that, especially in old people) for quite a while.




as what you could adapt meciona to my project?

GoForSmoke

Your avr and leds are to be held on the spokes? A gyro with them should tell the rate of turn.

It will be a project in itself to get that working but the capability is there.

You could put a magnet on a frame stay or fork (the parts that hold the wheels) and a Hall sensor or reed switch to read that but then you only have data from a full turn of the wheel which is only good at constant speed. The gyro should read fast enough for many times in a turn of the wheel.

Sorry but I am only good with English and was never more than a beginner en Francais. I think that meciona is Italian for something to do with machines but that is just a guess. If you had written machina then I would guess Spanish but with either language I am useless.
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Naruto128

#13
Aug 21, 2013, 12:37 am Last Edit: Aug 21, 2013, 01:06 am by Naruto128 Reason: 1

Your avr and leds are to be held on the spokes? A gyro with them should tell the rate of turn.

It will be a project in itself to get that working but the capability is there.

You could put a magnet on a frame stay or fork (the parts that hold the wheels) and a Hall sensor or reed switch to read that but then you only have data from a full turn of the wheel which is only good at constant speed. The gyro should read fast enough for many times in a turn of the wheel.

Sorry but I am only good with English and was never more than a beginner en Francais. I think that meciona is Italian for something to do with machines but that is just a guess. If you had written machina then I would guess Spanish but with either language I am useless.



I want to draw a circle, but this is always open.
after this time will be used to divide into smaller parts,
  to
draw something more complex

i speak spanish.

I've seen numbers Povisa project bike, which only uses the hall sensor for constant and variable speeds. what he says can be a bit tricky to implement my project gyroscope.

someone who helps to make the time for variable speeds.


Code: [Select]

volatile unsigned long microsecondsPerRevolution = 0;
volatile boolean interruptHit = false;

void setup() {
 pinMode(2, INPUT); //
 attachInterrupt(0, rpm, FALLING);  // hall sensor

 pinMode(13, OUTPUT);    
 digitalWrite(13, LOW);   // set the LED off
}

void loop() {
 static unsigned long start_time;

 if (interruptHit) {
   digitalWrite(13, HIGH);   // LED on
   start_time = micros();
   interruptHit = false;
 }

 unsigned long mpr;

 // Copy the microsecondsPerRevolution value with interrupts disabled, otherwise we might be
 // half way through copying the value and the ISR will change it!
 noInterrupts();
 mpr = microsecondsPerRevolution;
 interrupts();

 if(micros() - start_time > mpr)
   digitalWrite(13, LOW);   // LED off
}


void rpm() {
 static unsigned long old_time;
 unsigned long new_time = micros();

 microsecondsPerRevolution = new_time - old_time;

 interruptHit = true;
 old_time =  new_time;
}


rbqaa

How many "slices" of your image are you trying to display per revolution?  As in how many times are you turning on and off your LED's per revolution?
I have a suggestion.  Calculate how long the last revolution took, in microseconds. 

Each revolution:
An interrupt will be triggered.
When your interrupt triggers calculate how long it took for the previous revolution.  Divide the time it took for the previous revolution by the number of "slices" you are trying to display.  This will be your delay time in between slices.  Almost done.  You also need to know how long it takes for your processor and LED drivers to push the data out and latch per "slice."  This will have to be benchmarked on its own.  My suggestion is to take your image and have it just push out the entire image with no pausing and time how long it takes for the entire image to cycle through.  You dont have to spin the wheel for this, just have it output the time in microseconds to the terminal.  I would do at least ten attempts at this and record each time.  Divide that time by the number of "slices" and you should have a "decent" knowledge of how long each slice takes to push out to the LEDs and latch.  So now you know how long each "slice" will take to display, and how long to pause before displaying the next "slice."

From here it will take some fiddling with to get the timing right, but you should be a closer than you were before.  Granted sudden accelerations in either direction will cause the image to rotate a little, but this should at least eliminate the variable gap in the image. 

Do you have any drawings of how you are "slicing" up your images?  How are you creating the data for the images? 

Does that make sense?

RBQAA

Go Up