Help met "blink" without delay

Arduino specifieke Software
Berichten: 26
Geregistreerd: 06 Jun 2014, 00:07

Help met "blink" without delay

Berichtdoor raduen » 09 Nov 2019, 01:53

Help,

Ik heb een ATTiny85 met een motion sensor en een 5v relay 220v naar een 220v lamp.

De code zet de ATTiny85 in sleep mode en als de motion sensor beweging detecteerd wordt deze it de sleep mode gehaald en het relay aanzet.
Het licht brand dan voor 60000 milliseconds (interval) en gaat dan uit en de Tiny85 valt dan weer in sleep modus. Dit werkt allemaal goed.

Wat ik wil doen is dat zolang de motion sensor beweging detecteerd de Tiny85 niet in slaap modus gaat.

Als de motion == HIGH tel ik bijvoorbeeld 1 minuut bij maar dit werkt niet. Het ergerste is dat als ik interval verhoogd de Tiny85 niet meer uit slaap stand komt.

Help

Zie code

Code: Alles selecteren
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include "ClickButton.h"

// MOTION DETECTION
  const int motionDetectorPin = PB0;
  int MotionDetected = 0;

// LED STATUS/SETTINGS
  const int statusLED = PB4;
  volatile int ledState = LOW;
  volatile int countFlash = 1;

// Time stetting led
 

// RELAIS
  const int REL_PIN = PB3;
  int RelaisState = HIGH;

//BUTTON
  const int buttonPin1 = PB2;
  int buttonState = 0;
  ClickButton button1(buttonPin1, HIGH);//, CLICKBTN_PULLUP);

// TIME LINE IS ON
  unsigned long previousMillis = 0;
  volatile unsigned long interval = 60000;

// While Light is On don't Sleep
 

void setup() {

    pinMode(motionDetectorPin, INPUT);
    pinMode(statusLED, OUTPUT);
 
    pinMode(REL_PIN, OUTPUT);
    digitalWrite(REL_PIN, HIGH);
 
    // BUTTON SETTINGS
    button1.debounceTime   = 20;   
    button1.multiclickTime = 250; 
    button1.longClickTime  = 1000;
     
    digitalWrite(statusLED, HIGH); delay(500);
    digitalWrite(statusLED, LOW);  delay(500);
    digitalWrite(statusLED, HIGH); delay(2000);
    digitalWrite(statusLED, LOW);
   
}

void sleep()
{
    GIMSK |= _BV(PCIE);
    PCMSK |= _BV(PCINT0);
    ADCSRA &= ~_BV(ADEN);
    MCUCR |= _BV(SM1); MCUCR &= ~_BV(SM0);
   
    sleep_enable();
 
    sei();
    sleep_cpu(); // SLEEP
   
    cli();
    PCMSK &= ~_BV(PCINT1);
    sleep_disable();
    ADCSRA |= _BV(ADEN);
 
    sei();
}

ISR(PCINT0_vect) {
    MotionDetected = digitalRead(motionDetectorPin);
    // als ik hiet interval verhoogd werkt het ook niet
    //interval = interval + 5000;
    RelaisState = LOW;
    lighIsOn = true;
}


void turnOn() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
      previousMillis = currentMillis;
   
      digitalWrite(REL_PIN, HIGH);
      lighIsOn = false;     
   }
   
   checkButton();
 
}

