Competition Giveaway
This week I make a lovely candle from a cheap solar light - then give it away!
Here is the code for the candle as promised:
/* Candle with Three PWM Pseudo-random flickering to simulate a candle. Output is via 3xPWM channels, variables can be changed to alter the simulation Sun 30 Nov 2025 19:53:23 AEDT */ #include <stdint.h> #include <stdlib.h> #include "../device.h" #include "../easy-pdk/calibrate.h" #include "../auto_sysclock.h" #include "../delay.h" #include <stdbool.h> #define LED4_BIT 4 #define LED0_BIT 0 #define LED3_BIT 3 bool debug = false; uint16_t myrand = 2901; // happy birthday uint8_t slowcounter = 0; uint8_t medcounter = 0; uint8_t fastcounter = 0; uint8_t slowstart = 0; uint8_t slowend = 0; uint8_t medstart = 0; uint8_t medend = 0; uint8_t faststart = 0; uint8_t fastend = 0; uint8_t faster = 0; // cutoff percentages for types of flicker uint8_t percentnormal = 82; // cutoff for normal/calm uint8_t percentsputter = 20; // cutoff for sputtering/normal uint8_t flickdelay = 40; // initial speed of flicker uint8_t flickdelaysputter = 9; // "sputtering" activity uint8_t flickdelaynormal = 40; // "normal" activity uint8_t flickdelaycalm = 95; // "calm" activity uint8_t choosearray = 1; // normal waves int delaycounter = 50; int delaydelay = 20; uint8_t waves[9][4] = { {4, 6, 40, 50} , // sputter flicker waveslow {6, 8, 50, 80} , // sputter flicker wavemed {8, 10, 110, 130} , // sputter flicker wavefast {15, 25, 60, 100} , // normal flicker waveslow {10, 25, 110, 140} , // normal flicker wavemed {20, 25, 100, 120} , // normal flicker wavefast {40, 60, 100, 140} , // calm flicker waveslow {50, 70, 120, 160} , // calm flicker wavemed {70, 80, 140, 180} // calm flicker wavefast }; bool fastup = true; bool slowup = true; bool medup = true; void mydelay(uint8_t counter) { for (uint8_t thiscount = 0; thiscount <= counter; thiscount++) { _delay_us(1); } } uint16_t gimmerand(uint16_t small, uint16_t big) { myrand ^= (myrand << 13); myrand ^= (myrand >> 9); myrand ^= (myrand << 7); if (abs(myrand) % 13 == 0) { myrand = myrand - 23; } if (abs(myrand) % 17 == 0) { myrand = myrand + 11; } return abs(myrand) % 23 * (big - small) / 23 + small; } void getnewslow(uint8_t whicharray) { slowstart = gimmerand(waves[whicharray][0], waves[whicharray][1]); slowend = gimmerand(waves[whicharray][2], waves[whicharray][3]); } void getnewmed(uint8_t whicharray) { medstart = gimmerand(waves[whicharray+1][0], waves[whicharray+1][1]); medend = gimmerand(waves[whicharray+1][2], waves[whicharray+1][3]); } void getnewfast(uint8_t whicharray) { faststart = gimmerand(waves[whicharray+2][0], waves[whicharray+2][1]); fastend = gimmerand(waves[whicharray+2][2], waves[whicharray+2][3]); faster = gimmerand(2, 6); } void myblink(uint8_t howmany) { for (uint8_t blinkcount = 1; blinkcount <= howmany; blinkcount++) { PA = 0b00000000; _delay_ms(10); PA = 0b00100000; _delay_ms(10); } } // Main program void main() { _delay_ms(100); // settle if (debug) { PAC |= (1 << 5); myblink(5); } // see datasheet PWMG1DTL = 0x00; PWMG1DTH = 0x00; PWMG1CUBL = 0xff; PWMG1CUBH = 0xff; PWMG1C = 0b10100111; PWMG1S = 0b00000000; PWMG0DTL = 0x00; PWMG0DTH = 0x00; PWMG0CUBL = 0xff; PWMG0CUBH = 0xff; PWMG0C = 0b10100111; PWMG0S = 0b00000000; PWMG2DTL = 0x00; PWMG2DTH = 0x00; PWMG2CUBL = 0xff; PWMG2CUBH = 0xff; PWMG2C = 0b10100111; PWMG2S = 0b00000000; getnewfast(choosearray); getnewslow(choosearray); getnewmed(choosearray); slowcounter = slowstart; fastcounter = faststart; medcounter = medstart; PAC |= (1 << LED4_BIT) | (1 << LED0_BIT) | (1 << LED3_BIT); // Main processing loop while (1) { // ramp up slow if (slowup) { slowcounter++; if (slowcounter > slowend) { // ramp finished so switch boolean slowup = !slowup; } } else { // ramp down slow slowcounter--; if (slowcounter < slowstart) { // ramp finished so switch boolean slowup = !slowup; getnewslow(choosearray); } } // ramp up med if (medup) { medcounter++; if (medcounter > medend) { // ramp finished so switch boolean medup = !medup; } } else { // ramp down med medcounter--; if (medcounter < medstart) { // ramp finished so switch boolean medup = !medup; getnewmed(choosearray); } } // ramp up fast if (fastup) { fastcounter = fastcounter + faster; if (fastcounter > fastend) { // ramp finished so switch boolean fastup = !fastup; } } else { // ramp down fast fastcounter = fastcounter - faster; if (fastcounter < faststart) { // ramp finished so switch boolean fastup = !fastup; getnew...and here is the video for your enjoyment... vid
fast(choosearray); } } // delay + a re-purposed random for ramp speeds mydelay(flickdelay + faster); delaycounter = delaycounter - 1; if (delaycounter == 0) { delaycounter = gimmerand(1, 100); if (delaycounter > percentnormal) { // calm if (debug) myblink(3); flickdelay = flickdelaycalm; choosearray = 6; delaycounter = 100-delaycounter; } else if (delaycounter > percentsputter) { // "normal" if (debug) myblink(2); flickdelay = flickdelaynormal; choosearray = 3; } else { // sputtering if (debug) myblink(1); flickdelay = flickdelaysputter; choosearray = 0; } delaycounter = delaycounter * delaydelay; } PWMG2DTL = slowcounter & 255; PWMG2DTH = slowcounter; PWMG0DTL = fastcounter & 255; PWMG0DTH = fastcounter; PWMG1DTL = medcounter & 255; PWMG1DTH = medcounter; } } // Startup code - Setup/calibrate system clock unsigned char _sdcc_external_startup(void) { AUTO_INIT_SYSCLOCK(); AUTO_CALIBRATE_SYSCLOCK(TARGET_VDD_MV); return 0; }
...and here is the video for your enjoyment! Good luck in the competition.

No comments:
Post a Comment