Cable locker intruder alarm (a very simple setup)

Please notice: Working code for the Attiny85, with power saving to give a very long battery life, is in reply #18

At work I have a locker with extension cords, power supplies, plugs, connectors, network cables and a lot of other nice stuff needed to make the daily life function.

It is there for anybody in my part of the house to have, whenever they need it.
Unfortunately, that led to people from other parts of the house “coming shopping” when they needed something, and the locker was an awful mess.
In the end I had to remove the handle on the locker to limit the access. The handle is in my office now, and anyone needing it, can borrow it.
It has kept the locker nice and tidy for several weeks.

But this week I found one of our student halfway inside the open locker, and he insisted, that it wasn’t locked when he came, and then he could just as well help himself to a couple of cables, and see what else was in the locker?
:grin:

I’m certain that I locked it last time I was in the locker, meaning that someone has had an unauthorized access.
(Probably that very student, I know him quite well!)

So I made a simple little setup with an ATtiny, an LDR and an awfully loud (and very cheap) “window alarm”.
(The alarms were cheaper than the batteries in them, so I bought a handful and used the batteries for other things. I simply soldered leads to the springs in the battery compartment for this setup)

Before you flame me for coding with a shovel:
This is an early version, primarily made to have “something working”
In later versions, I’ll look into making the code more elegant, and take measures to save power.

  • It beeps when switched on, to give ample time to close the locker
  • then it calibrates to the light level in the locker, and gives a long beep to signal “armed”
    If the light level is raised (the door is opened)
  • it gives some short beeps to warn me, waits for two seconds… and if I have not switched it off by that time, fires the siren.
    If the door is closed again, it will keep wailing for another 30 seconds.
/*
  Cable storage locker alarm
  
  ATTINY VERSION 2
 
 Callibration is based on
 http://arduino.cc/en/Tutorial/Calibration
 David A Mellis and Tom Igoe
 
By Peter_I 
2014
 
 The circuit:
 * LDR attached to analog input 1 and 5V with 10k pull down to GND
 * Siren attached digital pin 0
 * Piezo beeper attached to pin 1 (PWM)
 (If used on Arduino, adjust pins accordingly)
 
 Only sensorMax is interesting, and an "intrusion" is considered to be when
 "sensorMax + treshold" is exceeded.
 "Intrusion" results short beeps, 2 sec delay followed by the siren.
 The short beeps will remind me to switch off the alarm when I open the locker.
 
 */

//The constants:
const int sensorPin = A1;     // pin that the sensor is attached to
const int sirenPin = 0;        // pin that the LED is attached to, 0 on ATTiny
const int beepPin = 1;        // piezobeeper on PWM pin
const int treshold = 100;      // treshold value
const int beepLength = 1000;     // A long beep, max 1500ms
const int shortBeep = 100;      // and a shorter beep
const int sirenTime = 30000; // How long to wail


// variables:
int sensorValue = 0;         // the sensor value
int sensorMax = 0;           // maximum sensor value
long previousMillis = 0;        // for timing
unsigned long currentMillis = 0; // for timing

void setup() 
{
// Serial.begin(9600);    // comm, disable on ATTiny
// turn on LED to signal the start of the calibration period:
pinMode(sirenPin, OUTPUT);
pinMode (beepPin, OUTPUT);

analogWrite(beepPin, 128);  //5 beeps to give time to close box
delay (beepLength);
analogWrite(beepPin, 0);
delay (beepLength);
analogWrite(beepPin, 128);
delay (beepLength);
analogWrite(beepPin, 0);
delay (beepLength);
analogWrite(beepPin, 128);
delay (beepLength);
analogWrite(beepPin, 0);
// calibrate during the next five seconds
while (millis() < 10000) 
{
sensorValue = analogRead(sensorPin);
// record the maximum sensor value
if (sensorValue > sensorMax) 
{
sensorMax = sensorValue;
//      Serial.print("sensorMax=   ");
//      Serial.println(sensorMax);
}
}
// signal the end of the calibration period
analogWrite(beepPin, 128);  //Long beep to signal "ARMED"
delay (2*beepLength);
analogWrite(beepPin, 0);
}