void checkButton() {
   if (button1.clicks != 0) LEDfunction = button1.clicks;

  // hoelang het licht moet blijven branden als er geen beweging meer is.
  // als button 1x wordt gedrukt tel 5 sec erbij. Dit werkt wel bij de volgende keer dat het licht weer aan gaat.
   if(LEDfunction == 1) {
      interval += 5000;
      countFlash = countFlash + 1;
      ledState += 1000; //1min
       
  }

  // bij dubble klik reset naar 1 minuut
  if(LEDfunction == 2) {
      interval = 60000;
      ledState = 1000; // 1min
      countFlash = 1;
  }
 
  // update the LED
  if (LEDfunction > 0 ){
      LEDfunction = 0;     
      blinkLED (statusLED, countFlash, 1000);
  }
}
void blinkLED(byte targetPin, int numBlinks, int blinkRate) {
  for (int i=0; i < numBlinks; i++) {
    digitalWrite(targetPin, HIGH); 
    delay(blinkRate);
    digitalWrite(targetPin, LOW);
    delay(blinkRate);
  }
}
void loop() {

  // Don't Sleepif Light is On
  if (!lighIsOn) {
     //ledState = LOW;
     digitalWrite(statusLED,LOW);
     sleep();
  }

  //If Motion is detected
  if (MotionDetected == HIGH) {   
     digitalWrite(statusLED, HIGH);
     digitalWrite(REL_PIN, LOW);     
     interval = interval + 50000;
     button1.Update();
     turnOn();
  }
  else
  {     
    digitalWrite(statusLED, LOW);
    button1.Update();
    turnOn();
  }

}

Advertisement

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Help met "blink" without delay

Berichtdoor Koepel » 09 Nov 2019, 10:20

Je project bestaat uit verschillende lagen en verschillende onderdelen. Er gebeurt nogal wat. Je zou kunnen beginnen met een goede beschrijving. Bij een goede en logische beschrijving heb je al de helft van het programmeerwerk gedaan.

Gebruik je een gewone PIR sensor ? Een PIR sensor is geen "aanwezigheids"-detector.
Je kunt je project dus niet gebruiken om een lamp aan te doen als iemand aanwezig is. Je kunt wel de lamp aan laten zolang er beweging is.

Kun je eens letten op het gebruik van spaties, lege regels, inspringen en haakjes in je sketch ? Het is nu een rommeltje :o

Je maakt het jezelf extra moeilijk door een ATtiny te gebruiken. Dat is geen officieel Arduino board. Ik kan het dus ook niet uitproberen op een Arduino Uno.
Ik weet niet hoe je het interrupt hebt ingesteld. Komt er een interrupt als de motion sensor aan gaat en ook weer uit gaan ? Of alleen als de motion sensor aan gaat ?

Normaal gesproken wordt 'previousMillis' geupdate naar 'currentMillis'. Het voordeel is dat het heel vaak gedaan kan worden, en dan blijft de timeout goed werken. Jij maakt de interval langer als de sensor een signaal afgeeft. Als de sensor meerdere signalen achter elkaar afgeeft, dan wordt de interval te lang.
Met een drukknop de interval langer maken kan volgens mij wel en dat kan ook samen met het updaten van 'previousMillis'.

Mijn voorkeur heeft om de millis() timer in de loop() te doen.

De AVR (ATtiny, ATmega) familie microcontrollers zijn 8-bit. Daarom is het handiger om in een interrupt een 8-bit variabele te gebruiken als je iets wil doorgeven aan de code in de loop(). Een 'char', 'unsigned char', 'byte', 'bool' zijn 8-bit. De 'bool' is true/false en kan ook als een "vlag" gebruikt worden. Ik bedoel een soort van "seinvlag", het Engelse "flag" is een beter woord.

Het gaat dus om een single shot timer. Die bestaat uit twee delen. Het ene deel zet de 'previousMillis' en kan die steeds updaten. Het ander deel kijkt of de timer al is afgelopen. Voorbeeld: https://github.com/Koepel/Fun_with_millis/blob/master/millis_single_delay.ino.
Volgens mij is jouw sketch bezig met de timeout of de ATtiny is in sleep mode. Misschien heb je die 'enabled' variabele uit mijn voorbeeld niet nodig.

Met de knop de tijd verlengen met 5 seconden, is dat voor iedere keer dat de knop wordt ingedrukt ?

