Фазы Луны и 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.

clip_image002

Если вы не разбираетесь в электронных схемах, вам поможет приведенная ниже таблица с описанием соединения компонентов.

Контакт 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, посвященного его личным проектам и хобби. Отдав более двенадцати лет работе в госорганах, он надеется в один прекрасный день очутиться в мире, где создают игры и игрушки.