ATTINY85 Magnetic Door Sensor (3xAAANiMh 1.2v)(RESOLVED)

Go To Last Post
62 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <RCSwitch.h>
const int sensor = 3;
RCSwitch mySwitch = RCSwitch();

void sleep() {
    GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
    PCMSK |= _BV(PCINT3);                   // Use PB3 as interrupt pin
    ADCSRA &= ~_BV(ADEN);                   // ADC off
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement
    sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
    sei();                                  // Enable interrupts
    sleep_cpu();                            // sleep
    cli();                                  // Disable interrupts
    PCMSK &= ~_BV(PCINT3);                  // Turn off PB3 as interrupt pin
    sleep_disable();                        // Clear SE bit
    ADCSRA |= _BV(ADEN);                    // ADC on
    sei();                                  // Enable interrupts
}

ISR(PCINT0_vect) {

}

void initADC()
{
  ADMUX = (1 << ADLAR) | (0 << REFS1) | (0 << REFS0) | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (0 << MUX0);      

  ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0);
}

void setup() {
initADC();
pinMode(sensor, INPUT_PULLUP);
mySwitch.enableTransmit(1);
mySwitch.setProtocol(1);
mySwitch.setPulseLength(401);
mySwitch.setRepeatTransmit(5);
}

void loop() {
    ADCSRA |= (1 << ADSC);
    while (ADCSRA & (1 << ADSC) );

    if (ADCH > 180)
    {
      int state;
      state = digitalRead(sensor);
        if (state == HIGH){
          mySwitch.send(10107000, 24); //On
          delay(2000);
          sleep();
        }
        else{
          mySwitch.send(10108000, 24); //Off
          delay(2000);
          sleep();
        }
    }
    else {
    mySwitch.send(10109000, 24); //low battery code
    delay(2000);
    sleep();
    }

}

Is this code any good?? 

It suppose to be a door sensor that should send the state signal and then goes to sleep and wakes again when the interrupt pin changes.

I am not able to send the close command when i shut the door.

please help me :)

This topic has a solution.
Last Edited: Sun. Apr 25, 2021 - 05:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Welcome to AVR Freaks!

 

Does it send other commands? Is your wireless link even working? How have you tested it?

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi and thank you for your response.

The 3 codes are being received by an ESP32 with OpenMQTTGateway installed.

That is connected to the Home Assistant & Node-Red.

I made an Node-Red RF433 "Filter" that does the magic with the code.

These 3 commands are the only 3 commands it will send ON/OFF/LOWPOWER | 10107000/10108000/10109000

When i open the door it will send the ON command, but when i close it, it does not send the OFF command

Maybe my code is not right and i needed a bit of a help.

is it possible the interupt pin only wakes the attiny up when the pin is high and not when low?

The voltage is measured by PB4/pin3 with the internal reference voltage.

And a MC-38 magnetic sensor is connected to the PB3/pin2.  [acts as interrupt]

Best Regards

danny

Last Edited: Sun. Feb 7, 2021 - 10:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If that is the case, then it is most certainly code. I've not looked at it in detail.

 

I don't see what wakes it up. In most I have used, you need to set a wakeup source. 

 

Do you know that the door sensor is properly reporting the door state?

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi and thank you again,

 

the wake-up source is the mc38 magnetic sensor connected to PB3.

And yeah only the on state :)

regards

 

danny

Last Edited: Sun. Feb 7, 2021 - 10:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not sure what you mean by

 

only the on state

 

Does it not generate an interrupt when going from open to close?

 

Jim 

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Sun. Feb 7, 2021 - 10:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

It could be i have to check my wiring on the board, but before is do i wanted to make sure my code was alright :P

Maybe someone could see an error or so :)

I am quite new to this and im learning like crazy. 

I have a long way to go :P

 

I have an attiny85 with an mc-38 magnetic door sensor and 1 rf433 transmitter module connected to 3 AAA battery's with a voltage regulator to keep it 5V as internal voltage reference

-the battery live wire is connected to the regulator and to the ADC2/PB4/Pin3

-the regulated 5v goes to the VCC [This is how i measure the battery status]

- The MC38 is connected to PB3/Pin2 - It should act as an interrupt

- The RF433 transmitter is connected to PB1 and vcc and gnd

 

When i go from close to open it works, but when i go from open to close it stops

it looks like it wont interrupt when i go from open to close 

danny

