Самостоятельное изготовление часов является непростым, но в то же время увлекательным занятием. Часы с необычными способами отображения времени всегда привлекали внимание и становились предметом гордости их создателей.
В этом проекте мы сделаем часы на основе старых вольтметров, стрелки которых будут отображать время на шкалах напряжения. Управлять всем этим будет плата Arduino.
Схема подключения в данном случае довольно простая. Здесь помимо Arduino есть часы реального времени DS3231, двигатели и счетчики в виде вольтметров. Двигатели этих счетчиков подключены к трем выводам ШИМ, а часы реального времени – к двум выводам SCL и SDA интерфейса I2C.
Внешний вид подключения может быть таким.
Разберите счетчики, и прикрепите бумажные циферблаты с необходимыми шкалами к счетчикам. Установите счетчики на пластину и подключите их, подключите модуль часов реального времени.
Загрузите приведенный далее скетч и установите режим на 2, установите нижнее положение каждого диска, изменив числа в переменных hoursMinimum, minutesMinimum и secondsMinimum, и повторно загрузите скетч. Отрегулируйте переменные так, чтобы все стрелки вольтметров находились на левом конце циферблатов. Проделайте то же самое, но чтобы стрелки оказались на правом конце циферблатов.
Чтобы установить время, введите его в вызов функции setDS3231time в функции setup(), используя режим 1. Когда скетч загружен, должно отображаться время, а секунды должны отсчитываться.
Установите режим на 0 и загрузите скетч, пока батарея часов остается подключенной, время будет отображаться при включенном Arduino.
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
int mode = 0;
int hoursPin = 5;
int minutesPin = 6;
int secondsPin = 9;
float hoursValue = 0;
float minutesValue = 0;
float secondsValue = 0;
float hoursMinimum = 14;
float minutesMinimum = 14;
float secondsMinimum = 22;
float hoursMaximum = 230;
float minutesMaximum = 230;
float secondsMaximum = 236;
void setup() {
pinMode(hoursPin, OUTPUT);
pinMode(minutesPin, OUTPUT);
pinMode(secondsPin, OUTPUT);
Wire.begin();
Serial.begin(9600);
if(mode == 1){
// s m h day d m y
setDS3231time(30, 46, 16, 7, 12, 9, 20);
}
}
void loop() {
byte second, minute, hour, weekday, day, month, year;
switch(mode){
case 0:
case 1:
readDS3231time(&second, &minute, &hour, &weekday, &day, &month, &year);
secondsValue = second;
minutesValue = minute;
hoursValue = hour;
if(hoursValue > 11){
hoursValue -= 12;
}
analogWrite(secondsPin, secondsMinimum + (((secondsMaximum - secondsMinimum) / 60) * secondsValue));
analogWrite(minutesPin, minutesMinimum + (((minutesMaximum - minutesMinimum) / 60) * minutesValue));
analogWrite(hoursPin, hoursMinimum + (((hoursMaximum - hoursMinimum) / 12) * hoursValue));
break;
case 2:
analogWrite(secondsPin, secondsMinimum);
analogWrite(minutesPin, minutesMinimum);
analogWrite(hoursPin, hoursMinimum);
break;
case 3:
analogWrite(secondsPin, secondsMaximum);
analogWrite(minutesPin, minutesMaximum);
analogWrite(hoursPin, hoursMaximum);
break;
}
delay(100);
}
byte decToBcd(byte val){
return((val / 10 * 16) + (val % 10));
}
byte bcdToDec(byte val){
return ((val / 16 * 10) + (val % 16));
}
void setDS3231time(byte second, byte minute, byte hour, byte weekday, byte day, byte month, byte year){
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(weekday));
Wire.write(decToBcd(day));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void readDS3231time(byte *second, byte *minute, byte *hour, byte *weekday, byte *day, byte *month, byte *year){
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*weekday = bcdToDec(Wire.read());
*day = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
© digitrode.ru