Блог Дмитрия Сошникова

про технологии и человеческое счастье

Обманутые ожидания, Голливуд и счастье

Сегодня мне подумалась одна мысль, которая напрямую не относится к технологиям, но которая мне кажется достаточно важной, чтобы с вами поделиться чуть более подробно, чем в формате твиттера. Она про счастье.

Что очень часто делает нас несчастными? Рассмотрим пример. Идем мы на какой-нибудь фильм, который нам все друзья очень рекомендовали смотреть, потому что он волшебный и вообще прекрасный. Скажем, звёздные войны. Смотрим, и вдруг понимаем, что как-то не очень. В результате настроение плохое, весь день испорчен, с друзьями поссорились – у них ведь нет вкуса, что с ними дружить… Печаль.

Речь тут не про звёздные войны, я их кстати пока не смотрел. Речь про то, что делают нас несчастными в этом случае обманутые ожидания. Нам обещали хороший фильм, а оказалось не очень. Рожая ребенка мы думали, что он будет лучшим учеником в классе по математике, а он любит рисовать и получать подарки на новый год. И ещё много разных обманутых ожиданий делают нашу жизнь гораздо более невыносимой и несчастной.

А теперь задумаемся, что же формирует наши ожидания. В каких-то случаях наши друзья. В каких-то – наш собственный опыт. Но во многом наши ожидания от жизни формируются под воздействием той медиа-среды, которая нас окружает с детства. Например, кино. Во многом кино, потому что книги сейчас читают всё меньше.

А что мы видим в фильмах? По крайней мере в тех, которые в основном показывают в кинотеатрах. Там happy end. Там счастливые и красивые люди на экранах улыбаются, а если и сталкиваются с какими-то сложностями – то всё быстро как-то разрешается, и в конце главные герои обнимаются и уходят в закат, чтобы там жить долго и счастливо, пока смерть не разлучит их. Однако саму смерть, да и саму жизнь после happy end, уже не показывают, ну по крайней мере почти никогда.

Это формирует у нас определенные ожидания от жизни. Всё всегда должно быть и заканчиваться хорошо. Любовь – одна единственная на всю жизнь. Разворачивающиеся вокруг действия просто не могут не сделать нашу жизнь насыщенной и интересной (ведь всё неинтересное – вырезано и осталось за кадром). Мы в центре жизни, и пусть вокруг кучами погибают второстепенные герои – до них никому нет дела, главный герой непобедим, не болеет гриппом и уже через час-другой после начала фильма обязательно будет счастлив.

А в жизни всё иногда получается не совсем так радужно. Мы болеем. Болеют наши близкие. Ребенок приносит из школы двойки и рваные учебники. А мы периодически оказываемся в позиции второстепенных героев. И получаются они самые – обманутые ожидания и постоянное несчастье, оттого, что наша жизнь не соответствует кем-то установленному и зафиксированному в голливудских фильмах шаблону счастья.

В чем же мораль? Не смотрите фильмов. Не имейте ожиданий и идите навстречу каждому новому дню с чистым сознанием, чтобы с чистого листа восторгаться тем замечательным вещам, которые даёт нам жизнь. Почаще смотрите вокруг и находите поводы для счастья. Например, как Полианна (фильм про неё все-таки можно и нужно посмотреть, ведь нет правил без исключений, ну а еще лучше прочитать книгу).

P.S. Как вы наверное заметили, это слегка необычный пост. Мне бы хотелось этим постом начать небольшую серию заметок о жизни – ведь размышлять о ней и делиться мыслями на мой взгляд не менее важно, чем говорить о технологиях. Вы согласны? Дайте мне знать, что вы думаете о такой идее, и про что хотели бы услышать.

P.P.S. Все упомянутые в заметке персонажи являются сугубо вымышленными. Любые совпадения случайны. Моя дочь @vickievalerie любит математику и никогда не получает по ней двойки.

Add a comment

Магия треугольника Серпинского в функциональном стиле