Last Edited: Sun. Feb 7, 2021 - 10:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you put a volt meter on the door sensor line, what do you see when you open the door and when you close the door?

 

Door sensors tend to use magnetic reed switches. These don't bounce much, but they are STILL mechanical switches and mechanical switches DO bounce. This always creates problems when you try to use with interrupts. Cannot be confident but my hunch is that might be part of it. The IMPORTANT question is what your volt meter shows.

 

Is Arduino Pin3 the same as PB3? Just noticed, your last post. You say PB3/pin2. Yet you have the pullup turned on for Arduino pin3. Turn on the pull-up for the pin you are actually using. Then, I think it will work better

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Mon. Feb 8, 2021 - 02:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 

Yeah PB3 is fysical pin 2 :)

i thought sensor = 3  is sensor is PB3?

I will check with the volt meter :) but gotto go now to work:P

 

greets,

 

danny

Last Edited: Mon. Feb 8, 2021 - 05:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As far as I understand, 

 

pinMode(sensor, INPUT_PULLUP);

Refers to the Arduino IO pin number. If it were PB3, there would have to be something to distinguish it from, let's say PA3 or PC3 (not that the Tiny85 has either of these). You have to visualize this in the context of a function that has to work with all of the Arduino boards. Note in the reference, below, the argument "pin" refers to "Arduino Digital pin number".

 

Jim

 

Reference

 

Syntax

pinMode(pin, mode)

Parameters

pin: the Arduino pin number to set the mode of.
mode: INPUT, OUTPUT, or INPUT_PULLUP. See the Digital Pins page for a more complete description of the functionality.

Returns

Nothing

Example Code

The code makes the digital pin 13 OUTPUT and Toggles it HIGH and LOW

void setup() {
  pinMode(13, OUTPUT);    // sets the digital pin 13 as output
}

void loop() {
  digitalWrite(13, HIGH); // sets the digital pin 13 on
  delay(1000);            // waits for a second
  digitalWrite(13, LOW);  // sets the digital pin 13 off
  delay(1000);            // waits for a second
}

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Mon. Feb 8, 2021 - 08:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks man for all your help :)

I removed the code and the function sleep is not used at the moment.

I added a buzzer to PB1 or just Digital Pin 1

and the sensor at PB1

This little code does the job at the moment and im going to improve it :)

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

#define INTERRUPT_PIN PCINT3 
#define INT_PIN PB3    
void sleep() {
    GIMSK |= (1 << PCIE);                     // Enable Pin Change Interrupts
    PCMSK |= (1 << INTERRUPT_PIN);                  // Use PB3 as interrupt pin
    ADCSRA &= ~_BV(ADEN);                   // ADC off
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement
    sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
    sei();                                  // Enable interrupts
    sleep_cpu();                            // sleep
    cli();                                  // Disable interrupts
    PCMSK &= ~_BV(INTERRUPT_PIN);                  // Turn off PB3 as interrupt pin
    sleep_disable();                        // Clear SE bit
    ADCSRA |= _BV(ADEN);                    // ADC on
    sei();                                  // Enable interrupts
}
void setup() {
   pinMode(INT_PIN, INPUT_PULLUP);
   GIMSK |= (1 << PCIE);                     // Enable Pin Change Interrupts
   PCMSK |= (1 << INTERRUPT_PIN);  
   pinMode(1, OUTPUT);                         
}

ISR(PCINT0_vect)
{
  if( digitalRead(INT_PIN) == HIGH ) {
  digitalWrite(1, HIGH);
  }else{
 digitalWrite(1, LOW);
  }
}

void loop(){
  
  
  
  }

 

Last Edited: Tue. Feb 9, 2021 - 07:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bump

 

Last Edited: Fri. Feb 19, 2021 - 07:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not familiar with the ardreno code how interrupts work but typically you don't call the interrupt from the main loop the hardware vectors the pin change to the interrupt code

 

But anyway , Here is a sample code (GCC compiler)  not using interrupts. It polls the pin, waits 100 ms and then polls the pin a second time allowing for the bounce in mechanical switches.

Once it sends your switch code it waits in a loop until the pin is changed again, polling and then sleeping and continuing the while loop and sleeping if its still set or cleared for each state to allow for bounce.

 

If you use a hardware interrupt you would set a flag in the interrupt to signal the main loop the pin state has changed and the same code would then just be checking the flag variable instead of the pin port directly.