void loop() 
{
sensorValue = analogRead(sensorPin);  // read the sensor
if (sensorValue > treshold + sensorMax)  //is there light from an open door?
{
//   Serial.println(sensorValue);
//3 quick beeps to signal "Alarm tripped!"
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
// end of beepery. Now, you have 2 more seconds to switch off, or I'll scream
delay (2000);        // said 2 seconds
digitalWrite (sirenPin, HIGH); // You didn't make it:  Wheeeeeeeeeeeeeeeeeeeeeeeeeee!
delay (sirenTime);         
}
else 
digitalWrite (sirenPin, LOW);      // off

delay (1); 
}

I’ll booby trap the locker with it in the week to come, and see if someone gets a surprise.
(I’ll let you know if something funny happens)
:smiley:

image.jpg

image.jpg

cable locker alarm schematic.jpg

...an awfully loud (and very cheap) "window alarm"...

Link?

[quote author=Coding Badly link=topic=215015.msg1573500#msg1573500 date=1391376674] Link? [/quote]

With pleasure.

I bought them at the local DIY shop, but they are identical to these: http://www.ebay.com/itm/6X-WIRELESS-Home-Window-Door-Entry-Burglar-Security-ALARM-System-Magnetic-Sensor-/281228498400

They simply work with a magnet and a reed switch. (And a small circuit to drive the piezo speaker)

Edit: Even cheaper (and free shipping) http://www.ebay.com/itm/Self-adhesive-Wireless-Magnetic-Sensor-Burglar-Door-Window-Entry-Alarm-90-dB-TE-/291054691265?pt=LH_DefaultDomain_0&hash=item43c43623c1

So you have two noise makers? A small piezoelectric beeper and that white thing which is extremely loud?

Yup.

The small beeper is for signaling "on, get the door closed", "end of calibration, going hot" and "hey, I was triggered. Switch off the power or the siren will be screaming"

Nice. I may have to build one.

Thanks!
:smiley:

I think I found just the example I need to make it sit in there and be alert for a loooong time on 3 AA batteries:
https://learn.sparkfun.com/tutorials/h2ohno/low-power-attiny

EDIT:
Children’s drawing schematic added to first post in thread.
The photos were a little unclear with regards to connections.

the sleep part is not as easy as I thought.

I copied piece by piece from here: https://github.com/sparkfun/H2OhNo/blob/master/firmware/WatchDogTest/WatchDogTest.ino

But when I came to: " setup_watchdog(3); //Wake up after 128 msec"

it gave me:

Kabelskabsalarm_ATtinySLEEP_Ver_3_FEB_2014.ino: In function 'void setup()': Kabelskabsalarm_ATtinySLEEP_Ver_3_FEB_2014:72: error: 'setup_watchdog' was not declared in this scope

I'm too tired to do anything about it now, I'll revisit it tomorrow. (or try to adjust the example given here: http://donalmorrissey.blogspot.dk/2010/04/sleeping-arduino-part-5-wake-up-via.html Then I'll just do the "closet open" evaluation instead of toggling the LED) :sleeping:

Bear in mind that there are some minor variations with the AVR watchdogs. Whoever wrote that Sparkfun article failed to mention which processor(s) they were targeting. Even if you get past the compiler problem, the code may not work as you expect.

When trying to conserve power, the first step is to slow the processor's clock. Is yours configured to run at 1 MHz?

Maybe have a look at Nick Gammon’s article “Power saving techniques for microprocessors“ here

  • It is configured to 8mHz, so there is a bit to get from that.

  • I've read Nick's power saving writeup with great interest.

I've not had the time to test it yet (family and work can really disturb your free time!).

If the above mentioned does not work, I think I'll try the library mentioned here: http://www.openhomeautomation.net/arduino-battery/ On the surface, it seems to be really simple to use. I would love to be able to just insert a Sleepy::loseSomeTime(1000); to make it sleep for a second. If that can drop my power consumption with a factor of 100, I'll be more than satisfied.

Jean-Claude Wippler has done significant good work with ATtiny processors. There is a high probability his library will work (and work well). Were I in your shoes I would not bother with the Sparkun stuff.

I installed the Jeelib.h.

But I think I’m missing some basic point.

My own code:

/*
  Cable storage locker alarm
  
  ATTINY VERSION 4
  With power saving
 
 Callibration is based on
 http://arduino.cc/en/Tutorial/Calibration
 David A Mellis and Tom Igoe
 
 Sleep is based on the example at:
 http://www.openhomeautomation.net/arduino-battery/
 
 By Peter_I 2014
 
 The circuit:
 * LDR attached to analog input 1 and 5V with 10k pull down to GND
 * Siren attached digital pin 0
 * Piezo beeper attached to pin 1 (PWM)
 (If used on Arduino, adjust pins accordingly)
 
 Only sensorMax is interesting, and an "intrusion" is considered to be when
 "sensorMax + treshold" is exceeded.
 "Intrusion" results short beeps, 2 sec delay followed by the siren.
 The short beeps will remind me to switch off the alarm when I open the locker.
 
 */


#include <Ports.h> // Low power functions library
#include <SoftwareSerial.h>

ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup the watchdog

//The constants:
const int sensorPin = A1;     // pin that the sensor is attached to
const int sirenPin = 0;        // pin that the LED is attached to, 0 on ATTiny
const int beepPin = 1;        // piezobeeper on PWM pin
const int treshold = 100;      // treshold value
const int beepLength = 1000;     // A long beep, max 1500ms
const int shortBeep = 100;      // and a shorter beep
const int sirenTime = 30000; // How long to wail


// variables:
int sensorValue = 0;         // the sensor value
int sensorMax = 0;           // maximum sensor value
long previousMillis = 0;        // for timing
unsigned long currentMillis = 0; // for timing

void setup() 
{
// Serial.begin(9600);    // comm, disable on ATTiny
// turn on LED to signal the start of the calibration period:
pinMode(sirenPin, OUTPUT);
pinMode (beepPin, OUTPUT);

analogWrite(beepPin, 128);  //5 beeps to give time to close box
delay (beepLength);
analogWrite(beepPin, 0);
delay (beepLength);
analogWrite(beepPin, 128);
delay (beepLength);
analogWrite(beepPin, 0);
delay (beepLength);
analogWrite(beepPin, 128);
delay (beepLength);
analogWrite(beepPin, 0);
// calibrate during the next five seconds
while (millis() < 10000) 
{
sensorValue = analogRead(sensorPin);
// record the maximum sensor value
if (sensorValue > sensorMax) 
{
sensorMax = sensorValue;
//      Serial.print("sensorMax=   ");
//      Serial.println(sensorMax);
}
}
// signal the end of the calibration period
analogWrite(beepPin, 128);  //Long beep to signal "ARMED"
delay (2*beepLength);
analogWrite(beepPin, 0);
}

void loop() 
{
sensorValue = analogRead(sensorPin);  // read the sensor
if (sensorValue > treshold + sensorMax)  //is there light from an open door?
{
//   Serial.println(sensorValue);
//3 quick beeps to signal "Alarm tripped!"
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
// end of beepery. Now, you have 2 more seconds to switch off, or I'll scream
delay (2000);        // said 2 seconds
digitalWrite (sirenPin, HIGH); // You didn't make it:  Wheeeeeeeeeeeeeeeeeeeeeeeeeee!
delay (sirenTime);         
}
else 
digitalWrite (sirenPin, LOW);      // off
delay (1);

Sleepy::loseSomeTime(5000);  //go to sleep, save some power, hug a tree!

}

And the “blink” example given at http://www.openhomeautomation.net/arduino-battery/

#include <JeeLib.h> // Low power functions library
int led_pin = 13;
ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup the watchdog

void setup() {
 pinMode(led_pin, OUTPUT);
}

void loop() {

 // Turn the LED on and sleep for 5 seconds
 digitalWrite(led_pin, HIGH);
 Sleepy::loseSomeTime(5000);

 // Turn the LED off and sleep for 5 seconds
 digitalWrite(led_pin, LOW);
 Sleepy::loseSomeTime(5000);
}

will compile and upload perfectly well.

But as soon as I choose the board to be Attiny85 (8mHz)
It gags when compiling, giving me:

In file included from Kabelskabsalarm_ATtinySLEEP_Ver_4_FEB_2014_ino.ino:30:
C:\Users\peter_I\Documents\Arduino\libraries\jeelib/Ports.h:700: error: ‘Serial’ was not declared in this scope
C:\Users\peter_I\Documents\Arduino\libraries\jeelib/Ports.h:701: error: ‘Serial’ was not declared in this scope

It looks a lot like the problem in this thread, that never ended up with a solution?

Here, http://jeelabs.net/boards/6/topics/307 the answer is given as:

A few more words for anyone with the same problem landing on this post:

I first used the instructions of this page: http://hlt.media.mit.edu/?p=1695 and downloaded the library from the ATtiny.zip link described there. Its contents are the same with the GitHub repository given on the same page. The zip contains a directory structure and 3 files: boards.txt, tiny14/pins_arduino.h and tiny8/pins_arduino.h . I didn’t pay attention to the directory names, tiny14 and tiny8, but these were not the ATtiny that I wanted to use.

The library that solved my compilation problem was downloaded from here: http://code.google.com/p/arduino-tiny/downloads/detail?name=arduino-tiny-0100-0015.zip . It contains a set of core files and a range of bootloaders for the ATtiny family of micro-controllers.

But I do not get the meaning of that, and when I attempt to get the zip, it tells me that:

This file has been deprecated. Another file would probably be better. Do you want to continue?

I said “no”.

(I have 4 atmega328 on the table. They look at me, snickering! but I think it is overkill to make a bare bones Arduino, just to keep a locker safe)

Which core are you using to get support for the ATtiny85 processor?

[quote author=Coding Badly link=topic=215015.msg1578010#msg1578010 date=1391638048]

Which core are you using to get support for the ATtiny85 processor?

[/quote]

I use the cores from the MIT high-low tech. And that could very well be the problem.

Are there a better set of cores to use somewhere? I can find references in lots of places, like here https://code.google.com/p/arduino-tiny/ but which one to choose?

As I understand it, I should go to the hardware folder in Arduino, put anything related to tinies away in another folder, and drag the new cores there instead?

You could take a look at Jack Christensens sleep code for the ATtiny85.

http://forum.arduino.cc/index.php?topic=167467.0

I have used it with this core without issues:

https://code.google.com/p/arduino-tiny/

Success!
Or at least not total failure
(I changed so many parameters, I’m not quite sure what made a difference :blush: )

Now it will compile, but still not fall asleep.
(This starts to remind me, of when the kids were small!)

I uninstalled the core, and reinstalled the one Erni linked to.
Then I transplanted major parts of the code from here:

(I tested it on a tiny with an LED. It goes to 5 microamps when sleeping!)
http://www.insidegadgets.com/2011/02/05/reduce-attiny-power-consumption-by-sleeping-with-the-watchdog-timer/

/*
 * Watchdog Sleep Example 
 * Demonstrate the Watchdog and Sleep Functions
 * LED on digital pin 0
 * 
 * KHM 2008 / Lab3/  Martin Nawrath nawrath@khm.de
 * Kunsthochschule fuer Medien Koeln
 * Academy of Media Arts Cologne
 *
 * Modified on 5 Feb 2011 by InsideGadgets (www.insidegadgets.com)
 * to suit the ATtiny85 and removed the cbi( MCUCR,SE ) section 
 * in setup() to match the Atmel datasheet recommendations
 */

#include <avr/sleep.h>
#include <avr/wdt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

int pinLed = 0;
volatile boolean f_wdt = 1;

void setup(){
  pinMode(pinLed,OUTPUT);
  setup_watchdog(8); // approximately 4 seconds sleep
}

void loop(){
  if (f_wdt==1) {  // wait for timed out watchdog / flag is set when a watchdog timeout occurs
    f_wdt=0;       // reset flag

    digitalWrite(pinLed,HIGH);  // let led blink
    delay(1000);
    digitalWrite(pinLed,LOW);

    pinMode(pinLed,INPUT); // set all used port to intput to save power
    system_sleep();
    pinMode(pinLed,OUTPUT); // set all ports into state before sleep
  }
}

// set system into the sleep state 
// system wakes up when wtchdog is timed out
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out 
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {

  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  WDTCR |= _BV(WDIE);
}
  
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
  f_wdt=1;  // set global flag
}

And it ended up looking like this:

Compiling, but not going to sleep like a good little Tiny should!

/*
  Cable storage locker alarm
  
  ATTINY VERSION 5
  With power saving according to http://www.insidegadgets.com/2011/02/05/reduce-attiny-power-consumption-by-sleeping-with-the-watchdog-timer/
 Code transplanted shamelessly from the "ATtiny85_watchdog_example"
 
 Callibration is based on
 http://arduino.cc/en/Tutorial/Calibration
 David A Mellis and Tom Igoe
 

 By Peter_I 2014
 
 The circuit:
 * LDR attached to analog input 1 and 5V with 10k pull down to GND
 * Siren attached digital pin 0
 * Piezo beeper attached to pin 1 (PWM)
 (If used on Arduino, adjust pins accordingly)
 
 Only sensorMax is interesting, and an "intrusion" is considered to be when
 "sensorMax + treshold" is exceeded.
 "Intrusion" results in short beeps, 2 sec delay followed by the siren.
 The short beeps will remind me to switch off the alarm when I open the locker.
 
 */

#include <avr/sleep.h>
#include <avr/wdt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


//The constants:
const int sensorPin = A1;     // pin that the sensor is attached to
const int sirenPin = 0;        // pin that the LED is attached to, 0 on ATTiny
const int beepPin = 1;        // piezobeeper on PWM pin
const int treshold = 100;      // treshold value
const int beepLength = 1000;     // A long beep, max 1500ms
const int shortBeep = 100;      // and a shorter beep
const int sirenTime = 30000; // How long to wail


// variables:
int sensorValue = 0;         // the sensor value
int sensorMax = 0;           // maximum sensor value
long previousMillis = 0;        // for timing
unsigned long currentMillis = 0; // for timing

volatile boolean f_wdt = 1;



void setup() 
{
setup_watchdog(8); // approximately 4 seconds sleep
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
// Serial.begin(9600);    // comm, disable on ATTiny
// turn on LED to signal the start of the calibration period:
pinMode(sirenPin, OUTPUT);
pinMode (beepPin, OUTPUT);

analogWrite(beepPin, 128);  //3 beeps to give time to close door
delay (beepLength);
analogWrite(beepPin, 0);
delay (beepLength);
analogWrite(beepPin, 128);
delay (beepLength);
analogWrite(beepPin, 0);
delay (beepLength);
analogWrite(beepPin, 128);
delay (beepLength);
analogWrite(beepPin, 0);
// calibrate during the next five seconds
while (millis() < 10000) 
{
sensorValue = analogRead(sensorPin);
// record the maximum sensor value
if (sensorValue > sensorMax) 
{
sensorMax = sensorValue;
//      Serial.print("sensorMax=   ");
//      Serial.println(sensorMax);
}
}
// signal the end of the calibration period
analogWrite(beepPin, 128);  //Long beep to signal "ARMED"
delay (2*beepLength);
analogWrite(beepPin, 0);
}

void loop() 
{
  if (f_wdt==1) // wait for timed out watchdog / flag is set when a watchdog timeout occurs
  {  
    f_wdt=0;       // reset flag
sensorValue = analogRead(sensorPin);  // read the sensor
if (sensorValue > treshold + sensorMax)  //is there light from an open door?
{
//   Serial.println(sensorValue);
//3 quick beeps to signal "Alarm tripped!"
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
// end of beepery. Now, you have 2 more seconds to switch off, or I'll scream
delay (2000);        // said 2 seconds
digitalWrite (sirenPin, HIGH); // You didn't make it:  Wheeeeeeeeeeeeeeeeeeeeeeeeeee!
delay (sirenTime);         
}   // end of "is there an intruder?" if loop
else 
digitalWrite (sirenPin, LOW);      // off
delay (1);

  } // end of watchdog loop

}  //end of void loop

// set system into the sleep state 
// system wakes up when wtchdog is timed out
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out 
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {

  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  WDTCR |= _BV(WDIE);
}
  
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
  f_wdt=1;  // set global flag
}

Your code never calls system_sleep.

Ouch, that was embarrassing!
:blush:
And it did the trick!
Wohoooooooooo!
Now it obediently goes to sleep, and wakes up once every second to see if there is anything to scream about.
It measures so quickly, that my multimeter can’t read how much current it draws. It just flickers a bit when measuring.

Currents during use (according to my cheap multimeter):

Starting and beeping: 19 mA
Calibrating: 7-8 mA
Idle in light: 0.3 mA (It will draw some current in light because of the LDR)
Activated, feeding power to transistor: 11 mA
Activated, siren screaming: 80 mA
Idle in total darkness: 8 microAmperes !!!

That is far better than anything I had dared hope for!
I do not have the means to measure the average power drawn, but I feel confident, that the short proportion of the time spent measuring, and reducing the idle current with a factor of 1000, should give me at least a year of battery life, instead of just a week.

…And I have learned the hard way, that the sleep code is different for different AVRs.
The code that will compile for the Uno, will not compile on the Attiny85 (and the other way around).
Choosing the right board when developing the code is important.

I have not checked, if that would have solved my previous problems (but it is not unlikely that it would).

The code, that could use a bit of cleaning up, so far:

/*
  Cable storage locker alarm
  
  ATTINY VERSION 7
  With power saving according to http://www.insidegadgets.com/2011/02/05/reduce-attiny-power-consumption-by-sleeping-with-the-watchdog-timer/
 Code transplanted shamelessly from the "ATtiny85_watchdog_example"
 
 Callibration is based on
 http://arduino.cc/en/Tutorial/Calibration
 David A Mellis and Tom Igoe
 

 By Peter_I 2014
 
 The circuit:
 * LDR attached to analog input 1 and 5V with 10k pull down to GND
 * Siren attached digital pin 0
 * Piezo beeper attached to pin 1 (PWM)
 (This code is tested on an Attiny85 @ 8 mHz with internal oscillator and BOD disabled,
 it will not compile on an Arduino Uno, because the sleep code for the 
Atmega328 is different)
 
 Only sensorMax is interesting, and an "intrusion" is considered to be when
 "sensorMax + treshold" is exceeded.
 "Intrusion" results in short beeps, 2 sec delay followed by the siren.
 The short beeps will remind me to switch off the alarm when I open the locker, and give me time
to switch off the alarm.
 
 */

#include <avr/sleep.h>
#include <avr/wdt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


//The constants:
const int sensorPin = A1;     // pin that the sensor is attached to
const int sirenPin = 0;        // pin that the LED is attached to, 0 on ATTiny
const int beepPin = 1;        // piezobeeper on PWM pin
const int treshold = 100;      // treshold value
const int beepLength = 1000;     // A long beep, max 1500ms
const int shortBeep = 100;      // and a shorter beep
const int sirenTime = 30000; // How long to wail


// variables:
int sensorValue = 0;         // the sensor value
int sensorMax = 0;           // maximum sensor value
long previousMillis = 0;        // for timing
unsigned long currentMillis = 0; // for timing

volatile boolean f_wdt = 1;



void setup() 
{
setup_watchdog(6); // approximately 1 second sleep
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
// Serial.begin(9600);    // comm, disable on ATTiny
// turn on LED to signal the start of the calibration period:
pinMode(sirenPin, OUTPUT);
pinMode (beepPin, OUTPUT);

analogWrite(beepPin, 128);  //3 beeps to give time to close door
delay (beepLength);
analogWrite(beepPin, 0);
delay (beepLength);
analogWrite(beepPin, 128);
delay (beepLength);
analogWrite(beepPin, 0);
delay (beepLength);
analogWrite(beepPin, 128);
delay (beepLength);
analogWrite(beepPin, 0);
// calibrate during the next five seconds
while (millis() < 10000) 
{
sensorValue = analogRead(sensorPin);
// record the maximum sensor value
if (sensorValue > sensorMax) 
{
sensorMax = sensorValue;
//      Serial.print("sensorMax=   ");
//      Serial.println(sensorMax);
}
}
// signal the end of the calibration period
analogWrite(beepPin, 128);  //Long beep to signal "ARMED"
delay (2*beepLength);
analogWrite(beepPin, 0);
}

void loop() 
{
  if (f_wdt==1) // wait for timed out watchdog / flag is set when a watchdog timeout occurs
  {  
    f_wdt=0;       // reset flag
delay (1);
sensorValue = analogRead(sensorPin);  // read the sensor
if (sensorValue > treshold + sensorMax)  //is there light from an open door?
{
//   Serial.println(sensorValue);
//3 quick beeps to signal "Alarm tripped!"
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
analogWrite(beepPin, 128);  
delay (shortBeep);
analogWrite(beepPin, 0);
delay (2*shortBeep);
// end of beepery. Now, you have 2 more seconds to switch off, or I'll scream
delay (2000);        // said 2 seconds
digitalWrite (sirenPin, HIGH); // You didn't make it:  Wheeeeeeeeeeeeeeeeeeeeeeeeeee!
delay (sirenTime);         
}   // end of "is there an intruder?" if loop
else 
{digitalWrite (sirenPin, LOW);      // off
    delay (1);
    
    system_sleep(); //Thanks to Coding Badly for reminding me of this line!
    
}  // end of else
  } // end of watchdog loop

}  //end of void loop

// set system into the sleep state 
// system wakes up when wtchdog is timed out
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out 
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {

  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  WDTCR |= _BV(WDIE);
}
  
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
  f_wdt=1;  // set global flag
}

I popped by a friend who is the owner of a magnificent oscilloscope.

"Waking up, doing the measurement and going back to sleep " takes 2.1 ms.

Doing that once a second must mean, that the power consumption is reduced by a factor 500 relative to being constantly on.

I could bring the time lower, since I've given it a delay of 1 ms before measuring (to let it stabilize) and measuring once a second, is far more often than needed. Every second or every fourth second should be plenty.

But my back-of-a-napkin estimate tells me, that from a 2000 mA/h battery pack, that should give me something like 10 years of stand by. The batteries are likely to die from age or boredom before then.

I'll measure the batteries in a couple of months, and see how they are.

(And should some cable pilfering student get a shock during pilferous activities, I'll tell it here too :grin: )