MezData-Logo Creative Commons License 169 Lösungen Button :MEZ-ENTWICKLUNG: Das BruScheiKa Projekt

Die Lokation

BruScheiKa bedeutet Brunzen Scheissen Kaufen. Früher war in dem Klohäuschen ein Kiosk integriert.

Die Funktion der Elektronik

Angeschlossene Komponenten

Zwei Figuren mit steuerbaren Augen, Mund und zwei Händen. 3 Münzprüfer mit je zwei Sensoren für unterschiedliche Münzen. An jedem Münzprüfer befindet sich eine LED

Blockschaltbild

ISP-Programmieradapter

MISO 1 6 Pol 2 VTG (VCC)
SCK 3 4 MOSI
Reset 5 6 GND

Belegung Stecker IR-Empfänger

1 2 3
Gnd + Signal

Belegung Stecker Servos

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
S1 F1
Augen
S2 F1
Mund
S3 F1
HandR
S4 F1
HandL
S5 F2
Augen
S6 F2
Mund
S7 F2
HandR
S8 F2
HandL
NC NC
- + S - + S - + S - + S - + S - + S - + S - + S

+ - S2 + - S4 + - S6 + - S8
2 4 6 8 10 12 14 16 18 20 22 24 26
1 3 5 7 9 11 13 15 17 19 21 23 25
- S1 + - S3 + - S5 + - S7 +

Belegung Stecker Münzer

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
M1 M2 M3 NC
Gnd Sk Sg LED NC GND Sk Sg LED NC GND Sk Sg LED NC

LED und Sensoren gegen GND

Sk LED Gnd Sg NC Sk LED
2 4 6 8 10 12 14 16
1 3 5 7 9 11 13 15
Gnd Sg NC Sk LED GND Sg

Belegung Stecker CD-Spieler

1 2 3 4 5 6 7 8 9 10 11 12 13 14
CD1 CD2 CD3 CD4 CD5 CD6 NC NC
- + - + - + - + - + - +
+ + + + + +
2 4 6 8 10 12 14
1 3 5 7 9 11 13
- - - - - -

Belegung Stecker Relais

1 2 3 4 5 6 7 8 9 10
+5V R1 R2 R3 NC NC NC NC NC NC

Relais mit Freilaufdiode gegen +5V

µController ATmega16

Belegung Bedeutung Pin             Pin Bedeutung Belegung
M1 LED (XCK/T0) PB0 1 A
T
M
E
G
A

1
6
40 PA0 (ADC0) Audio Li
M2 LED (T1) PB1 2 39 PA1 (ADC1) Audio Re
M1 Sk (INT2/AIN0) PB2 3 38 PA2 (ADC2) CD1
M1 Sg (OC0/AIN1) PB3 4 37 PA3 (ADC3) CD2
M2 Sk (SS) PB4 5 36 PA4 (ADC4) CD3
M2 Sg (MOSI) PB5 6 35 PA5 (ADC5) CD4
M3 Sk (MISO) PB6 7 34 PA6 (ADC6) CD5
M3 Sg (SCK) PB7 8 33 PA7 (ADC7) CD6
/RESET 9 32 AREF
VCC 10 31 GND
GND 11 30 AVCC
XTAL2 12 29 PC7 (TOSC2) Servo 8
XTAL1 13 28 PC6 (TOSC1) Servo 7
(RXD) PD0 14 27 PC5 (TDI) Servo 6
(TXD) PD1 15 26 PC4 (TDO) Servo 5
IR-Empfänger (INT0) PD2 16 25 PC3 (TMS) Servo 4
(INT1) PD3 17 24 PC2 (TCK) Servo 3
M3 LED (OC1B) PD4 18 23 PC1 (SDA) Servo 2
Relais1 (OC1A) PD5 19 22 PC0 (SCL) Servo 1
Relais2 (ICP1) PD6 20 21 PD7 (OC2) Relais3

Teilfunktionen

8 Servos ansteuern

Die Pulsweite soll in 10 µs Servo-Schritten verstellbar sein. Hier die naheliegenden Kombinationen:

CPU Frequenz Vorteiler µs pro Zahl Bewertung
1 MHz 1:1 1 Int. Oszillator ist vorkalibriert, Standard, Multiplikation mit 10 notwendig
4 MHz 1:8 2 Mehraufwand bei Kalibrierung, Multiplikation mit 5 notwendig
8 MHz 1:8 1 Mehraufwand bei Kalibrierung, Multiplikation mit 10 notwendig
Gewählt 8 MHz mit Vorteiler 1:8, zum Multiplizieren mit 10 gibt es ja beim Mega16 praktische Befehle.

Um die 20 ms = 20 000 µs zu zählen brauchen wir den 16 Bit Timer1. Betriebsart Clear Timer on Compare Mode . Der Timer zählt von 0 bis zu einem einstellbaren TOP Wert und springt dann wieder auf 0. Ein Ausgang kann beim Sprung von TOP auf 0 gesetzt und bei Erreichen eines einstellbaren Wertes OCR1A wieder rückgesetzt werden.

ICR1 als TOP weil nicht verändert mit Wert 19 999 für 20 ms Wiederholungsintervall, OCR1A = Servo-Schritt * 10. Bei Erreichen von OCR1A wird ein Interrupt ausgelöst.

Einstellungen bei Initialisierung

Register Bit 7 6 5 4 3 2 1 0 Beschreibung
TCCR1A Bedeutung COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
Wert 0 0 0 0 0 0 0 0

Waveform Generation Mode: CTC mit ICR1 als TOP

TCCR1B Bedeutung ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
Wert 0 0 0 1 1 0 1 0 Vorteilung Timer mit CPU-CLK / 8
TIMSK Bedeutung OCIE2 TOIE2 TICE1 OCIE1A OCIE1B TOIE1 OCIE0 TOIE0 Input Capture Interrupt Enable (ICF1)
Wert 0 0 1 1 0 0 0 0 Output Compare Interrupt Enable

Audio in Mundbewegung wandeln

Einstellungen bei Initialisierung

Register Bit 7 6 5 4 3 2 1 0 Beschreibung
ADMUX Bedeutung REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0 Interne 2,56V Referenzspannung, Wert ist linksbüdig in ADCH:ADCL
Wert 1 1 1 0 0 0 0 0 Linker Kanal an PC0 (ADC0)
ADCSRA Bedeutung ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0 Wandler an, Auto Trigger Enable, Interrupt frei
Wert 1 1 1 1 1 1 1 1 Vorteiler auf CLK /1 28
SFIOR Bedeutung ADTS2 ADTS1 ADTS0 - ACME PUD PSR2 PSR10 Free Running Mode
Wert 0 0 0

Handbewegungen erzeugen

Ablaufsteuerung des Automaten Münzeinwurf

Ablauf bei grosser Münze Prellen des Sensors am Anfang

IR Empfänger

Gebräuchliche Codes

[IR Code Knowledgebase]

Verbesserungen ToDo

  1. Redesign der Servoansteuerung, Problem mit negativen Zahlen und Nullpunkt
  2. Schwätzo soll schneller Servos bewegen
  3. IR Empfang
  4. 6 Kanäle
  5. Während Vorstellung eingeworfene Münzen sollen neue Sequenz starten

Prototyp Platine mit LCD-Anzeige

Schlimmer C-Quellcode

Quellcode [BruScheiKa.c]
// BruScheiKa V 1.0 beta (c) Oliver Mezger 26.3.2010
#include <avr/io.h>     // Definitionen laden
#include <util/delay.h> // Delay-Bibliothek laden
#include <avr/interrupt.h>

// Zuordnungen zu Ports
#define RelaisIn        PIND
#define RelaisOut       PORTD
#define RelaisDdr       DDRD
#define MuenzIn         PINB
#define MuenzOut        PORTB
#define MuenzDdr        DDRB
#define CDIn            PINA
#define CDOut           PORTA
#define CDDdr           DDRA
#define ServosIn        PINC
#define ServosOut       PORTC
#define ServosDdr       DDRC

// Automatenspezifische Einstellungen

#define F1Augen 0
#define F1Mund  1
#define F1Rumpf 2
#define F1Hand  3
#define F2Augen 4
#define F2Mund  5
#define F2Rumpf 6
#define F2Hand  7

