Фазы Луны и Arduino
Опубликовано 18 августа 2009 в 12:14 | Coding4Fun
Ничто не приносит такого удовлетворения умельцу, как наблюдение собственного творения в реальном мире
, когда есть огромный выбор электронных игрушек и гаджетов, можно без особых усилий смастерить собственное устройство, переделав существующее.
Отличный способ подстегнуть свое воображение — посещение магазина игрушек и разных безделушек. Я стараюсь проявлять детскую непосредственность в таком магазине: рассматриваю каждую вещицу и стараюсь представить, как усовершенствовать ее конструкцию, что надо сделать, чтобы она стала интересней и играть с ней было веселей.
В этой статье вы познакомитесь с одним из самых интересных результатов моего хобби — простой ночник, который показывает разные фазы Луны под контролем инфракрасного дистанционного управления, мы переделаем его таким образом, что он будет показывать фазу Луны, соответствующую текущей дате.
· Исполняемая программа: Загрузить программу установки (EN)
· Исходный текст : Загрузить
· Сложность: средняя
· Необходимое время : 8 часов
· Затраты: $90
· НеобходимоеПО : Arduino Development Environment, фрагмент Lunarupdate arduino, Visual Basic или Visual C# Express
· Оборудование: Ночник ThinkGeek R/C Moon Phase - $29.99, модуль часов реального времени Sparkfun DS1307 - $19.99, Arduino Duemilanove - $34.95, 0-100k потенциометр - $0.95, дополнительно: трансформатор 9V DC - $7.00 (только если вы хотите подключать светильник к сети, а не к батарейкам).
Сбор материала
Что требуется для реализации проекта?
Очевидно, что каким-то образом надо отслеживать текущую дату и, желательно, сохранять ее даже в случае разрядки батареек. Нам также потребуется некоторым образом управлять светодиодами нашего устройства и вычислять текущую фазу луны на основании даты. Кроме того, было бы здорово каким-то удобным для пользователя способом изменять хранимую дату, поскольку со временем она может «уходить».
Все остальное, что требуется для запуска нашего прототипа, легко найти и не потребует особых затрат.
Arduino — это платформа с открытым исходным кодом для создания прототипов. Она ориентирована на художников и дизайнеров, которые могут с ее помощью быстро воплощать в жизнь свои идеи в виде прототипов. Для их создания применяется С-подобный язык с высоким уровнем абстракции, скрывающий технические подробности программирования микроконтроллеров. Как и другие проекты с открытым исходным кодом, Arduino имеет множество реализаций. Вы даже можете построить свою. Готовая плата Arduino стоит не больше $30, собственная же обойдется гораздо дешевле.
Модуль часов реального времени DS1307. Для отслеживания даты мы будем использовать модуль часов реального времени DS1307. Я приобрел DS1307 в колорадском магазине SparkFun Electronics, специализирующемся на товарах для изготовления моделей. Он имеет генератор, резервное питание на миниатюрном аккумуляторе и его можно связать с Arduino с помощью стандартной двухпроводной шины I2C.
Я также использую стандартный потенциометр (переменное сопротивление) на 100 кОм, подключенный последовательно к существующему фоторезистору, с тем чтобы изменять чувствительность ночника к свету в различных условиях.
И наконец, для подстройки часов DS1307 я написал простейшую программку на C#, которая запрашивает системное время компьютера и передает его Arduino, которая, в свою очередь, по шине I2C устанавливает дату на DS1307.
Первые шаги
Если вам приходилось сталкиваться с загадочным внутренним мироустройством электронных устройств, вы оцените простоту используемого нами ночника.
Используемое оборудование продемонстрировано в видеоклипе.
По сути, все, что мы сделали, — заменили стандартный контроллер светильника контроллером Arduino, соединенным с часами DS1307.
Если вы не разбираетесь в электронных схемах, вам поможет приведенная ниже таблица с описанием соединения компонентов.
Контакт Arduino: |
Подключен к: |
Цифровой контакт 3 |
Центральный контакт потенциометра |
Цифровые контакты 7-12 |
Светодиоды (красный — 7 … пурпурный — 12) |
Аналоговый контакт 5 |
Контакт DS1307 SCL |
Аналоговый контакт 4 |
Контакт DS1307 SDA |
Земля |
Земля DS1307 |
Земля |
(-) Отрицательный контакт батареи |
Земля |
Внешний контакт потенциометра |
Земля |
Земля (коричневый) провод LED-панели |
5V |
Ножка LDR |
5V |
5V в DS1307 |
VIN |
Центральная ножка выключателя питания |
Также подключены:
Неиспользуемая ножка LDR |
Неиспользуемая ножка потенциометра |
Внешняя ножка выключателя питания |
(-) Положительный контакт батареи |
На самом деле это все не так сложно, как может показаться. Когда у вас будут все комплектующие, вы сможете легко определить перечисленные выше компоненты и связать все вместе, используя в качестве инструкции приведенную выше таблицу.
Программа
Код для обеспечения совместной работы Arduino и DS1307 есть на сайте Arduino. Это фантастический ресурс, на котором представлены примеры программ, демонстрирующие возможности взаимодействия Arduino с различными аппаратными и программными средствами.
Получив дату из DS1307, мы можем вычислить фазу Луны в нашей программе Arduino:
1: // Адаптация программы вычисления фазы Луны
2: // Стефана Р. Шмитта (Stephen R. Schmitt), написанной на языке Zeno.
3: // https://home.att.net/~srschmitt/lunarphasecalc.html
4:
5: byte getPhase(int Y, int M, int D) {
6: double AG, IP;
7: byte phase;
8: long YY, MM, K1, K2, K3, JD;
9: YY = Y - floor((12 - M) / 10);
10: MM = M + 9;
11: if(MM >= 12)
12: MM = MM - 12;
13:
14: K1 = floor(365.25 * (YY + 4712));
15: K2 = floor(30.6 * MM + 0.5);
16: K3 = floor(floor((YY / 100) + 49) * 0.75) - 38;
17:
18: JD = K1 + K2 + D + 59;
19: if(JD > 2299160)
20: JD = JD -K3;
21:
22: IP = normalize((JD - 2451550.1) / 29.530588853);
23: AG = IP*29.53;
24:
25: if(AG < 1.20369)
26: phase = B00000000;
27: else if(AG < 3.61108)
28: phase = B00000001;
29: else if(AG < 6.01846)
30: phase = B00000011;
31: else if(AG < 8.42595)
32: phase = B00000111;
33: else if(AG < 10.83323)
34: phase = B00001111;
35: else if(AG < 13.24062)
36: phase = B00011111;
37: else if(AG < 15.64800)
38: phase = B00111111;
39: else if(AG < 18.05539)
40: phase = B00111110;
41: else if(AG < 20.46277)
42: phase = B00111100;
43: else if(AG < 22.87016)
44: phase = B00111000;
45: else if(AG < 25.27754)
46: phase = B00110000;
47: else if(AG < 27.68493)
48: phase = B00100000;
49: else
50: phase = 0;
51:
52: return phase;
53: }
И в завершении: Arduino может взаимодействовать с ПК через стандартный последовательный интерфейс благодаря контроллеру FTDI «USB — последовательный интерфейс», поставляемому с многими платами Arduino.
C #:
1: // Событие Click используется для отправки данных на Arduino.
2: // Следующий простейший пример демонстрирует запись данных в
3: // последовательный порт. В более сложных программах применяются
4: // протоколы и избыточное кодирование для обеспечения достоверности
5: // передаваемых данных.
6: private void updateButton_Click(object sender, EventArgs e)
7: {
8: byte[] result = new byte[7];
9:
10: DateTime currTime = DateTime.Now;
11:
12: serialPort.PortName = “COM4”;
13: serialPort.BaudRate = 19200;
14: serialPort.DataBits = 8;
15: serialPort.Parity = Parity.None;
16: serialPort.StopBits = StopBits.One;
17:
18: try
19: {
20: serialPort.Open();
21: }
22: catch (IOException ioe)
23: {
24: // Обработать исключения.
25: }
26:
27: // Некоторые модели Arduino автоматически перезагружаются при
28: // открытии последовательного порта. Для этого
29: // делается небольшая задержка.
30: Thread.Sleep(10000);
31:
32: result[0] = BitConverter.GetBytes(currTime.Second)[0];
33: result[1] = BitConverter.GetBytes(currTime.Minute)[0];
34: result[2] = BitConverter.GetBytes(currTime.Hour)[0];
35: result[3] = BitConverter.GetBytes(1)[0];
36: result[4] = BitConverter.GetBytes(currTime.Day)[0];
37: result[5] = BitConverter.GetBytes(currTime.Month)[0];
38: result[6] = BitConverter.GetBytes((currTime.Year % 2000))[0];
39:
40: try
41: {
42: serialPort.Write(result, 0, result.Length);
43: serialPort.Close();
44: }
45: catch (InvalidOperationException ioe)
46: {
47: // Обработать другие исключения.
48: }
49: catch (TimeoutException te)
50: {
51: // Обработать другие исключения.
52: }
53: }
Arduino
Осталось только «научить» Arduino читать и обрабатывать данные. Вот какой код для Arduino получится с использованием нашего простейшего примера, приведенного выше.
1: void loop() {
2: while(Serial.available()) {
3: reader = Serial.read();
4: if(reader == 255) {
5: // ничего не делаем
6: }
7: else {
8: // заполняем массив значениями
9: needsUpdate = true;
10: update[addr] = reader;
11: addr += 1;
12: }
13: }
14:
15: // Получив все значения, обновляем часы.
16: if((needsUpdate) && (addr == 7)) {
17: setDateDs1307(update[0],
18: update[1],
19: update[2],
20: update[3],
21: update[4],
22: update[5],
23: update[6]);
24: // Сохраняем последние две цифры года в ППЗУ.
25: EEPROM.write(0, update[6]);
26: }
27: delay(100);
28: needsUpdate = false;
29: addr = 0;
30: }
Завершение
Вот и все. Можете скачать мою программу с imagitronics.org или написать свою. Присоединяйтесь к проекту, нам есть чем заняться: Надо реализовать коммуникационный протокол, сделать настольное приложение более надежным, найти способы удешевить устройство, применив USB HID-контроллер и обеспечив питание светильника через USB.
Я написал эту статью, чтобы привлечь больше энтузиастов к конструированию микроконтроллерных устройств и развеять миф о сложности подобных проектов.
Запомните мой девиз: мечтайте, создавайте, ломайте и повторяйте все с начала.
Благодарности
· Джону Вотерсу (John Vaughters) за его функции для DS1307 RTC (EN).
· SparkFun Electronics за библиотеку EAGLE CAD (EN).
· Робу Фалуди (Rob Faludi) за библиотеку Arduino EAGLE CAD (EN).
· Стефану Шмитту (Stephen Schmitt) за пример с фазами Луны на языке программирования Zeno.
Об авторе
Тим Фарли (Tim Farley) — ветеран войны в Ираке, системный интегратор в МО, автор сайта imagitronics.org, посвященного его личным проектам и хобби. Отдав более двенадцати лет работе в госорганах, он надеется в один прекрасный день очутиться в мире, где создают игры и игрушки.
Comments
- Anonymous
June 15, 2010
Чувак, спасибо за формулу рассчёта фазы луны! Задолбался искать нормальную.