Binäruhr

Aus Fingers Wiki
Wechseln zu: Navigation, Suche

2015-04-11 17.33.01.jpg 2015-04-11 17.33.13.jpg 2015-04-11 18.30.10.jpg

Die Binäruhr ist ein Übungsstück für Atmel Programmierung und meine zweite Uhr nach der Kettenuhr. Sie zeigt Datum (Tag), Stunde und Minute an. (Rot/Gelb/Grün)

Gehäuse

Das Gehäuse habe ich mit Openoffice Draw gezeichnet und im Fablab aus HDF ausgelasert. Die Teile passen sehr gut zueinander. Es kann entweder gestellt werden oder am Loch in der Rückwand aufgehängt werden. Für das Stromkabel sind rechts, links und unten Öffnungen vorgesehen.

Elektronik

Die Uhr wird von einem Atmega8 gesteuert. Die Uhrzeit stellt der MCP7940 zur Verfügung. Die Zeiteinstellung muss nach dem Verbinden mit dem Netzteil gemacht werden und die Uhr kann nicht nachgestellt werden. Über einen Photowiderstand am ADC wird die Helligkeit bestimmt und die Pins an denen die LEDs hängen wahlweise als Ein- oder Ausgang geschaltet um die Helligkeit nachts zu verringern.


Leider habe ich vor dem Löten den Schaltplan nicht aufgemalt sonden aus dem Gedächtnis gearbeitet. Aus den Kommentaren im Bereich der LED-Steuerung sind die Anschlüsse ersichtlich. Den Quelltext habe ich zum Glück gespeichert. Den I2C Teil habe ich aus dem Internet geklaut.


/*
 * Binaeruhr.c
 *
 * Created: 05.06.2014 14:22:57
 *  Author: Daniel */ 
 
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include <util/twi.h>
 
struct zeit{ int tag,stunden,minuten; };
static int eingabe();
static int read(unsigned char Adresse);
static void write(unsigned char Adresse, char Wert);
 
 
int main(void)
{
	DDRD=0b00111111;
	DDRC=0b00000111;
	DDRB=0b11111111;
	PORTD=0xff;
	_delay_ms(1000);
	PORTD=0b11000000;
	PORTC=0b00110000;
	_delay_ms(100);
 
	PORTB=0x01;
	uint8_t jahr = eingabe(); //Jahr in Jahren seit 2000
 
 
	PORTB=0x02;
	uint8_t monat = eingabe(); //Monat
 
 
	PORTB=0x03;
	uint8_t datum = eingabe(); //Datum
 
 
	PORTB=0x04;
	uint8_t stunde = eingabe(); //Stunde
 
 
	PORTB=0x05;
	uint8_t minute = eingabe(); //Minute
 
 
 
	uint8_t sekundebcd= 0b10000000;  //Zehnerstellen + Einserstellen + Oszi an bit
	uint8_t minutebcd= ((minute / 10) << 4) + ((minute % 10) & 0b00001111) ;  //Zehnerstellen + Einserstellen
	uint8_t stundebcd= ((stunde / 10) << 4) + ((stunde % 10) & 0b00001111) ;  //Zehnerstellen + Einserstellen
	uint8_t datumbcd= ((datum / 10) << 4) + ((datum % 10) & 0b00001111) ;  //Zehnerstellen + Einserstellen
	uint8_t monatbcd= ((monat / 10) << 4) + ((monat % 10) & 0b00001111) ;  //Zehnerstellen + Einserstellen
	uint8_t jahrbcd= ((jahr / 10) << 4) + ((jahr % 10) & 0b00001111) ;  //Zehnerstellen + Einserstellen
 
 
 
	write(0x01, minutebcd);  //Minuten setzen
	write(0x02, stundebcd);  //Stunden setzen
	write(0x04, datumbcd);  //Stunden setzen
	write(0x05, monatbcd);  //Stunden setzen
	write(0x06, jahrbcd);  //Stunden setzen
	write(0x00, sekundebcd);  //Sekunden setzen zulestz um erst am Schluss den Oszillator zu starten
 
 
 
	ADCSRA=0b11100100;
	ADMUX=0b01000011;
 
    while(1)
    {
		//uint8_t sekundebcd=read(0x00);
		uint8_t minutebcd=read(0x01);
		uint8_t stundebcd=read(0x02);
		uint8_t datumbcd=read(0x04);
		//uint8_t sekunde=(sekundebcd & 0b00001111) + 10*((sekundebcd & 0b01110000)>>4);   //binärwerte der Zeit
		uint8_t minute=(minutebcd & 0b00001111) + 10*((minutebcd & 0b01110000)>>4);
		uint8_t stunde=(stundebcd & 0b00001111) + 10*((stundebcd & 0b00110000)>>4);
		uint8_t datum=(datumbcd & 0b00001111) + 10*((datumbcd & 0b00110000)>>4);
		PORTD=minute;  //PORTD zeigt Minuten
		PORTC=datum & 0b00000111; //PORTC zeigt 1,2,4 er Stelle des Datums
		PORTB=stunde + (((datum & 0b00011000)>>3)<<6); //PORTB zeigt Stunden und 16,8er Stelle des Datums da von PORTC(nur 7 pins) schon 3 belegt sind (2xi2c+ADC) und reset nicht verwendet werden soll.
		_delay_ms(100);
 
		uint16_t helligkeitswert=ADCW;
 
 
		if (helligkeitswert>15)
		{
			DDRD=0b00111111;
			DDRC=0b00000111;
			DDRB=0b11111111;
		}
 
		if (helligkeitswert<8)
		{
 
			DDRD=0b00000000;
			DDRC=0b00000000;
			DDRB=0b00000000;
		}
 
	}
}
 
 
 
