Самодельный ИК-пульт для iRobot Roomba

    Опрос в моём предыдущем посте «Управляем роботом-пылесосом iRobot Roomba через ИК» показал, что сообществу интересно узнать, как изготовить самому ИК-пульт для Roomb-ы. Итак, встречайте! =)



    Схема пульта:



    Я использовал:
    • МК ATTINY2313A-SU,
    • кнопки DTSM-20,
    • транзистор BC846,
    • SMD светодиод для индикации,
    • ИК-диод L-34F3C,
    • кварц на 7,3728МГц.
    • несколько резисторов и конденсаторов.


    Изначально я планировал сделать «спартанский» вариант — плата с кнопками в термоусадке, но потом всё-таки решил собрать всё в корпусе. Корпус выбирал из того, что есть в продаже, мне понравился GAINTA G401. Под него и делал плату:



    Функции кнопок:
    SW1 — Dock
    SW2 — Pause/Power
    SW3 — Forward Left
    SW4 — Clean
    SW5 — Left
    SW6 — Forward
    SW7 — Spot
    SW8 — Right
    SW9 — Forward Right

    Как в последствии выяснилось, кнопка SW2, которая, по задумке, при нажатии передаёт команду «Pause», а при долгом нажатии «Power» — не нужна, т.к. эти функции выполняет кнопка «Clean». Она работает так же, как и кнопка на самом роботе-пылесосе: короткое нажатии — чистить, во время работы — остановка, а долгое нажатие — выключение. Т.ч. если кто будет повторять пульт — просто не устанавливайте SW2.

    Листинг программы
    /*
    Пульт управление роботом-пылесосом Irobot Roomba. Программа для контроллера Atmel ATTINY2313A.
    FUSE-биты:
    
    Fuse Low Byte:
    CKDIV|CKOUT|SUT|SKSEL|
      0  |  1  |10 |0100 | 0x64 Default
      1  |  1  |10 |1100 | 0b11101100=0xEC  для кварца 3-8 МГц
    */
    
    //#define F_CPU 7.3728E6
    //#define __AVR_ATtiny2313A__
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/sleep.h>
    
    /*------<Макросы>-----*/
    //Частота 39477 Гц
    //Период 25,3 мкс:
    #define P_GEN {TCNT0=0; PORTB |= 0x8; while (TCNT0 < 93); PORTB &= ~0x8; while (TCNT0 < 186);}
    
    //Roomba коды:
    #define LEFT 			129
    #define FORWARD 		130
    #define RIGHT 			131
    #define SPOT 			132
    #define DOCK 			133
    #define CLEAN 			136
    #define PAUSE 			137
    #define POWER 			138
    #define FORWARD_LEFT  	139
    #define FORWARD_RIGHT 	140
    #define TEST 			170
    
    
    /*----------------<Функции:>----------------*/
    void init(void)
    {
    //Установка делителя частоты на /1:
    	CLKPR = (1<<CLKPCE);
    	CLKPR = (0<<CLKPS0)|(0<<CLKPS1)|(0<<CLKPS2)|(0<<CLKPS3);
    //Настройка портов:
    	PORTD = 0xFF;
    	DDRD  = 0x0;
    	PORTB = (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2);
    	DDRB  = (1<<DDB3)|(1<<DDB4);
    //Настройка прерываний:
    	GIMSK = 0x30; //(1<<PCIE)|(1<<4);
    	PCMSK = 0x3; //(1<<PCINT0)|(1<<PCINT1);
    	PCMSK2 = 0x7F;
    }
    
    void ir_tx(unsigned char data_ir)
    {
    	PORTB |= (1<<PB4); //Включим светодиод
    /*
    Кодирование данных:
    1:
    __________
    2862uS    |988uS
              |_____
    0:
    _____
    887uS|  2862uS
         |__________
    В конце пауза ~16870 uS
    */
    	unsigned char cnt;
    //Настраиваем таймеры:
    	TCCR0B = (0<<CS12)|(0<<CS11)|(1<<CS10); // Для несущей f/1
    	TCCR1B = (0<<CS12)|(1<<CS11)|(1<<CS10); // Для данных f/64	
            for (cnt=0; cnt<8; cnt++)
            {
                TCNT1=0;
                if (data_ir & (0x80 >> cnt))
                {	//Если 1
                    while (TCNT1 < 330) P_GEN;
                    while (TCNT1 < (330+114)) ;
                }
                else
                {	//Если 0
                    while (TCNT1 < 113) P_GEN;
                    while (TCNT1 < (330+114)) ;
                }
            }
            TCNT1=0;
            while (TCNT1 < 1950)  ;   
    	PORTB &= ~(1<<PB4);	//Выключим светодиод
    }
    
    void send_command(void)
    {
    	volatile unsigned char button_b;
    	volatile unsigned char button_d;
    	volatile unsigned char button_b_new;
    	volatile unsigned char button_d_new;
    	unsigned char pause_cnt = 0;
    	TCCR1B = (0<<CS12)|(1<<CS11)|(1<<CS10); // f/64
    	TCNT1=0;
    	while (TCNT1 < 346); //346 - Задержка 3 ms
    
    	button_b = ~PINB & ((1<<PINB0)|(1<<PINB1));
    	button_d = ~PIND & 0x7F;
    	button_b_new = button_b;
    	button_d_new = button_d;
    	
        while ((button_b == button_b_new)&&(button_d == button_d_new))
        {
            if ((button_b_new == 0) && (button_d_new == 0)) break;		
    		if (button_b == (1<<PINB0)) {ir_tx(DOCK);}
            if ((pause_cnt < 20) && (button_b == (1<<PINB1))) {ir_tx(PAUSE); pause_cnt++;}
    		if (pause_cnt >= 20) {ir_tx(POWER);}
            if (button_d == (1<<PIND0)) {ir_tx(FORWARD_LEFT);}
            if (button_d == (1<<PIND1)) {ir_tx(CLEAN);}
            if (button_d == (1<<PIND2)) {ir_tx(LEFT);}
            if (button_d == (1<<PIND3)) {ir_tx(FORWARD);}
            if (button_d == (1<<PIND4)) {ir_tx(SPOT);}
            if (button_d == (1<<PIND5)) {ir_tx(RIGHT);}
            if (button_d == (1<<PIND6)) {ir_tx(FORWARD_RIGHT);}
    		button_b_new = ~PINB & ((1<<PINB0)|(1<<PINB1));
            button_d_new = ~PIND & 0x7F;
    		
        }
    }
    
    /*----------------------<Обработка прерываний:>------------------------*/
    ISR(PCINT_B_vect)
    {
    	cli();
    	send_command();
    	sei();
    }
    
    ISR(PCINT_D_vect)
    {
    	cli();
    	send_command();
    	sei();
    }
    
    /*-----------------<основной цикл программы>-----------------------*/
    int main(void)
    {
    	init();
    	sei();
    	for(;;)
    	{
    		set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    		sleep_mode();
    	}
    }
    
    



    Фото в сборе:



    Подписи кнопок, конечно, выглядят коряво — теперь я понимаю, что гравировка — дело не простое! :)

    Сама плата:





    Проводники, которые предполагалось выполнять на обратной стороне сделал проводами.

    Видео, демонстрирующие работу:




    Файлы KiCAD-проекта: RemoteControlPCB.zip.
    Прошивка: RoombaRemoteControl.elf.hex.

    Для прошивки через программатор USBasp, программой avrdude:
    avrdude -p t2313 -c usbasp -U flash:w:./RoombaRemoteControl.elf.hex
    

    Прошивка fuse-битов для работы с кварцем:
    avrdude -p t2313 -c usbasp -U lfuse:w:0xEC:m
    
    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 29
    • –11
      посмотрев на первую картинку, еще не прочитав заголовка — первая мысль была — они опять выпустили очередного «убийцу айфона».
    • +2
      Каждый раз, когда я вижу упоминание этого робота, первое, что приходит на ум это вот это видео: www.youtube.com/watch?v=9j0QQhzCehE
      • 0
        Изначально с появления роботов-пылесосов недоумеваю, где же моющие пылесосы… объяснение наверняка логичное и простое — маленьким его сделать просто технически невозможно, а большой будет заметно дороже и не таким всепроникающим… но все равно мокрую грязь убирать они не могут.

        p.s. пылесос karcher водяным фильтром убирает мокрую грязь легко и не принужденно (если ее поливать сверху водой).
        • 0
          Моющие также есть.
          У роботов iRobot — это модели Scooba
          domorob.com/robot-uborka/iRobot/wet/
          Правда с ними несколько сложнее, чем с роботами для сухой уборки. Нужно еще воду заливать и сливать два раза за цикл.
          • +1
            Пока они не будут это делать автоматически на базе, даже смотреть на них не буду, смысла нет.
          • +3
            Реквестирую бесшланговую передачу воды
        • 0
          У меня моющий…
      • 0
        Ролик по теме. Такое распознавать они еще не могут ))
    • +1
      Хороший пост, а не проще было подключить 315 мГц трансмиттер (http://www.ebay.com/itm/1pcs-315Mhz-RF-transmitter-and-receiver-link-kit-for-Arduino-ARM-MCU-WL-/261086921764?pt=LH_DefaultDomain_0&hash=item3cc9fe4424) [линки что-то перестали вставляться]?
      Даже с экономической точки зрения выгодно — ток в режиме передачи — 5 мА.
      • 0
        В смысле один на румбу повесить, а второй в пульт? Я не хотел ничего навешивать на румбу — хотел обойтись штатными средствами.
        У моего пульта ток не больше, вот из-за дальности можно задуматься.
    • +2
      Вы таким графическим обозначением кнопок вынесли мозг половине электронщиков Хабра :)

      image
      • 0
        Согласен, не по ГОСТ-у. :) Это из стандартной библиотеки KiCAD.
        • 0
          Да, но нарисовать кнопку по ГОСТу (даже просто похожую на неё, не соблюдая размеры) в KiCAD дело одной минуты.
          Я его стандартных либ почти не использую, разве что простые выводные детали.
          • 0
            Не желаете поделиться библиотекой? ;-)
            • 0
              Вечером, как дома буду. Но, учитывая сегодняшнее число, и день недели, могу и забыть, напомните в лс :)
              Есть библиотека SMD посадочных мест, и несколько УГО. Посадочные места проверены не все, но делал по этому документу.

              Делаю по мере необходимости. Нужна в проекте новая деталька — нарисовал. Так что всей библиотеке по ГОСТу не дождётесь :)
              • 0
                Интересный документ… я, обычно, использую рекомендации из описания компонентов. А т.к. на работе использую Altium, то не хотелось тратить время на рисование УГО в KiCAD.
                • 0
                  Я оттуда в основном пассивные брал. С микрухами и силовыми транзисторами лучше брать описание из даташитов. Этот документ — общая рекомендация (при том немного устаревшая), никто не заставляет производителя следовать ему и не клепать свои корпуса.
    • +1
      Не плохой проектик, но есть предложение использовать в качестве донора корпуса нормальный пульт, любой который у Вас завалялся или купить подходящий. Уверен что получится гораздо красивее.
      • +1
        Это дело вкуса, обычно у бытовой техники гораздо больше кнопок — много неиспользуемых останется. Разве что от кондиционера кого подойдет…
        Вот нарисовать свой корпус и распечатать на 3D принтере — это интересно! Судя по статьям на хабре это не так дорого.
        • 0
          Распечатать действительно интересно, но к сожалению технология, которая наиболее доступна на сегодняшний день, это makerbot и иже с ним, не позволяет получить даже удовлетворительного качества печати ИМХО.
    • 0
      Может просто купить Neato и не напрягаться?
      • +1
        Neato в 1.5 раза дороже. Когда выбирал, исходил из категории до 15 000 р. Neato не уложился. :)
        К тому же, я и не напрягался, как говорится, «just for fun»!
        • 0
          Не понял про цену
          на сайте иробота самый дешевый румба 350, неато 400
          доставка из за бугра будет примерно одинаковая.

          1.5 раза если покупать здесь?
          а зачем здесь покупать, когда можно заказать из за бугра и будет намного дешевле?

          just for fun, хорошо :)
          • 0
            Я покупал в конце 2012-го, может цены изменились, но на тот момент, по моим подсчетам, за Neato нужно было отдать >21 т.р, меньше никак не получалось. Мой iRobot Roomba 630 мне обошелся в 14,5 т.р. Если заказывать из-за бугра можно сэкономить 1 т.р., ну максимум 2 т.р. — экономия не большая и совсем не хотелось ждать, т.ч. я пошёл и купил в магазине.
            Если я ошибаюсь на счет цены Neato, киньте ссылку, пожалуйста.
            • 0
              Я не знаю как вы считаете
              www.ebay.com/itm/NEW-Neato-XV-11-Robotic-Vacuum-System-220v-240v-Ready-/140728625722?pt=LH_DefaultDomain_0&hash=item20c4146a3a
              вот ссылка на ебэй на продавца с историей (хотя можно найти прям магазин...)
              с доставкой в рашу 399+95$ итого ~15000р
              • 0
                Да, Вы правы! Если постараться можно найти за приемлемую цену.
                Но коней на переправе не меняют. ;-) Меня Roomba вполне устраивает.
                • +1
                  надо отдать должное iRobot
                  я 2.5 года назад купил восстановленный Scooba с сайта иробота за 200$ (с 4500mAh новой батареей) + доставка в рашу — не помню…
                  Работает он раз в неделю по 2 заправки воды
                  С тех пор кроме колесиков (и блока с щеткой) ничего не менял.
                  Жаль неато моющих не делает
    • 0
    • 0
      Небольшое замечание по управлению Roomb-ой с пульта: если рядом базовая станция, то он так и норовит на неё вернуться, как только перестаёшь им управлять.

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.