Control Roomba vaccum

Support forum for the iRed Mac software

Moderators: marcus, tinbert

Control Roomba vaccum

Postby jvl » Sat 16. May 2009, 08:58

Hi,

Can I use IRTRANS to control my Roomba ?
I've tried using Pronto ccf codes converted with IRED but it is not reliable.
What I would like is to be able to build the codes to control the roomba as it is described here http://www.irobot.com/images/consumer/hacker/Roomba_SCI_Spec_Manual.pdf
but I don' t know where and how to start
Any idea ?

Does someone have something which works ?
This pronto code works sometimes for cleaning : 0000 0069 0000 0008 0071 0027 0023 0071 0023 0071 0023 0071 0071 0027 0023 0071 0023 0071 0023 030B


Thanks

JVL
jvl
 
Posts: 4
Joined: Tue 23. Dec 2008, 18:58

Re: Control Roomba vaccum

Postby IRTrans » Sat 16. May 2009, 13:11

The manual does not show any IR Codes or formats - it describes a serial command format that has nothing to do with IR.

The best way would be to learn the IR Codes from a remote control with IRTrans / iRed.

IRTrans
IRTrans
Administrator
 
Posts: 2115
Joined: Mon 21. Apr 2008, 23:32

Re: Control Roomba vaccum

Postby jvl » Sat 16. May 2009, 18:31

Hi,

This guy did a program to send the roomba code via infrared

Code: Select all
/*   

    Copywright 2007 Daniel Perron


    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.


*/


/* 



    Author : Daniel Perron
   Date   : 28 October 2007

    Version : 1.1
   Name : ir.c 
 
     
   Compiler used :  SDCC ( may 31 2007)

    How to compile: 
                        sdcc --model-small --iram-size 128 --data-loc 0x20 ir.c
                        packihx ir.ihx > ir.hex




    Description:     Send ,from rs-232 , ir command to roomba cleaner robot


    - Normal mode. Send a string of command , maximum of 24 characters, ended by a cariage return.

    - Direct mode. Execute command one character at the time.
   


     Caracter command;

              F      -> Send I.R. forward.
           L      -> Send I.R. left.
           R      -> Send I.R. right.
           P      -> Send I.R. power.
           D      -> Send I.R. dock.
           C      -> Send I.R  clean.
           M      -> Send I.R. maximum clean.
           S      -> Send I.R. spot clean.
           #hh   -> Send I.R. Raw data where hh is a 8 bits hexadecimal value.
             A      -> Power ON base station.
           Z      -> Power OFF base station.
           W      -> Wait NTimes * 100ms.
           1..9   -> set NTimes value. NTimes=1 to 9.
           !      -> Enter direct mode.
              ESC   -> Exit from direct mode.



     P.S. any data is send NTimes.  A command like "5ZWWWWPWCA" will turn off base station, wait 2 seconds,Power ON roomba,Wait half of second,
                                   start clean command and finally power up base station again. The Ir command is send Ntimes without gap.
                           This ensure that the command is received by the I.R. receiver. On this sample NTimes is equal to 5.
                           Ntimes could be change at any times like "9W1W5P5W".  Ntimes= 1..9; (only one digit number,Zero excluded).



     Processor:  at80c2051 at 11.0592Mhz.  20 pins Atmel 8051 familly processor
 
     Port 1 bit 0..7   -> Output -> All I.R. Led signal.
    Port 3 bit 7      -> Outout -> Base station Relay.
    Port 3 bit 5      -> Input  ->  0 = Disable Txm , 1 = Enable Txm.



*/
     


#include <at89x51.h>

#define LEDS P1
#define BASE_STATION P3_7

#define TransmitEnable P3_5

#include <stdio.h>
#include <ctype.h>



bit BitHigh;

bit DirectMode;


#define TOKEN_NONE         0
#define TOKEN_IR         1
#define TOKEN_NTIMES      2
#define TOKEN_WAIT         3
#define TOKEN_DIRECT_MODE   4
#define TOKEN_BREAK         5
#define TOKEN_HELP         6
#define TOKEN_STATION_OFF   7
#define TOKEN_STATION_ON   8
#define TOKEN_DATA         9
#define TOKEN_DATA_HNIBBLE   10
#define TOKEN_DATA_LNIBBLE   11

unsigned char TokenType;

unsigned char TxmHeader;
unsigned char TxmData;
unsigned char RcvData;
unsigned char TxmBitCount;
unsigned char NTimes;

unsigned char RawIrData;
unsigned char Timer10ms;
unsigned char TimerCountDown;



