Friday, April 29, 2022

0000 0000 1001 0011

Redesigning an old project - a hallway PWM light

A few years ago I made a few hallway lights which definitely favoured function over form. They were so UGLY and also had two power supplies, one for the lights (9V) and one for the microcontroller (3V - 2AA cells).


They worked and were surprisingly robust and useful! I have since improved my coding skills to include better sleeping for the ATTiny13, and my electronics skills have increased to the point where I am more confident running useful lights from a single power supply.

Also in the interim I designed a PCB for the project.



Next I would like to maybe move the LDR to the PIR unit as per this information, and also play around with the number and type of LEDs.

The code is quite simple - perhaps an ASM version would be even slimmer, but for now this seems fine.

// -----------------------------------------------------------------
// Description: A couple of parallel Leds connected to a transistor
// controlled by an Attiny13. The μC sleeps most of the time,   but is 
// interrupted by a PIR on PB2,   The μC then checks the light 
// levels.  If it's light then it will sleep again,   but if it's dark
// it will light the leds slowly,   hold for awhile and and then fade
// out.
// 
// Author: OneCircuit            Date: Thu 31 Mar 2022 18:28:44 AEDT
// -----------------------------------------------------------------
// 
// ATMEL ATTINY13 μC
// 
//                                   +-\/-+
//  RESET--ACD0--5/A0--PCINT5--PB5  1|    |8  VCC
//   CLKI--ACD3--3/A3--PCINT3--PB3  2|    |7  PB2--PCINT2--2/A1--SCK--ADC1
//         ACD2--4/A2--PCINT4--PB4  3|    |6  PB1--PCINT1---1---MISO--OCOB--INT0*
//                             GND  4|    |5  PB0--PCINT0---0---MOSI--OCOA*
//                                   +----+
//  * indicates PWM port
// 

#include <avr/pgmspace.h>     // for reading the progmem values
#include <avr/sleep.h>        // the sleep routines

#define LEDs PB0              // pwm pin
#define InterruptPin PB2      // interrupt pin

#define photoresistor A2      // A2 analog in

// The leds will fade exponentially to compensate for human perception,  
// which is not linear. You can calculate as a curve,   but float
// values will blow the little Attiny13 out of the water,   so a lookup
// table in progmem makes more sense for saving memory. 

const uint8_t PROGMEM fadevalues[] = {

  0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    2,
  2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    3,
  3,    3,    3,    3,    3,    3,    3,    3,    3,    3,    3,    4,    4,    4,    4,    4,
  4,    4,    4,    4,    4,    5,    5,    5,    5,    5,    5,    5,    5,    6,    6,    6,
  6,    6,    6,    7,    7,    7,    7,    7,    7,    8,    8,    8,    8,    8,    8,    9,
  9,    9,    9,    10,   10,   10,   10,   10,   11,   11,   11,   11,   12,   12,   12,   13,
  13,   13,   13,   14,   14,   14,   15,   15,   15,   16,   16,   16,   17,   17,   18,   18,
  18,   19,   19,   20,   20,   20,   21,   21,   22,   22,   23,   23,   24,   24,   25,   25,
  26,   27,   27,   28,   28,   29,   30,   30,   31,   32,   32,   33,   34,   35,   35,   36,
  37,   38,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,
  52,   53,   54,   55,   57,   58,   59,   60,   62,   63,   64,   66,   67,   69,   70,   72,
  73,   75,   76,   78,   80,   81,   83,   85,   87,   88,   90,   92,   94,   96,   98,   100,
  103,  105,  107,  109,  112,  114,  117,  119,  122,  124,  127,  130,  132,  135,  138,  141,
  144,  147,  150,  153,  157,  160,  164,  167,  171,  174,  178,  182,  186,  190,  194,  198,
  202,  206,  211,  215,  220,  224,  229,  234,  239,  244,  249,  255,  255,  255,  255,  255 };

void powerDown(void)
{
    GIMSK |= (1<<PCIE);                   // activate Pin change interrupts
    PCMSK |= (1<<InterruptPin);           // sets the Pin change interrupt mask
    ADCSRA &= ~(1<<ADEN);                 // turn off ADC
    ACSR|=(1<<ACD);                       // turn off Analog comparator.
    sei();                                // enable global interrupts
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // sleep deeply little one
    BODCR |= (1<<BODS)|(1<<BODSE);        // turn off brownout detection
    BODCR |= (1<<BODS);
    BODCR &= ~(1<<BODSE);
    
    sleep_enable();                       // enable sleep mode
    sleep_mode();                         // system sleeps here
    
    sleep_disable();                      // ISR routine returns here so wake up        
    GIMSK &= ~(1<<PCIE);                  // deactivate Pin change interrupts
    ADCSRA |= (1 << ADEN);                // turn on ADC
    ACSR = (0<<ACD);                      // turn on Analog comparator.
    delay(50);                            // settle time

    // read the input pin, local variable saves memory
    uint16_t val = analogRead(photoresistor);    

    if(val < 250) {
    pinMode(5,OUTPUT);
    slowfade(true);               // fade in
    delay(30000);                 // hold that thought
    slowfade(false);              // fade out
    pinMode(5,INPUT_PULLUP);

    }

}