That flag would be declared using volatile keyword so it is only changed by the interrupt itself.

 

That way the switch code is only sent once for each state. Of course you can add switch code sending in the sleep loop to send every x seconds while waiting for the state to change.

 

 

int main()
{
	while(1)
	{
		if( PINB = PINB & (1 << INT_PIN))
		{
			delay(100);
			if( PINB = PINB & (1 << INT_PIN))
			{
				mySwitch.send(10107000, 24);
			}
		}
		
		while(PINB = PINB & (1 << INT_PIN))
		{
			enters_sleep();
		}
		
		
		if ( !(PINB = PINB & (1 << INT_PIN )))
		{
			delay(100);
			if (!(PINB = PINB & (1 << INT_PIN )))
			{
				mySwitch.send(10108000, 24);
			}
			
			while(!(PINB = PINB & (1 << INT_PIN)))
			{
				enters_sleep();
			}
			
		}
	}
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <RCSwitch.h>

#define INTERRUPT_PIN PCINT3
#define INT_PIN PB3

RCSwitch mySwitch = RCSwitch();

int timerhigh = 0;
int timerlow = 0;

void setup() {
  mySwitch.enableTransmit(1);
  mySwitch.setProtocol(1);
  mySwitch.setPulseLength(320);
  mySwitch.setRepeatTransmit(5);
  pinMode(INT_PIN, INPUT_PULLUP);
  external_interrupt();

}

ISR (PCINT0_vect){
  MCUCR&=~(1<<SE);    
}
 
void external_interrupt()
{
  sei();                //enabling global interrupt
  GIMSK|= (1<<PCIE);    //Pin change interrupt enable
  PCMSK|=(1<<INTERRUPT_PIN);
}

void enters_sleep()
{
  MCUCR|=(1<<SM1);      // enabling sleep mode and powerdown sleep mode
  MCUCR|= (1<<SE);     //Enabling sleep enable bit
  __asm__ __volatile__ ( "sleep" "\n\t" :: ); //Sleep instruction to put controller to sleep
  //controller stops executing instruction after entering sleep mode
} 

void loop() {

if( PINB = PINB & (1 << INT_PIN)){
 delay(100);
  if( PINB = PINB & (1 << INT_PIN)){
   mySwitch.send(10107000, 24);
  }
  while(PINB = PINB & (1 << INT_PIN)){
   enters_sleep();
  }
}
if ( !(PINB = PINB & (1 << INT_PIN ))){
 delay(100);
  if (!(PINB = PINB & (1 << INT_PIN ))){
   mySwitch.send(10108000, 24);
  }
  while(!(PINB = PINB & (1 << INT_PIN))){
   enters_sleep();
  }
 }
}

I hope i understood it a little right.

Is this a bit what you meant?

My solution did work but i knew it was not perfect.

 

I am a real newbie and i am trying to learn this.

Please forgive me if i am a bit slow in some things.

 

thanks for your feedback

 

danny

Last Edited: Fri. Feb 12, 2021 - 05:51 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks good, how is it working? 

 

By the way you don't need the interrupt code, the code is reading the pin in the main loop.

 

If you do want to use an interrupt you need a function that gets control when the interrupt triggers. In that code you would have one line of code to set a flag variable. In the main loop then you would only have to 

compare the flag variable if its 1 or 0 instead of reading the pin. You don't need an interrupt because this is all your code is doing, polling one pin. If you had all kinds of code doing all kinds of things

you could still get buy without an interrupt depending on how long you could wait for the main loop to call the function that reads the pin.

 

For example a microsecond  timer that starts and stops on a pin change where you want very accurate timing would need to use an interrupt on the pin change to immediately vector the code to the interrupt routine

and INTERRUPT the code running in your main loop at the next instruction where that code might store a time variable of exactly when the pin changed and then return to your main code as if it never happened.

Like an oscilloscope probe reading high and low signals for example needs very fast response.

 

  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi and thanks again,

 

yeah i actually forgot the 

ISR (PCINT0_vect){
  MCUCR&=~(1<<SE);    
}

 

I always thought you need an interrupt to wake from sleep.

I can test it without :)

I am going to test it today and will I will let you know :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

bump