Het knipperen van de led duurt even. Tijdens een delay kun je niets doen. Het kijken of een knop wordt ingedrukt werkt dan even niet. Dat is vervelend.
Dit is extra functionaliteit die het ingewikkelder maakt. Is dat echt nodig ?
Ik zou een tweede millis() timer gebruiken voor het knipperen van de led.
Het knipperen wordt weer een apart onderdeel in de loop() met millis() en een eigen "previousMillis". Voorbeeld: https://github.com/Koepel/Fun_with_millis/blob/master/millis_within_millis.ino.

Ik heb nog niet nagedacht wanneer en hoe de led uitgezet wordt :( Waarschijnlijk met een teller als de led aan of uit gaan, en dan het knipperen stoppen door 'enableBlink' op false te zetten.

Jij hebt jouw gedachten in code gezet. Maar je project is niet eenvoudig. Ik laat de Arduino loop() lekker lopen en kijk of er iets moet gebeuren. Je kunt dan nog meer dingen toevoegen. Die sleep() mode is dan nog het enige dat het ingewikkeld maakt.

Code: Alles selecteren
bool MotionDetected;  // een 'vlag' vanuit de interrupt

unsigned long previousMillis;  // voor de timer
unsigned long interval = 60000UL;  // 1 minuut, UL = Unsigned Long

unsigned long previousMillisBlink; // voor het knipperen van de led.
unsigned long intervalBlink = 1000;  // knipper interval voor de led.
bool enableBlink;   // knippert de led wel of niet.

void loop()
{
  unsigned long currentMillis = millis();

  // ---------------------------------------
  // verwerk de interrupt
  // ---------------------------------------
  if( MotionDetected)
  {
    // Een signaal vanuit de interrupt.
    // Update de 'previousMills' naar de huidige 'currentMillis'.
    // De timeout begint weer van voor af aan.
    previousMillis = currentMillis;
    ...
    MotionDetected = false;  // de vlag resetten
  }

  // ---------------------------------------
  // Kijk of de motion detector nog steeds actief is
  // ---------------------------------------
  // Dit hangt af van de motion detector.
  // Blijft de uitgang van de motion detector echt hoog als er steeds beweging is ?
  if( digitalRead( MotionDetectorPin) == HIGH)
  {
    previousMillis = currentMillis;
  }

  // ---------------------------------------
  // verwerk de knoppen, verleng zonodig de interval
  // ---------------------------------------
  ...


  // ---------------------------------------
  // knipperen van de led
  // ---------------------------------------
  if( enableBlink)
  {
    // knipper led
    ...
  }

  // ---------------------------------------
  // Is de tijd om ?
  // ---------------------------------------
  if (currentMillis - previousMillis >= interval)
  {
    // zet licht uit
    ...
    sleep();
  }
}

ISR( PCINT0_vect)
{
  // Kijk of de sensor aan gaat.
  // Is het nodig om een digitalRead() te doen ?
  if( digitalRead( motionDetectorPin) == HIGH)
  {
    MotionDetected = true;       // zet de vlag
  }
}

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Help met "blink" without delay

Berichtdoor Koepel » 09 Nov 2019, 13:39

"volatile" vergeten :oops:
volatile bool MotionDetected; // een 'vlag' vanuit de interrupt

Berichten: 26
Geregistreerd: 06 Jun 2014, 00:07

Re: Help met "blink" without delay

Berichtdoor raduen » 09 Nov 2019, 22:06

Hallo Koepel,

Bedankt voor je snelle reactie.

Om de code wat "kleiner" te maken heb ik alle de meeste comments uitgehaald en hier en daar spaties en tabs gebruikt om naar mijn idee het wat leesbaarder te maken maar zo te zien was dat geen goed idee.

Ik heb het trouwens voor elkaar.
Schoot me binnen dat ik ooit eens keer met de motion sensor aan het spelen was en de J1 jumper op H had gezet. :D

De volatile is een "ik zie het niet meer zitten" poging geweest. :lol:

Thanks.

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: RussellAlets en 20 gasten