Сегодня мы поговорим про замечательную геометрическую фигуру: треугольник Серпинского. Это фрактальная самоподобная структура, которая однако очень проста в построении.

image

Алгоритм построения треугольника таков:

  • Задаем координаты трех вершин-аттракторов (x1,y1), (x2,y2) и (x3,y3)
  • Выбираем некоторую точку (x,y) внутри треугольника
  • Повторяем много раз:
    • Ставим точку с координатами (x,y)
    • Выбираем случайным образом одну из вершин (xi,yi)
    • Вычисляем координаты новой точки по формуле ((x+xi)/2,(y+yi)/2)

Такой алгоритм легко реализовать на любом языке программирования, однако его реализация на функциональных языках имеет ряд интересных моментов. В частности, для вычисления координат всех точек треугольника мы используем концепцию корекурсии.

В соответствии с этим, мы реализуем функцию sierpinski, которая будет возвращать бесконечную последовательность координат точек треугольника:

let sierpinski (p1,p2,p3) =
   let rec sierpinski' pt =
      seq {
        let p = pick [p1;p2;p3]
        let pt' = mid pt p
        yield pt'
        yield! sierpinski' pt'
      }
   sierpinski' (mid3 p1 p2 p3)

В этом определении мы используем вспомогательную вложенную рекурсивную функцию sierpinski’, которая в качестве аргумента передает координаты текущей точки pt. Координаты вершин p1,p2,p3 в данном случае являются внешними по отношению к этой функции. Далее мы выбираем одну из вершин случайным образом, вычисляем координаты очередной точки, “возвращаем” (с помощью yield) эти координаты, и затем рекурсивно возвращаем бесконечный остаток списка, который получается из рекурсивного вызова. Затем чтобы сформировать результат мы вызываем sierpinsky’, передавая ему в качестве начальной точки среднюю точку, вычисленную из координат вершин.

Для вычисления средних точек мы определим следуюшие вспомогательные функции:

let mid (x1,y1) (x2,y2) = (x1+x2)/2,(y1+y2)/2
let mid3 (x1,y1) (x2,y2) (x3,y3) = (x1+x2+x3)/3,(y1+y2+y3)/2

Для выбора вершины случайным образом мы используем немного нефукнциональный подход, который зато позволяет быстро получить требуемую функциональность:

let Rnd = new Random()
let pick (L:'t list) = L.[Rnd.Next(0,Seq.length L)]

В завершение остаётся лишь построить полученный треугольник. Для этого можем использовать стандартную библиотеку FSharp.Charting:

sierpinski ((0,0),(300,600),(600,0)) |> Seq.take 5000 |> Chart.FastPoint

Вот какой получился результат:

image

Весь исходный код можно найти здесь: http://fssnip.net/ta.

В качестве самостоятельного упражнения, попробуйте в качестве эксперимента модифицировать функцию sieprinski, чтобы она могла принимать произвольное число вершин. И посмотрите, будет ли сохраняться фрактальное свойство для квадратов, шестиугольников и т.д. Буду рад видеть результаты ваших экспериментов в комментариях!

Add a comment

Windows Remote Arduino–управляем настольной лампой прямо из универсального приложения Windows

Сейчас в Майкрософт мы проводим “неделю интернета вещей”, поэтому тема моего очередного поста – о подключении устройств к Windows. Я уже писал про различные сценарии подключение датчиков к облаку, но бывают сценарии, когда нам хочется просто подключить датчики или устройства к нашему компьютеру и удаленно ими управлять. Например, мы хотим сделать приложение, которое будет включать и выключать настольную лампу. В этих случаях самым простым решение будет использование Windows Remote Arduino – проекта, который был недавно объявлен в рамках партнерства с Arduino.

Что такое Windows Remote Arduino

Windows Remote Arduino – это библиотека WinRT, которая позволяет управлять цифровыми и аналоговыми каналами платы Arduino из Windows/Windows Phone приложения, с помощью привычных команд типа digitalRead/Write и analogRead/Write. При этом сама плата может быть подключена к компьютеру по USB или Bluetooth – важно, чтобы обеспечивался последовательный канал передачи данных. Помимо простых команд включения/выключения входов/выходов, в том или ином виде предусмотрена работа с шиной I2C и (в перспективе) сервоприводами.

image

Для работы необходимо, чтобы на плате Arduino была запущена специальная программа, поддерживающая выполнение команд по протоколу Firmata, а библиотека Windows Remote Arduino обменивается командами с платой, предоставляя программисту высокоуровневые функции управления.

Библиотеки Windows Remote Arduino доступны для Windows 8.1/Windows Phone 8.1 и для универсальных приложений Windows 10. Чтобы использовать их в своем проекте, в настоящее время проще всего клонировать Git-репозиторий проекта и добавить необходимые проекты в своё решение (пример я опишу ниже).

Пример – включатель лампочки

В моём примере я буду разрабатывать интеллектуальное приложение, включающее настольную лампу. Для этой цели я использую плату Arduino Uno и реле, способное коммутировать 220В. Реле подключается к какому-нибудь цифровому выходу (например, 7). Также для обнаружения присутствия человека будем использовать инфракрасный датчик присутствия, который включим в аналоговый вход A0. Для удобства коммутации мы используем Troyka Shiled от Амперки.

На приведенном ниже видео смотрите подробнее про hardware setup, а также весь проект в действиии.

 

Устанавливаем скетч Firmata на плату Arduino

Первым делом необходимо установить на плату Arduino стандартный скетч для выполнения команд Firmata. Такой скетч уже включен в стандартную поставку Arduino IDE – достаточно выбрать в меню File –> Examples –> Firmata –> Standard Firmata. Открывшийся при этом скетч необходимо загрузить в плату обычным образом.

image

На этом этапе полезно будет убедиться, что все аппаратное обеспечение настроено правильно. Для этого можно использовать специальную программу firmata_test.exe (или любую из программ, описанных здесь) – вы должны быть в состоянии управлять лампочкой, переключая состояние цифрового выхода 7, а также на входе A0 вы должны получать значение 0, если движения вокруг сенсора нет, и большое положительное значение (около 600 и более) в противном случае.

image image

Готовим проект с Windows Remote Ardunio

Чтобы использовать Windows Remote Arduino в своём проекте, необходимо подключить соответствующие библиотеки. На текущий момент технология достаточно молодая, и библиотеки существуют в виде исходных текстов. Мы надеемся, что со временем появятся пакеты NuGet, сейчас же процесс включения библиотек выглядит следующим образом:

1. Создадим новый проект – в нашем случае это будет универсальное приложение Windows 10

2. Клонируйте GitHub-репозиторий проекта Windows Remote Arduino в какую-нибудь локальную папку:

git clone https://github.com/ms-iot/remote-wiring/

ВАЖНО: в репозитории имеются несколько версий библиотеки. На момент написания статьи последняя ветка master содержала много ошибок при работе с аналоговыми и цифровыми входами, поэтому я использовать наиболее стабильную ветку revert-18-develop. Очень надеюсь, что в скором времени выйдет еще более стабильная версия, и клонировать можно будет как показано выше, без указания ветки.

3. В получившемся дереве проектов есть папки Microsoft.Maker.Win10 и Microsoft.Maker.Win8_1. Мы будем использовать вариант для Windows 10, но проект поддерживает и универсальные приложения Windows 8.1

4. В папке Microsoft.Maker.Win10 есть три проекта: Microsoft.Maker.Firmata, Microsoft.Maker.Serial и Microsoft.Maker.RemoteWiring. Эти три проекта нужно добавить в созданный нами проект (Add Existing Project)

5. В результате получится следующее дерево проектов:

image image

6. Чтобы проекты компилировались в правильном порядке, необходимо установить правильные зависимости проектов. Нажмите правой кнопкой на наш проект, выберите “Зависимости сборки –> Зависимости проектов”, и установите галочки напротив всех трех добавленных проектов. Остальные зависимости должны быть уже установлены, но вы можете их проверить: проект Firmata зависит от проекта Serial, проект RemoteWiring – от проектов Firmata и Serial. Соответственно, на вкладке “Порядок сборки” проекты должны собираться в таком порядке: Serial, Firmata, RemoteWiring и наше приложение.

7. В нашем основном проекте правой кнопкой нажмите на References и добавьте расширение Microsoft Visual C++ AppLocal Runtime Package for Windows UAP. Там же в пункте “Общие проекты” выберите все три добавленных проекта Windows Remote Arduino.

image

8. ВАЖНО: Чтобы наше приложение могло использовать возможности работы с последовательным портом, необходимо в манифест приложения (файл Package.appxmanifest) в раздел <Capabilities> добавить следующий код:

<DeviceCapability Name="serialcommunication">
  <Device Id="any">
    <Function Type="name:serialPort"/>
  </Device>
</DeviceCapability>

9. Мы готовы к созданию нашего приложения, которое будет использовать библиотеки Windows Remote Arduino! Чтобы убедиться, что всё работает правильно, попробуйте выполнить сборку получившегося приложения.

Создаем приложение с Windows Remote Arduino

Наше приложение будет иметь три кнопки: для включения лампочки, для выключения, и для авто-режима, в котором лампочка будет управляться датчиком присутствия. Для начала добавим на главную страницу приложения MainPage.xaml эти три кнопки, установив их в неактивное состояние:

<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
    <Button x:Name="on" IsEnabled="False" Content="ON" FontSize="30" Width="150" Height="150" Click="on_Click"></Button>
    <Button x:Name="off" IsEnabled="False" Content="OFF" FontSize="30" Width="150" Height="150" Click="off_Click"></Button>
    <Button x:Name="auto" IsEnabled="False" Content="AUTO" FontSize="30" Width="150" Height="150" Click="auto_Click" ></Button>
    <TextBlock x:Name="txt"/>
    <ListBox x:Name="lst"/>
</StackPanel>

Этот код добавляется внутрь того контейнера Grid, который уже по умолчанию есть у страницы. Также для каждой кнопки создадим функцию-обработчик на C# (кликнув дважды на каждую кнопку, или через окно свойств Visual Studio).

Для начала инициализируем объект Remote Arduino. Для этого в классе окна в файле MainPage.xaml.cs опишем две переменные

UsbSerial usbcomm;
RemoteDevice arduino;

Для подключение к Arduino опишем функцию connect(), которую затем вызовем из конструктора MainPage():

private async void connect()
{
    var dev = await UsbSerial.listAvailableDevicesAsync();
    usbcomm = new UsbSerial(dev[0]);
    arduino = new RemoteDevice(usbcomm);
    usbcomm.ConnectionEstablished += Comm_ConnectionEstablished;
    usbcomm.begin(57600, SerialConfig.SERIAL_8N1);
}

Здесь мы сначала определяем список доступных портов, куда может быть подключен Arduino, затем создаем последовательное соединение UsbSerial с этим портом, а затем поверх этого – объект RemoteDevice, который будет представлять собой виртуальный Arduino. После этого мы вызываем функцию begin, передавая параметры последовательного соединения.

ВАЖНО: Скорость последовательного канала, используемая протоколом Firmatа, задается в скетче StandardFirmata. По умолчанию она равна 57600, поэтому мы выбираем именно эту скорость в нашем приложении. Если скорости не будут совпадать, то соединение не будет работать.

При установлении соединения с платой, будет вызвана функция Comm_ConnectionEstablished, которую мы опишем следующим образом:

private void Comm_ConnectionEstablished()
{
    Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,new Windows.UI.Core.DispatchedHandler(() =>
    {
        arduino.pinMode(14, PinMode.ANALOG);
        arduino.pinMode(relay_pin, PinMode.OUTPUT);
        dt = new DispatcherTimer() { Interval = new TimeSpan(500) };
        dt.Tick += loop;
        dt.Start();
        on.IsEnabled = true;
        off.IsEnabled = true;
        auto.IsEnabled = true;
    }));
}