Last Edited: Fri. Feb 19, 2021 - 10:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
bump
Last Edited: Fri. Feb 19, 2021 - 07:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
bump
Last Edited: Fri. Feb 19, 2021 - 07:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know how your sleep code works, I was assuming it might sleep for a few seconds and then return where the loop I had it in would again test for a pin change. Yes the other way is to use an interrupt to break out of sleep but adrino code I don't know how that works. When doing an interrupt you set the interrupt flag on and you also have code for what happens when the interrupt triggers, I don't see that code.

 

Here is an example (codevision compiler) of two interrupts being set up. The main program sets the proper bits to initialize the interrupts, the interrupt routines are executed when a hardware interrupt triggers.

 

#include <tiny45.h>

// Declare your global variables here

// Pin change interrupt service routine
interrupt [PC_INT0] void pin_change_isr(void)
{
//Code to execute on interrupt pin change

}

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Code to execute on interrupt
}

void main(void)
{

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Any change
// Interrupt on any change on pins PCINT0-5: On
GIMSK=(1<<INT0) | (1<<PCIE);
MCUCR=(0<<ISC01) | (1<<ISC00);
PCMSK=(0<<PCINT5) | (0<<PCINT4) | (1<<PCINT3) | (0<<PCINT2) | (0<<PCINT1) | (0<<PCINT0);
GIFR=(1<<INTF0) | (1<<PCIF);


// Globally enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

      }
}

 

Last Edited: Wed. Feb 17, 2021 - 05:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

These:

boolean wdt = 0;
int wdtcounter = 0;

MUST be volatile:

volatile boolean wdt = 0;
volatile int wdtcounter = 0;

Read:

 

https://www.avrfreaks.net/forum/...

 

to find out why.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah i read it and thank you for this. :)

I will change it to volatile in the code

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi metron,

 

thanks for your help, i am trying to understand what you mean :P

I have updated my solution every time since hoping someone could correct  my mistakes so i will learn more.

interrupt [PC_INT0] void pin_change_isr(void)
{
//Code to execute on interrupt pin change

}
ISR (PCINT0_vect){
  MCUCR&=~(1<<SE);
} 

is this the same? 

 

 

GIMSK=(1<<INT0) | (1<<PCIE);

MCUCR=(0<<ISC01) | (1<<ISC00); // this i did not see before and will check this in the datasheet thanks for the info

my int0 has nothing connected to, do I need this still?

 

thanks for all the help,

 

Danny

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

should i also use 

uint8_t instead of int? oer does it not matter?
Last Edited: Wed. Feb 17, 2021 - 05:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 if(wdt == 0){
  if ( digitalRead(INT_PIN) == HIGH){
    delay(2000);
    if ( digitalRead(INT_PIN) == HIGH){
     mySwitch.send(10109125, 24);
    }
  while( digitalRead(INT_PIN) == HIGH ){
    enters_sleep();
   }
  }
  if( digitalRead(INT_PIN) == LOW){
    delay(2000);
    if( digitalRead(INT_PIN) == LOW){
     mySwitch.send(10109150, 24);
    }
    while( digitalRead(INT_PIN) == LOW ){
     enters_sleep();
    }
   }
  }
}

thanks for this 1 metron :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

 

degiel1982 wrote:

should i also use 

uint8_t instead of int? oer does it not matter?

Because it is so important that the software in cars does not have major bugs (imagine an ABS system that applied the brakes at the wrong time or a cruise control that could not hold the desired speed!) there is a body called The Motor Industry Software Reliability Association ("MISRA") that have drawn up an agreed standard across all the world's major motor manufacturers for how to write safe, reliable software. They effectively produce a "rule book" that says "when writing C you must do this, this and this and you must not do that, that and that". Among their many rules is one that says you should not use native C types unsigned char, signed char, unsigned short, signed short, unsigned int, signed int, unsigned long, signed long but must, instead, use the types defined in <stdint.h>. The AVR micro is actually a very good illustration of why this should be as it's unusual in that an in t is just 2 bytes and can either represet 0..65535 or -32768..+32767. So if someone wrote some code for one CPU where sizeof(int)==4 then brought that code to an AVR then a simple looking line like:

int n = 123456;

would not work on an AVR as intended. On the AVR 'n' would contain -7616. If the author had used:

int32_t n = 123456;

then whatever CPu that is built for n will contain 123456 because an int32_t will always accommodate the value 123456.

 

So, yes, my answer would be that you should always use <stdint.h> types. The one exception MISRA make is the type "char". Not everyone realises this but there are THREE types of char. They are "unsigned char", "signed char" and "char". If you were going to use unsigned/signed char you should use uint8_t/int8_t but if the variable really is holding characters like "char c = 'X';" then that is the one occasion you might use one of the base types.

 

