Forum: Mikrocontroller und Digitale Elektronik Atmega1284p Power-Down und WakeUp via UART


von Daniel (Gast)


Lesenswert?

Hallo,

Habe ein kleines Problem, habe hier eine Testschaltung mit einem Atmel 
1284P und einem Rauchmelder der bei Auslösung UART Daten auswirft, die 
kann ich lesen soweit so gut.

Nun möchte ich das der Atmel solange in Power-Down geht, bis auf dem 
UART Daten vom Rauchmelder empfangen werden.

Der Atmel wird mit einem Quarz 10 Mhz betrieben, vom RX habe ich eine 
Leitung an PCINT0 (PA0) angeklemmt und verwende folgenden Code:
1
int count;
2
3
int main(void)
4
{
5
    sei();
6
    uart0_init();
7
    unsigned char data;
8
9
    while(1)
10
    {
11
       data = uart_gets();
12
       if(data & UART_NO_DATA)
13
       {
14
       }
15
       else
16
       {
17
            uart1_puts( (unsigned char) data);
18
       }
19
20
        PCICR = (1<<PCINT0);
21
        PCMSK0 = (1<<PCINT0);
22
        
23
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
24
        sleep_enable();
25
        sei();
26
27
        LED_PORT &= ~(1 << LED_PWR_PIN); // PWR LED Aus
28
29
        sleep_cpu();
30
        sleep_disable();
31
        LED_PORT |= (1<<LED_PWR_PIN); // PWR LED an.
32
    }
33
}
34
35
ISR(PCINT0_vect)
36
{
37
   count++;
38
}

Da RXD noch mit PCINT0 (PA0) verbunden ist, gibts flanken, leider 
erwacht der Atmel nicht aus seinem Dornrößchen schlaf.

An was könnte das liegen? Ist mein Code falsch?


Grüße,
Daniel

von Thomas E. (thomase)


Lesenswert?

Daniel schrieb:
> PCICR = (1<<PCINT0);
> PCMSK0 = (1<<PCINT0);
Das ist zwar grundsätzlich falsch, aber in diesem Fall zufällig richtig.
1
PCMSK0 = (1 << PCINT0);
2
PCICR = (1 << PCIE0);

ist die richtige Initialisierung.

Nach dem Startbit wird der Controller sofort wieder schlafen gelegt. 
Damit läuft auch der UART nicht.

1
int count;
2
unsigned char bSleep;
3
4
int main(void)
5
{    
6
    uart0_init();
7
    unsigned char data;
8
    
9
    PCMSK0 = (1 << PCINT0);
10
    PCICR = (1 << PCIE0);
11
    PCIFR = PCIFR;
12
13
    LED_PORT |= (1<<LED_PWR_PIN); // PWR LED an.
14
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
15
    sleep_enable();
16
    bSleep = 1;
17
    sei();
18
 
19
   while(1)
20
    {
21
       data = uart_gets();
22
       if(data & UART_NO_DATA)
23
       {
24
       }
25
       else
26
       {
27
            uart1_puts( (unsigned char) data);
28
            while(UARAT_BUSY);
29
            bSleep = 1;
30
       }
31
32
        if(bSleep)
33
        { 
34
           LED_PORT &= ~(1 << LED_PWR_PIN); // PWR LED Aus
35
           sleep_cpu();
36
           bSleep = 0;
37
           LED_PORT |= (1<<LED_PWR_PIN); // PWR LED an.
38
        }
39
    }
40
}
41
42
ISR(PCINT0_vect)
43
{
44
   count++;
45
}

mfg.