#define M1Led   0 // an Muenz
#define M2Led   1 // an Muenz
#define M3Led   4 // an Relais
#define M1Sk    2
#define M1Sg    3
#define M2Sk    4
#define M2Sg    5
#define M3Sk    6
#define M3Sg    7

#define CD1 2
#define CD2 3
#define CD3 4
#define CD4 5
#define CD5 6
#define CD6 7

#define Relais1 5  // Summe an sobald Automat laueft
#define Relais2 6  // Tisch hebt sich links
#define Relais3 7  // Tisch hebt sich rechts

// Figur 1 Mann links aus Sicht der Zuschauer
#define F1AugenMitte    50
#define F1AugenRechts   99
#define F1AugenLinks    1

#define F1MundAuf   2    // > 1 sonst ins Negative 
#define F1MundZu    42   // 50

#define F1RumpfVorne    0
#define F1RumpfHinten   100

#define F1HandOben      0
#define F1HandUnten     100
// Figur 2 Frau rechts aus Sicht der Zuschauer
#define F2AugenMitte    50
#define F2AugenRechts   100
#define F2AugenLinks    0

#define F2MundAuf       18
#define F2MundZu        52

#define F2RumpfRechts   100
#define F2RumpfLinks    0

#define F2HandOben      0
#define F2HandUnten     100

#define vuTest 0
#define anfangWarten 15 // 25 Sekunden warten bis Sprache kommt
#define schnauzAus 10 // 10 Sekunden bis Auschalten nach Stille
// Reihenfolge der Sequenzen {tisch,kindertraum,geleitschutz}
const unsigned char R2an[] ={108,0,0};  // Tisch links
const unsigned char R2aus[] ={120,0,0};
const unsigned char R3an[] ={0,0,116};  // Tisch rechts
const unsigned char R3aus[] ={0,0,123};

typedef enum {stop,mitte,rechts,links,vorne,hinten,oben,unten,bewegen,bewegen2} bewegungen;

//volatile unsigned char test = 3;
volatile unsigned char sprachSituation=0; //links,rechts
volatile bewegungen F1Zustand[3] ={bewegen,bewegen,bewegen}; //Augen,Neigung,Hand
volatile bewegungen F2Zustand[3] ={mitte,stop,stop}; //Augen,Drehung,Hand

volatile unsigned char servosAn=0,aktServo=0, servo[8]={50,50,50,50,50,50,50,50}; //0 = 1000ms,100 = 2000ms

volatile unsigned int systemZeit =0; // Inkrement alle 20ms durch Timer1
volatile unsigned int sekundenUhr = 0; // Inkrement jede Sekunde
volatile unsigned char lebensTakt = 0; // Takt fuer Lebenssteuerung der Figuren
volatile unsigned char keyEnter = 0,keyExit =0; // Ergebnisse Muenzpruefung
volatile char ausTimer = 0;

void setF1(bewegungen a,bewegungen b, bewegungen c){
  F1Zustand[0] = a;
  F1Zustand[1] = b;
  F1Zustand[2] = c;
}

