bluehash 1,581 Posted May 17, 2011 Author Share Posted May 17, 2011 Mid-month bump for project submissions. Link to post Share on other sites
EngIP 31 Posted May 23, 2011 Share Posted May 23, 2011 I'll open the competition (and set the bar low enough to encourage others) with my latest creation - Persistence of vision on a diet. Essentially just a proof of concept for me to waste a few hours on, but the results were good enough to put a satisfied smile on my face. It uses 8 LEDs and 1 resistor in conjunction with an MSP430G2211, and the code just switches columns after a pre-set delay. The keen eyed out there might spot the lack of a resistor in series with the LEDs - I'm relying on the current limited outputs of the uC to prevent any excess current/heat/smoke/fire and it seems to work. EDIT: I'm "getting away with it" but the outputs aren't current limited, and should have a resistor in series. Enough babble, the circuit in all it's glory. The code. #include //This is the header file for your chip. void delay(unsigned int delayTime); void main(void) { WDTCTL = WDTPW + WDTHOLD; //Hold the WDT (WatchDog Timer) P1DIR = 0xff; //Set Port 1 (P1) to output. unsigned int i=250; //This is the delay value between each column (found by trial and error) while(1){ P1OUT = 0x00; delay(i); P1OUT = 0x7C; //Mr GreenFace's first column. delay(i); //The delay P1OUT = 0x82; delay(i); P1OUT = 0xA9; delay(i); P1OUT = 0xA1; delay(i); P1OUT = 0xA9; delay(i); P1OUT = 0x82; delay(i); P1OUT = 0x7C; //Mr GreenFace's last column. delay(i); P1OUT = 0x00; delay(i); } } void delay(unsigned int delayTime){ int x; for (x=0;x x=x*1; } } The (very dodgy) schematic is attached. Video of the project in action. The circuit on stripboard. First text effort. An attempt at mixing inverse and regular text...Not great About the best picture I managed to get... bluehash 1 Link to post Share on other sites
bluehash 1,581 Posted May 23, 2011 Author Share Posted May 23, 2011 Thanks EngIp, four more projects,People! Link to post Share on other sites
lpdc 11 Posted May 25, 2011 Share Posted May 25, 2011 As this was suggested to me last month, I will try and submit my color matching game. As it is a beginner's first project, I am not sure if it is really worthy to be featured in a contest but you never know... Plus, the prizes look extremely attractive. This is an improved version which now features sound feedback to help the player. The goal is to match a target color by adjusting separately red, green and blue components of an RGB LED. The length of the beeps and their pitch also help you into finding the proper combination. The required parts are very few and the game is driven by a MSP430G2233. You can find some more details in the original post along with references to the websites I learnt/got inspiration from. Here is a video of the resulting game : Here is also the circuit Finally, here is the code : /* ****** Color matching game. By Fabrice C. ****** This is my first program with a microcontroller so everything is probably not as pretty as it should... Original inspiration came from : http://www.fangletronics.com/2010/02/amazing-dr-boardmans-colour-conundrum.html A lot of code was inspired by the tutorials/examples from : http://mspsci.blogspot.com/ and http://www.msp430launchpad.com/2010/09/simple-adc-example-on-launchpad.html and http://blog.hodgepig.org/2010/09/30/jam-jar-lamp/ */ #include #include #include #include /****************************************************/ #define P1_LED_BIT (BIT0|BIT1|BIT2|BIT6|BIT7) #define P2_LED_BIT (BIT6) /****************************************************/ static uint8_t led_brightness[6] = {0x00,0x00,0x00,0x00,0x00,0x00}; // This variable stores the brightness of the 2 RGB leds : {R1,G1,B1,R2,G2,B2} static uint32_t sys_ticks = 0; // Used to keep track of PWM static bool ADCDone = false; // Flag to check that the ADC sampling is done static uint16_t ADCValue; // Result of ADC (converted value) static int sampled_channel; // Channel being sampled by ADC static int seed; // seed for random number generation static long color_dif = 3000; // Color_dif represents how close the player is from the target static uint32_t beep_tick =0; // timer-linked counter for the beeper static bool beep_on = false; // flag to determine if the beeper is supposed to be on or not. static int beep_frequency = 40; //The frequency of the beeping /****************************************************/ static void cpu_init(void) // Initialisation of the micro controller { WDTCTL = WDTPW + WDTHOLD; // Stop Watch dog timer // configure system clock to about 16MHz BCSCTL1 &= ~(BIT0 + BIT1); // set bits 0 and 1 to 0 BCSCTL1 |= BIT2 + BIT3; // set bits 2 and 3 to 1 DCOCTL &= ~(BIT5 + BIT7); // set bits 5 and 7 to 0 DCOCTL |= BIT6; // set bit 6 to 1 // seems like overkill but lower frequencies generated // quite a lot of flickering. PWM algo/usage may need improvement _enable_interrupt(); // to be able to use interrupts // Without this the timer and ADC callback functions would never be called. } bool match(int delta) // function returning true if the 2 RGB values are within // a distance "delta" (euclidian distance) { int Dr; int Dg; int Db; Dr = (int)led_brightness[0]-led_brightness[3]; Dg = (int)led_brightness[1]-led_brightness[4]; Db = (int)led_brightness[2]-led_brightness[5]; unsigned int D;//no sqrt so no need for double D = (unsigned int)((Dr*Dr)+(Dg*Dg)+(Db*Db)); color_dif = (long)D; //updating the color_dif value for the sound feedback (this is the lenght of the beeps) // we now check channel by channel if the target is close or not. if ((-8 Dr = 1; else Dr = 0; if ((-8 Dg = 1; else Dg = 0; if ((-8 Db = 1; else Db = 0; // Now we will modulate the frequency of the beep depending on the number of channels which are on target // (None : low tone, all of them : high tone) switch(Dr+Dg+Db) { case 0: beep_frequency = 30; break; case 1: beep_frequency = 120; break; case 2: beep_frequency = 210; break; case 3: beep_frequency = 250; } // cannot manage to do a sqrt without getting a compiling error // so I am comparing the 2 squared values instead. if ( D <= (delta*delta)) return true; else return false; } void play_tune (int freq, int duration) // Function that detracts sound modulation interrupts to play a given sound for a given duration { beep_frequency = freq; color_dif = duration; beep_tick = 0; //starts ticking beep_on=true; //makes sure the buzzer is on while (1) { if (!beep_on) break; //stops when the end of the duration is reached } } void win (void) // Procedure to show the player he won. LEDs blink and a short "tune" is played { int R; int G; int B; R= led_brightness[3]; G= led_brightness[4]; B= led_brightness[5]; // saves current RGB values of the target color //LEDs off led_brightness[0] = 0; led_brightness[1] = 0; led_brightness[2] = 0; led_brightness[3] = 0; led_brightness[4] = 0; led_brightness[5] = 0; // plays the short "tune" play_tune(0,3000); play_tune(67,6000); play_tune(75,6000); play_tune(84,6000); play_tune(200,15000); play_tune(40,1800); play_tune(200,25000); play_tune(0,1000); int n; int i; for (i=0; i<10; i++) // blinks the 2 RGB leds 10 times { for (n=0; n<1500; n++); // delay // LEDs on led_brightness[0] = R; led_brightness[1] = G; led_brightness[2] = B; led_brightness[3] = R; led_brightness[4] = G; led_brightness[5] = B; for (n=0; n<1500; n++); //delay //LEDs off led_brightness[0] = 0; led_brightness[1] = 0; led_brightness[2] = 0; led_brightness[3] = 0; led_brightness[4] = 0; led_brightness[5] = 0; } } // Binary Code Modulation static void bcm_tick(uint8_t led_ticks) { uint8_t bcm1 = 0x00; uint8_t bcm2 = 0x00; // This commented code does not work so I used the code from // http://www.msp430launchpad.com/2010/09/simple-adc-example-on-launchpad.html // instead // if (led_brightness[0] <= led_ticks) // bcm1 |= BIT0; // if (led_brightness[1] <= led_ticks) // bcm1 |= BIT1; // if (led_brightness[2] <= led_ticks) // bcm1 |= BIT2; // // if (led_brightness[3] <= led_ticks) // bcm1 |= BIT6; // if (led_brightness[4] <= led_ticks) // bcm1 |= BIT7; //To be fixed : may want the BIT6 on this port to also stay on. // if (led_brightness[5] <= led_ticks) // bcm2 |= BIT7; // // P1OUT = bcm1; // P2OUT = bcm2; // switch(led_ticks) { case 0x1: case 0x2: case 0x4: case 0x8: case 0x10: case 0x20: case 0x40: case 0x80: // led_ticks is a power of 2 if (led_brightness[0] & led_ticks) bcm1 |= BIT0; if (led_brightness[1] & led_ticks) bcm1 |= BIT1; if (led_brightness[2] & led_ticks) bcm1 |= BIT2; if (led_brightness[3] & led_ticks) bcm1 |= BIT6; if (led_brightness[4] & led_ticks) bcm1 |= BIT7; if (led_brightness[5] & led_ticks) bcm2 |= BIT7; if (beep_frequency & led_ticks) if (beep_on) //beeps if necessary bcm2 |= BIT6; P1OUT = bcm1; P2OUT = bcm2; } } // Timer0 ISR #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) //Call back function when the timer ticks { bcm_tick(sys_ticks); sys_ticks++; beep_tick++; if (beep_tick > color_dif) { beep_tick = 0; beep_on = !beep_on; } // Following was meant to work with other BCM function but did not work. // if (sys_ticks > 255 ) // sys_ticks = 0; // This was meant to enter low power mode but interrups stopped for some reason //__bis_SR_register(CPUOFF + GIE); //__bic_SR_register_on_exit(CPUOFF); } void Single_Measure(unsigned int chan) // Frunction starting the ADC sampling { ADC10CTL0 &= ~ENC; // Disable ADC ADC10CTL0 = ADC10SHT_3 + ADC10ON + ADC10IE; // 16 clock ticks, ADC On, enable ADC interrupt ADC10CTL1 = ADC10SSEL_3 + chan; // Set 'chan', SMCLK ADC10CTL0 |= ENC + ADC10SC; // Enable and start conversion } #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR (void) // Call back function for when the ADC sampling is done { ADCValue = ADC10MEM; //saves measured value from register into ADCValue variable ADCDone = true; // sets the flag acknowledging that the ADC is done //__bic_SR_register_on_exit(CPUOFF); } void Generate_New_Target(void) // Generates a random color for the target of the game and plays a short tune { uint32_t T = 0; while (1) { led_brightness[3] = rand(); led_brightness[4] = rand(); led_brightness[5] = rand(); T = led_brightness[3] + led_brightness[4] + led_brightness[5]; // We check the total brightness of the 3 components as we don't want a // color to be too dark or too bright if (500 > T < 200) break ; } // plays a little tune to notify the start of the game play_tune(20,6000); play_tune(80,6000); play_tune(140,6000); play_tune(200,6000); play_tune(250,9000); play_tune(0,9000); } int main(void) // Main Program { cpu_init(); // setup LED pins P1DIR |= P1_LED_BIT; // All LED pins as outputs //select i/o function of pins P2SEL &= ~(BIT6|BIT7); // Acitvates the 2 ports on pins 12 and 13 //set them as outputs P2DIR = BIT6 | BIT7; P2OUT &= ~(BIT6|BIT7); P1OUT &= ~P1_LED_BIT; // Turn off LED // TimerA SMCLK in UP mode TACTL = TASSEL_2 | MC_1; // Enable interrupt for TACCR0 match TACCTL0 = CCIE; // Set TACCR0, starts timer. TACCR0 = 130; // This must be short enough to look good and long enough for TIMER0_ISR to complete // but I don't really understand the magic number //Measures the value of Channel 3 (R potentiometer) Single_Measure(INCH_3); while (1) // waits until the measurement is finished { if (ADCDone) break; } ADCDone = false; seed = ((uint32_t)ADCValue*255)/990; // uses the measured value as the seed for random number generation // if a constant seed is used, the order in which the target colors // are asked will always be the same when the micro controller is reset. // This way, provided the R potentiometer was changed since last time, // a new color will be asked first. (crude but it works most of the time) srand(seed); // Sets the R, G, and B brightness of the target color to a random value Generate_New_Target(); Single_Measure(INCH_3); sampled_channel = 1; // Keeps track of the channel being measured while(1) // Endless loop { // tests if the dialed in values are close enough to the target if (match(5) == true) { win(); // display winning animation // Sets a new color as target Generate_New_Target(); } if (ADCDone) // if we have a measurement result available { ADCDone = false; // my potentiometers are not the best ones, I never // manage to get the sampled value up to 1023 // so I clip everything to 990 in order to make // sure that the player can dial in a maximum // brightness value of FF if (ADCValue > 990) ADCValue = 990; switch(sampled_channel) { // adjust the brightness of a LED to the value // measured on the corresponding potentimeter // and makes ready to sample the next channel case 1: led_brightness[0] = ((uint32_t)ADCValue*255)/990; Single_Measure(INCH_4); sampled_channel = 2; break; case 2: led_brightness[1] = ((uint32_t)ADCValue*255)/990; Single_Measure(INCH_5); sampled_channel = 3; break; case 3: led_brightness[2] = ((uint32_t)ADCValue*255)/990; Single_Measure(INCH_3); sampled_channel = 1; break; } } } } Wish me luck for the contest and if you like this project, please don't hesitate to vote for me. Cheers, Fabrice RobG and GeekDoc 2 Link to post Share on other sites
NatureTM 100 Posted May 25, 2011 Share Posted May 25, 2011 I really liked the glitchy sound you added Fabrice. Was that in the original? I didn't see it in the video. Link to post Share on other sites
oPossum 1,083 Posted May 26, 2011 Share Posted May 26, 2011 I have my contest idea working, so I will describe what is is. There is still some work to be done, so code and schematic will be posted later. EDIT: Created a thread for this project here This thread will be updated after the whole project has been presented. Link to post Share on other sites
zeke 693 Posted May 26, 2011 Share Posted May 26, 2011 Oooo! I'm looking forward to seeing this project. Link to post Share on other sites
lpdc 11 Posted May 26, 2011 Share Posted May 26, 2011 Hi NatureTM, Paulbo mentioned on his blog that there was some sound feedback to help the player but I think he turned it off in his video so I don't know how it would compare. What I did here is to have the beep duration and intervals to get smaller as the color difference decreased. In addition to this, the pitch of the beep gets higher with the number of channels that match their individual targets. This really helps the player as the game is really not that easy without the sound feedback. (while testing, I have been known to pause the program and use the debugger and cheat to find an elusive color) Link to post Share on other sites
DanAndDusty 62 Posted May 26, 2011 Share Posted May 26, 2011 I like the sound of your project oPossum.. I recently did something along similar lines but MUCH simpler. I had a broken Digi Photo frame I cannibalised and discovered an IR receiver on it. No part number but it worked along the lines of the usual ones (normally Hi, low when carrier freq detected etc).. I did the detective work manually that your project does automatically. I measured the duration of the various pulses (encoded pulses) and sent the info via the USB UART to the PC. My problem was that I could only measure a max of about 20 pulses with the memory of the G2231. The next project/code program deciphered the pulses and wrote out the info of the bits (Toggle, Address, command etc) to the serial port. My plan was to create a programmable/Learning IR transmitter for if (when) we lose the remote for the TV at home. However as my wife is expecting our 2nd child in about 2 weeks (any day now though she says) the transmitter project is still a bunch of schematics in my head. So congrats and Im very interested in seeing your thinking and solution, I get the feeling Im going to learn a lot. Dan Link to post Share on other sites
oPossum 1,083 Posted May 26, 2011 Share Posted May 26, 2011 To measure the CIR carrier frequency, each individual pulse of IR must be detected. Common IR demodulator modules can not do this - they respond to a burst of IR, not each pulse. There are parts made for this specific application such as the Vishay TSOP98200 and TSOP98260. Unfortunately these parts are difficult to obtain. There are general purpose IR detectors like the Fairchild QSE159 and Osram SFH5140, but they require 5 volts. A photodiode and a transimpedance amplifier works well, but requires careful construction (not a breadboard) to work well. I used an ordinary IR LED as a detector. Here is a video showing how it works... Here is the code... #include "msp430g2211.h" main(void) { volatile unsigned d; unsigned n, p; P1DIR = 0xDA; // Setup I/O P1REN = 0x25; // Pullup on P1.0 - counter input P1OUT = 0x07; // Ground on P1.3 - IR LED ground P1SEL = 0x11; // Enable external counter input TACTL = 0x0024; // Continuous count up, no prescale p = 0; // Reset previous count for(; { n = TAR; // Get current count if(n != p) { // Compare to previous P1OUT |= 0x40; // Turn on green LED if count has changed } else { P1OUT &= ~0x40; // Turn off green LED if count is the same } p = n; // Set previous count to current count d = 10; // Wait a while do { --d; } while(d); // } } Measuring the carrier frequency requires counting pulses in a specific time period. Next post will show how that is done. zborgerd, bluehash and lpdc 3 Link to post Share on other sites
Astrom27 3 Posted May 26, 2011 Share Posted May 26, 2011 HI Is it to late to post the projects for the contest i forgot how late it was in the month.... I will try to post it later if it is ok.. Link to post Share on other sites
bluehash 1,581 Posted May 27, 2011 Author Share Posted May 27, 2011 Nope.. go ahead. This will probably roll over to the next month. Once we have five projects, the contest closes. Link to post Share on other sites
RobG 1,892 Posted May 27, 2011 Share Posted May 27, 2011 Wait, if it rolls over to June, is the limit still 5 projects? Link to post Share on other sites
bluehash 1,581 Posted May 27, 2011 Author Share Posted May 27, 2011 I apologize. I shouldn't have put it that way. Since the voting starts 7 days prior to a month's end, this month's(May) deadline has already passed. Since there are less than five projects, the POTM rolls over to June. Once we have five projects, the contest closes. I'll take that back. The Contest will close on the 23rd of June, 2011, as long as there are greater than five projects. Thanks, and goodluck! Link to post Share on other sites
bluehash 1,581 Posted May 27, 2011 Author Share Posted May 27, 2011 This came in: Link to post Share on other sites
Recommended Posts