Forum: Mikrocontroller und Digitale Elektronik Arduino Nano + Hall Sensor + PIR Sensor + Fotowiderstand


von Mikal H. (michael1987)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe eine kleine Schaltung aufgebaut, doch leider klappt Sie nicht 
wie gewünscht.

Kurz der Hintergrund:
- Die Schaltung soll später an 3xAA Batterien betrieben werden, daher 
würde ich gerne Strom sparen.
- Der Arduino Nano wird später durch einen Standalone Atmega328P ersetzt 
(habe ich noch einige rumliegen.
- Es fehlt noch eine RGB LED am Ausgang, die später in verschiedenen 
Farben leuchten soll.

- Der PIR Sensor soll bei Bewegung den Mikrocontroller einschalten.
- Dann soll dieser 10 Sekunden eingeschaltet bleiben (Dies soll der 
Ausgang D7 machen mit High zum Transistor)
- Die Helligkeit der LED soll mittels des Fotowiderstand geregelt werden 
(Ist im Code noch nicht implementiert, aber das Auslesen des Wertes 
klappt.
- Mit einem Magneten kann man die Farbe der LED wechseln, je nachdem wie 
lange man über dem Hall-Sensor SL353LT bleibt.
- Sollte in der Zwischenzeit eine Bewegung erkannt werden, dann soll der 
Timer natürlich wieder bei 0 anfangen und dann wieder 10 Sekunden warten 
bis zum ausschalten, daher die Leitung vom PIR Sensor OUT nach D10.

Ich bekomme es so hin, dass ich mit dem PIR Sensor nur 0.016mA Strom 
benötige bis eine Bewegung erkannt wird. Der Controller schaltet sich 
auch ein und fängt an die Zeit zu zählen und er kommt auch in die if 
Schleife und druckt auf der Seriellen Schnittstelle "OutputOff" sobald 
keine Bewegung mehr erkannt wird. Aber er schaltet sich dann nicht mehr 
aus. Es kommen dann nur noch komische zeichen an der seriellen 
Schnittstelle an.

Erst wenn ich die Leitungen von D7 und D10 entferne, klappt das mit dem 
Ausschalten, allerding schaltet er dann aus, sobald keine Bewegung mehr 
besteht und die Ausschaltverzögerung fehlt mir.

Leider komme ich derzeit nicht wirklich weiter. habe schon einiges 
versucht, aber ich verstehe einfach nicht, warum es nicht fiunktioniert.

Vielleicht hat ja jemand einen Tipp oder erkennt das sofort.

Entschuldigung für den schlechten Schaltplan, aber auf meinem temporären 
Laptop habe ich nichts gescheites gefunden.
1
int LightSensorPin = A7;
2
int LightSensorValue = 0;
3
unsigned long previousMillis = 0; 
4
const long interval = 1000;
5
unsigned long TimeSinceMagnet = 0;
6
unsigned long TimeStart = 0;
7
int ResetTimeStart = 0;
8
int WaitTimeLedColor = 1500; // time in ms
9
int PirSensorLogicInputPin = 10;
10
int PirSensorLogicInputStatus = 0;
11
12
const int hallSensorPin = 2; // Pin an dem der Hall-Sensor angeschlossen ist
13
14
int hallSensorStatus = 0;
15
16
unsigned long SwitchOffCounter = 0;
17
const long SwitchOffCounterLimit = 10000; //10 Sekunden nach Bewegung oder entfernen des Magneten anbleiben
18
const int SwitchOffCounterPin = 7;
19
int ResetSwitchOffCounter = 0;
20
unsigned long SwitchOffCounterStart = 0;
21
22
void setup() {
23
  Serial.begin(9600);
24
  // Pin fuer die interne LED als Ausgang definieren
25
  pinMode(LED_BUILTIN, OUTPUT);
26
  pinMode(SwitchOffCounterPin, OUTPUT);
27
  digitalWrite(SwitchOffCounterPin, HIGH);
28
  // Pin fuerr den Hall-Sensor als Eingang definieren
29
  pinMode(hallSensorPin, INPUT);
30
  pinMode(PirSensorLogicInputPin, INPUT);
31
}
32
33
void loop() {
34
  //Serial.println(millis());
35
  // Status des Hall-Sensors auslesen
36
  hallSensorStatus = digitalRead(hallSensorPin);
37
  PirSensorLogicInputStatus = digitalRead(PirSensorLogicInputPin);
38
  Serial.print("PIR-Input-PIN:");
39
  Serial.println(PirSensorLogicInputStatus);
40
  
41
42
  if (hallSensorStatus == LOW) {
43
    //SwitchOffCounter auf 0 setzten
44
    if (ResetTimeStart == 0) {
45
      TimeStart = millis();
46
      ResetTimeStart = 1;
47
    }
48
    else {
49
    TimeSinceMagnet = millis()-TimeStart;
50
    //Serial.println(TimeSinceMagnet);      
51
    // LED einschalten    
52
    digitalWrite(LED_BUILTIN, HIGH);
53
    //Serial.println("A");  
54
    if (TimeSinceMagnet <= WaitTimeLedColor) {
55
      Serial.println("ROT");
56
    }
57
    else if (TimeSinceMagnet > WaitTimeLedColor && TimeSinceMagnet <= 2*WaitTimeLedColor) {
58
      Serial.println("BLAU");
59
    }
60
    else if (TimeSinceMagnet > 2*WaitTimeLedColor && TimeSinceMagnet <= 3*WaitTimeLedColor) {
61
      Serial.println("GELB");
62
    }
63
    else if (TimeSinceMagnet > 3*WaitTimeLedColor && TimeSinceMagnet <= 4*WaitTimeLedColor) {
64
      Serial.println("GRUEN");
65
    }
66
    else {
67
      TimeStart = millis();
68
      Serial.println("ResetTime");
69
    }
70
    }
71
  } 
72
  else {
73
    ResetTimeStart = 0;
74
    LightSensorValue = analogRead(LightSensorPin);
75
    Serial.println(LightSensorValue);
76
    //Serial.println("ResetTimeStart = 0");
77
    // LED ausschalten
78
    digitalWrite(LED_BUILTIN, LOW);
79
  }
80
81
//////////////////////////
82
  if (PirSensorLogicInputStatus == LOW) {
83
    //SwitchOffCounter auf 0 setzten
84
    if (ResetSwitchOffCounter == 0) {
85
      SwitchOffCounterStart = millis();
86
      ResetSwitchOffCounter = 1;
87
    }
88
    else {
89
    SwitchOffCounter = millis()-SwitchOffCounterStart; 
90
    Serial.print("SwitchOffCounter: ");
91
    Serial.println(SwitchOffCounter);
92
    if (SwitchOffCounter >= SwitchOffCounterLimit) {
93
      digitalWrite(SwitchOffCounterPin, LOW);
94
      //pinMode(SwitchOffCounterPin, INPUT_PULLUP);
95
      Serial.println("OutputOff");
96
    }
97
    else {
98
      //digitalWrite(SwitchOffCounterPin, HIGH);
99
      Serial.println("OutputStillON");
100
    }
101
    }
102
  } 
103
  else {
104
    ResetSwitchOffCounter = 0;
105
  }
106
/////////////////////////
107
108
109
}

von K. S. (the_yrr)


Lesenswert?

Mikal H. schrieb:
> Ich bekomme es so hin, dass ich mit dem PIR Sensor nur 0.016mA Strom
> benötige bis eine Bewegung erkannt wird.
Wie viel Strom braucht der µC im Deep Sleep und lohnt der Aufwand 
überhaupt?

> Der Controller schaltet sich
> auch ein und fängt an die Zeit zu zählen und er kommt auch in die if
> Schleife und druckt auf der Seriellen Schnittstelle "OutputOff" sobald
> keine Bewegung mehr erkannt wird.
Da du erst ausschaltest und danach die Ausgabe machst, ist schon die 
Tatsache dass dieser Text kommt ein Fehler.

Der Fehler liegt aber in der Hardware:
Wenn du den µC ausschaltest, liegt das "GND" (jenseits vom Kollektor) 
auf demselben Potential wie VCC. Damit bekommt auch die Basis Vcc ab, im 
Endeffekt betreibst du den Transistor im linearen Bereich. Wenn man den 
Spannungsabfall an den 6k8 ignoriert, wird "GND" auf ca. 3*0.7V = 2.1V 
liegen und der µC immer noch mit Vcc-2.1V versorgt.

Das verwendete Symbol für den BC517 ist kein Darlington (was er laut 
Datenblatt ist), sondern ein Sziklai Paar.

Beitrag #6323238 wurde von einem Moderator gelöscht.
von Mikal H. (michael1987)


Lesenswert?

K. S. schrieb:
> Der Fehler liegt aber in der Hardware:
> Wenn du den µC ausschaltest, liegt das "GND" (jenseits vom Kollektor)
> auf demselben Potential wie VCC. Damit bekommt auch die Basis Vcc ab, im
> Endeffekt betreibst du den Transistor im linearen Bereich. Wenn man den
> Spannungsabfall an den 6k8 ignoriert, wird "GND" auf ca. 3*0.7V = 2.1V
> liegen und der µC immer noch mit Vcc-2.1V versorgt.

Danke für die Antwort.

Was genau sind die 3x0.7V = 2.1V ? Woher kommt dies?

Hättest du einen Vorschlag wie ich dies verbessern kann, also den uC 
ausschalten und die Hardware besser verschalten?

von Wolfgang (Gast)


Lesenswert?

Mikal H. schrieb:
> Was genau sind die 3x0.7V = 2.1V ? Woher kommt dies?

Wenn du mal einen vernünftigen Schaltplan zeichnest, siehst du das 
direkt.

0.7V ist ein Pi*Daumen-Wert für die Vorwärtsspannung einer Si-Diode.

von Mikal H. (michael1987)


Lesenswert?

Hallo zusammen,

also wenn ich die türkise Leitung entferne klappt es so weit. Nur 
benötige ich diese ja um den uC am Leben zu erhalten, damit er nicht 
ausschaltet. jetzt schaltet er direkt aus, wenn keine Bewegung mehr 
erkannt wird.

Wenn ich die Spannung zwischen "GND am Arduino Pin" und zwischen den 
Kathoden der beiden 1N5818 messe, dann bekomme ich bei Bewegung 4.3V. 
Nach 10 Sekunden Ohne Bewegung habe ich noch 1.0V
Das sollten ja eigentlich 0V an dieser Stelle sein.
Wie kann ich das hinbekommen? Habt ihr da einen Vorschlag?

Danke

: Bearbeitet durch User
von Georg M. (g_m)


Angehängte Dateien:

Lesenswert?

Den Mikrocontroller muss man nicht ausschalten. Im Power-down-Modus 
liegt sein Stromverbrauch unter 1µA, also viel niedriger als beim 
PIR-Sensor.

von Georg M. (g_m)


Lesenswert?


von Peter D. (peda)


Lesenswert?

Der GND des Sensors ist bestimmt nicht offen.

Es gibt keine Selbstabschaltung mit nur einem Transistor. Alle sind 
bisher daran gescheitert.
Wie schon gesagt wurde, ist das auch unnötig, Sleepmode und gut.

von K. S. (the_yrr)


Lesenswert?

Mikal H. schrieb:
> Was genau sind die 3x0.7V = 2.1V ? Woher kommt dies?
das ist die Diode von Pin D7 und die beiden BE Strecken des Darlington.

> also wenn ich die türkise Leitung entferne klappt es so weit
Wie gesagt, wenn du abschaltest hat diese Leitung "GND" Potential (das 
GND vom Arduino). Da dieses GND aber eine Positive Spannung gegenüber 
dem echten GND hat, schaltet der Transistor ein.

> Wie kann ich das hinbekommen? Habt ihr da einen Vorschlag?
Mindestens ein weiterer Transistor, aber es ergibt einfach keinen Sinn 
die 0.1µA zu sparen bei einer Schaltung die 16µA verbraucht.

Lies nach welche externen Interrupts im Deep Sleep funktionieren, 
aktiviere einen davon und leg die Pinke Leitung auf den Pin. Die Diode 
ist dann auch überflüssig. Statt Abzuschalten aktivierst du dann den 
Deep Sleep, eventuell vorher den Watchdog deaktivieren. Brow out 
detection solltest du auch aktivieren, ist ziemlich sicher Teil deines 
eigentlichen Problems gewesen.

von Georg M. (g_m)


Angehängte Dateien:

Lesenswert?

Auch im Schlafmodus ist die Stromaufnahme von der Höhe der 
Betriebsspannung und von der Temperatur abhängig, bleibt aber deutlich 
unter 1µA.

von MaWin (Gast)


Lesenswert?

Mikal H. schrieb:
> Vielleicht hat ja jemand einen Tipp

Alles abreissen und noch mal von vorn.

ATmega ohne Nano-Platine an 4.5V.
Lichtsensor (glücklicherweise kein LDR sondern Photodiode) mit GND an 
Batterie-Minus, mit VCC an einen Ausgangspin. Der Ausgangspin wird 
eingeschaltet wenn man messen will. OUT kommt an einen Analogeingang.
PIR mit GND an Batterie-Minus, mit VCC an einen Ausgangspin der 
eingeschaltet wird wenn man messen will. OUT an einen Eingangspin der 
per Pin-Change-Interrupt den uC sus sleep aufwecken kann.
Den Hsllsensor ebenso verdrahten.
Den ganzen Unsinn mit dem falsch gezeichneten Darlington und den nicht 
richtig sperrenden Schottky-Dioden (die lassen rückwärts 100 x mehr 
Strom durch als din ATmega im sleep zieht, wie kommt man auf solche 
Bauteile..) entfernen.

von Hubert G. (hubertg)


Lesenswert?

Und wenn das alles funktioniert solltest du die Beschaltung des 
Hallsensor mit dem Datenblatt vergleichen. Seite 5.

von Mikal H. (michael1987)


Lesenswert?

MaWin schrieb:
> Alles abreissen und noch mal von vorn.
>
> ATmega ohne Nano-Platine an 4.5V.
> Lichtsensor (glücklicherweise kein LDR sondern Photodiode) mit GND an
> Batterie-Minus, mit VCC an einen Ausgangspin. Der Ausgangspin wird
> eingeschaltet wenn man messen will. OUT kommt an einen Analogeingang.
> PIR mit GND an Batterie-Minus, mit VCC an einen Ausgangspin der
> eingeschaltet wird wenn man messen will. OUT an einen Eingangspin der
> per Pin-Change-Interrupt den uC sus sleep aufwecken kann.
> Den Hsllsensor ebenso verdrahten.
> Den ganzen Unsinn mit dem falsch gezeichneten Darlington und den nicht
> richtig sperrenden Schottky-Dioden (die lassen rückwärts 100 x mehr
> Strom durch als din ATmega im sleep zieht, wie kommt man auf solche
> Bauteile..) entfernen.

Also das habe ich jetzt mal gemacht.

Ich habe an dem Atmega nur den PIR Sensor gehängt und eine LED am 
Ausgang.

Mein Problem. Es ist jetzt alles invertiert.

Bei erkannter Bewegung messe ich 0.03 mA
Decke ich den PIR ab habe ich kurzzeitig 18mA und die LED leuchtet ca 
eine halbe Sekunde und dann geht der Strom auf 0.465 mA.

Eigentlich sollte doch bei abgedecktem PIR Sensor der Wer au 0.03mA 
gehen und nicht wie bei mir.

Ich habe folgendes Skript verwendet. Wieso ist es invertiert?
1
#include <avr/sleep.h>
2
3
const byte LED = 10;
4
  
5
void wake ()
6
{
7
  sleep_disable(); // cancel sleep as a precaution
8
  detachInterrupt (0); // precautionary while we do other stuff
9
}  // end of wake
10
11
void setup () 
12
  {
13
  digitalWrite (2, HIGH);  // enable pull-up
14
  }  // end of setup
15
16
void loop () 
17
{
18
 
19
  pinMode (LED, OUTPUT);
20
  digitalWrite (LED, HIGH);
21
  delay (500);
22
  digitalWrite (LED, LOW);
23
  delay (50);
24
  pinMode (LED, INPUT);
25
  
26
  ADCSRA = 0;  // disable ADC
27
  
28
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
29
  sleep_enable();
30
  
31
  noInterrupts (); // Do not interrupt before we go to sleep, or the ISR will detach interrupts and we won't wake.
32
  
33
  attachInterrupt (0, wake, FALLING); // will be called when pin D2 goes low  
34
  EIFR = bit (INTF0);  // clear flag for interrupt 0
35
 
36
  MCUCR = bit (BODS) | bit (BODSE); //turn off brown-out enable in software BODS must be set to one and BODSE must be set to zero within four clock cycles
37
  MCUCR = bit (BODS);  // The BODS bit is automatically cleared after three clock cycles
38
  
39
  // We are guaranteed that the sleep_cpu call will be done
40
  // as the processor executes the next instruction after
41
  // interrupts are turned on.
42
  interrupts ();  // one cycle
43
  sleep_cpu ();   // one cycle
44
45
  } // end of loop
Quelle: http://www.gammon.com.au/power

von MaWin (Gast)


Lesenswert?

Mikal H. schrieb:
> Decke ich den PIR ab habe ich kurzzeitig 18mA und die LED leuchtet ca
> eine halbe Sekunde und dann geht der Strom auf 0.465 mA.

Logisch braucht sie bei LOW am Eingang mehr als die 30uA bei high, denn 
du hast den internen pull up eingeschaltet, dachtest du das bleibt für 
den Stromverbrauch folgenlos ?
Auch würde ich die LED ausschalten und nicht auf Input setzen.

von Mikal H. (michael1987)


Lesenswert?

MaWin schrieb:
> Mikal H. schrieb:
>> Decke ich den PIR ab habe ich kurzzeitig 18mA und die LED leuchtet ca
>> eine halbe Sekunde und dann geht der Strom auf 0.465 mA.
>
> Logisch braucht sie bei LOW am Eingang mehr als die 30uA bei high, denn
> du hast den internen pull up eingeschaltet, dachtest du das bleibt für
> den Stromverbrauch folgenlos ?
> Auch würde ich die LED ausschalten und nicht auf Input setzen.

Danke für die Antwort.
Es ging mir ja mehr darum, dass wenn die LED nicht leuchtet.

keine Bewegung am PIR: Strom = 0.465 mA
Bewegung am PIR= 0.03 mA

Das sollte umgekehrt sein, weil er bei Bewegung ja aufwachen sollte.

Danke

von MaWin (Gast)


Lesenswert?

Wenn er aufgewacht ist, leuchtrt die LED.
Wenn die LED nicht leuchtet, schläft er.
Der Unterschied 0.03 zu 0.45 kommt durch den Ausgang des PIR, ob der 
gehdn de  pull up arbeitet oder nicht

von Mikal H. (michael1987)


Lesenswert?

Also ich stehe gerade auf dem Schlauch.

Wir kann ich z.B. die LED bei Bewegung 3x im Abstand mit 200ms blinken 
lassen und ohne Bewegung 2x mit 1000ms blinken lassen.
Und zusätzlich noch den Strom verringern während das High des PIR 
anliegt reduzieren, so dass ich bei keiner Bewegung auf 0.03mA komme.

attachInterrupt (0, wake, FALLING);

Hier muss ich wohl

attachInterrupt (0, wake, RISING);

eintragen

von Mikal H. (michael1987)


Lesenswert?

Also, so habe ich es mal geschaft, dass bei einer Bewegung die LED R, G, 
B nacheinander aufleuchten.
Nachdem die Blaue LED (LED_B) ausgeht, dauert es noch ca 1 Sekunde und 
dann geht der Strom von 0.28mA auf 0.024mA
Diese 0.28mA finde ich im Code nicht, da nachdem die LED auf LOW 
geschaltet wird nichts mehr aus meiner sicht passiert. Oder dauert das 
disable ADC so lange?
1
#include <avr/sleep.h>
2
3
const byte LED = 10;
4
const byte LED_B = 9;
5
const byte LED_R = 11;
6
  
7
void wake ()
8
{
9
  sleep_disable(); // cancel sleep as a precaution
10
  detachInterrupt (0); // precautionary while we do other stuff
11
}  // end of wake
12
13
void setup () 
14
  {
15
  }  // end of setup
16
17
void loop () 
18
{
19
  pinMode (LED_R, OUTPUT);
20
  digitalWrite (LED_R, HIGH);
21
  delay (1000);
22
  digitalWrite (LED_R, LOW);
23
  pinMode (LED_R, INPUT);
24
  delay(400);
25
  pinMode (LED, OUTPUT);
26
  digitalWrite (LED, HIGH);
27
  delay (1000);
28
  digitalWrite (LED, LOW);
29
  pinMode (LED, INPUT);
30
  delay(400);
31
  pinMode (LED_B, OUTPUT);
32
  digitalWrite (LED_B, HIGH);
33
  delay (1000);
34
  digitalWrite (LED_B, LOW);
35
  pinMode (LED_B, INPUT);
36
  
37
  ADCSRA = 0;  // disable ADC
38
  
39
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
40
  sleep_enable();
41
  
42
  noInterrupts (); // Do not interrupt before we go to sleep, or the ISR will detach interrupts and we won't wake.
43
  
44
  attachInterrupt (0, wake, RISING); // will be called when pin D2 goes low  
45
  EIFR = bit (INTF0);  // clear flag for interrupt 0
46
 
47
  MCUCR = bit (BODS) | bit (BODSE); //turn off brown-out enable in software BODS must be set to one and BODSE must be set to zero within four clock cycles
48
  MCUCR = bit (BODS);  // The BODS bit is automatically cleared after three clock cycles
49
  
50
  // We are guaranteed that the sleep_cpu call will be done
51
  // as the processor executes the next instruction after
52
  // interrupts are turned on.
53
  interrupts ();  // one cycle
54
  sleep_cpu ();   // one cycle
55
56
  } // end of loop

: Bearbeitet durch User
von Georg M. (g_m)


Lesenswert?

Mikal H. schrieb:
> Oder dauert das disable ADC so lange?

Nein, natürlich nicht.
Außerdem, wenn der PIR-Sensor allein nur 16µA verbraucht, sind 24µA 
zusammen mit dem schlafenden Mikrocontroller etwas zu viel.

Ist es möglich, den Stromverbrauch von Komponenten getrennt zu messen?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.