void F1leben(){ // Mann Links
  const unsigned char F1RumpfSpeed = 1;
  const unsigned char F1HandSpeed =2;
  const bewegungen Augenbewegung[] ={mitte,mitte,mitte,links,links,mitte,rechts,mitte,mitte,rechts,links,links,links}; // max 16 Eintraege

  static unsigned char augenposition = 0;
  static unsigned char richtungen = 0; // Bit 0 Rumpf, Bit 1 Hand
  bewegungen n;
  unsigned char i;
  if (F1Zustand[0] == bewegen){
    augenposition++;
    i = augenposition >>4;
    if (i >= sizeof(Augenbewegung)){
      augenposition = 0;
      i =0;
    }
    n = Augenbewegung[i];
  }
  else
    n = F1Zustand[0];
  switch(n){
    case stop:
      break;
    case mitte:
      servo[F1Augen] = F1AugenMitte;
      break;
    case rechts:
      servo[F1Augen] = F1AugenRechts;
      break;
    case links:
      servo[F1Augen] = F1AugenLinks;
      break;
    default:;  
  }
  switch(F1Zustand[1]){ // Rumpf
    case stop:
      break;
    case vorne: if (F1RumpfVorne > servo[F1Rumpf]) servo[F1Rumpf]+=F1RumpfSpeed;
            else if (F1RumpfVorne < servo[F1Rumpf]) servo[F1Rumpf]-=F1RumpfSpeed;
      break;
    case hinten: if (F1RumpfHinten > servo[F1Rumpf]) servo[F1Rumpf]+=F1RumpfSpeed;
            else if (F1RumpfHinten < servo[F1Rumpf]) servo[F1Rumpf]-=F1RumpfSpeed;
      break;
    case bewegen:
      if (richtungen&1){
        if (F1RumpfVorne > servo[F1Rumpf]) servo[F1Rumpf]+=F1RumpfSpeed;
        else if (F1RumpfVorne < servo[F1Rumpf]) servo[F1Rumpf]-=F1RumpfSpeed;
        else richtungen &= 0b11111110;
      }
      else{
        if (F1RumpfHinten > servo[F1Rumpf]) servo[F1Rumpf]+=F1RumpfSpeed;
        else if (F1RumpfHinten < servo[F1Rumpf]) servo[F1Rumpf]-=F1RumpfSpeed;
        else richtungen |= 1;
      }
      break;
    default:;
  }
  switch(F1Zustand[2]){ // Hand
    case stop:
      break;
    case oben: if (F1HandOben > servo[F1Hand]) servo[F1Hand]+=F1HandSpeed;
            else if (F1HandOben < servo[F1Hand]) servo[F1Hand]-=F1HandSpeed;
      break;
    case unten: if (F1HandUnten > servo[F1Hand]) servo[F1Hand]+=F1HandSpeed;
            else if (F1HandUnten < servo[F1Hand]) servo[F1Hand]-=F1HandSpeed;
      break;
    case bewegen:
      if (richtungen&2){
        if (F1HandOben > servo[F1Hand]) servo[F1Hand]+=F1HandSpeed;
        else if (F1HandOben < servo[F1Hand]) servo[F1Hand]-=F1HandSpeed;
        else richtungen &= 0b11111101;
      }
      else{
        if (F1HandUnten > servo[F1Hand]) servo[F1Hand]+=F1HandSpeed;
        else if (F1HandUnten < servo[F1Hand]) servo[F1Hand]-=F1HandSpeed;
        else richtungen |= 2;
      }
      break;
    default:;
  }
}

void setF2(bewegungen a,bewegungen b, bewegungen c){
  F2Zustand[0] = a;
  F2Zustand[1] = b;
  F2Zustand[2] = c;
}

