Forum: Mikrocontroller und Digitale Elektronik Attiny412 Arduino megatinyCore sleepMode


von DerNeue (Gast)


Lesenswert?

Hallo zusammen,

ich mache gerade die ersten Schritte mit dem Attiny412 und der 
megaTinyCore in Arduino.

Ich habe leider ein Problem mit dem "aufwachen" aus dem Sleep-Mode mit 
einer steigenden Flanke an einem Pin.

https://cdn.tindiemedia.com/images/resize/PrhuQ78RWdU0AKZwkpfWuOkc2gk=/p/full-fit-in/2336x1752/i/77443/products/2019-08-25T00%3A37%3A05.079Z-ATtiny_xy2.png?1606306133

An Pin 2 (also PA1) habe ich einen Taster. Dieser ist an der einen Seite 
an 5V und an der anderen Seite an Pin 2 (PA1) angeschlossen.

Normal sollte ja beim drücken der Taste ein High anliegen und damit der 
Mikrocontroller aufwachen. Doch leider macht er das nicht.
Später würde ich gerne auch noch einen Wert eines Sensors mittels ADC 
auslesen, aber da bis jetzt nicht einmal das aufwachen klappt, habe ich 
den Code mal auf das Minimum reduziert.

Die Pixel LEDs hängen an der 5V Versorgungsspannung und GND hängt am 
"Collector" eines NPN Transistor. Die Basis mit 10kOhm an Pin 1 (PA7) 
und der Emitter ist mit Masse verbunden.
Die Datenleitung ist mit einem 300Ohm widerstand mit Pin 3 (PA2) 
verbunden.

In Zeile 28, habe ich es eigentlich mit RISING versucht, aber das klappt 
leider nicht. Mit BOTHEDGES klappt es ein paar mal, dann hängt sich der 
uC irgendwie auf und ich bekomme Ihn nicht mehr geweckt.
Zeile 29 benötige ich zum ausschalten der Pixel LEDs. Diese verbinden 
sich sonst über die Datenleitung mit der Masse und ich benötige zu viel 
Strom.

Ifrgendwie bin ich ratlos. Ich suche schon die ganze Zeit im Internet 
aber finde leider nichts gescheites.

Hier habe ich mich schon eingelesen:
http://www.technoblogy.com/show?2RA3
https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/PowerSave.md

1
#include <tinyNeoPixel.h>
2
#include <avr/sleep.h>
3
4
// Which pin on the Arduino is connected to the NeoPixels?
5
#define PIN            3
6
// How many NeoPixels are attached to the Arduino?
7
#define NUMPIXELS      3
8
tinyNeoPixel strip = tinyNeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);
9
10
ISR(PORTA_PORT_vect) {
11
  PORTA.INTFLAGS = PORT_INT1_bm;
12
}
13
14
void setup() {
15
   pinMode(4, INPUT_PULLUP);
16
   PORTA.PIN1CTRL = PORT_PULLUPEN_bm;
17
   delay(100);
18
   strip.begin();
19
20
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
21
   sleep_enable();
22
}
23
24
void loop() {
25
   LightLEDColor(100, 0, 0, 0);
26
   delay(5000);
27
   LightLEDColor(0,0,0,0);
28
   PORTA.PIN1CTRL = PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc;
29
   digitalWrite(3, HIGH);
30
   pinMode(3,INPUT);
31
   sleep_cpu();
32
   strip.begin();
33
   PORTA.PIN1CTRL = PORT_PULLUPEN_bm; 
34
   strip.begin();   
35
}
36
37
void LightLEDColor(int R, int G, int B, int W)
38
{
39
   for (int i = 0; i < NUMPIXELS; i++) {
40
    strip.setPixelColor(i, strip.Color(R, G, B, W));
41
    delay(1);
42
  }
43
  strip.show();
44
}

von Nummer E. (ritaripp)


Lesenswert?

<An Pin 2 (also PA1) habe ich einen Taster. Dieser ist an der einen 
Seite
an 5V und an der anderen Seite an Pin 2 (PA1) angeschlossen>

PA1 liegt durch Pullup auf Vcc . Leg den Taster auf Masse.

Unbenutzte Pins ziehen im Deepsleep 1mA, also abschalten:
PORTA.PINxCTRL =4;    //INPUT_DISABLE  ,Digital input buffer disabled

: Bearbeitet durch User
von DerNeue (Gast)


Lesenswert?

