This program makes a sort of animation with the 4 led lights that resembles a wave motion. Because of my obsessive development, it is quite long and complicated, but very fun and educational for begginers (like I was a few days ago). Uses terminal program like putty for interaction.

Dependencies:   mbed

Committer:
emollison
Date:
Tue Sep 06 16:01:35 2011 +0000
Revision:
0:403b6acd3179

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emollison 0:403b6acd3179 1 /*
emollison 0:403b6acd3179 2 Programmer: Eric Mollison
emollison 0:403b6acd3179 3 Date: 9-6-2011
emollison 0:403b6acd3179 4 Hardware: only mbed
emollison 0:403b6acd3179 5 Description: "LED Wave" makes the 4 LEDs on the mbed shift in brightness
emollison 0:403b6acd3179 6 with PWM (pulse width modulation) so as to appear to move
emollison 0:403b6acd3179 7 smoothly to a side. LEDs are updated with a Ticker interrupt
emollison 0:403b6acd3179 8 so that most of the processor capacity can collect input from
emollison 0:403b6acd3179 9 a keyboard (if you installed the driver for the mbed
emollison 0:403b6acd3179 10 communicating with the pc). Optimized with precomputed values
emollison 0:403b6acd3179 11 so that each step takes ~14us.
emollison 0:403b6acd3179 12 Note:
emollison 0:403b6acd3179 13 To use interactively, look up:
emollison 0:403b6acd3179 14 http://mbed.org/handbook/SerialPC
emollison 0:403b6acd3179 15 to find where to install drivers and putty or another terminal program
emollison 0:403b6acd3179 16 Also note:
emollison 0:403b6acd3179 17 You don't need to declare:
emollison 0:403b6acd3179 18 "Serial pc(USBTX, USBRX);"
emollison 0:403b6acd3179 19 probably because the code is in the mbed.h to autoinitialize
emollison 0:403b6acd3179 20 i/o functions like printf, putc getc, etc. (so I guess)
emollison 0:403b6acd3179 21 */
emollison 0:403b6acd3179 22
emollison 0:403b6acd3179 23
emollison 0:403b6acd3179 24 #include "mbed.h"
emollison 0:403b6acd3179 25 #define PULSEWIDTH 18000 //time(us) for each pulse from the PWM
emollison 0:403b6acd3179 26 //flicker undetectable at pw <= 20000
emollison 0:403b6acd3179 27 //a pw too low will make too few brightness levels making another type of flicker
emollison 0:403b6acd3179 28 #define PI 3.1415926 //used to calculate sine from angle(radians): -PI/2 to PI/2
emollison 0:403b6acd3179 29
emollison 0:403b6acd3179 30 #define OSCIQUAR 500 //steps per quarter of a circle of angle
emollison 0:403b6acd3179 31 //5925 is max (wont work with too large of an array)
emollison 0:403b6acd3179 32 //11898 is max short array size that ever worked
emollison 0:403b6acd3179 33 //suspect malloc can do better
emollison 0:403b6acd3179 34 //can be smooth but fast at as low as 10
emollison 0:403b6acd3179 35
emollison 0:403b6acd3179 36 //OSCIQUAR * 2 = array size, and * 4 = steps or steps per cycle
emollison 0:403b6acd3179 37 #define STEPTIME 20000 //time(us) for each timed update or step of the lights
emollison 0:403b6acd3179 38 //no noticable flicker at 20ms step time
emollison 0:403b6acd3179 39 //13 us is the minimum (step takes >=13 microseconds)
emollison 0:403b6acd3179 40 //20 us is minimum to allow for keyboard input
emollison 0:403b6acd3179 41 //1 or 0 will freeze
emollison 0:403b6acd3179 42
emollison 0:403b6acd3179 43 #define LEDSTEP1(Num) { \
emollison 0:403b6acd3179 44 led##Num##.pulsewidth_us(getValFromCirc(OSCIQUAR,pwpt##Num##)); \
emollison 0:403b6acd3179 45 pwpt##Num##+=stepRate; \
emollison 0:403b6acd3179 46 if(pwpt##Num >= OSCIQUAR*4) pwpt##Num##-=OSCIQUAR*4; \
emollison 0:403b6acd3179 47 else if(pwpt##Num < 0) pwpt##Num##+=OSCIQUAR*4; \
emollison 0:403b6acd3179 48 }
emollison 0:403b6acd3179 49
emollison 0:403b6acd3179 50 #define DEBUGINT(Int) printf("%s = %d\n", #Int, Int);
emollison 0:403b6acd3179 51
emollison 0:403b6acd3179 52
emollison 0:403b6acd3179 53 //prototypes
emollison 0:403b6acd3179 54 void setpws(int qlen, int max);
emollison 0:403b6acd3179 55 void setpws_subt(int qlen, int max);
emollison 0:403b6acd3179 56 short getValFromCirc(int qlen, int cpt);
emollison 0:403b6acd3179 57 void step();
emollison 0:403b6acd3179 58
emollison 0:403b6acd3179 59 static int maxStepRate = OSCIQUAR*4*STEPTIME/1000000+1; //set so that cycles take at least 1 second
emollison 0:403b6acd3179 60 static int stepAccel = maxStepRate/50+1; //change in velocity with each keypress
emollison 0:403b6acd3179 61 static int stepRate = maxStepRate/10+1; //initial velocity of moving light
emollison 0:403b6acd3179 62
emollison 0:403b6acd3179 63
emollison 0:403b6acd3179 64 PwmOut led1(LED1); //pwmout sets up the leds for pulse width modulation
emollison 0:403b6acd3179 65 PwmOut led2(LED2);
emollison 0:403b6acd3179 66 PwmOut led3(LED3);
emollison 0:403b6acd3179 67 PwmOut led4(LED4);
emollison 0:403b6acd3179 68 Timer timer; //timer is for testing performance
emollison 0:403b6acd3179 69 Ticker t_step; //t_step controls the updates to brightness
emollison 0:403b6acd3179 70 static short *pwvals; //array of precomputed brightnesses
emollison 0:403b6acd3179 71 //used short instead of int to save ram
emollison 0:403b6acd3179 72
emollison 0:403b6acd3179 73 int main()
emollison 0:403b6acd3179 74 {
emollison 0:403b6acd3179 75
emollison 0:403b6acd3179 76 printf("\nInitializing LED wave program...\n");
emollison 0:403b6acd3179 77 pwvals = new short[OSCIQUAR*2];
emollison 0:403b6acd3179 78 timer.start(); //begin counting time
emollison 0:403b6acd3179 79 int begin, end;
emollison 0:403b6acd3179 80 led4=1;
emollison 0:403b6acd3179 81
emollison 0:403b6acd3179 82 begin = timer.read_us(); //find time to pre-compute
emollison 0:403b6acd3179 83 setpws_subt(OSCIQUAR, PULSEWIDTH);
emollison 0:403b6acd3179 84 end = timer.read_us();
emollison 0:403b6acd3179 85
emollison 0:403b6acd3179 86 printf("intializing array of %d takes %d us\n", OSCIQUAR*2, end - begin);
emollison 0:403b6acd3179 87
emollison 0:403b6acd3179 88 led1.period_us(PULSEWIDTH); //sets period for all leds on pwm
emollison 0:403b6acd3179 89
emollison 0:403b6acd3179 90 t_step.attach_us(&step, STEPTIME); //make ticker update LED
emollison 0:403b6acd3179 91 printf("Successfully started cycling LEDs\n");
emollison 0:403b6acd3179 92 printf("\nPush '=' or '+' to accelerate shift to the left.\n");
emollison 0:403b6acd3179 93 printf("Push '-' to accelerate right.\n");
emollison 0:403b6acd3179 94 printf("Push '0'(zero), 's' or 'S' to stop motion.\n\n");
emollison 0:403b6acd3179 95 while(1) //keyboard read loop
emollison 0:403b6acd3179 96 {
emollison 0:403b6acd3179 97 char c = getc(stdin);
emollison 0:403b6acd3179 98 if (c=='=' || c=='+')
emollison 0:403b6acd3179 99 {
emollison 0:403b6acd3179 100 if(stepRate<maxStepRate)
emollison 0:403b6acd3179 101 {
emollison 0:403b6acd3179 102 stepRate+=stepAccel;
emollison 0:403b6acd3179 103 if(stepRate>maxStepRate)stepRate=maxStepRate;
emollison 0:403b6acd3179 104 DEBUGINT(stepRate)
emollison 0:403b6acd3179 105 }
emollison 0:403b6acd3179 106 }
emollison 0:403b6acd3179 107 else if (c=='-')
emollison 0:403b6acd3179 108 {
emollison 0:403b6acd3179 109 if(stepRate>-maxStepRate)
emollison 0:403b6acd3179 110 {
emollison 0:403b6acd3179 111 stepRate-=stepAccel;
emollison 0:403b6acd3179 112 if(stepRate<-maxStepRate)stepRate=-maxStepRate;
emollison 0:403b6acd3179 113 DEBUGINT(stepRate)
emollison 0:403b6acd3179 114 }
emollison 0:403b6acd3179 115 }
emollison 0:403b6acd3179 116 else if (c=='s' || c=='S' || c=='0')
emollison 0:403b6acd3179 117 {
emollison 0:403b6acd3179 118 stepRate=0;
emollison 0:403b6acd3179 119 DEBUGINT(stepRate)
emollison 0:403b6acd3179 120 }
emollison 0:403b6acd3179 121 //wait_ms(10);
emollison 0:403b6acd3179 122
emollison 0:403b6acd3179 123 }//end keyboard read loop
emollison 0:403b6acd3179 124
emollison 0:403b6acd3179 125 }
emollison 0:403b6acd3179 126
emollison 0:403b6acd3179 127 /*
emollison 0:403b6acd3179 128 repeated function run by Ticker which updates the lights at regular intervals
emollison 0:403b6acd3179 129 so that they appear to smoothly shift with "anti-aliasing"
emollison 0:403b6acd3179 130 */
emollison 0:403b6acd3179 131 void step()
emollison 0:403b6acd3179 132 {
emollison 0:403b6acd3179 133 static int pwpt1=0, pwpt2=OSCIQUAR, pwpt3=OSCIQUAR*2, pwpt4=OSCIQUAR*3;
emollison 0:403b6acd3179 134 static int step_counter=0, time=0;
emollison 0:403b6acd3179 135 const int check_interval=1000; //if over 100M, may overflow time
emollison 0:403b6acd3179 136 if(++step_counter==check_interval)
emollison 0:403b6acd3179 137 {
emollison 0:403b6acd3179 138 printf("Time(us) to step = %8f\n", (float)time/check_interval);
emollison 0:403b6acd3179 139 step_counter=0;
emollison 0:403b6acd3179 140 time=0;
emollison 0:403b6acd3179 141 }
emollison 0:403b6acd3179 142 time-=timer.read_us();
emollison 0:403b6acd3179 143
emollison 0:403b6acd3179 144 //just showing how to shorten code with macros
emollison 0:403b6acd3179 145 #ifdef LEDSTEP
emollison 0:403b6acd3179 146 LEDSTEP(1)
emollison 0:403b6acd3179 147 LEDSTEP(2)
emollison 0:403b6acd3179 148 LEDSTEP(3)
emollison 0:403b6acd3179 149 LEDSTEP(4)
emollison 0:403b6acd3179 150 #else
emollison 0:403b6acd3179 151 led1.pulsewidth_us(getValFromCirc(OSCIQUAR,pwpt1));
emollison 0:403b6acd3179 152 led2.pulsewidth_us(getValFromCirc(OSCIQUAR,pwpt2));
emollison 0:403b6acd3179 153 led3.pulsewidth_us(getValFromCirc(OSCIQUAR,pwpt3));
emollison 0:403b6acd3179 154 led4.pulsewidth_us(getValFromCirc(OSCIQUAR,pwpt4));
emollison 0:403b6acd3179 155
emollison 0:403b6acd3179 156 pwpt1+=stepRate;
emollison 0:403b6acd3179 157 pwpt2+=stepRate;
emollison 0:403b6acd3179 158 pwpt3+=stepRate;
emollison 0:403b6acd3179 159 pwpt4+=stepRate;
emollison 0:403b6acd3179 160
emollison 0:403b6acd3179 161 if(pwpt1 >= OSCIQUAR*4) pwpt1-=OSCIQUAR*4;
emollison 0:403b6acd3179 162 else if(pwpt1 < 0) pwpt1+=OSCIQUAR*4;
emollison 0:403b6acd3179 163 if(pwpt2 >= OSCIQUAR*4) pwpt2-=OSCIQUAR*4;
emollison 0:403b6acd3179 164 else if(pwpt2 < 0) pwpt2+=OSCIQUAR*4;
emollison 0:403b6acd3179 165 if(pwpt3 >= OSCIQUAR*4) pwpt3-=OSCIQUAR*4;
emollison 0:403b6acd3179 166 else if(pwpt3 < 0) pwpt3+=OSCIQUAR*4;
emollison 0:403b6acd3179 167 if(pwpt4 >= OSCIQUAR*4) pwpt4-=OSCIQUAR*4;
emollison 0:403b6acd3179 168 else if(pwpt4 < 0) pwpt4+=OSCIQUAR*4;
emollison 0:403b6acd3179 169 #endif
emollison 0:403b6acd3179 170
emollison 0:403b6acd3179 171 time+=timer.read_us();
emollison 0:403b6acd3179 172
emollison 0:403b6acd3179 173 }
emollison 0:403b6acd3179 174
emollison 0:403b6acd3179 175 /*
emollison 0:403b6acd3179 176 initializes the array of pre-computed values for light intensity
emollison 0:403b6acd3179 177 applied by the PWM such that lights turn completely off for an instant
emollison 0:403b6acd3179 178 */
emollison 0:403b6acd3179 179 void setpws_subt(int qlen, int max)
emollison 0:403b6acd3179 180 {
emollison 0:403b6acd3179 181 int i=0;
emollison 0:403b6acd3179 182 float tempsin, tempexp;
emollison 0:403b6acd3179 183 float tempsinadd=.5-qlen;
emollison 0:403b6acd3179 184 float tempsinmul=(PI/(OSCIQUAR*2));
emollison 0:403b6acd3179 185 float expmul=4;
emollison 0:403b6acd3179 186 float subtractor=(exp(-2*expmul))-.99/max;
emollison 0:403b6acd3179 187 int newmax=max+(int)(subtractor*max);
emollison 0:403b6acd3179 188
emollison 0:403b6acd3179 189 do
emollison 0:403b6acd3179 190 {
emollison 0:403b6acd3179 191 tempsin = sin((i+tempsinadd)*tempsinmul);
emollison 0:403b6acd3179 192 tempexp = exp((tempsin-1)*expmul)-subtractor;
emollison 0:403b6acd3179 193 pwvals[i] = (short)(tempexp*newmax);
emollison 0:403b6acd3179 194 //pwvals[i] = (short)(exp((sin((i+tempsinadd)*tempsinmul)-1)*4)*max);
emollison 0:403b6acd3179 195 }while(++i<2*qlen);
emollison 0:403b6acd3179 196 }
emollison 0:403b6acd3179 197
emollison 0:403b6acd3179 198 /*
emollison 0:403b6acd3179 199 initializes the array of pre-computed values for light intensity
emollison 0:403b6acd3179 200 applied by the PWM. Setpws_subt is an alternative.
emollison 0:403b6acd3179 201 */
emollison 0:403b6acd3179 202 void setpws(int qlen, int max)
emollison 0:403b6acd3179 203 {
emollison 0:403b6acd3179 204 int i=0;
emollison 0:403b6acd3179 205 float tempsin, tempexp;
emollison 0:403b6acd3179 206 float tempsinadd=.5-qlen;
emollison 0:403b6acd3179 207 float tempsinmul=(PI/(OSCIQUAR*2));
emollison 0:403b6acd3179 208 float expmul=4;
emollison 0:403b6acd3179 209
emollison 0:403b6acd3179 210 do
emollison 0:403b6acd3179 211 {
emollison 0:403b6acd3179 212 //currently ~2000 cycles per loop
emollison 0:403b6acd3179 213
emollison 0:403b6acd3179 214 tempsin = sin((i+tempsinadd)*tempsinmul);
emollison 0:403b6acd3179 215 tempexp = exp((tempsin-1)*expmul);
emollison 0:403b6acd3179 216 pwvals[i] = (short)(tempexp*max);
emollison 0:403b6acd3179 217 //pwvals[i] = (short)(exp((sin((i+tempsinadd)*tempsinmul)-1)*expmul)*max);
emollison 0:403b6acd3179 218 }while(++i<2*qlen);
emollison 0:403b6acd3179 219 }
emollison 0:403b6acd3179 220
emollison 0:403b6acd3179 221 /*
emollison 0:403b6acd3179 222 selects a value from an array by position on a circle from -PI/2 to (3/2)*PI
emollison 0:403b6acd3179 223 when the array is for -PI/2 to PI/2 and reverses from PI/2 to (3/2)*PI
emollison 0:403b6acd3179 224 */
emollison 0:403b6acd3179 225 short getValFromCirc(int qlen, int cpt)
emollison 0:403b6acd3179 226 {
emollison 0:403b6acd3179 227 if (cpt < 2*qlen)
emollison 0:403b6acd3179 228 {
emollison 0:403b6acd3179 229 return pwvals[cpt];
emollison 0:403b6acd3179 230 }
emollison 0:403b6acd3179 231 else
emollison 0:403b6acd3179 232 {
emollison 0:403b6acd3179 233 return pwvals[4*qlen-cpt-1];
emollison 0:403b6acd3179 234 }
emollison 0:403b6acd3179 235 }