void slowfade(boolean fadein){

if (fadein) {
  for (uint8_t lighting = 0; lighting < 255; lighting++){    
    analogWrite(LEDs, pgm_read_byte(&fadevalues[lighting]));  // read from the lookup table
    delay(5);                                                // increase for a slower fade
  }
}
else {
  for (uint8_t lighting = 255; lighting > 0; lighting--){     // count backwards
    analogWrite(LEDs, pgm_read_byte(&fadevalues[lighting]));  // from the lookup table
    delay(50);                                                // increase for a slower fade 
}
}
}

ISR(PCINT0_vect)
{
  // wake up little one...
}

void setup ()
{
  // all inputs and pullups to save power
  pinMode(1,INPUT_PULLUP);
  pinMode(2,INPUT_PULLUP);
  pinMode(3,INPUT_PULLUP);
  pinMode(5,INPUT_PULLUP);
  pinMode(6,INPUT_PULLUP);
  pinMode(7,INPUT_PULLUP);
}  // end of setup

void loop () {
  powerDown(); // call the function that sleeps
}

In the meantime - these updated units are working fine (and so much prettier!)




Sunday, April 24, 2022

0000 0000 1001 0010

Mailbag #12 - unearthing treasure

Lost in the move from an HDD to an SSD, several package openings have come to light recently. They are a little venerable, but I though it might be useful to cobble a few together and make a franken-mailbag. Enjoy!


 

Friday, April 15, 2022

0000 0000 1001 0001

Inline through-hole fuses

For some reason I cannot remember (isn't that always the way) I ordered a series of inline through-hole fuses that look like little inductors:

I suppose that they could be used in the lab PSU project - maybe on the output to each voltage (3.3V, 5V, 12V and variable) - so that if there is a short circuit or runaway current somewhere that somehow gets past the switching power regulator (ZK-4KX) then these little guys will throw themselves in front of the ruling monarch burn out and save the day.


So this week in the circuit I test a few to destruction for the good of Science and my amusement. There are a few more in the bin than you get to see me destroy in the video below - it was a bit of fun (who doesn't love magic smoke) but now I need to order a few more!


Friday, April 8, 2022

0000 0000 1001 0000

Mailbag #11

A few items arrived recently and so I've cobbled together some video of me mumbling my way through opening them up!

The really interesting one was a water solenoid valve - it is pitched at 12V but opens fine with 9V - very handy if there is a 9V battery available.

The plan is to maybe build a hydro-based power station on the property (which is very steep!) - if I can hook up an ESP8266 or an ESP32 to control such a valve the possibilities are very very interesting.


Of course, there's a bit of experimentation to go first - I'm no engineer, just a tinkerer.

Enjoy!



Saturday, April 2, 2022

0000 0000 1000 1111

5V to 240V conversion

All of my early projects were 5V - a legacy from my Arduino days. When I ditched the Arduino in favour firstly of the Nano and the Pro Mini, and then later for "raw" ATMega 328/168/88 chips, I kept the 3x1.5V AA power delivery configuration that had served all of those projects so well.

For a few recent projects however, it was more appropriate to use some old phone chargers to deliver 5V (or otherwise) to provide power, and thus no switching of batteries required!

For instance - the Cat Laser Toy and the Rowing Exercise Clock are both plugged in via 5V adapters.

I have been making PIR activated digital clocks for some time (pre-blog and pre-YT) which have been chugging away quite happily in many homes over many years.

The clocks sit around sleeping most of the time, but when they detect a warm presence via the PIR, they poll a DS3231 module for time and temperature, display these on a TM1637 display, and then go to sleep again.

The downside is that those 3xAA batteries need to be replaced from time to time depending on the frequency of sleep interruption. In a high-traffic area such as our kitchen/dining room, this could be as often as once every 3 months - too much!

I have tried using NiMH - but it is difficult to find high capacity versions that give more than a few weeks of service - inconvenient!

So for this project I am taking one of my "high traffic" clocks and putting in a 5V conversion via an AC/DC converter and a USB module.

Is it successful - time will tell (pun intended)?