https://bullwhip.physio-control....

https://bullwhip.physio-control....

https://uk.mathworks.com/help/bu...

https://lost-contact.mit.edu/afs...

 

 

Last Edited: Thu. Feb 18, 2021 - 10:49 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bump

Last Edited: Sat. Feb 20, 2021 - 02:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
bump
Last Edited: Sat. Feb 20, 2021 - 02:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

CHANGED 27/02/21:

 

Watchdog(6 sec interrupt), 12 hourly voltage update

 

#include <SystemStatus.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <RCSwitch.h>
#include <avr/delay.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

#define F_CPU 8000000
volatile long wdcount = 0;
boolean old = 0;
volatile boolean f_wdt;
RCSwitch mySwitch = RCSwitch();
volatile boolean first = 1;
void setup() {
setup_watchdog(8);
//All pins set to something
pinMode(0, INPUT_PULLUP);
pinMode(2, OUTPUT); // VCC RF Transmitter
pinMode(3, INPUT_PULLUP); //MC-38 Sensor
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
digitalWrite(2,LOW);

//rcswitch setup

 mySwitch.enableTransmit(1);
 mySwitch.setProtocol(1);
 mySwitch.setPulseLength(320);
 mySwitch.setRepeatTransmit(15);
}

void loop() {
 if(f_wdt ==1){

  f_wdt=0;
    if((wdcount == 5 && first ==  1) || wdcount == 43200){
      if(wdcount == 43200){
        wdcount = 0;
      }
      if(first == 1){
        first = 0;
      }
       //enable ADC
       ADCSRA |= (1 << ADEN);
       digitalWrite(2,HIGH);
       delay(500);
       int vcc = SystemStatus().getVCC();
       String strVcc = String(vcc);
       strVcc = "1110" + strVcc;
       long vcc2 = strVcc.toInt();
       mySwitch.send(vcc2, 24);
       delay(500);
       digitalWrite(2,LOW);   

     }

  if ( digitalRead(3) == HIGH && old == 1){
    old = 1;
  }
  if ( digitalRead(3) == LOW && old == 0){
    old = 0;
  }
  if ( digitalRead(3) == LOW && old == 1){
    digitalWrite(2,HIGH);
    delay(500);
    old = 0;
    mySwitch.send(10109125, 24);
    delay(500);
    digitalWrite(2,LOW);

  }
  if ( digitalRead(3) == HIGH && old == 0){
    digitalWrite(2,HIGH);
    delay(500);
    old = 1;
    mySwitch.send(10109150, 24);
    delay(500);
    digitalWrite(2,LOW);
  }

  delay(500);
  system_sleep();

 }
}

void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF
  power_all_disable();
  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
  power_all_enable();
}

ISR(WDT_vect) {
 f_wdt = 1;
 wdcount++;

}

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);
}

 

 

 

 

Last Edited: Tue. Mar 2, 2021 - 05:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you even know if your door sensor is 100% working?  Did you first try hooking it to an led (or drive an led pin from the avr) to verify it is at least showing both door opening & closing ?? That should be the first step.  If you don't know 100% find out.  Maybe you already did.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I did ;), it works it has been tested.

I still have to test the batterylife but it looks like it works.

   

 

even with fast on off switching it does not get bothered and updates to the right state until now.

It did not hang once or gave me the wrong state

The sleep mode is quite new to me and that is the only thing im not sure about if it actually works. but it does the 2 second time change so i guess so :P

I have no possibility yet to measure mAh or lower ( no good multimeter)

 

my next thought was maybe when the door sensor has for 1 minute the same state it wont wake up every 2 seconds but stays to sleep until maybe a pin interrupt has been triggered and go back to the 2 second timer sleep

 

 

 

 

Last Edited: Sat. Feb 20, 2021 - 08:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So far so good!!!  On the 50th opening you will find 20 million cash behind the door.  

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lol i hope so :)

it could be possible i miss something while it is working. if somebosy notice please tell me

Last Edited: Sat. Feb 20, 2021 - 08:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lol i found an issue :P 

it seems that my old variable is not saved and stays at 0

is that normal when going to sleep mode? can i do something about this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As  a moderator, I find your bumps very, very annoying. If you don't get answers within YOUR time frame... stiff luck. Others have lives that do not revolve around you. Learn to live with it.

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for your opinion :)