// be carefull  String are store in unused
// data memory gap. The  working register block  2,3 and 4
#define STRING_MAX 24
__data __at (0x8) unsigned char String[STRING_MAX]  ;




unsigned char StringCount;

void Delay_off(unsigned char  count)
{
  unsigned char loop;

     LEDS=0xff; // leds off
   for(loop=0;loop<count;loop++)
   {
     _asm    nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
     _endasm;
     }

}


void Delay_on(unsigned char count)
{
  unsigned char loop;


  // 11.0592Mhz / 12 =  921600 cycles/sec
  // 921600 cycle/sec / 38400 Hertz  = 24 Cycles

   for(loop=0;loop<count;loop++)    // 8 cycles for loop
   {
     LEDS=0; // led on              // 2 cycles
     _asm    nop                    // nop is 1 cycle
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop
             nop

     _endasm;
     LEDS=0xff; // led off          // 2 cycles
     _asm    nop
             nop
     _endasm;
     }

}




const char * StringHelp =   "\r\n"\
                     "=================================\r\n"\
                      " IR remote\r\n"\
                            " D.J.P. V1.1, 12 Oct 2007.\r\n"\
                     "=================================\r\n"\
                     " F   -> Forward\r\n"\
                     " L   -> Left\r\n"\
                     " R   -> Right\r\n"\
                     " P   -> Power\r\n"\
                     " D   -> Dock\r\n"\
                     " C   -> Clean\r\n"\
                     " M   -> Max clean\r\n"\
                     " S   -> Spot clean\r\n"\
                     " A   -> Base Station ON\r\n"
                     " Z   -> Base Station OFF\r\n"
                     "#hh  -> Send I.R. Raw data\r\n"
                     "        where hh = byte hex value\r\n"
                     " !   -> Enter interactive mode \r\n"
                     " W   -> wait NTIMES * 100 ms\r\n"
                     "1..9 -> Set NTimes values\r\n"
                     "=================================\r\n"\
                     "\r\n";



void SendIr(unsigned char Data)
{

  TxmHeader= 0x4a; // roomba header
  TxmData= Data;



     for(TxmBitCount=16;TxmBitCount>0;TxmBitCount--)
            {

                __asm
                        mov A,_TxmData
                        rlc A
                        mov _TxmData,A
                        mov A,_TxmHeader
                        rlc A
                        mov _TxmHeader,A
                        mov _BitHigh,C;
                __endasm;


               if(BitHigh)
                 {
                    Delay_on(114); // 38Khz  for 3 ms
                    Delay_off(38);  // 38Khz for 1ms
                 }
               else
                  {
                    Delay_on(38);    // 38Khz  for 1 ms
                    Delay_off(114);  //  38Khz for 3 ms
                  }

            }
             Delay_off(152);

}


void NSendIr(unsigned char Data)
{
  unsigned char loop;

  if(NTimes==0) NTimes=1;
  if(NTimes>9)  NTimes=9;

  for(loop=0;loop<NTimes;loop++)
     SendIr(Data);
}



void printerror()
{
if(TransmitEnable)
{
   TI=0;
   SBUF='X';
   while(!TI);
}
}


void printchar(char value)
{
if(TransmitEnable)
{
   TI=0;
   SBUF=value;
   while(!TI);
}
}


void print(const char * String)
{
if(TransmitEnable)
{
  while(*String)
  {
   TI=0;
   SBUF= *(String++);
   while(!TI);
  }
}
}


void printNibble(unsigned char value)
{
if(TransmitEnable)
{
    value = value & 0xf;
   if(value >9) value += 'A' - 10;
   else value += '0';
   TI=0;
   SBUF=value;
   while(!TI);
}
}

void printHex(unsigned char value)
{
if(TransmitEnable)
{
    print("0x");
   printNibble(value >> 4);
   printNibble(value);
}
}


unsigned char GetHex(unsigned char value)
{
   if( value < '0' ) return(16);
   if(!( value > '9')) return(value - '0');
   if(!( value < 'A' )) 
      if(!(value > 'F' ))
         return(value - 'A' + 10);
   return(16);
}






