hi guys, im working on a project for a bike pov. I use a hall effect sensor to measure the time between 2 cycles of my wheel but the interrupts only works a few times at low speed. Does sombody know how to fix this?
#include "FastLED.h" //FastLED library
#include <avr/pgmspace.h>
#define noRings 36
#define noSectors 72
CRGB Leds_N[noRings]; //each Ledstrip has it's own array for the colour values
CRGB Leds_O[noRings];
CRGB Leds_Z[noRings];
CRGB Leds_W[noRings];
int N;
int O;
int Z;
int W;
long ColorValues[noSectors][noRings]PROGMEM ={};
// we declare these as volatile so they can be modified outside the setup()/loop() functions
volatile long lastTimer = 0;
volatile long wheelTimer = 1;
volatile int abortSignal = 0;
void setup() {
FastLED.addLeds<NEOPIXEL, 5>(Leds_N, 0, noRings); //the different arrays are declared to there output port
FastLED.addLeds<NEOPIXEL, 6>(Leds_O, 0, noRings);
FastLED.addLeds<NEOPIXEL, 9>(Leds_Z, 0, noRings);
FastLED.addLeds<NEOPIXEL, 10>(Leds_W, 0, noRings);
attachInterrupt(0, magnetHit, RISING); //creates an interrupt each time the hall-sensor passes the magnet
}
void loop()
{
}
void magnetHit() // this funciton is called when the magnet is hit. update the amount of time for each loop
{
wheelTimer = millis() - lastTimer;
lastTimer = millis();
Wheel();//calls out to the Wheel function
}
void Wheel()
{
for (int y =0; y <= noSectors ; y++)// refreshes every quarter of the turn with the correct function
{
N=0;
O=noSectors*3/4;
Z=noSectors*1/2;
W=noSectors*1/4;
Firstquarter(y);
FastLED.show(); //sends out the arrays to the neopixels
delay(wheelTimer / noSectors); //a delay thats waits each quarter of the turn
}
}
void Firstquarter(int y)//the first scenario the wheel is in
{
N+=y;
O+=y;
Z+=y;
W+=y;
if(O>=noSectors)
{O-=72;}
if(Z>=noSectors)
{Z-=72;}
if(W>=noSectors)
{W-=72;}
for( int i=0; i < noRings; i++)
{
Leds_N[i] = pgm_read_dword_near(&ColorValues[N][i]);
Leds_O[i] = pgm_read_dword_near(&ColorValues[O][i]);
Leds_Z[i] = pgm_read_dword_near(&ColorValues[Z][i]);
Leds_W[i] = pgm_read_dword_near(&ColorValues[W][i]);
}
}
Your ISR (Interrupt Service Routine) - magnetHit() - is very time consuming. You want to spend as least amount of time in the ISR as possible. In fact, your ISR may take so long, that you might get a hit from the magnet while you are still in the ISR!!
This will cause you to "interrupt the interrupt" and will just keep beginning new instances of magnetHit() inside itself and will never be able to get anything done.
Solution: only call wheel() in the main loop() function. For instance:
void loop()
{
Wheel();
}
void magnetHit() // this funciton is called when the magnet is hit. update the amount of time for each loop
{
wheelTimer = millis() - lastTimer;
lastTimer = millis();
}
Thanks a lot
. But now i have another problem. The function wheel also made sure that the picture didn't rotate with the wheel and now it does...
Schellie:
The function wheel also made sure that the picture didn't rotate with the wheel and now it does...
What does that mean? I'm not familiar with what the project is supposed to do.
Power_Broker:
What does that mean? I'm not familiar with what the project is supposed to do.
I need to make a spokePOV. A picture is converted to hex color values and stored in ColorValues[], then i need to recreate the picture in my bicycle wheel at any speed. I use the hall sensor as a reference for the top of the picture(thanks for the help and sorry for the bad english).
void Wheel()
{
for (int y =0; y <= noSectors ; y++)// refreshes every quarter of the turn with the correct function
{
N=0;
O=noSectors*3/4;
Z=noSectors*1/2;
W=noSectors*1/4;
Firstquarter(y);
FastLED.show(); //sends out the arrays to the neopixels
delay(wheelTimer / noSectors); //a delay thats waits each quarter of the turn
}
}
This is not correct, and can not possibly stay in sync with the wheel.
delay(wheelTimer / noSectors); //a delay thats waits each quarter of the turn
The comment is not correct.
The for loop in Wheel() iterates over noSectors , which has been set to 72, and you call a delay each time equal to the time of a revolution divided by noSectors. The sum total of delays add up to the time of a complete revolution. Firstquarter(y); and FastLED.show(); must take some time.
By the time everything else happens in your program the interrupt has fired again and the loop will call wheel() again sometime after the magnet crossing and you get out of sync.
Do want to fire the leds only 4 times per rotation or 72? In either case, using delay(wheelTimer/xx) does not seem correct.
delay() will not increment within an ISR, so that's one possible reason the earlier version failed.
I need to fire 4 ledsstrips 72 times. But thats the only possible way i know to program this. I can use the timer in Micros() and a delayMicroseonds() for better results but i cant get it synced. If you know how to do that please tell me