I bumped the messages because it was not important info and wrong code, not because I did not get any answers:)

I can understand you find it annoying and I'm sorry

maybe till next time :)

 

 

Last Edited: Sun. Feb 21, 2021 - 07:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

issue is btw resolved. i added it in the solution

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2


 

 

CONTACT/PIR Sensor Code for ATTINY85 RF433 (3x AAA 1.2v Rechargeable Batterys)

 

NOTE IN ADVANCE: 

I use a 3.3V Step-Up/Step-Down Voltage Regulator w/ Fixed 3V Low-Voltage Cutoff S9V11F3S5C3 from Polulu for my 5V and 3.3v projects

It also cuts off at 3V to save your battery when almost empty.

 

External Libraries used:

 

rc-switch

 

EnableInterrupt

 

-  AttinyCore SpenceKonde 

 

Code:

#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/delay.h>
#include <EnableInterrupt.h>
#include <RCSwitch.h>

#define F_CPU 8000000UL

RCSwitch mySwitch = RCSwitch();

volatile boolean stateSensor = 0;
volatile boolean watchdogInterruptFlag = 0;
volatile int counter = 0;
volatile boolean firstVccReadFlag = 0;
volatile boolean previousSensorState  = 0;

/****************************************************/
const boolean device = 0;                           // 0 = Contact Sensor | 1 = PIR Sensor
/****************************************************/
const unsigned int deviceID = 1010;
const unsigned int openRFcode_P = 9250;
const unsigned int closedRFcode_P = 9225;
/****************************************************/
const boolean enableVoltage = 1;                     // Don't need voltage readings? turn this off
const unsigned int vccSampleAmount = 100;            // The first voltage reading is mostly not perfect. So here you can choose how many samples it should take before giving you an averaged result.
/****************************************************/
const boolean enableADC = 0;                         // When enabled it will read the voltage from pin (PB4) if you have enableVoltage enabled. When disabled it will read the internal voltage if you have enableVoltage enabled
float ADCVoltageRef = 5;                             // The voltage you give your attiny85 if you have powered yours with 3.3V then enter 3.3
/*****************************************************/
const unsigned int voltageTransmission_Seconds = 0;
const unsigned int voltageTransmission_Minutes = 0;
const unsigned int voltageTransmission_Hours = 2;
/*****************************************************/
const boolean enableWatchdog = 1;
/*****************************************************/

unsigned long calculateTransmissionTime(unsigned int Seconds1,unsigned int Minutes1,unsigned int Hours1){
  unsigned int result1 = 0;
  result1= round(((Seconds1*1)+(Minutes1*60)+(Hours1*3600)) / (8));
  return result1;
}
const unsigned long voltageTransmissionTime = calculateTransmissionTime(voltageTransmission_Seconds,voltageTransmission_Minutes, voltageTransmission_Hours);

long stringify(unsigned int deviceID, unsigned int rfCode){
  String SdeviceID = String(deviceID);
  String SrfCode = String(rfCode);
  String SfullCode = SdeviceID + SrfCode;
  long  fullCode = SfullCode.toInt();
  return fullCode;

}

const unsigned long openRFcode = stringify(deviceID, openRFcode_P);
const unsigned long closedRFcode = stringify(deviceID, closedRFcode_P);

void sensorInterrupt(void){}

void initADC(){
  ADMUX = (1 << ADLAR) | (0 << REFS1) | (0 << REFS0) | (0 << MUX3)  | (0 << MUX2)  | (1 << MUX1)  | (0 << MUX0);
  ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0);
}

long samplingVcc(unsigned int sampleAmount){
  unsigned long sumResult = 0;
  unsigned int a = 0;
  if(!enableADC){
      ADMUX = _BV(MUX3) | _BV(MUX2);
      ADCSRA |= (1 << ADEN);
      a = 0;
      do{;
        sumResult = sumResult + readVCC_Internal();
        a++;
      }
      while(a < sampleAmount);
      ADCSRA &= ~(1 << ADEN);
      a = 0;
      sumResult = round(sumResult / sampleAmount);
      return sumResult;
  }
  else{
    ADCSRA |= (1 << ADEN);
    ADCSRA |= (1 << ADSC);
    a = 0;
    do{
      sumResult = sumResult + readVCC_ADC(ADCVoltageRef);
      a++;
    }
    while(a < sampleAmount);
      ADCSRA &= ~(1 << ADEN);
      a = 0;
      sumResult = round(sumResult / sampleAmount);
      return sumResult;
  }
}
long readVCC_ADC(unsigned int VoltageRef){
  float mvSteps = ((VoltageRef * 1000) / 256);
  int result;
  while (ADCSRA & (1 << ADSC) );
  result = ADCH * mvSteps;
  result = round(result);
  return result;
}
long readVCC_Internal(){
  delay(20); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring
  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH; // unlocks both
  long result = (high<<8) | low;
  result = 1126400L / result; // Calculate Vcc (in mV); 1126400 = 1.1*1024*1000
  result = round(result);
  return result;
}

