Sunday, March 17, 2024

0000 0000 1110 0011

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!




1 comment:

  1. 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