: Bearbeitet durch User
von Daniel (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Daniel schrieb:
>> PCICR = (1<<PCINT0);
>> PCMSK0 = (1<<PCINT0);
> Das ist zwar grundsätzlich falsch, aber in diesem Fall zufällig richtig.
> PCMSK0 = (1 << PCINT0);
> PCICR = (1 << PCIE0);
>
> ist die richtige Initialisierung.
>
> Nach dem Startbit wird der Controller sofort wieder schlafen gelegt.
> Damit läuft auch der UART nicht.
>
> int count;
> unsigned char bSleep;
>
> int main(void)
> {
>     uart0_init();
>     unsigned char data;
>
>     PCMSK0 = (1 << PCINT0);
>     PCICR = (1 << PCIE0);
>     PCIFR = PCIFR;
>
>     LED_PORT |= (1<<LED_PWR_PIN); // PWR LED an.
>     set_sleep_mode(SLEEP_MODE_PWR_DOWN);
>     sleep_enable();
>     bSleep = 1;
>     sei();
>
>    while(1)
>     {
>        data = uart_gets();
>        if(data & UART_NO_DATA)
>        {
>        }
>        else
>        {
>             uart1_puts( (unsigned char) data);
>             while(UARAT_BUSY);
>             bSleep = 1;
>        }
>
>         if(bSleep)
>         {
>            LED_PORT &= ~(1 << LED_PWR_PIN); // PWR LED Aus
>            sleep_cpu();
>            bSleep = 0;
>            LED_PORT |= (1<<LED_PWR_PIN); // PWR LED an.
>         }
>     }
> }
>
> ISR(PCINT0_vect)
> {
>    count++;
> }
>
> mfg.

Hallo,

Das ist mir gar nicht aufgefallen, das der UART nicht läuft ist mir 
klar, daher habe ich vom UART (RXD) eine Strippe zum INT gezogen, da 
eben der UART nicht läuft, aber dennoch flanken am RXD + INT0 ankommen.

passt das dann trotzdem so? das ganze läuft mit 3.3V :)

werde dein Code nachher mal testen, aber richtig, der Atmel legt sich 
direkt nach dem Start schlafen, nur wecken funktionierte nicht...

Grüße,
Daniel

von Peter D. (peda)


Lesenswert?

Daniel schrieb:
> vom RX habe ich eine
> Leitung an PCINT0 (PA0) angeklemmt

Was gefällt Dir an PCINT24 nicht?

von Thomas E. (thomase)


Lesenswert?

Peter Dannegger schrieb:
> Was gefällt Dir an PCINT24 nicht?
Das ist erst die nächste Baustelle.

Daniel schrieb:
> nur wecken funktionierte nicht...
Woher weisst du das? Das kurze Aufblitzen der Led kriegst du 
wahrscheinlich gar nicht mit.

mfg.

von Daniel (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Peter Dannegger schrieb:
> Was gefällt Dir an PCINT24 nicht?


Mein Problem war mit PCINT24, das auf dem UART nur Mist kam obwohl 
nichts gesendet wurde. Liegt evtl am UART Interrupt von der Fleury 
Library?

Daher meine Lösung mit nicht PCINT24

> Das ist erst die nächste Baustelle.
>
> Daniel schrieb:
> nur wecken funktionierte nicht...
>
> Woher weisst du das? Das kurze Aufblitzen der Led kriegst du
> wahrscheinlich gar nicht mit.
>
> mfg.

Das ist korrekt, das kriege ich so nicht mit aber ich hatte noch ein 
Salae Logic 16 dran. Und der zeigte lediglich low Pegel für die Power 
LED an.

// offtopic an:

Ich habe nur jetzt aktuell das Phänomen, wenn ich übers Atmel Studio 6.2 
SP1 den Code per ISP uploade, dann kriege ich keine Verbindung zum Atmel 
obwohl mir im Studio die 3.3V angezeigt werden beim auslesen.

Was noch auffällig ist, ist der Code oben und ich flashe neu, steht 
hinter meinem AVR JTAGice mkII [Busy] ich muss erst den jtagice vom USB 
trennen bevor das wieder läuft. Und das nach jedem flashen via ISP 6 
PIN.

Habe das selbe Problem mit einem avrisp mkII, was mich verwirrt.

Daher kann ich das aktuell nicht testen :/

von Thomas E. (thomase)


Lesenswert?

Daniel schrieb:
> Ich habe nur jetzt aktuell das Phänomen, wenn ich übers Atmel Studio 6.2
> SP1 den Code per ISP uploade, dann kriege ich keine Verbindung zum Atmel
> obwohl mir im Studio die 3.3V angezeigt werden beim auslesen.
>
> Was noch auffällig ist, ist der Code oben und ich flashe neu, steht
> hinter meinem AVR JTAGice mkII [Busy] ich muss erst den jtagice vom USB
> trennen bevor das wieder läuft. Und das nach jedem flashen via ISP 6
> PIN.
>
> Habe das selbe Problem mit einem avrisp mkII, was mich verwirrt.

Dann bring erstmal deine Umgebung in Ordnung. Eventuell durch 
Neuinstallation. Du wärest nicht der erste, der sich da was zerschossen 
hat.

So ist nicht gewährleistet, dass das Programm überhaupt richtig 
übertragen wird.

mfg.

von Daniel (Gast)


Lesenswert?

Hallo,

// offtopic an
So, nach Software und Treiber Problemen, klappts nun, aber nicht so wie 
gedacht. (Der Fehler lag definitiv am Atmel Studio 6.2, keine Probleme 
mehr mit Studio 6.1 SP1)

Zur Erklärung, ich habe ein Rauchmelder der Firma GIRA, der verfügt über 
ein UART Ausgang, das es hier auch Funk-Module für teures Geld zu kaufen 
gibt, daher bau ich ein eigenes.

Da später noch ein RFM Modul dran kommt, ist der Power-Down eigentlich 
schon Wichtig, wenn ich nich an 30 Meldern nach Wochen Batterien 
wechseln möchte.

Der Atmega1284p ist aktuell nur mein Entwicklungsboard, dieser wird 
später ersetzt durch ein Atmega8L, bevor fragen kommen :)

