Page 1 of 2

Help decoding unique protocol of a toy robot

Posted: Sun Mar 13, 2022 2:13 am
by dunderMethod
Hello!
My goal:
Write a python library which allows me to control a toy robot that uses a unique IR protocol. I have searched extensively but no one else on the internet seems to have attempted to decode this toy's signals. It's called Botley and it aims to teach kids some programming fundamentals ie: breaking a problem down to a series of basic steps and executing. I am already writing a Python library so that kids can transition to a real programming language and control this robot using the simple commands they are already familiar with.

How the toy works:
The toy is a small, two-wheeled robot (with a rear caster) that comes with an simple IR remote. You arrange an obstacle course for the robot then use the remote to program a basic sequence of direction commands (Options: Left-45deg, Forward, Right-45deg, Left-90deg, Backward, Right-90deg). The commands are stored in a queue (in the remote's internal EEPROM). When you are done entering commands you press the Send button which transmits the queue (up to 150 direction commands) to the robot. The robot beeps to indicate receipt and proceeds with executing the series of commands.

It is important to note that the direction command buttons only add directions to the remote's command queue, they are not transmitted directly to the robot when pressed.

The remote also has buttons which do immediately transmit: Light, Sound, Erase, and Loop buttons.
Light: Changes the color of the lights on the robot as soon as the button is pressed.
Sound: This button cycles through High > Low > Off > High etc to change the volume of the remote's speaker; It seems to control the volume of the robot's speaker too.
Erase: Pressed once, it deletes the last direction command from the remote's command queue - No transmission. Pressed and held, it clears the remote's command queue and transmits something.
Loop: Used when adding direction commands to the remote's command queue. Press Loop > enter direction commands > Press loop again and the sequence between the loop button presses is appended to the command queue a second time. For some reason each press of the loop button includes an IR transmission but there is no response from the robot.

The following button does not transmit anything: EDIT: I wasn't getting any signals when I wrote this but in my next post I did record a signal when pressing the OD button.
Object Detection: Press once to enable OD then enter a sequence of commands which the robot should execute if it encounters an obstacle. Press OD again to complete the object avoidance command sequence.

Note: I have dumped the contents of the remote's EEPROM. The EEPROM, as far as I can tell, only stores the user's command queue. Each memory address starting from 0x01 stores an individual direction command entered by the user. I have generated a mapping of direction buttons to the corresponding values stored in memory. This is how I was able to determine that the loop button just appends the loop sequence to the end of the command queue (so there is no loop command in the queue, just the repeated contents of the loop). I also found that direction commands entered with Object Detection enabled are stored as different values in EEPROM. This difference should be observable in the IR signals.

I have used AnalysIR to record all of the raw IR signals corresponding to the different button presses but none can be decoded by the software (as expected). I've attached the saved session:
Mar 12 2022 192914_botley_ir_History.txt
I've been searching around a lot but I'm only finding information about common protocols. This seems to be a fairly unique protocol, particularly because of the Send button and the fact that it can transmit up to 150 commands in one message.

Prior to buying AnalysIR I used an RPi and pigpio with the IR Record and Playback example code provided here https://abyz.me.uk/rpi/pigpio/examples.html I've been using the Light button for testing and have been able to record a consistent signal but when I attempt to transmit it to the robot from the RPi The robot's lights just blink once and nothing happens (same response for other buttons). So I know that at least something is getting transmitted and some part of that is detected by the robot.

Any way, I am here seeking help/guidance on analyzing and decoding this protocol. Once it is decoded I will test transmission from the RPi. If that works I want to try piping the commands to the headphone jack on my PC with a 3.5mm IR transmitter connected as I think this will be the cheapest/easiest way for people to use my python library with the toy robot.

I'm at a loss for what to do next and appreciate any help.
Thanks!

Re: Help decoding unique protocol of a toy robot

Posted: Tue Mar 15, 2022 1:54 pm
by AnalysIR
First of all thanks for the detailed post.

It should be straight forward to add support for this protocol.

However, some Questions:
- what is the make and model# of the remote and robot
- Each captured signal seems to have a lost of bursts of data (some repeated). So to zoom in on whether each command must be sent once or multiple times, please recapture the signals but only press the remote button very very briefly. This will get us the minimal useful set of data for each signal/command.
- what are you using to record the signals. Its just that the carrier frequency seems a bit variable.

Once I get the above I will add support in and send you an updated ini file.

Re: Help decoding unique protocol of a toy robot

Posted: Tue Mar 15, 2022 11:55 pm
by dunderMethod
Thanks for your support! Yes, I am trying to be as detailed as possible since you don't have access to the hardware and it's a unique setup. Sorry in advance If I get too verbose!

- Yeah, I noticed the carrier freq is inconsistent. I've tried blocking ambient light with a black hoodie but it is still quite variable.

- I'll try not to press the buttons for too long. The remote beeps and blinks for the duration of the transmission which can take ~1second or more. When the queue has a lot of commands it can take several seconds for transmission to complete. I don't think holding the button too long will result in duplicate transmission (I think the remote is smarter than that) so if you're seeing duplicates it's probably part of the protocol or the fact that the same motion command is in the queue more than once. (I could be wrong though)

- There are some repeats in the history, multiple samples of the light and loop buttons for example. I included these as additional samples so we can see if anything changes between them.

- Make/Model: Botley 2.0 https://www.amazon.com/Learning-Resourc ... 083T58PKM/Have a look at the remote, that may provide some helpful context.

- I am logging data on Windows 10 using an Arduino Uno with a common Keyes IR receiver like this https://arduinomodules.info/ky-022-infr ... er-module/ I have an RPi available as well if that would help. I can also attempt to desolder and use the robot's IR receiver (I have a spare robot) if we continue having issues.

- I've encoded some info into the button name fields in the history. Example: "send_FFFF" is 4x consecutive forward direction commands in the queue, followed by pressing the send button. So in that case we should see a send command (I saw some patterns that look like a header and footer with the actual commands in between) with the forward direction command repeated 4 times. I assume this is where you saw the multiple bursts of data (some repeated).

- We would want to extract the forward command and the send command separately so my program can encode each direction command in the user's queue to it's corresponding IR code, then pass the list of encoded direction commands to a send function which adds the send command's header/footer then transmits the whole thing to the robot. (assuming it is as simple as wrapping a list of encoded commands with the send header/footer)

- In order to extract and decode all of the individual direction commands, I've included several send commands with different combinations of direction commands in the queue. Similar to my "send_FFFF" note, I'll use this format to let you know what the order and contents of the send command is by making similar notes in the "button" field in the session history. This should give us a good idea of what the header/footer needs to look like and whether anything in the header/footer changes based on the length of the queue (or anything else).

- I've attached a new saved session with more notes in the "Button" field.
Here are some hints to help make sense of the notes:

- Notes starting with "send_" followed by things like "L4" and "B" (which are my shorthand for different direction commands) are recordings where I added direction commands to the queue, in the order they are listed in the note, then I pressed send to transmit the queue from the remote to the IR receiver.

- Shorthand for direction commands: Left, 45deg = L4 | Forward = F | Right, 45deg = R4 | Left, 90deg = L9 | Backward = B | Right, 90deg = R9 | Object Detection = OD

Notes on OD:
The OD button is momentary but latches on/off. When I press OD something gets transmitted and the red LED on the remote stays on to indicate we are in OD mode. When I add direction commands by pressing direction buttons on the remote (Ex: F, L9, B...) with OD mode ON, I expect that those commands will yield a different value than they do when OD is off. I expect this because I found different values are stored in the EEPROM when OD is on vs. off. When I press OD again to end the Object Detection sequence, the red LED turns off and something gets transmitted (but it doesn't send the queue. I'm not sure why OD transmits, there is no response from the robot.) either way, I've recorded those transmissions with notes OD-ON and OD-OFF)

- There is a note in the saved session "send_L4_F_R4_L9_B_R9_OD_ON_L4_F_R4_L9_B_R9_OD-OFF_L4_F_R4_L9_B_R9" So I filled the queue with all of the normal direction commands, then "OD-ON", then I pressed each of the direction commands again, in the same order (these should be different from the first set), then "OD-OFF", then I pressed all of the normal direction commands again (these should match the first set but not the second), then I pressed send to transmit and capture the data. So we want to extract each of the direction commands, if the OD commands are different from the normal commands we will need to save those separately.

Sound:
The sound button cycles through 3 different volume levels as described in my first post. I'm calling these "High", Low", and "Off". In the saved session you will see notes like "sound_H-L" which is the signal I recorded when transitioning from volume High to Low. They may all end up being the same command but I recorded each of the transitions just in case.

Clear:
I saved quite a few "Clear" commands, some when the queue was already empty (the note just says "Clear") and some when clearing an existing queue of several direction commands (The note says "clear_L4_F_R4..."). I'm curious to see if they are all the same command or if we get a different transmission based on whether the queue was already empty or not.

Botley_says:
According to the manual there is a mini-game built in. If you clear the queue then enter F_R9_B_L9 and send, the robot will enter a mini-game mode. I assume the robot is just looking for this particular sequence and the remote isn't sending a special command, but I recorded it just to be sure. So the recording marked "botley_says" may contain a unique command to start the mini-game, or it may just contain normal F_R9_B_L9 commands. We'll have to see.

Pairing:
Up to 4 remotes and robots can be independently paired and used at the same time without interfering. I'd like to have a function in my program which allows pairing with up to 4 robots (1:1, but 1:4 could be cool too!) So I've tried to capture the pairing sequence.

According to the manual, here is how to pair:
1. Press and hold the F button until the remote beeps. (a transmission is sent. I recorded it as "pairing_init")
2. Enter any 4-button sequence (I entered F_F_B_B)
3. Press Send (transmission sent, I recorded it as "pairing_complete_with_FFBB")

I also recorded a "pairing_timeout" where instead of following step 2, I just let the remote sit for ~10 sec. The remote beeps then transmits something as it exits pairing mode.

Thoughts on pairing: I'm curious how pairing is handled. Does it simply change some value in the transmission header and the robots just ignore messages that don't contain the value they expect? Is the entire message encoded differently for each robot? I've included a transmission labeled "send_L4_F_R4_L9_B_R9_after_pair" so we can compare this with the "send_L4_F_R4_L9_B_R9" recordings to see what is different about them.

Once we understand how pairing works I can record more pairing data and hopefully I'll be able to pair to 4 robots!

I really appreciate your help and experience here. It is a lot of work though. If you tell me how to configure AnalysIR for best results with this signal and provide some pointers I'm happy to help in the process of decoding.

Between the last saved session and this one we should have samples of all of the the signals this thing sends (except for some pairing data)
Mar 15 2022 191958_botley_ir_2_History.txt
Thanks again!

Re: Help decoding unique protocol of a toy robot

Posted: Wed Mar 23, 2022 12:51 am
by dunderMethod
FYI, I just purchased the SendIR module, I think it will make testing much easier.
I also desoldered the IR RX from a spare robot board and have used that to record more signals. The carrier seems to be keeping in the 32610 - 39060 range so perhaps we can assume it is a 38000 carrier?

Re: Help decoding unique protocol of a toy robot

Posted: Wed Mar 23, 2022 11:55 am
by AnalysIR
Yes, I saw that...thanks for the order.

Sorry about the delay in getting back to you, we had a big/extended National Holiday here late last week/end (St Patrick's Day :mrgreen: )

I should be able to get back to it over the next couple of days.

Re: Help decoding unique protocol of a toy robot

Posted: Wed Mar 23, 2022 2:53 pm
by dunderMethod
No worries, Cheers! 🍻

Re: Help decoding unique protocol of a toy robot

Posted: Fri Mar 25, 2022 2:29 pm
by AnalysIR
Some progress made after figuring out that this is a very unusual protocol....

It seems the header is just the mark and each bit starts with a space followed by a constant width Mark.
Thus it is a 16 bit protocol.

I have managed to configure this using our generic decoding algorithm. However it will miss the first bit.

I will add this to the queue for updating, but it will require a software release, which may take some time.

I will email you the updated ini file shortly along with install instructions.

So you can just manually add the first bit to the the decoded 15 bits that the new ini file will provide.

Re: Help decoding unique protocol of a toy robot

Posted: Fri Mar 25, 2022 10:09 pm
by dunderMethod
Thanks! I've added the .ini and it is decoding the first part of the signals.
How do I manually add the first bit? Is it the one in the gray gap between purple and white?
Screenshot 2022-03-25 180653.jpg

Re: Help decoding unique protocol of a toy robot

Posted: Sat Mar 26, 2022 2:23 pm
by AnalysIR
Yes

If its less than 1000 long its a zero...otherwise a 1

So the value is correct for the shorter pulse and you just need to note that there is an extra 1 when it is longer

So for example
The signal OD_Disable decodes to 3F00, but it is actually 7F00, when the extra 1 bit is added

Also to decode subsequent bursts:
- enter the seq# of the pulse before the burst (say 35) and click on the History row to decode from that position.

(The Seq# is displayed when hovering over a pulse or from the Channel1/2 grid)

Re: Help decoding unique protocol of a toy robot

Posted: Sat Mar 26, 2022 8:59 pm
by dunderMethod
...header is just the mark and each bit starts with a space followed by a constant width mark...
If I'm interpreting this correctly, then the first Space + Mark after the header should be the first bit like so:
2022-03-26_13-39-14.png
If that's correct, the first burst from "sound_L-O" is 0x7F00. I used photoshop to create this image; I've adjusted the colors below the signal as well so I think this is what AnalysIR would produce once you've implemented the update you mentioned in your post:
signal_fix.jpg

I'm going to explain my interpretation of all this this so let me know if I've got it right/wrong:
Rules: [Header = 4150, Mark = 642, Space1 = Mark, Space0 = Mark * 2]

A message is composed of bursts with long silence between: Message = [burst_1]......[burst_2]......[burst_n]......
A burst is composed of: [header, byte_1, byte_2]

The header is just a really long Mark: Header = Mark * 6.46

Each byte is composed of 8 bits where:
- Assuming no variation/transmission loss, each bit's value can be determined by the ratio of [space:mark]:
bit = 1 if space > mark else 0 | bit = 1 = [space, space:mark] | bit = 0 = [space:mark]

- Since there is always variation in the IR signal we use empiric thresholds to interpret spaces/marks:
...If (the space is) less than 1000 long its a zero...otherwise a 1...


Next Steps:
So if all this is correct, then I just need to write a simple decoder to convert each burst in a message into a HEX value then start looking for patterns among the messages so I can identify the anatomy of a message? Once I understand the anatomy of a message, I can write an encoder module which will allow my program to dynamically build and transmit messages to the robot?!