Go Down

Topic: 7 Segement Uhr 100mm Bauhöhe mit Attiny84 (Read 838 times) previous topic - next topic

volvodani

Nov 11, 2012, 03:34 pm Last Edit: Nov 12, 2012, 08:56 am by volvodani Reason: 1
Mein Projektvorstellung:
Eine 4 Ziffern 7Segementuhr mit 100mm Bauhöhe der Segemente.
Benötigte Hardware:
1* Attiny84
1* DS1307 RTC von Maxim
1* Batteriehalter
4* 74HC595 Schieberegister
4* ULN2803 Darlington Array
1* IRFL024 N-Channel Mosfet
1* 7805CV  Festspannungregler 5V
1* Batteriehalter CR20xx
1* Ribbon IKEA Bilderrahmen
Möbefolie weiß zu Beziehen des Glases.

Ziel war es alles auf einen Attiny84(44) CPU umzusetzten. Die Dateien der Cores sind von hier http://hlt.media.mit.edu/?p=1695 Diese laufen aber nur unter der 1.0.1 auf der 1.0.2 habe ich es durch einiges an probieren nicht hinbekommen.
Ich nutzte die TinyWireM-Libraries mit Erweiterungen von mir der defines für die x4er Serie, da die USI Interface auf anderen Pins bzw. Ports sitzt als bei den x5ern. Die Kommuniktion zu RTC läuft über I2C, wobei die externen Pullups zwingend erforderlich sind.
Ich wollte kein Multiplexing nutzten damit ich die volle Helligkeit der Anzeigen nutzten kann, deswegen die 4 Schieberegister+ 4 ULN2803.
Mit dem IRFD024 Mosfet habe ich die Output-Enable der Schiebregister mit PWM angesteuert um die Helligkeit der Segemente zu handlen.
Die Steuerung läuft via One-Button Steuerung.
Kurzer Druck im Normalmodus stellt die Helligkeit in 6 Stufen regeln. Ein Langer Druck bewirkt die beiden Setmodes (1= Stellen Minuten 2= Stellen Stunden).
Gruß
Der Dani

Hier  der Code

So ist das Leben:
Manchmal bis du das Denkmal, manchmal die Taube!

volvodani

#1
Nov 12, 2012, 08:57 am Last Edit: Nov 12, 2012, 11:26 am by volvodani Reason: 1
Code: [Select]
/*
Attiny84 Big 7 Segment Uhr mit 74HC595

*/


#include <TinyWireM.h>
#include <USI_TWI_Master.h>


#define Shiftdata  8          // Pin 8 Datenleiung Schieberegister connected to Data in (DS) of 74HC595
#define Shiftclock 10           // Pin 9 Clockleitung connected to clock pin (SH_CP) of 74HC595
#define Shiftlatch 9         // Pin 10 Latchleitung connected to latch pin (ST_CP) of 74HC595
#define PWMOUT 7
#define BUTTON 1
#define RTCPuls 2
#define LDR 3
#define RTC_ADDRESS 0x68
#define TIME 750

byte ie,iz,hz,he,mz,me=0;  // Modulespeicher der stunden Minuten
boolean ldruck,druck=false;   // Stellknopf für Zeit
boolean longpress,shortpress=false;  // Unterscheidung langer kurzer druck
boolean blinktakt=false;             // Blinktakt 500ms
boolean lpuls,puls=false;            // Sekundenpuls
boolean hell=false;
unsigned long lmillis,start,ptime=0;
byte ss=0;
byte mm=0;
byte hh=0;
byte mEiner,mZehner,hEiner,hZehner=0;
byte setmode=0;
byte PWMArray[7]={
 10,20,40,80,160,255};
byte Pointer=4;