unsigned char GetCommand(unsigned char value)
{

   unsigned char IrData;

value= toupper(value);

   if((TokenType == TOKEN_DATA) || (TokenType == TOKEN_DATA_HNIBBLE))
   {
      IrData = GetHex(value);
       RawIrData = RawIrData * 16;
      RawIrData += IrData;
      if(IrData == 16) TokenType = TOKEN_NONE;
      else if(TokenType == TOKEN_DATA) TokenType= TOKEN_DATA_HNIBBLE;
      else TokenType = TOKEN_DATA_LNIBBLE;
      return(RawIrData);
   }


 if(value > '0')
  if(value < ':')
   {
    TokenType= TOKEN_NTIMES;
    return(value - '0');
   }

TokenType= TOKEN_IR;

   

  switch(value)
  {

 case 'F':  return(130);
 case 'L':  return(129);
 case 'R':  return(131);
 case 'P':  return(138);
 case 'D':  return(143);
 case 'C':  return(136);
 case 'M':  return(133);
 case 'S':  return(132);
 case 'H':
           if(DirectMode)
            TokenType=TOKEN_HELP;
          else
             TokenType=TOKEN_NONE;
            break;
case 'W':
            TokenType=TOKEN_WAIT;
         break;

case 'Z':
           TokenType=TOKEN_STATION_OFF;
         break;
case 'A':   TokenType=TOKEN_STATION_ON;
           break;

case '#':   TokenType=TOKEN_DATA;
           break;

case '!':   TokenType=TOKEN_DIRECT_MODE;
           break;

case 27:   TokenType=TOKEN_BREAK;
           break;

default:   // any unknowned command send 'X' back
           TokenType=TOKEN_NONE;

}

return 0;
}



unsigned char ExecuteToken(unsigned char Token,unsigned char value)
{

   unsigned char  loop2;
   unsigned char  loopNtimes;

   switch(Token)
         {
         case  TOKEN_IR: 
                         NSendIr(value); break;
         case  TOKEN_NTIMES: NTimes=value; break;
         case  TOKEN_WAIT:   
                                 for(loopNtimes=0;loopNtimes<NTimes;loopNtimes++)
                            for(loop2=0;loop2<100;loop2++)
                               Delay_off(38);
                            break;

         case  TOKEN_STATION_OFF: BASE_STATION= 1; break;

         case  TOKEN_STATION_ON: BASE_STATION= 0; break;

            case  TOKEN_BREAK:      DirectMode=0;
                           StringCount=0;
                           break;
         case  TOKEN_DIRECT_MODE: DirectMode=1;
                           StringCount=0;
                           break;
         case  TOKEN_DATA:
         case  TOKEN_DATA_HNIBBLE: break;

         case  TOKEN_HELP:         print(StringHelp);
                                  return(0);
                                  break;

         case  TOKEN_DATA_LNIBBLE:
                                  NSendIr(RawIrData); break;
                        
         default:
                StringCount=0;
            printerror();
            return(0);



            }

   return 1;


}


unsigned char GetStringToken(void)
{

   unsigned char  loop;
   unsigned char  value;
   if(RcvData== '\r')
   {


      for(loop=0;loop<StringCount;loop++)
      {

            value=GetCommand(String[loop]);
         if(!ExecuteToken(TokenType,value))
         {
            printerror();
            StringCount=0;
            return(0);
         }
      }
      StringCount=0;
      printchar('.');

   }
   else
   {

                if(StringCount < STRING_MAX)
              {
              String[StringCount++]=RcvData;
                printchar(RcvData);; // ok string command ok echo it
              }
              else
              {
               StringCount=0;
               printerror();
                  return(0);

              }

   }

   return(1);
}



void main(void)
{
 unsigned char value;

   
  LEDS=0xff;   // turn led off
  NTimes=3;    // In debug mode send the character 5 times.

 DirectMode=0; // StringCode mode off

 BASE_STATION=0;
 
 StringCount=0;
 TokenType= TOKEN_NONE;

 
  // init serial

  ES=0;  // disable serial
 /* PCON BIT 7 DOUBLE THE BAUD RATE IF SET */
 /* PCON=PCON AND 7FH */
 /* DOUBLE BAUD RATE */


 // set 8bit data

 SCON = 0x50;

 TR1  = 1;   // enable t1
 TR0  = 0;
// // TR0  = 1;  // enable t0 has wait timer

 
 //TH1=0xFD;  //9600baud for 11.0592Mhz

 TH1= 0xE8;   //1200 baud

// // TH0= 0xDB;   // set 16bit counter  at 9216 to get 10 ms timeout flag


// // TMOD = 0x21;  // T1 has baud rate T0 has 16 bit timer
TMOD = 0x20;

PT0= 1;
TR0= 1;
ET0= 0;
RI=0;
EA=1;

//   print(StringStart);

  while(1)
   {
        if(RI)  // ARE we getting character from rs 232
         {

            RcvData= SBUF;   // caracter to transfer
            RI=0;
         if(RcvData == 10) continue;
         if(DirectMode)
         {

                 value=GetCommand(RcvData);
            if(TokenType==TOKEN_NONE)
               printerror();
             else
             {
             if(ExecuteToken(TokenType,value))
                printchar(RcvData);
             }

         }
         else
         {
           if(!GetStringToken())  // GetStringCodeCommand
              {
                 //ok bad command or buffer full
                 // forget string command
                 TokenType=TOKEN_NONE;
                 StringCount=0;
                 continue;
              }
          }
      }
   }
}