void F2leben(){
  const unsigned char F2RumpfSpeed = 2;
  const unsigned char F2HandSpeed =2;
  const bewegungen Augenbewegung[] ={mitte,mitte,links,rechts,rechts,mitte,mitte,rechts,links}; // max 15 Eintraege

  static unsigned char augenposition = 0;
  static unsigned char richtungen = 0; // Bit 0 Rumpf, Bit 1 Hand
  bewegungen n;
  unsigned char i;
  if (F2Zustand[0] == bewegen){ // Augen
    augenposition++;
    i = augenposition >>4;
    if (i >= sizeof(Augenbewegung)){
      augenposition = 0;
      i =0;
    }
    n = Augenbewegung[i];
  }
  else
    n = F2Zustand[0];
  switch(n){
    case stop:
      break;
    case mitte:
      servo[F2Augen] = F2AugenMitte;
      break;
    case rechts:
      servo[F2Augen] = F2AugenRechts;
      break;
    case links:
      servo[F2Augen] = F2AugenLinks;
      break;
    default:;  
  }
  switch(F2Zustand[1]){ // Rumpf
    case stop:
      break;
    case rechts: if (F2RumpfRechts > servo[F2Rumpf]) servo[F2Rumpf]+=F2RumpfSpeed;
            else if (F2RumpfRechts < servo[F2Rumpf]) servo[F2Rumpf]-=F2RumpfSpeed;
      break;
    case links: if (F2RumpfLinks > servo[F2Rumpf]) servo[F2Rumpf]+=F2RumpfSpeed;
            else if (F2RumpfLinks < servo[F2Rumpf]) servo[F2Rumpf]-=F2RumpfSpeed;
      break;
    case bewegen:
     if (richtungen&1){
       if (F2RumpfRechts > servo[F2Rumpf]) servo[F2Rumpf]+=F2RumpfSpeed;
       else if (F2RumpfRechts < servo[F2Rumpf]) servo[F2Rumpf]-=F2RumpfSpeed;
       else richtungen &= 0xfe;
     }
     else{
       if (F2RumpfLinks > servo[F2Rumpf]) servo[F2Rumpf]+=F2RumpfSpeed;
       else if (F2RumpfLinks < servo[F2Rumpf]) servo[F2Rumpf]-=F2RumpfSpeed;
       else richtungen |= 1;
     } 
     break;
    default:;
  }
  switch(F2Zustand[2]){  // Hand
    case stop:
      break;
    case oben: if (F2HandOben > servo[F2Hand]) servo[F2Hand]+=F2HandSpeed;
            else if (F2HandOben < servo[F2Hand]) servo[F2Hand]-=F2HandSpeed;
      break;
    case unten: if (F2HandUnten > servo[F2Hand]) servo[F2Hand]+=F2HandSpeed;
            else if (F2HandUnten < servo[F2Hand]) servo[F2Hand]-=F2HandSpeed;
      break;
    case bewegen:
     if (richtungen&2){
       if (F2HandOben > servo[F2Hand]) servo[F2Hand]+=F2HandSpeed;
       else if (F2HandOben < servo[F2Hand]) servo[F2Hand]-=F2HandSpeed;
       else richtungen &= 0b11111101;
     }
     else {
       if (F2HandUnten > servo[F2Hand]) servo[F2Hand]+=F2HandSpeed;
       else if (F2HandUnten < servo[F2Hand]) servo[F2Hand]-=F2HandSpeed;
       else richtungen |= 2;
     }
    default:;
  }
}
void vuMeter(unsigned char n){ // Anzeige des Pegels
  int vu;
  if (n<8){
    if (n<2){
      if (n<1)
        vu = 0;
      else
        vu = 1;
    }
    else{
     if (n<4)
       vu = 3;
     else
       vu = 7;
    }
  }
  else{
    if (n<16)
      vu = 15;
    else if (n<32)
      vu = 31;
    else
      vu = 63;
  }
  vu = ~vu;
  CDOut = (CDOut & 0b00000111) | (vu<<3); // Bit 7..3
}

#define anzahlSamples 40
#define sprechSchwelle 4
#define servoInkrement 2
ISR(ADC_vect){
  static unsigned char wert = 0, i=0;
  char n;
  n = ADCH; // ADC auslesen
  if (i<=1); // Messung verwerfen
  else if (i<anzahlSamples){ // Maximum aus den Messungen 1..5
    if (n>wert) wert = n;
  }else if (i==anzahlSamples){ // Ausgeben und Kanal umschalten
    // Achtung es muss gelten Mundzu > Mundauf
    if (wert >sprechSchwelle){
      n = servo[F1Mund] - servoInkrement;
      if (n<F1MundAuf) servo[F1Mund]=F1MundAuf;
      else servo[F1Mund]= n;
      sprachSituation |= 1;
      ausTimer =0;
    }
    else {
      n = servo[F1Mund] + servoInkrement;
      if (n>F1MundZu) servo[F1Mund]=F1MundZu;
      else servo[F1Mund]= n;
    }
    if (vuTest) vuMeter(wert);
    wert = 0;
    ADMUX |= 1; // Kanal 1
  }
  else if (i<=anzahlSamples+2); // Messung verwerfen
  else if (i<2*anzahlSamples){ // Maximum aus 18..23 
    if (n>wert) wert = n;
  }else{ // Ausgeben und Kanal umschalten
    // Achtung es muss gelten Mundzu > Mundauf
    if (wert >sprechSchwelle){
      n = servo[F2Mund] - servoInkrement;
      if (n<F2MundAuf) servo[F2Mund]=F2MundAuf;
      else servo[F2Mund]= n;
      sprachSituation |= 2;
      ausTimer = 0;
    }
    else {
      n = servo[F2Mund] + servoInkrement;
      if (n>F2MundZu) servo[F2Mund]=F2MundZu;
      else servo[F2Mund]= n;
    }
    if (vuTest) vuMeter(wert);
    wert = 0;
    ADMUX &= 0xfe; // Kanal 0
    i = 0;
  }
  i++;
}