Hallo,
danke für den Hinweis. Habe es ausprobiert mit Taster auf GND und das 
hat auch funktioniert.
Dann habe ich noch weiter versucht und habe es nochmal mit dem Taster an 
5V versucht.
So hat das dann auch geklappt. Änderung in Zeile 23.

Jetzt wollte ich zum ausprobieren mal einen AM312 Bewegungsmelder als 
Auslöser verwenden.
https://i.stack.imgur.com/qWMTw.jpg

Dieser hat mit dem Multimeter ein 3V ausgangssignal bei Bewegung für 2 
Sekunden.
Nun dachte ich, ich kann einfach das OUT an den Pin 2 (PA1) anschliessen 
kann und damit den Mikrocontroller aufwecken kann.
Leider nicht. Mit dem Multimeter iegen jetzt an OUT nur noch 0V an bei 
Bewegung. Löse ich die Verbindung zwischen Sensor OUT und uC Pin 2 
(PA1), dann messe ich an OUT des Sensors wieder 3V bei Bewegung.

Liegt dies am Pullup des PIN 2 ???
Ich dachte ich könnte mir si vielleicht sogar noch den Taster sparen, 
aber ist doch nicht so einfach. Oder doch und ich mache es falsch?
1
#include <tinyNeoPixel.h>
2
#include <avr/sleep.h>
3
// Which pin on the Arduino is connected to the NeoPixels?
4
#define PIN            3
5
// How many NeoPixels are attached to the Arduino?
6
#define NUMPIXELS      3
7
tinyNeoPixel strip = tinyNeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);
8
ISR(PORTA_PORT_vect) {
9
  PORTA.INTFLAGS = PORT_INT1_bm;
10
}
11
void setup() {
12
   pinMode(4, INPUT_PULLUP);
13
   PORTA.PIN1CTRL = PORT_PULLUPEN_bm;
14
   delay(100);
15
   strip.begin();
16
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
17
   sleep_enable();
18
}
19
void loop() {
20
   LightLEDColor(100, 0, 0, 0);
21
   delay(5000);
22
   LightLEDColor(0,0,0,0);
23
   PORTA.PIN1CTRL = PORT_ISC_LEVEL_gc | PORT_INVEN_bm;
24
   digitalWrite(3, HIGH);
25
   pinMode(3,INPUT);
26
   sleep_cpu();
27
   strip.begin();
28
   PORTA.PIN1CTRL = PORT_PULLUPEN_bm; 
29
   strip.begin();   
30
}
31
void LightLEDColor(int R, int G, int B, int W)
32
{
33
   for (int i = 0; i < NUMPIXELS; i++) {
34
    strip.setPixelColor(i, strip.Color(R, G, B, W));
35
    delay(1);
36
  }
37
  strip.show();
38
}

von Georg M. (g_m)


Lesenswert?

DerNeue schrieb:
> Nun dachte ich, ich kann einfach das OUT an den Pin 2 (PA1) anschliessen
> kann und damit den Mikrocontroller aufwecken kann.
> Leider nicht.

Doch.


DerNeue schrieb:
> Mit dem Multimeter iegen jetzt an OUT nur noch 0V an bei
> Bewegung. Löse ich die Verbindung zwischen Sensor OUT und uC Pin 2
> (PA1), dann messe ich an OUT des Sensors wieder 3V bei Bewegung.
>
> Liegt dies am Pullup des PIN 2 ???

Mit dem AM312 brauchst du keinen Pullup.

Trotzdem ist etwas falsch. Der Pullup liefert eine positive Spannung und 
der AM312 auch. Woher dann 0V?

von Nummer E. (ritaripp)


Lesenswert?

Versuch mal mit AM312 statt Taster:

23  PORTA.PIN1CTRL = PORT_ISC_BOTHEDGES_gc;


und besser

ISR(PORTA_PORT_vect) {
  PORTA.PIN1CTRL = 0; //verhindert mehrfach Interupt
  PORTA.INTFLAGS = PORT_INT1_bm;

}

von Peter D. (peda)


Lesenswert?

DerNeue schrieb:
> Normal sollte ja beim drücken der Taste ein High anliegen und damit der
> Mikrocontroller aufwachen. Doch leider macht er das nicht.

Du brauchst eine Flanke zum aufwachen. Nach Loslassen der Taste bleibt 
die Pinkapazität aber auf 5V geladen und denkt gar nicht daran auf 0V zu 
wechseln.

Der AM312 wird bei 5V vermutlich die Grätsche machen.

von DerNeue (Gast)


Lesenswert?

Hallo zusammen,

also Danke schonmal für eure Antworten.