So habe den Code aktuell nun so modifiziert, das er aktuell perfekt 
funktioniert:
1
/*
2
 * Rauchmelder___DEV_Board.c
3
 *
4
 * Created: 21.11.2014 00:03:50
5
 *  Author: Sany-iMac
6
 */ 
7
8
#define F_CPU 8000000UL
9
#define UART_BAUD_RATE  9600
10
11
#include <avr/io.h>
12
#include <util/delay.h>
13
#include <avr/interrupt.h>
14
#include <avr/pgmspace.h>
15
#include <avr/sleep.h>
16
#include "uart_lib/uart.h"
17
#include "gira_lib/gira_lib.h"
18
19
#define LED_DDR DDRC
20
#define LED_PORT PORTC
21
#define LED_PWR_PIN PC4
22
23
uint8_t count;
24
unsigned char bSleep;
25
unsigned char uart_rm_data;
26
unsigned char uart_debug_data;
27
unsigned char rauchmelder_serial;
28
29
int main(void)
30
{
31
  LED_DDR |= (1<<LED_PWR_PIN);
32
  LED_PORT |= (1<<LED_PWR_PIN); // PWR LED an
33
  
34
  /************************************************************************/
35
  /* UART Initialisierung                          */
36
  /* UART0 = Rauchmelder                                                  */
37
  /* UART1 = PC Debug Konsole (entfällt später)              */
38
  /* RXD0 mit PCINT0 verbunden / Interrupt zum Empfangen          */
39
  /************************************************************************/
40
  
41
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU)); // Rauchmelder Gira (3.3v)
42
  uart1_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU)); // PC Debug
43
  
44
  sei();
45
  /************************************************************************/
46
  /* Sleep-Mode                                                           */
47
  /************************************************************************/
48
  
49
  PCMSK0 = (1<<PCINT0);
50
  PCICR = (1<<PCIE0);
51
  PCIFR = PCIFR;
52
  
53
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
54
  sleep_enable();
55
  bSleep=1;
56
  
57
  uart1_puts("=> Frage Seriennummer von Rauchmelder ab\r\n");
58
  gira_rm_authentication();
59
  _delay_ms(250); // Auf ACK vom Melder warten
60
  rauchmelder_serial = gira_rm_getSerialNumer(); // Rauchmelder sendet 5 mal Seriennummer via UART0
61
  _delay_ms(50);
62
  
63
  while(1)
64
    {
65
        uart_rm_data = uart_getc();
66
    
67
    if(uart_rm_data & UART_NO_DATA)
68
    {
69
      /* Tu nichts */
70
    } 
71
    else 
72
    {
73
      // Empfangene Daten an UART1 Debug übergeben
74
      
75
      uart1_putc((unsigned char) uart_rm_data);
76
      //while(uart_busy()); // Auskommentiert, da es in der fleury keine UART_BUSY gibt.
77
      bSleep = 1;
78
    }
79
    
80
    if(bSleep)
81
    {
82
      LED_PORT &= ~ (1 << LED_PWR_PIN); // PWR LED Aus
83
      sleep_cpu();
84
      bSleep = 0;
85
      LED_PORT |= ( 1 << LED_PWR_PIN);
86
    }
87
    }
88
}
89
90
ISR(PCINT0_vect)
91
{
92
  count++;
93
}

