Solar Hall Light
V3 of the Hall Light sees the PFS154 swing into action (well, only at around 50kHz) and as well the Stable Joule Thief throwing solar energy at a little AAA NiCad battery.
The code has come a long way since the early days, and here it is in all it's glory:
/* OneCircuit Hall Light V3 (based on PFS154) Uses PIR to sense warm body, PIR wakes up IC PFS154 uses PWM to light up path for given number of seconds, then sleep resumes. +-\/-+ VDD 1| |8 GND PA7/X1 2| |7 PA0/INT0/COM2/CO/PG0PWM PA6/X2 3| |6 PA4/COM3/CIN+/CIN4-/PG1PWM PA5/PRSTB/PG2PWM 4| |5 PA3/TM2PWM/COM4/CIN1-/PG2PWM +----+ Mon 11 Mar 2024 14:31:51 AEDT */ #include <pdk/device.h> #include "auto_sysclock.h" #include "delay.h" #include <stdbool.h> // Pin Defines - all pins are on port A #define WAKEUP_PIN 0 // PIR sensor input pin, used to wake from deep sleep #define LED_PIN 3 // LED output pin // LED is active low (current sink) #define turnLedOn() PA &= ~(1 << LED_PIN) #define turnLedOff() PA |= (1 << LED_PIN) // change speed of pwm ramp, and the hold time for full brightness #define rampspeed 50 #define holdtime 150 volatile bool lightmeup = false; // PFS154 has space for two arrays, but you could also // read one of them "backwards" uint8_t ledup[] = {1, 1, 2, 2, 3, 3, 4, 5, 7, 9, 11, 14, 17, 22, 28, 35, 44, 56, 70, 89, 112, 142, 180, 200 }; uint8_t leddown[] = {200, 180, 142, 112, 89, 70, 56, 44, 35, 28, 22, 17, 14, 11, 9, 7, 5, 4, 3, 3, 2, 2, 1, 1 }; void sleeping() { MISC = MISC_FAST_WAKEUP_ENABLE; // fast wakeup PADIER = 0; // on reset all pins are set as wake pins, 0 to disable PBDIER = 0; // no port B on PFS154, but still needs to be set // Set PIR Sensor pin as input PAC &= ~(1 << WAKEUP_PIN); // set as input PAPH |= (1 << WAKEUP_PIN); // enable pullup resistor __disgint(); // disable global interrupts INTEN = 0; // disable all interrupts PADIER = (1 << WAKEUP_PIN); // enable only wakeup pin PBDIER = 0; // port B does not wake INTEGS |= INTEGS_PA0_FALLING; // trigger when switch closes and pulls pin to ground INTEN |= INTEN_PA0; // enable interrupt on wakeup pin INTRQ = 0; // reset interrupts turnLedOff(); __engint(); // enable global interrupts __stopsys(); // go to deep sleep return; } void ramping() { // see candle projects for explanation PWMG2DTL = 0x00; PWMG2DTH = 0x00; PWMG2CUBL = 0xff; PWMG2CUBH = 0xff; PWMG2C = 0b10100111; PWMG2S = 0b00000000; for (uint8_t i = 0; i < sizeof(ledup) / sizeof(ledup[0]); i++) { PWMG2DTL = ledup[i] & 255; PWMG2DTH = ledup[i]; _delay_ms(rampspeed); } for (uint16_t i = 0; i < holdtime; i++) { _delay_ms(rampspeed); } for (uint8_t i = 0; i < sizeof(leddown) / sizeof(leddown[0]); i++) { PWMG2DTL = leddown[i] & 255; PWMG2DTH = leddown[i]; _delay_ms(rampspeed); } PWMG2DTL = 0 & 255; PWMG2DTH = 0; PWMG2C = 0b00100001; lightmeup = false; return; } void interrupt(void) __interrupt(0) { INTEN = 0; // disable all interrupts PADIER = 0; // disable wakeup pin PBDIER = 0; // disable port B wake pins to be sure lightmeup = true; } // Main program void main() { // Initialize hardware PAC |= (1 << LED_PIN); // Set LED as output // Main processing loop while (1) { if (lightmeup) { ramping(); } else { sleeping(); } } } // Startup code - Setup/calibrate system clock unsigned char _sdcc_external_startup(void) { AUTO_INIT_SYSCLOCK(); AUTO_CALIBRATE_SYSCLOCK(TARGET_VDD_MV); return 0; }
I love the finished product and the journey was pretty nice as well!
Hello My Friend, I follow your projects with interest. I am also working on some projects related to padauk processors. Your project caught my attention and I want to make a motion sensor with PMS150C. I want to make a project that turns on the LED when it detects movement, counts for 15 seconds and then turns off and waits for movement again. Do you think this is possible?
ReplyDelete