void setup(){
 pinMode(Shiftdata,OUTPUT);
 pinMode(Shiftclock,OUTPUT);
 pinMode(Shiftlatch,OUTPUT);
 pinMode(BUTTON,INPUT_PULLUP);
 pinMode(RTCPuls,INPUT);
 pinMode(PWMOUT,OUTPUT);
 TinyWireM.begin();                                  // Start I2C Kommunikation
 TinyWireM.beginTransmission(0x68);                  // Beginn Kommunikation auf  Adresse 0x68
 TinyWireM.send(0x07);                               // Pointer auf Control Register 0x07  
 TinyWireM.send(0x10);                               // Steuerwort Ex "0x30" Bin110000 Ausgang RTC Ausgang auf 1Hz Logic normal Levels setzn
 TinyWireM.endTransmission();                        // Beenden der I2C Kommunitkation
 HourRead();                                         // RTC Funktion lesen der aktuellen zeit Stunden
 MinuteRead();                                       // RTC Funktion lesen der aktuellen zeit Minuten
 RTC_Start();                                        // Start der Uhr
}


void loop(){
 /*=>Routine OneButton Control<=*/
 druck=digitalRead(BUTTON);            // Einlesen des Button (Achtung invertierte Logik da intrener Pull Up Widerstand aktiviert)
 if (druck==false&&ldruck==true){      // Steigende Flanke des Button
   start=millis();                     // Startzeit des Bettätigen
   ldruck=false;                       // Hilfsflag zur Flanken erkennung
 }
 if (druck==true&&ldruck==false){      // Falende Flanke des Buttons
   ptime=millis()-start;               // Die Länge in ms des Gedückten Zustandes
   ldruck=true;
 }
 if (ptime>=TIME){                    // Wenn der Druck länger (Hier750ms)
   longpress=true;                    // War ein Langer druck
   ptime=0;                           // Zeit wieder Zurücksetzten
 }
 if (ptime<TIME&&ptime>=50) {         // Wenn der Druck kürzer 750ms und länger 50ms (gegen prellen)
   shortpress=true;                   // War ein kurzer Durck
   ptime=0;                           // Zeit wieder zurücksetzuten
 }
 /*One Button End*/

 puls=digitalRead(RTCPuls);                 // Einlessen des RTC Sekunden Puls
 if (puls==true&&lpuls==false){             // wenn Sekundenpuls da und vorher nicht da war (steigende Flanke)
   lpuls=true;
   ss++;                                    // intern Sekunden zählen
 }
 if (ss>=60&&setmode==0){                   // Nach 60 Sekunden
   HourRead();                              // RTC Funktion lesen der aktuellen zeit Stunden
   MinuteRead();                            // RTC Funktion lesen der aktuellen zeit Minuten
   ss=0;                                    // Rücksetzzeten internen Sekunden Zähler auf 0
 }
 if (puls==false){                          // RTC Sekunden Hilfspuls
   lpuls=false;
 }
 if (shortpress==true){                    // Routine Kurzes drücken
   if (setmode==0){                        // In Normalmodus
     Pointer++;                            // ändern des Pointer der Helligkeit
     if (Pointer>=6){                      // Bei Pointer 6 und größer auf Pointer Null
       Pointer=0;
     }
   }
   if (setmode==1){                        // Minuten stellen
     mm++;
     if (mm>=60){
       mm=0;
     }
   }
   if (setmode==2){                        // Stunden stellen
     hh++;
     if(hh>=24){
       hh=0;
     }
   }
   shortpress=false;
 }
 if (longpress==true){                      // Routine Langes drücken
   setmode++;                               // Stellmodus erhöhen
   if (setmode==3){                         // Bei erreichen des Modus 3
     RTC_Set();                             // Neue Uhrzeit übernehmen in die RTC
     RTC_Start();                           // RTC Starten
     setmode=0;                             // Rücksetzten des Setmodes auf 0 (Normale Anzeige)
   }
   longpress=false;                         // Rücksetzten des Flags Langes Drücken
 }
 if (millis()-lmillis>=500){                // Aktalisiernung alle halbe Sekunden
   blinktakt= !blinktakt;                   // Blinktakt der Stellen anzeige
   mEiner=mm%10;                            // Einer Minuten
   mZehner=(mm-mEiner)/10;                  // Zehner Minuten
   hEiner=hh%10;                            // Einer Stunden
   hZehner=(hh-hEiner)/10;                  // Zehner Stunden
   hz=Dec2Shift(hZehner);                   // Wandeln der Zahlen in 7 Segment Ansteuerbytes
   he=Dec2Shift(hEiner);                    // dto.
   mz=Dec2Shift(mZehner);                   // dto.
   me=Dec2Shift(mEiner);                    // dto
   if (blinktakt==false){                  // Blinkroutine des Stellmodus
     if(setmode==1){                       // Minuten stellen
       me=0;
       mz=0;
     }
     if (setmode==2){                      // Stunden Stellen
       he=0;
       hz=0;
     }
   }
   digitalWrite(Shiftlatch, LOW);     // Latch aussetzten um in den Storage speicher zu schreiben
   shiftOut(Shiftdata, Shiftclock, MSBFIRST,  me);                    // Shift out der einzelenen Puffer wobei im letzten
   shiftOut(Shiftdata, Shiftclock, MSBFIRST,  mz);                    // Shift out der einzelenen Puffer wobei im letzten
   shiftOut(Shiftdata, Shiftclock, MSBFIRST,  he);                    // Shift out der einzelenen Puffer wobei im letzten
   shiftOut(Shiftdata, Shiftclock, MSBFIRST,  hz);                    // Shift out der einzelenen Puffer wobei im letzten
   digitalWrite(Shiftlatch, HIGH);                                        // Aktiverien des Latches (Schieben des Shift ind Storageregister) zum Anzeigen
   lmillis=millis();  
 }
 if (hh>=22&&hh<=8&&hell==true){                         // wenn Später 22Uhr und Früher als 8Uhr und es vorher Hell war dann dunkelschlaten
   Pointer=1;
   hell=false;
 }
 if (hh<22&&hh>8&&hell==false){                       // Wenn vor 22Uhr und nach 8 Uhr und vorher dunkel war dann Hell Schalten
   Pointer=5;
   hell=true;
 }
 analogWrite(PWMOUT,PWMArray[Pointer]);
}