ISR(WDT_vect) {
  counter = counter + 1;
  watchdogInterruptFlag = 1;
}

void sendRF(long rfCode){
  digitalWrite(2, HIGH);
  mySwitch.send(rfCode, 24);
  digitalWrite(2, LOW);
}

void goToSleep (){
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  ADCSRA &= ~(1 << ADEN);         // turn off ADC
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  sleep_enable();
  sleep_cpu();
  sleep_disable();
  power_all_enable();    // power everything back on
}

void setup() {
  if(enableWatchdog==1){
  setup_watchdog(9);
  }
  mySwitch.enableTransmit(1);
  mySwitch.setProtocol(1);
  mySwitch.setPulseLength(400);
  mySwitch.setRepeatTransmit(15);
  if(!enableADC){
    pinMode(4, INPUT_PULLUP);
  }
  else{
    initADC();
  }
  pinMode(3, INPUT_PULLUP);
  pinMode(0, INPUT_PULLUP);
  pinMode(2, OUTPUT);
  if(!device){
    enableInterrupt(PB3, sensorInterrupt, CHANGE);
  }
  else{
    enableInterrupt(PB3, sensorInterrupt, RISING);
  }
}

void loop() {
  disableInterrupt(PB3);

    if(!watchdogInterruptFlag){
      if(!device){
        stateSensor = digitalRead(3);
        if(stateSensor && previousSensorState==0){
          previousSensorState=1;
          sendRF(openRFcode);
          delay(1000);
          stateSensor = digitalRead(3);
          if(stateSensor){
            if(!enableWatchdog && enableVoltage){
              long voltageReading = stringify(deviceID, samplingVcc(vccSampleAmount));
              delay(100);
              sendRF(voltageReading);
            }
            enableInterrupt(PB3, sensorInterrupt, CHANGE);
            goToSleep ();
          }
        }
        else if(!stateSensor && previousSensorState == 1){
          previousSensorState=0;
          sendRF(closedRFcode);
          delay(1000);
          stateSensor = digitalRead(3);
          if(!stateSensor){
            if(!enableWatchdog && enableVoltage){
              long voltageReading = stringify(deviceID, samplingVcc(vccSampleAmount));
              delay(100);
              sendRF(voltageReading);
             }
            enableInterrupt(PB3, sensorInterrupt, CHANGE);
            goToSleep ();
          }
        }
        else{
          enableInterrupt(PB3, sensorInterrupt, CHANGE);
          goToSleep ();
        }
      }
      else{
        digitalWrite(2, HIGH);
        mySwitch.send(openRFcode, 24);
        digitalWrite(2, LOW);
        enableInterrupt(PB3, sensorInterrupt, RISING);
        goToSleep ();
      }
   }
   else{
      watchdogInterruptFlag = 0;

      if(counter == 5 && !firstVccReadFlag && enableVoltage==1 && enableWatchdog==1){
        firstVccReadFlag = 1;
        long voltageReading = stringify(deviceID, samplingVcc(vccSampleAmount));
        delay(100);
        sendRF(voltageReading);
        if(!device){
          enableInterrupt(PB3, sensorInterrupt, CHANGE);
        }
        else{
          enableInterrupt(PB3, sensorInterrupt, RISING);
          goToSleep ();
        }
      }
      else if(counter == voltageTransmissionTime && firstVccReadFlag == 1 && enableVoltage==1 && enableWatchdog==1){
        counter = 0;
        long voltageReading = stringify(deviceID, samplingVcc(vccSampleAmount));
        delay(100);
        sendRF(voltageReading);
        if(!device){
          enableInterrupt(PB3, sensorInterrupt, CHANGE);
        }
        else{
          enableInterrupt(PB3, sensorInterrupt, RISING);
          goToSleep ();
        }
      }
      else{
        if(device){
          enableInterrupt(PB3, sensorInterrupt, RISING);
          goToSleep ();
        }
      }
   }
}

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);
} 

 

 