My question is how is it possible to build an infrared code via ired or irtrans.
Isn't a infrared code just a serie of pulse and pause sent at a certain frequency ?

Thanks for your help

JVL
jvl
 
Posts: 4
Joined: Tue 23. Dec 2008, 18:58

Re: Control Roomba vaccum

Postby IRTrans » Sat 16. May 2009, 21:44

Looks like this device uses IRDA control - that is no IR Control format. It is basically RS232 transfer via IR.
The IRTrans devices do not support that as they only support IR remote.

IRTrans
IRTrans
Administrator
 
Posts: 2115
Joined: Mon 21. Apr 2008, 23:32

Re: Control Roomba vaccum

Postby IRTrans » Fri 19. Jun 2009, 13:19

Hi,
we just checked an original Roomba remote control here in our office.

It uses RF (ZigBee) for control and not IR - therefore it is not possible to learn or send these codes with the IRTrans.

IRTrans
IRTrans
Administrator
 
Posts: 2115
Joined: Mon 21. Apr 2008, 23:32

Re: Control Roomba vaccum

Postby jvl » Thu 9. Jul 2009, 08:50

OK I have managed to make it work on the mac with IRED

The good Pronto codes found on internet are
Code: Select all
TITLE= Roomba
UP=Up
0000 0069 0000 0008 0070 0027 0023 0070 0023 0070 0023 0070 0023 0070 0023 0070 0070 0027 0023 030B
LEFT=Left
0000 0069 0000 0008 0070 0027 0023 0070 0023 0070 0023 0070 0023 0070 0023 0070 0023 0070 0070 02C8
RIGHT=Right
0000 0067 0000 0008 0072 0024 0024 0072 0024 0072 0024 0072 0024 0072 0024 0072 0072 0024 0072 02D0
CIRCLE=Spot
0000 0067 0000 0008 0074 0024 0024 0074 0024 0074 0024 0074 0024 0074 0074 0024 0024 0074 0024 0314
CROSS=Clean
0000 0069 0000 0008 0071 0027 0023 0071 0023 0071 0023 0071 0071 0027 0023 0071 0023 0071 0023 030B
TRIANGLE=Dock (MAX?)
0000 0069 0000 0008 0070 0027 0024 0070 0024 0070 0024 0070 0024 0070 0070 0027 0024 0070 0070 02C8
L_SQUARE=Power off
0000 0069 0000 0008 0070 0027 0023 0070 0023 0070 0023 0070 0070 0027 0023 0070 0070 0027 0023 030B
L_TRIANGLE=Pause
0000 0069 0000 0008 0070 0023 0023 0070 0023 0070 0023 0070 0070 0023 0023 0070 0023 0070 0070 02C8


You need to have Ired and convert the pronto code (Tools/Convert Pronto Code), copy paste the code and convert.

Then save it and here is the trick, use an applescript to send this code three times
Code: Select all
tell application "iRed"
   delay 5
   send ir Code "Clean" of RC "Roomba"
   delay 0.1
   send ir Code "Clean" of RC "Roomba"
   delay 0.1
   send ir Code "Clean" of RC "Roomba"
end tell


Don't ask me why but it works and it works every time !

I now can launch my roomba whenever I want

hope this helps ;)

JVL
jvl
 
Posts: 4
Joined: Tue 23. Dec 2008, 18:58

Re: Control Roomba vaccum

Postby IRTrans » Thu 9. Jul 2009, 11:43

Thank you for the info !

Looks like the Roomba supports RF AND IR.

IRTrans
IRTrans
Administrator
 
Posts: 2115
Joined: Mon 21. Apr 2008, 23:32

Re: Control Roomba vaccum

Postby RobotDeveloper » Sun 3. Jun 2012, 20:29

Hello,

You can find a comprehansive guide for sending commands to Roomba on this knowledge base: How to send commands to Roomba

Please note that the baud rate (connection speed) is very important. If the connection is done using the wrong baud rate - the Roomba will only start cleaning. Baud rate settings for Roomba

Hope this helps! :idea:
RobotDeveloper
 
Posts: 1
Joined: Sun 3. Jun 2012, 20:22


Return to iRed / Mac

Who is online

Users browsing this forum: No registered users and 2 guests