Steampunk Analog mätare månfas klocka (8 / 11 steg)
Steg 8: Använda RTC för att köra mätarna
Vi behöver också lite kod till minuter och timmar och till återvända mätarna till noll när de max ut. Detta är verkligen rakt fram, men jag stötte på lite problem. När nålarna återgår till noll från deras full resor kan göra de det ganska kraftfullt. Tillräckligt för att göra en klickande buller och orsaka oro över livslängden av d'Arsonval rörelser i mätarna. Jag ville genomföra en mjuk retur rutin i mjukvaran som vid första rodna verkade ganska lätt att göra. Jag så småningom fick det att fungera och jag kommer att visa dig hur. Några av er elektronik gurus skulle kunna räkna ut en maskinvarulösning för detta (cap avgifter och avlopp genom en diod resistor arrangemang när PWM går till noll eller något). Om så är fallet, låt mig veta. Jag tog programvara sökvägen, och har inte använt någon mer tid att tänka om det.
En liten video av koden nedan körs. O'scope spår är det Kvadrera vinkar från RTC. Meddelande varje gång det löneförhöjningar, sekunder hand steg.
Här är ett program som kommer att läsa den RTC utifrån ett avbrott som genereras av RTC fyrkantsvåg bifogas pin 2 av arduino och utgång sekunder värdet på stift 5 (PWM).
Denna rutin inkluderar inte den mjuk returen för nålen.
#include < Wire.h >
#define DS3231_I2C_ADDRESS 104
#define int_pin 2
#define gauge_pin 5
byte sekunder, minuter, timmar, dag, datum, månad, år.
byte secpos;
char veckodag [4].
booleska int_tick;
byte tMSB, tLSB;
float temp3231;
void setup()
{
Wire.BEGIN();
Serial.BEGIN(9600);
Wire.beginTransmission(DS3231_I2C_ADDRESS); 104 är DS3231 enhetsadress
Wire.send(0x0E); //
Wire.send(B00000000);
Wire.endTransmission();
pinMode (int_pin, ingång);
digitalWrite(2,HIGH); slå på inre dra upp av stift 2
attachInterrupt (0, int0handler, RISING); bifoga avbrott noll till stift 2 och samtal funktion int0handler när stift 2 ser en stigande spänning
secpos = 0;
}
void loop()
{
om (int_tick) {
updategauge();
}
watchConsole(); används för att ändra tid och datum
}
void int0handler() {
int_tick = 1;
}
void updategauge() {
Serial.println("int");
get3231Date();
Serial.Print(weekDay); Serial.Print (","); Serial.Print (månad, DEC). Serial.Print("/"); Serial.Print (datum, DEC); Serial.Print("/"); Serial.Print (år, DEC). Serial.Print ("-");
Serial.Print (timmar, DEC); Serial.Print(":"); Serial.Print (minuter, DEC); Serial.Print(":"); Serial.Print (sekunder, DEC);
Serial.Print ("temperatur:"); Serial.println(get3231Temp());
secpos = sekunder * 4;
om (secpos > = 240) secpos = 0; Detta kommer att återvända den andra nålen i slutet av resor
analogWrite (gauge_pin, secpos);
int_tick = 0; återställa flaggan int fästing
}
Konvertera normala decimaltal till binary coded decimal
byte decToBcd(byte val)
{
tillbaka ((val/10 * 16) + (val % 10));
}
void watchConsole()
{
om (Serial.available()) {/ / leta efter röding i följetong kö och processen om hittade
om (Serial.read() == 84) {//If kommando = "T" Ange datum
set3231Date();
get3231Date();
Serial.println("");
}
}
}
void set3231Date()
{
T(SEC)(min)(Hour)(DAYOFWEEK)(dayOfMonth)(month)(Year)
T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99)
Exempel: 02-Feb-09 @ 19:57:11 för 3: e dagen i veckan -> T1157193020209
sekunder = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48)); Användning av (byte) typ gjutning och ASCII-matematik för att uppnå resultat.
minuter = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
timmar = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
dag = (byte) (Serial.read() - 48);
datum = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
månad = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
år = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.send(0x00);
Wire.send(decToBcd(seconds));
Wire.send(decToBcd(Minutes));
Wire.send(decToBcd(hours));
Wire.send(decToBcd(Day));
Wire.send(decToBcd(date));
Wire.send(decToBcd(month));
Wire.send(decToBcd(Year));
Wire.endTransmission();
}
void get3231Date()
{
skicka begäran om att ta emot data från register 0
Wire.beginTransmission(DS3231_I2C_ADDRESS); 104 är DS3231 enhetsadress
Wire.send(0x00); börja vid register 0
Wire.endTransmission();
Wire.requestFrom (DS3231_I2C_ADDRESS, 7); begära sju byte
IF(Wire.available()) {
sekunder = Wire.receive(); få sekunder
minuter = Wire.receive(); få minuter
timmar = Wire.receive(); få timmar
dag = Wire.receive();
datum = Wire.receive();
månad = Wire.receive(); Temp månad
år = Wire.receive();
sekunder = (((seconds & B11110000) >> 4) * 10 + (sekunder & B00001111)); konvertera BCD till decimal
minuter = (((minutes & B11110000) >> 4) * 10 + (minuter & B00001111)); konvertera BCD till decimal
timmar = (((hours & B00110000) >> 4) * 10 + (timmar & B00001111)); konvertera BCD till decimal (antar 24 timmarsvisning)
dag = (dag & B00000111); 1-7
datum = (((date & B00110000) >> 4) * 10 + (datum & B00001111)); 1-31
månad = (((month & B00010000) >> 4) * 10 + (månad & B00001111)); msb7 är talet overflow
år = (((year & B11110000) >> 4) * 10 + (år & B00001111));
}
annat {
Åh nej, inga data!
}
Växla (dag) {
fall 1:
strcpy (veckodag, "Sun");
bryta;
fall 2:
strcpy (veckodag, "Må");
bryta;
fall 3:
strcpy (veckodag, "Tis");
bryta;
fall 4:
strcpy (veckodag, "ons");
bryta;
fall 5:
strcpy (veckodag, "Tor");
bryta;
fall 6:
strcpy (veckodag, "Fr");
bryta;
fall 7:
strcpy (veckodag, "Sat");
bryta;
}
}
float get3231Temp()
{
Temp register (11h - 12h) få uppdateras automatiskt varje 64s
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.send(0x11);
Wire.endTransmission();
Wire.requestFrom (DS3231_I2C_ADDRESS, 2);
IF(Wire.available()) {
tMSB = Wire.receive(); 2: s komplettera int del
tLSB = Wire.receive(); bråk del
temp3231 = (tMSB & B01111111); gör 2: s matematik på Tmsb
temp3231 += ((tLSB >> 6) * 0,25); bara bryr sig om bitar 7 & 8
}
annat {
Åh nej, inga data!
}
återvända temp3231;
}