//solange Taste 1 drücken bis t passt, dann mit Taste zwei bestätigen
static int eingabe(){
	unsigned int a,key,lastkey;
	int t; //einzugebende Zeit
	t=0;
	lastkey=0;
	a=PORTD;
	PORTD|=0b11000000;  //für Saft an den Tastern sorgen
	while (1)
	{
		key=PIND & 0b11000000;
		if (key!=lastkey)
		{
			lastkey=key;
			if (!(PIND & 0b01000000))
			{
				t++;
				_delay_ms(100);
			}
			if (!(PIND & 0b10000000))
			{
				_delay_ms(100);
				while(!(PIND & 0b10000000));
				PORTD=a;
				return t;
			}
			else{}
 
		}
		_delay_ms(1);
		if (t==60)
		{
			t=0;
		}
 
		PORTD = (t | 0b11000000);
	}
}
 
 
 
 
static int read(unsigned char Adresse)
{
	unsigned char Empfaenger=0b11011110;
	unsigned char Sender=0b11011111;
	uint8_t c=0;
 
	TWBR=0x01;    // Bit rate
	TWSR=(0<<TWPS1)|(0<<TWPS0);
 
 
	// Clear TWI interrupt flag, Put start condition on SDA, Enable TWI
	TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);	
	while(!(TWCR & (1<<TWINT))); // Wait till start condition is transmitted	
	while((TWSR & 0xF8)!= 0x08); // Check for the acknowledgement	
 
 
	TWDR=Empfaenger;    // Address and read instruction
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte received	
	while((TWSR & 0xF8)!= 0x18);  // Check for the acknoledgement	
 
 
	TWDR=Adresse;    // put data in TWDR
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
	while((TWSR & 0xF8) != 0x28); // Check for the acknoledgement
 
 
	// Clear TWI interrupt flag, Put restart condition on SDA, Enable TWI
	TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
	while(!(TWCR & (1<<TWINT))); // Wait till start condition is transmitted
	while((TWSR & 0xF8)!= 0x10); // Check for the acknowledgement
 
 
	TWDR=Sender;    // put data in TWDR
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
	while((TWSR & 0xF8) != 0x40); // Check for the acknoledgement
 
 
    TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
    while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
    while((TWSR & 0xF8) != 0x58);
 
 
	c=TWDR;
 
 
	// Clear TWI interrupt flag, Put stop condition on SDA, Enable TWI
	TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	while(!(TWCR & (1<<TWSTO)));  // Wait till stop condition is transmitted
 
 
	return c;
 
}
 
 
static void write(unsigned char Adresse,char Wert)
{
	unsigned char Empfaenger=0b11011110;
 
	TWBR=0x01;    // Bit rate
	TWSR=(0<<TWPS1)|(0<<TWPS0);  
 
 
 
	// Clear TWI interrupt flag, Put start condition on SDA, Enable TWI
	TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
 
	while(!(TWCR & (1<<TWINT))); // Wait till start condition is transmitted
 
	while((TWSR & 0xF8)!= 0x08); // Check for the acknowledgement
 
 
 
 
	TWDR=Empfaenger;    // Address and read instruction
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte received
 
	while((TWSR & 0xF8)!= 0x18);  // Check for the acknoledgement
 
 
 
	TWDR=Adresse;    // put data in TWDR
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
	while((TWSR & 0xF8) != 0x28); // Check for the acknoledgement
 
 
 
	TWDR=Wert;    // put data in TWDR
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
	while((TWSR & 0xF8) != 0x28); // Check for the acknoledgement
 
	// Clear TWI interrupt flag, Put stop condition on SDA, Enable TWI
	TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	while(!(TWCR & (1<<TWSTO)));  // Wait till stop condition is transmitted 
 
}