Как заставить директора купить кондиционер

Утро, лето, жара. Я просыпаюсь в 6:00 весь в поту. В квартире 27, на улице 21. Но по дороге на работу солнце возьмет свое, а наш офис находится на солнечной стороне. Каждое утро я вхожу в душное помещение, открываю окна, в надежде хоть немного его проветрить, включаю кондиционер. Как вы понимаете, всем дует в спину и включить кондиционер на полную не получится. Температура немного стабилизируется к обеду. С 14:00 до 17:00 можно жить и работать, а дальше все повторяется сначала.

Удаленное управление кондиционером — дело не новое, есть Smart технологии и мобильные приложения. Но случается, что кондиционер старенький, не smart, а заранее его запустить и прийти утром в прохладное помещение желание есть. Потому и было принято решение — автоматизировать функцию включения при помощи сервопривода и механического нажатия на кнопку.

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

Я же с Arduino не работал, потому искал что-нибудь без внутрисхемного программирования. Купил у местных умельцев плату RoboIntellect controller 001 на которой распаяна микросхема PCA9685 и CH341T. Значит, связка USB компьютера с ШИМ контроллером уже есть. В дополнение нам понадобятся двусторонний скотч, малярный скотч, магнитик для упора, стёрка и нитка.

Схема выглядит приблизительно так. Через удаленный рабочий стол заходим на компьютер, к которому подключена наша плата. На первом канале ШИМ висит сервопривод. Через «умную» систему рычагов нажимаем на кнопку пульта. Управляет всем небольшой скрипт на Python.

77af7651e4094d7bd4b2ed02e2910250.jpg

Насколько я понял, плату RoboIntellect применяют в конструкторе, для которого написана библиотека RISDK. Её и будем использовать. После инициализации и создания компонентов нужна только одна функция RI_SDK_exec_ServoDrive_TurnByDutyCycle для вращения оси сервопривода. Вызываем функцию два раза: нажатие кнопки и возврат в начальное положение.

import sys
from ctypes import *

# Подключаем внешнюю библиотеку для работы с SDK
lib = cdll.LoadLibrary("./librisdk.dll")

# Указываем типы аргументов для функций библиотеки RI_SDK
lib.RI_SDK_InitSDK.argtypes = [c_int, c_char_p]
lib.RI_SDK_CreateModelComponent.argtypes = [c_char_p, c_char_p, c_char_p, POINTER(c_int), c_char_p]
lib.RI_SDK_LinkPWMToController.argtypes = [c_int, c_int, c_uint8, c_char_p]
lib.RI_SDK_LinkServodriveToController.argtypes = [c_int, c_int, c_int, c_char_p]
lib.RI_SDK_DestroySDK.argtypes = [c_bool, c_char_p]
lib.RI_SDK_exec_ServoDrive_Turn.argtypes = [c_int, c_int, c_int, c_bool, c_char_p]

def main():
    errTextC = create_string_buffer(1000)  # Текст ошибки. C type: char*
    i2c = c_int()
    pwm = c_int()
    servo = c_int()

    # Инициализация библиотеки RI SDK с уровнем логирования 3
    errCode = lib.RI_SDK_InitSDK(3, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Создание компонента i2c адаптера модели ch341
    errCode = lib.RI_SDK_CreateModelComponent("connector".encode(), "i2c_adapter".encode(), "ch341".encode(), i2c,
                                              errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    print("i2c: ", i2c.value)

    # Создание компонента ШИМ модели pca9685
    errCode = lib.RI_SDK_CreateModelComponent("connector".encode(), "pwm".encode(), "pca9685".encode(), pwm, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    print("pwm: ", pwm.value)

    # Создание компонента сервопривода модели mg90s
    errCode = lib.RI_SDK_CreateModelComponent("executor".encode(), "servodrive".encode(), "mg90s".encode(), servo,
                                              errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    print("servo: ", servo.value)

    # Связывание i2c с ШИМ
    errCode = lib.RI_SDK_LinkPWMToController(pwm, i2c, 0x40, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Связывание ШИМ с сервоприводом
    errCode = lib.RI_SDK_LinkServodriveToController(servo, pwm, 0, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Моментальный поворот сервопривода к значению угла, соответствующему 500 шагам
    # Диапазон углов 554 - 75
    # Нажатие кнопки
    errCode = lib.RI_SDK_exec_ServoDrive_TurnByDutyCycle(servo, 180, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Возврат в начальную позицию
    errCode = lib.RI_SDK_exec_ServoDrive_TurnByDutyCycle(servo, 80, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Удаление библиотеки со всеми компонентами
    errCode = lib.RI_SDK_DestroySDK(True, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    print("Success")

main()

Сперва все казалось легко и просто. При помощи скотча крепим сервопривод, запускаем скрипт и проблема решена. Но на деле даже в таком развлечении нашлись подводные камни. Движение пальца поступательное, а оси сервопривода — вращательное. Если просто толкать кнопку рычагом, то точка прилагаемого усилия меняется и пульт съезжает набок. Беспрерывная чреда экспериментов с учетом мнения бесконечного числа технических специалистов офиса позволили найти рабочее решение.

fe07c78931dfc1bb8dc30d3a7069ed77.jpg

Размещаем пульт на столе кнопкой (упором вниз), крепим один конец двусторонним скотчем. С другого конца тянем пульт при помощи нитки. Происходит нажатие.

c945739ce8047f8342ba02320c0e412c.JPG

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

© Habrahabr.ru