Ich habe jetzt mal ein ganz einfachen Code geschrieben. Die LEDs 
leuchten bei einem HIGH des AM312 auf und gehen aus, wenn dieser auf LOW 
ist.

Also der elektrische Aufbau scheint erstmal zu klappen.

Wenn ich in Zeile 13 von INPUT auf INPUT_PULLUP Wechsel, dann klappt es 
nicht mehr. Dann gehen einmal die LEDs an und nicht mehr aus.

Nun ist die Frage. Wie kann ich das in den Sleep Code implementieren?
1
#include <tinyNeoPixel.h>
2
3
// Which pin on the Arduino is connected to the NeoPixels?
4
#define PIN            3
5
6
// How many NeoPixels are attached to the Arduino?
7
#define NUMPIXELS      3
8
9
int StatusMotionOld = 0;
10
tinyNeoPixel strip = tinyNeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);
11
12
void setup() {
13
  pinMode(2, INPUT);
14
  strip.begin(); // This initializes the NeoPixel library.
15
}
16
17
void loop() {
18
   int StatusMotion = digitalRead(2);
19
   if (StatusMotion == StatusMotionOld)
20
   {}
21
   else{
22
   if (StatusMotion == HIGH) {
23
      strip.begin();
24
      LightLEDColor(100, 0, 0, 0);
25
      }
26
    else
27
    {
28
      pinMode(3, INPUT);
29
      digitalWrite(3, HIGH);
30
      delay(1000);
31
      }
32
    StatusMotionOld = StatusMotion;
33
   }
34
}
35
36
void LightLEDColor(int R, int G, int B, int W)
37
{
38
  for (int i = 0; i < NUMPIXELS; i++) {
39
    // pixels.Color takes RGBW values, from 0,0,0,0 up to 255,255,255,255
40
    strip.setPixelColor(i, strip.Color(R, G, B, W)); // Moderately bright green color.
41
    delay(1);
42
  }
43
  strip.show();
44
}

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ernst gemeinter Tipp. Gehe bitte nochmal die Bsp. der IDE durch. Deine 
ständige Konfiguration vom Taster macht keinen Sinn. Eingänge und 
Ausgänge werden in der Regel zu 99% einmal konfiguriert. Danach werden 
nur noch Pegel eingelesen und bei Ausgängen Pegel umgeschalten.

von Georg M. (g_m)


Lesenswert?

DerNeue schrieb:
> Nun ist die Frage. Wie kann ich das in den Sleep Code implementieren?

Der hybride Code ist etwas verwirrend, aber AVR ohne Arduino sieht 
ungefähr so aus:
1
/*------------------------------------------------
2
  ATtiny412 simple PIR LED control
3
4
         VDD 1|‾‾‾‾‾‾‾|8 GND 
5
         PA6 2|       |7 PA3
6
         PA7 3|       |6 UPDI 
7
 PIR --- PA1 4|_______|5 PA2 --- LED
8
9
 (PIR Sensor Output Voltage = VDD)
10
--------------------------------------------------*/
11
12
#include <avr/io.h>
13
#define F_CPU 3333333UL                      // default
14
#include <util/delay.h>
15
#include <avr/interrupt.h>
16
#include <avr/sleep.h>
17
18
ISR(PORTA_PORT_vect) 
19
{
20
  PORTA.INTFLAGS = PORT_INT1_bm;             // clear the interrupt flag
21
}
22
23
int main(void)
24
{
25
  PORTA.PIN1CTRL = PORT_INVEN_bm;             // invert PA1 input
26
  PORTA.DIRSET = PIN2_bm;                     // set PA2 as output
27
  SLPCTRL.CTRLA = SLPCTRL_SMODE_PDOWN_gc;     // select Power-Down sleep mode
28
  sei();                                      // enable global interrupts
29
30
  while (1)
31
  {
32
    PORTA.OUTSET = PIN2_bm;                   // PA2 ON
33
    _delay_ms(5000);                          // 5s ON
34
    PORTA.OUTCLR = PIN2_bm;                   // PA2 OFF
35
36
    PORTA.PIN1CTRL &= ~PORT_ISC_gm;           // clear ISC field
37
    PORTA.PIN1CTRL |= PORT_ISC_LEVEL_gc;      // level interrupt on PA1
38
    sleep_mode();                             // sleep
39
                                              // waked if PA1=HIGH
40
    PORTA.PIN1CTRL &= ~PORT_ISC_gm;           // clear ISC field
41
    PORTA.PIN1CTRL |= PORT_ISC_INTDISABLE_gc; // disable interrupt on PA1
42
  }
43
}

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.