I'm making a POV display (4 spokes) on a bike wheel using a Hall effect sensor to measure how long the last revolution took and based on that I calculate delays in the display. By pedalling at a constant rate I should get roughly a nice image but all I got is an unsynchronized mess. It seems like it is going and image is stable but after around half of a turn it scrambles.
I divided the wheel into 32 even parts which uses the same LED colour. Any advice how to achieve full synchronization. Any thoughts?
Here is my code:
#include "Adafruit_WS2801.h"
#include "SPI.h"
#ifdef __AVR_ATtiny85__
#include <avr/power.h>
#endif
#include <time.h>
#include <stdlib.h>
#define MIN_TIME 150000
#define MAX_TIME 1000000
#define RADIUS 240
#define MAGNETS_NUM 1
uint8_t shwFg = 1;
uint8_t dataPin1 = 2; // White wire on Adafruit Pixels
uint8_t dataPin2 = 3; // Yellow wire on Adafruit Pixels
uint8_t dataPin3 = 4; // Yellow wire on Adafruit Pixels
uint8_t dataPin4 = 5; // Yellow wire on Adafruit Pixels
uint8_t clockPin1 = 10; // White wire on Adafruit Pixels
uint8_t clockPin2 = 11; // Green wire on Adafruit Pixels
uint8_t clockPin3 = 12; // Green wire on Adafruit Pixels
uint8_t clockPin4 = 13; // Green wire on Adafruit Pixels
uint8_t hallPin = 20;
uint8_t pointer1 = 0;
uint8_t pointer2 = 8;
uint8_t pointer3 = 16;
uint8_t pointer4 = 24;
uint8_t LED1R[32] = {0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144, 1, 1, 1, 1, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144};
uint8_t LED2R[32] = {0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144, 1, 1, 1, 1, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144};
uint8_t LED3R[32] = {0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144, 1, 1, 1, 1, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144};
uint8_t LED4R[32] = {0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144, 1, 1, 1, 1, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144};
uint8_t LED5R[32] = {0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144, 1, 1, 1, 1, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144};
uint8_t LED6R[32] = {0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144, 1, 1, 1, 1, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144};
uint8_t LED7R[32] = {0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144, 1, 1, 1, 1, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144};
uint8_t LED8R[32] = {0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144, 1, 1, 1, 1, 128, 128, 128, 128, 0, 0, 0, 0, 144, 144, 144, 144};
uint8_t LED1B[32] = {128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1};
uint8_t LED2B[32] = {128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1};
uint8_t LED3B[32] = {128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1};
uint8_t LED4B[32] = {128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1};
uint8_t LED5B[32] = {128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1};
uint8_t LED6B[32] = {128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1};
uint8_t LED7B[32] = {128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1};
uint8_t LED8B[32] = {128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1, 128, 128, 128, 128, 1, 1, 1, 1};
uint8_t LED1G[32] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t LED2G[32] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t LED3G[32] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t LED4G[32] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t LED5G[32] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t LED6G[32] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t LED7G[32] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t LED8G[32] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
long now = 0;
long prev = 0;
int hallState = 0;
unsigned long previous = 0;
unsigned long dlyMic = 123456;
Adafruit_WS2801 strip = Adafruit_WS2801((uint16_t)8, dataPin1, clockPin1);
Adafruit_WS2801 strip2 = Adafruit_WS2801((uint16_t)8, dataPin2, clockPin2);
Adafruit_WS2801 strip3 = Adafruit_WS2801((uint16_t)8, dataPin3, clockPin3);
Adafruit_WS2801 strip4 = Adafruit_WS2801((uint16_t)8, dataPin4, clockPin4);
int a = 0;
unsigned long current = 0;
unsigned long delta = 0;
void GetDelay() {
previous = current;
current = micros();
}
void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
clock_prescale_set(clock_div_1); // Enable 16 MHz on Trinket
#endif
pinMode(hallPin, INPUT);
Serial.begin(115200);
strip.begin();
strip2.begin();
strip3.begin();
strip4.begin();
attachInterrupt(3, GetDelay, HIGH);
}
void delayMicroseconds2(unsigned int us) {
// calling avrlib's delay_us() function with low values (e.g. 1 or
// 2 microseconds) gives delays longer than desired.
//delay_us(us);
// for the 16 MHz clock on most Arduino boards
// for a one-microsecond delay, simply return. the overhead
// of the function call yields a delay of approximately 1 1/8 us.
if (--us == 0) return;
// the following loop takes a quarter of a microsecond (4 cycles)
// per iteration, so execute it four times for each microsecond of
// delay requested.
us <<= 2;
// account for the time taken in the preceeding commands.
us -= 2;
// busy wait
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" // 2 cycles
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
);
}
void loop() {
delta = current - previous;
delta<<5;
delta-=6800; //time required for loop
if (shwFg == 0) {
int i;
for (i = 0; i < 8; i++) {
strip.setPixelColor(i, 0, 0, 0);
strip2.setPixelColor(i, 0, 0, 0);
strip3.setPixelColor(i, 0, 0, 0);
strip4.setPixelColor(i, 0, 0, 0);
}
} else {
strip.setPixelColor(0, LED1R[pointer1] , (LED1B[pointer1] ) , (LED1G[pointer1] ) );
strip2.setPixelColor(0, LED1R[pointer2] , (LED1B[pointer2] ) , (LED1G[pointer2] ) );
strip3.setPixelColor(0, LED1R[pointer3] , (LED1B[pointer3] ) , (LED1G[pointer3] ) );
strip4.setPixelColor(0, LED1R[pointer4] , (LED1B[pointer4] ) , (LED1G[pointer4] ) );
strip.setPixelColor(1, LED2R[pointer1] , (LED2B[pointer1] ) , (LED2G[pointer1] ) );
strip2.setPixelColor(1, LED2R[pointer2] , (LED2B[pointer2] ) , (LED2G[pointer2] ) );
strip3.setPixelColor(1, LED2R[pointer3] , (LED2B[pointer3] ) , (LED2G[pointer3] ) );
strip4.setPixelColor(1, LED2R[pointer4] , (LED2B[pointer4] ) , (LED2G[pointer4] ) );
strip.setPixelColor(2, LED3R[pointer1] , (LED3B[pointer1] ) , (LED3G[pointer1] ) );
strip2.setPixelColor(2, LED3R[pointer2] , (LED3B[pointer2] ) , (LED3G[pointer2] ) );
strip3.setPixelColor(2, LED3R[pointer3] , (LED3B[pointer3] ) , (LED3G[pointer3] ) );
strip4.setPixelColor(2, LED3R[pointer4] , (LED3B[pointer4] ) , (LED3G[pointer4] ) );
strip.setPixelColor(3, LED4R[pointer1] , (LED4B[pointer1] ) , (LED4G[pointer1] ) );
strip2.setPixelColor(3, LED4R[pointer2] , (LED4B[pointer2] ) , (LED4G[pointer2] ) );
strip3.setPixelColor(3, LED4R[pointer3] , (LED4B[pointer3] ) , (LED4G[pointer3] ) );
strip4.setPixelColor(3, LED4R[pointer4] , (LED4B[pointer4] ) , (LED4G[pointer4] ) );
strip.setPixelColor(4, LED5R[pointer1] , (LED5B[pointer1] ) , (LED5G[pointer1] ) );
strip2.setPixelColor(4, LED5R[pointer2] , (LED5B[pointer2] ) , (LED5G[pointer2] ) );
strip3.setPixelColor(4, LED5R[pointer3] , (LED5B[pointer3] ) , (LED5G[pointer3] ) );
strip4.setPixelColor(4, LED5R[pointer4] , (LED5B[pointer4] ) , (LED5G[pointer4] ) );
strip.setPixelColor(5, LED6R[pointer1] , (LED6B[pointer1] ) , (LED6G[pointer1] ) );
strip2.setPixelColor(5, LED6R[pointer2] , (LED6B[pointer2] ) , (LED6G[pointer2] ) );
strip3.setPixelColor(5, LED6R[pointer3] , (LED6B[pointer3] ) , (LED6G[pointer3] ) );
strip4.setPixelColor(5, LED6R[pointer4] , (LED6B[pointer4] ) , (LED6G[pointer4] ) );
strip.setPixelColor(6, LED7R[pointer1] , (LED7B[pointer1] ) , (LED7G[pointer1] ) );
strip2.setPixelColor(6, LED7R[pointer2] , (LED7B[pointer2] ) , (LED7G[pointer2] ) );
strip3.setPixelColor(6, LED7R[pointer3] , (LED7B[pointer3] ) , (LED7G[pointer3] ) );
strip4.setPixelColor(6, LED7R[pointer4] , (LED7B[pointer4] ) , (LED7G[pointer4] ) );
strip.setPixelColor(7, LED8R[pointer1] , (LED8B[pointer1] ) , (LED8G[pointer1] ) );
strip2.setPixelColor(7, LED8R[pointer2] , (LED8B[pointer2] ) , (LED8G[pointer2] ) );
strip3.setPixelColor(7, LED8R[pointer3] , (LED8B[pointer3] ) , (LED8G[pointer3] ) );
strip4.setPixelColor(7, LED8R[pointer4] , (LED8B[pointer4] ) , (LED8G[pointer4] ) );
}
strip.show();
strip2.show();
strip3.show();
strip4.show();
pointer1++;
pointer1 &= 31;
pointer3++;
pointer3 &= 31;
pointer2++;
pointer2 &= 31;
pointer4++;
pointer4 &= 31;
delayMicroseconds2(delta);
}
Pardon me, it was late in the night and I put wrong code. Of course delay should depend on delta. Changed to newest code with less job in delay. Still yields similar results.
dlyMicShould be defined as "volatile". Your delays don't take into account that all the code inside the loop takes some time to ru Especially strip.show.