ISR(TIMER1_CAPT_vect){  // ISR wird alle 20ms aufgerufen
  static unsigned char su=0,lt=0; // interne Zaehler fuer Takte
  if (servosAn){
    ServosOut = 1; // Servo1 an
    OCR1A= servo[0]*10+1000+TCNT1; // Zeitmarke setzen
  }
  systemZeit++;
  su++;
  lt++;
  if (su >= 50){
    su=0;
    sekundenUhr++;
    ausTimer++;
  }
  if (lt >= 3){
    lt =0;
    lebensTakt++;
  }
  aktServo =0; // wieder Start mit Servo 0
}

ISR(TIMER1_COMPA_vect){  // ISR fuer die Flankensteuerung der Servos
  if (servosAn && aktServo < 8){
    aktServo++;
    ServosOut = 1 << aktServo; // neuen Servo an
    //OCR1A= (((servo[aktServo]<<1)+servo[aktServo])<<1)+1000+TCNT1; // Zeitmarke setzen
    OCR1A= servo[aktServo]*10+1000+TCNT1; // Zeitmarke setzen
  }
}

void keyCheck(){
  static unsigned char keyOld = 0; // alter Zustand
  unsigned char keyTest,tmp;
  keyEnter = 0, keyExit = 0;
  keyTest = ~MuenzIn >> 2 & 0b00111111;// Einlesen und zurechtschieben
  if (keyOld != keyTest){  // hat sich was getan
    _delay_ms(5); // Prellen abwarten
    tmp = (~MuenzIn >> 2)&0b00111111; // nochmal Einlesen und zurechtschieben
    if (tmp == keyTest){  // ist es stabil?
      keyEnter = (~keyOld) & keyTest; // steigende Flanke !alt und neu
      keyExit = keyOld & (~keyTest);  // fallende Flanke alt und !neu
      keyOld = keyTest;
    }
  }
}
int main(){
  CDDdr = 0b11111100;
  CDOut = 0b11111100; // Steuerung mit negativer logik
  ServosDdr = 0xff;     // Alle auf Ausgang
  MuenzDdr = 0b00000011; //
  RelaisDdr = 0b11110000; // drei Realais und M3Led
  ADMUX = 0b11100000; // Interne Ref, linksbuendig, ADC1
  ADCSRA = 0b11111111;  // ADWandler Free Running, Interrupt frei CLK/128
  ICR1 = 19999;         // Signal alle 20 ms
  TCCR1A = 0b00000000;  // Timer1 CTC Mode
  TCCR1B = 0b00011010;  // Keine Vorteilung Timer mit CPU-CLK / 8
  TIMSK =  0b00110000;  // ICF1 und OC1A Interrupt Enable
  sei();        // globale Interruptfreigabe
  unsigned char altLebensTakt =0;
  unsigned int altSekundenUhr =0;
  unsigned char n=0,f1Laber=0,f2Laber=0;
  typedef enum {blinken,anfang,startdelay,vorstellung,ende} automatenstatustyp;
  automatenstatustyp automatenstatus = blinken;
  typedef enum {tisch,kindertraum,geleitschutz} sequenztyp;
  sequenztyp sequenz = tisch;
schedul:
  while(automatenstatus == blinken){        // Warten auf Geld
    servosAn=0;
    keyCheck(); // Muenzeinwurf ueberpruefen
    if (keyEnter){
      if (keyEnter&0b00000011) sequenz = tisch; // Muenze an M1
      else if (keyEnter&0b00001100) sequenz = kindertraum; // Muenze an M2
      else if (keyEnter&0b00110000) sequenz = geleitschutz; // Muenze an M3
      automatenstatus = anfang;
      break;
    }
    if (altSekundenUhr != sekundenUhr){ // Blinken der LED
      altSekundenUhr = sekundenUhr;
      if (sekundenUhr&1){
        n = ~MuenzIn>>2; // Muenzer einlesen
        if ((n & 0b11) ==0) // keine Verstopfung bei M1
          MuenzOut |= 1;
        if ((n & 0b1100) ==0) // keine Verstopfung bei M2
          MuenzOut |= 2;
        if ((n & 0b110000) ==0) // keine Verstopfung bei M3
          RelaisOut |= 1<<M3Led;
      }
      else{  // LED ausschalten
        MuenzOut &= ~(3); // M1Led und M2Led
        RelaisOut &= ~(1<<M3Led);
      }
    }

  }
  if (automatenstatus == anfang){  // Anfang
    servosAn=1;
    altSekundenUhr=sekundenUhr=0;
    automatenstatus = startdelay;
    RelaisOut |= 1<<Relais1;  // Summenrelais an
    switch (sequenz){
      case tisch:
        CDOut &= ~(1<<CD1); // CD1 an negative Logik
        break;
      case kindertraum:
        CDOut &= ~(1<<CD2); // CD2 an negative Logik
        //CDOut &= ~(1<<CD1); // CD1 an negative Logik
        break;
      case geleitschutz:
        CDOut &= ~(1<<CD3); // CD3 an negative Logik
        //CDOut &= ~(1<<CD1); // CD1 an negative Logik
        break;
    }
  }
  while(automatenstatus == vorstellung || automatenstatus == startdelay){
    if (automatenstatus == startdelay){
      if (sekundenUhr > anfangWarten){
        automatenstatus = vorstellung;
        ausTimer = 0;
      }
    }
    else if (ausTimer > schnauzAus) automatenstatus = ende;   // wenn ruhe dann Ende
    if (altSekundenUhr != sekundenUhr){ // bei sekundenwechsel
      altSekundenUhr = sekundenUhr;
      if (R2an[sequenz]>0 && sekundenUhr == R2an[sequenz]) RelaisOut |= 1<<Relais2;
      if (R2aus[sequenz]>0 && sekundenUhr == R2aus[sequenz]) RelaisOut &= ~(1<<Relais2);
      if (R3an[sequenz]>0 && sekundenUhr == R3an[sequenz]) RelaisOut |= 1<<Relais3;
      if (R3aus[sequenz]>0 && sekundenUhr == R3aus[sequenz]) RelaisOut &= ~(1<<Relais3);

    }
    if (altLebensTakt !=lebensTakt){
      altLebensTakt =lebensTakt;
      if (automatenstatus == startdelay || lebensTakt&1)
        RelaisOut |= 1<<M3Led;
      else
        RelaisOut &= ~(1<<M3Led);
      //MuenzOut = (MuenzOut & 0b11111100) | sprachSituation;
      if (sprachSituation &1) f1Laber = 15; // wenn 1 dann Delay setzen
      else if (f1Laber>0){ // Nachlauf zum ueberbruecken von Sprechpausen
        f1Laber--;
        sprachSituation |= 1;
      }
      if (sprachSituation &2) f2Laber = 15; // wenn 1 dann Delay setzen
      else if (f2Laber>0){
        f2Laber--;
        sprachSituation |= 2;
      }
      MuenzOut = (MuenzOut & 0b11111100) | sprachSituation;
      switch (sprachSituation){
        case 0:     // keiner spricht
          setF1(bewegen,bewegen,bewegen); // Augen Rumpf (vorne hinten) Hand
          setF2(bewegen,bewegen,bewegen); // Augen Rumpf (rechts links) Hand
          break;
        case 1:     // links spricht Mann sitzt links
          setF1(bewegen,bewegen,bewegen);
          setF2(bewegen,rechts,bewegen);
          break;
        case 2:     // rechts spricht Frau steht rechts
          setF1(mitte,hinten,unten);
          setF2(bewegen,links,stop);
          break;
        case 3:     // beide sprechen
          setF1(rechts,bewegen,bewegen);
          setF2(links,links,stop);
          break;
      }
      sprachSituation = 0;
      F1leben();
      F2leben();
    }
  }
  if (automatenstatus == ende){  // Ende der Vorstellung
    servosAn=0;
    ServosOut=0; // wirklich ausschalten
    automatenstatus = blinken;
    RelaisOut &= 0b00011111;  // Summenrelais aus
    CDOut = 0b11111100; // alle CDs aus Steuerung mit negativer logik
  }
  goto schedul;
  return 0;
}

© Oliver Mezger 15.05.2010 MezData.de Den Kontakt herstellen...