Nach der Authentifizierung kriege ich vom Melder ein ACK zurück, kann 
dann die Seriennummer abfragen, diese schickt mir der melder nach 
absenden ca 0,2 - 0,3 Sekunden das erste mal Zurück. Dann weitere 4 mal 
im 5 Sekunden abstand.

So, im Power-Down Modus kriegt der Atmel das "ACK" vom Melder zurück, 
frägt die Seriennummer des Melders an geht (Geht auch über den UART 
raus) direkt danach in den Power-Down und kriegt (logisch) die erste 
Seriennummer übertragung nach ca 0,2 - 0,3 Sekunden nicht mehr mit bzw 
die Hochfahrzeit wohl ist zu lang durch den 8 Mhz Quarz/Crystal.

In den nachfolgenden 4 Übertragungen wacht der Atmel zwar auf, aber bei 
der UART Übertragung zum PC kommt nur mist an.

Die PWR-LED "Blinkt" zwar kurz wenn der Atmel etwas empfangen hat, aber 
ich weiß nicht ob der Atmel auch den vollen String vom Rauchmelder 
empfängt.

Nun stelle ich natürlich die Intelligente Frage die jeder Stellt, wie 
muss ich die Fleury UART lib erweitertern, so das ich evtl. mit bekomme 
ob der UART Busy ist?

Mein Code hier:
1
uint8_t uart_busy(void)
2
{
3
  return UART0_CONTROL & _BV(UART0_UDRIE);
4
}

funktioniert nich so dufte, welche Möglichkeit habe ich denn den 
"Schlafmodus" so zu verzögern, das die Übertragung gewährleistet ist?

Der Rauchmelder sendet mir mit jedem Event den Anfang und das Ende des 
Strings immer mit einem <STX>MELDUNG<ETX>

Oder kann ich die UART Lib irgendwie dazu kriegen die sleep_mode zu 
disablen?

grüße,
daniel

von Daniel (Gast)


Lesenswert?

Hallo, keiner eine Idee ?!?

Grüße daniel

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Daniel schrieb:
> Hallo, keiner eine Idee ?!?

 LOL.
 Warten must du sowieso, ob das die UART-gesteuerten genauen  1,04ms
 sind oder deine 1ms mit delay ist eigentlich egal, oder ?
1
     {
2
      // Empfangene Daten an UART1 Debug übergeben
3
      
4
      uart1_putc((unsigned char) uart_rm_data);
5
      //while(uart_busy()); // Auskommentiert, da es in der fleury keine UART_BUSY gibt.
6
7
      _delay_ms(1);     // reingeschrieben, da die Fleury-Lib grosstenteils Mist ist
8
9
      bSleep = 1;
10
    }

 Es funktioniert mit 1ms bestimmt, da der Stoppbit == Idle und ist somit
 sogar schneller.
 Falls doch nicht, einfach auf 2ms verlängern oder delay_us hinterher.

: Bearbeitet durch User
von Oliver (Gast)


Lesenswert?

Daniel schrieb:
> Der Fehler lag definitiv am Atmel Studio 6.2, keine Probleme
> mehr mit Studio 6.1 SP1

Na ja, auf den ersten Blick fällt schon mal ein fehlendes volatile auf.

Oliver

von Thomas E. (thomase)


Lesenswert?

Daniel schrieb:
> funktioniert nich so dufte, welche Möglichkeit habe ich denn den
> "Schlafmodus" so zu verzögern, das die Übertragung gewährleistet ist?

Daniel schrieb:
> In den nachfolgenden 4 Übertragungen wacht der Atmel zwar auf, aber bei
> der UART Übertragung zum PC kommt nur mist an.

Grundsätzlich solltest du die Kommunikation erstmal ohne Sleepmode zum 
Laufen bringen. Wenn das zu 100% funktioniert, baust du den Sleep ein. 
Im Moment kämpfst du an 2 Fronten. Du bist dir einerseits nicht sicher, 
ob sie sich überhaupt verstehen oder ob es am Sleepmode hapert.

Daniel schrieb:
> Oder kann ich die UART Lib irgendwie dazu kriegen die sleep_mode zu
> disablen?

Ein paar Bytes über UART einzulesen ist weder Hochtechnologie noch 
Geheimwissenschaft. Bau dir deine eigenen Funktionen zum Senden und 
Empfangen. Die Herausforderung liegt ohnehin in der Auswertung der 
empfangenen Daten. Dabei hilft dir die Fleury-Lib aber sowieso nicht.

mfg.

: Bearbeitet durch User
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.