Основной код функции обернут в вызов диспетчера, который запускает его в потоке UI – это важно. Далее мы устанавливаем режимы основных используемых пинов Arduino, создаем таймер, который будет вызывать каждые пол-секунды функцию loop(), а также делаем кнопки видимыми.

Интересный момент – установка порта 14 в аналоговый режим. Дело в том, что аналоговые входы в Arduino нумеруются после цифровых, и входу A0 соответствует номер 14. Режим необходимо установить именно ANALOG, а не INPUT, который означает цифровой ввод.

Теперь для включения/выключения лампочки достаточно описать функции-обработчики событий кнопок следующим образом:

private void on_Click(object sender, RoutedEventArgs e)
{
    auto_mode = false;
    arduino.digitalWrite(relay_pin, PinState.HIGH);
}

Функция off_Click делается по аналогии. Обратите внимание, что для работы с пинами удалённой платы Arduino используются привычные команды типа digitalRead/digitalWrite.

Переменная auto_mode – это переменная типа bool, которую нужно описать в нашем классе. Она нужна для того, чтобы обрабатывать автоматический режим. Кнопка AUTO будет устанавливать эту переменную в true:

private void auto_Click(object sender, RoutedEventArgs e)
{
    auto_mode = true;
}

Теперь дело осталось за малым – реализовать функцию loop, которая будет переключать лампу в зависимости от наличия сигнала с датчика присутствия. Делать это надо только в том случае, если auto_mode установлен:

private void loop(object sender, object e)
{
    if (auto_mode)
    {
        arduino.pinMode(14, PinMode.ANALOG);
        var on = arduino.analogRead(0) > 512;
        arduino.digitalWrite(relay_pin, on ? PinState.HIGH : PinState.LOW);
    }
}

ВАЖНО: Для более надежной работы прямо перед чтением порта лучше еще раз установить его режим в аналоговый. Так быть не должно, но на практике это улучшает стабильность. Также обратите внимание, что мы используем analogRead(0), хотя строчкой ранее указывали номер порта 14. В analogRead передается номер порта от 0 до 5, при установке режима порта надо прибавить к этим номерам 14.

Как подключить Arduino по Bluetooth и управлять со смартфона

В нашем случае мы написали универсальное приложение, которое можем разместить на Windows Phone 10. Однако это бесполезно, поскольку подключить плату Arduino по USB к смартфону невозможно. Однако если мы будем использовать Bluetooth вместо USB-соединения, подключив к Arduino bluetooth-плату, то мы сможем этим же приложением управлять нашей конструкцией со смартфона. В этом случае в манифест приложения необходимо добавить следующие строчки для разрешения коммуникации по Bluetooth:

<DeviceCapability Name="bluetooth.rfcomm">
  <Device Id="any">
    <Function Type="name:serialPort"/>
  </Device>
</DeviceCapability>

Мы не будем сейчас рассматривать использование bluetooth – это тема для отдельной статьи. Однако заметим, что с точки зрения программирования разницы почти нет – надо использовать объект BluetoothSerial вместо UsbSerial, а все остальные конструкции остаются без изменений.

Где взять исходный код

image

Исходный код моего проекта по традиции доступен на GitHub:

https://github.com/evangelism/RemoteArduinoLamp/tree/v1.0-serial

Пожалуйста, берите его, экспериментируйте, если найдете ошибки – делайте pull requests.

Выводы

Windows Remote Arduino – достаточно молодая и сырая технология, но уже сейчас она может упростить решения ряда задач, в которых необходимо напрямую управлять входами/выходами платы Arduino, подключенной к компьютеру. Конечно, всё тоже самое можно запрограммировать вручную, написав свой скетч и используя последовательный канал для взаимодействия с ним, но почему бы не использовать уже готовые наработки и сложившиеся стандарты (Firmata), чтобы не изобретать велосипеды.

Я надеюсь, вы будете использовать Windows Remote Arduino в своих проектах, и если вы сделаете что-то интересное – мне будет приятно об этом узнать! Пишите в комментариях, в твиттере или вконтакте!

3 comments