byte Dec2Shift(byte x){
 byte shiftdata[11]={
   63,6,91,79,102,109,125,7,127,111};               // Daten für die 7 Segement anzeigen entspircht 0,1,2,3,4,5,6,7,8,9
 return shiftdata[x];
}

void HourRead(){
 TinyWireM.beginTransmission(RTC_ADDRESS);
 TinyWireM.send(0x02);               // Pointer auf Sekunden
 TinyWireM.endTransmission();
 TinyWireM.requestFrom(RTC_ADDRESS, 1);
 hh= bcdToDec(TinyWireM.receive());
}

void MinuteRead(){
 TinyWireM.beginTransmission(RTC_ADDRESS);
 TinyWireM.send(0x01);               // Pointer auf Sekunden
 TinyWireM.endTransmission();
 TinyWireM.requestFrom(RTC_ADDRESS, 1);
 mm= bcdToDec(TinyWireM.receive());
}

void RTC_Start(){
 TinyWireM.beginTransmission(RTC_ADDRESS);
 TinyWireM.send(0x00);
 TinyWireM.send(decToBcd(ss));    // 0 to bit 7 starts the clock
 TinyWireM.endTransmission();
}


void RTC_Set(){
 TinyWireM.beginTransmission(RTC_ADDRESS);
 TinyWireM.send(0x01);
 TinyWireM.send(decToBcd(mm));
 TinyWireM.send(decToBcd(hh));      // If you want 12 hour am/pm you need to set
 TinyWireM.endTransmission();
}

byte decToBcd(byte val)
{
 return ((val/10)<<4)+(val%10);
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
 return ((val>>4)*10)+val%16;
}


Kompiliert sind das 2980 bytes also passt auch auf einen Attiny44
Gruß
Der Dani
So ist das Leben:
Manchmal bis du das Denkmal, manchmal die Taube!

Go Up