PIR Sensor Schematic (5V with ADC)

 

 

 

 

MC-38 Contact Sensor Schematic:

 

 

Last Edited: Sat. May 1, 2021 - 04:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

finally done :P improvements in the code are helpfull, if someone would like :)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all i have a question:

 

I wanted to set all pins to input what is possible when go to sleep and back to the original state when wake up.

Is it even possible to do that with the RF module pin 1?

Make it input then output?

 

thanks in advance

 

greetings

 

danny

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Normally, in sleep, the pins stay the way they were. If you need some special pin condition during sleep, set the pin that way just before entering sleep.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi again and thanks for the reply.

 


void goToSleep (){
  DDRB &= ~(1 << PB2);
  PORTB |= (1 << PB2);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  cbi(ADCSRA,ADEN);
  power_all_disable ();
  sleep_enable();
  sleep_cpu();
  sleep_disable();
  power_all_enable();
  DDRB |= (1 << PB2);
  PORTB &= ~(1 << PB2);
}

did you mean something like this?

With my RF module i am not specifying the pin 1 as output or input. just enableTransmit(1)

I was hoping i could change that to input and back to enable transmit. only dont know how :)

Thanks for all the help.

 

Regards 

Danny

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This project is very interesting, may I ask if there is a video demonstration when it is completed?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Hey hello :), thanks for your reply.

Eventually I will do this. I am still not happy with the code...

 

I am almost done with the new approach and currently i am testing it, but looks promising.

When I am done i will make an instructable about it :)

 

Thanks for your interest, just give me a bit time :)

This is the screenshot i have from my Home Assistant

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi again :)

 

My code has been updated :), the battery life has been improved a lot with this. 

When my instructable is done I will post the link here :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now I need electrical help and I am a world noob in this.......

I need a reverse voltage protection and i heard and read about p-channel mosfets. Is this any good and which 1 should I actually use? 

 

Thanks in advance.

 

greetings 

 

danny

Last Edited: Fri. Apr 30, 2021 - 05:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I have used the following simple circuit to protect from reverse polarity, but there is a gotcha, the diodes the current will flow through (two on each line) will drop the voltage. Standard diodes will drop 0.7v each but Schottky diodes will only drop 0.3v each.

 

 

Take a look at https://www.electronicdesign.com/power-management/article/21801509/reversepolarity-protection-in-automotive-design where they talk about single diode protection and P- and N-channel MOSFET protection, and then https://www.edn.com/protecting-against-reverse-polarity-methods-examined-part-1/ where they talk about several methods. The circuit I inserted above came from http://www.reuk.co.uk/wordpress/electric-circuit/reverse-polarity-protection/ where they describe its function in detail.

 

EDIT: Yes the above diagram looks very much like a bridge rectifier for converting AC to DC, but it doubles for polarity protection too.

Wayne

East London
South Africa

 

  • No, I am not an Electronics Engineer, just a 54 year old hobbyist/enthusiast
  • Yes, I am using Proteus to learn more about circuit design and electronics
  • No, I do not own a licensed copy of Proteus, I am evaluating it legitimately
  • No, I do not believe in software or intellectual property piracy or theft
Last Edited: Fri. Apr 30, 2021 - 05:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

First of all thanks for your reply and help :)

I did know about this 1 but I read about the power loss and voltage drop it has.

 

https://www.edn.com/protecting-against-reverse-polarity-methods-examined-part-2/ 

 

Here at Method 8: Series Mosfets they say it have the least power loss and my projects are all about battery life.

Only I dont get which mosfet I should buy or use for my projects :(

I dont get the technical stuff yet where to look at what info on the datasheet .

 

greetings

danny

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

BHAA-POL | Batteryholders.com | MPD | Batteryholders.com | MPD

...

Features reverse polarity protection

...

Any cell holders (polarized) for AAA?

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello and thanks for the help,

 

Yeah I thought about it and maybe it is my lack of google searching skills but I can not find any with 3xAAA and where I can buy them. :)

But this would be indeed the best solution to have to holder make it impossible to reverse the battery

 

greetings

danny

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

... and not a single decoupling capacitor insight.

Ross McKenzie ValuSoft Melbourne Australia

Pages