Custom Controller?

Hello, I had the idea to create a custom controller, but how would you do that with Vex? I am using the older PIC microcontroller, so would I be able to use the RX/TX communications? If I knew what is being sent over the antenna, maybe I could wire a XBee and an Arduino to sent and receive data from a controller. I don’t know. Does anyone think it is possible to make a custom controller for the pic without using and of the ports besides tx and rx, and make it wireless?

Is that even legal???

Yes it is possible (I have done it). The type of RF link you choose depends on exactly what you are trying to do, and what wiring/programming experience you have.

You could use RX/TX comms over a variety of radio links. XBee is a good one; here is a thread on some really cheap ones I used [drawings for [URL=“https://vexforum.com/gallery/showimage.php?i=4813&catid=member&imageuser=2440”]TX and RX]. This has the advantage of being a 2-way link, and you can decide how simple/fancy to make the data. You will have to write your own serial protocol on both ends, though.

The over-the-air protocol that the PIC controller uses is called PPM, which means Pulse Position Modulation. It works by sending a series of seven pulses, one to start the sequence and then one pulse per channel. The difference between the start time of each pulse determines the value of the channel. Here is a document that describes the raw signal. To transmit it as RF, you then have to modulate it at 75MHz. This is done in the VEX transmitter with the PC board adjacent to the antenna. It would be fairly easy to hack a vex controller to send a custom signal; this post describes how to do it. If you use this approach, you will use the standard remote control functions in your program.

Cheers,

  • Dean

So can I add extra buttons and controls to my Vex controller using the Tx and Rx ports? So Rx is Receive I believe, so why is there a Tx or Transmit port? Can I send data back to the controller?

I could possibly make an awesome controller and robot :smiley: Would I have to write C code to receive and transmit the data?

Yes - it is a completely different communication port, so you can do whatever you want there. You could make something that augments the existing controller (bolt-on LCD display + extra buttons), or you could make a new controller that handles everything (no need for the original Vex remote).

Exactly. You could use it to send a text stream to a LCD bolted onto the controller, or you could log sensor data to a file in a PC. You could even use it to network two (or potentially more) microcontrollers together on your robot.

It is just a stream of bytes that you can interpret however you want. Rx is a byte stream going into the microcontroller, and Tx is a byte stream coming out of the microcontroller.

Pretty much (or assembler if you feel the need). What do you use to program the PIC controller now?

You’ll need something running on the controller side too - perhaps another PIC microcontroller, or an Arduino, or even a PC with a serial adapter.

Cheers,

  • Dean

I use EasyC Pro to program my Vex controller, and sometimes I write the C code for autonomous, but I can really only do basic stuff. Not Basic the language, but simple stuff. So how would I write the code on the Arduino to receive data and do something with it? And how would I sent data?

Since it is streams of bytes, what would the bytes look like? Like a bunch of zeros and ones? Or strings like 129 “test” 7? Thanks for helping.

Would I have to encode and decode PPM to work with the Tx and Rx ports? I still am wondering what type of signal or bytes they output, and how to use them.

EasyC Pro has some serial I/O functions available using custom code blocks. One block to start the connection, one to read a byte, and one to send a byte. It isn’t hard to get something simple going, though it can be quite involved if you want to do something advanced.

Here is a sample EasyC Pro project that uses serial.

Arduino has serial functions built-in. You have similar functions to open the port, send one or more bytes, and receive one or more bytes. For a basic serial link: on the PIC end, you would open the Rx port and loop reading bytes. On the Arduino end, you would open the serial port and send a byte any time you wanted to send a command to the PIC. The back-channel (PIC sending to Arduino) would work similarly, but using Tx instead of Rx.

A byte is a group of 8 bits. Each bit can be on or off (1 or 0), so a byte contains 8 individual on/off states. You could use one byte to communicate the state of 8 buttons/switches. Or you can group the bits into numerical values (8 bits lets you encode 0…255 or -128…127). You can also interpret a byte as a single character; strings are sent one character (byte) at a time.

All these are possible, and you would choose the approach that best accomplishes your specific goals. As long as both ends agree on what the bytes mean, you should get the desired result. If one end is sending characters, but the other end is interpreting it as 8 switches, you are going to have a mess. This agreement between both ends is what is known as a “protocol”.

The PPM signal is completely independent of the serial port (Rx/Tx) - they are not related.

The PPM signal is what the Vex R/C remote uses, so the PPM signal is decoded automatically by the PIC and presented to your program as a series of channel values (ch1…ch6).

Cheers,

  • Dean

Thank you, you have been very helpful :slight_smile: I have read that Mega has 3 serial connections, and Uno and other similar versions have one. Since I have a Uno R3 (a broken R1,and a MintDuino(breadboard)) it has one serial. So my guess (not really guess) is that the serial is the Tx and Rx. Rx is pin 0, and Tx is pin 1. Would I use Serial.begin(bandwidth);, or would I use something else to communicate with Vex? I think I just answered my question. I would, and when the Arduino sends something to the computer via serial print or whatever, it flashes the Tx to show it is sending data. So Rx on the Arduino goes to Tx of the Vex, and vise versa. I will try it tomorrow, but the problem is, I have the EasyC Pro registered to the computer that won’t start. Hmmmm… And the one I am on doesn’t do Arduino, but does Vex…

Alright, this is what I am going to try, as a first test. I am going to program the Arduino to read a potentiometer and send that over serial, and program the Vex to read it and control a servo. I might have the Vex send back data for how fast to flash a led, but that might be later, once I get this working.

If you have any idea on how to write the code on both ends, please reply. I think I am going to have to use Serial.print on the Arduino side, and I don’t know what I am going to have to do on the Vex side.

Correct

Yep - you got it. I’ll post a simple example of this shortly…

What kind of computer doesn’t do Arduino? Since the IDE is free and runs on Mac/Windows/Linux and 32/64b, you should just install it everywhere!

Cheers,

  • Dean

It works with the IDE, it just won’t upload the code.

This should work for the Arduino code, right?

int servo=0;
// Potentiometer is on A0

void setup{
  Serial.begin(9600);
}

void loop{
  servo=analogRead(A0);
  Serial.println(servo); // Print or Println?
  delay(1);
}

Close, but a few minor issues.

First, the analog values are 10 bits (0…1023), but a byte is only 8 bits (0…255). To send an analog value over serial, you either need to send it as two bytes or drop two bits. For simplicity, lets drop the two lowest bits, which will scale the value to fit in a byte.

To do that, you can divide servo by 4, or you can “bit shift” it right by two bits by doing “servo >>= 2”. This does the same thing as dividing by four, but it is more expressive since what you are actually trying to do is shift all the bits down 2 places. Also, since we are only dealing with positive values for “servo”, I changed the type to be unsigned.

You want to do Serial.write(servo) rather than Serial.print(servo). .print converts the number to a string, which is great for a human viewing it, but not so great for software on the receiving end trying to decode the value. For instance, Serial.write(128) will send a single byte with a value of 128. Serial.print(128) will send the character codes ‘1’, ‘2’, and ‘8’. Serial.println(128) will send the ‘1’, ‘2’, and ‘8’ followed by additional character codes to force the cursor to the start of a new line.

Lastly, delay(1) is probably a bit on the short side for a delay. At 9600 bps, the serial port can send at most 960 bytes per second. With a 1ms delay loop you might overrun the transmitter occasionally. I would recommend going with delay(16) instead, sending about 60 times per second, which matches the update rate of the RC remote control.

So, here is your code with the suggested changes:

void setup (void) {
  Serial.begin(9600);
}

void loop (void) {
  unsigned int servo=analogRead(A0);
  servo >>= 2;
  Serial.write(servo);
  delay(16);
}

Whoops, I forgot to map… I told myself I was going to add it, but I forgot. This should work the same, I think. I did not know about .write either.

int servo;

void setup (void) {
  Serial.begin(9600);
}

void loop (void) {
  servo=analogRead(A0);
  servo=map(servo,0,1023,0,255);
  Serial.write(servo);
  delay(16);
}

Yes, this will work, though map() is computationally more expensive because of the multiply and divide that it does. In this case, it is about 60x more expensive (about 53µs instead of 0.88µs).

These numbers are tiny compared to the delay(16) you’ve got in there, so it will make no difference in this program, but I thought I’d point that out. I only use map() when the conversion can’t be achieved using a bit-shift.

Regarding int -vs- unsigned int, I recommend you always use unsigned variables in embedded programming unless you know you need to handle negative numbers. Embedded programs and drivers often have to do bit manipulation, and sign extension can cause unexpected results. This is just my personal preference, so YMMV.

Cheers,

  • Dean

Erm, trying to get my licence transferred from one pc to another. Just sent a support email.

I’m sure support wont email me back until monday… oh well, I can always plan on what I want to do. I can also research parts and such. Do you think XBee’s will be fast enough?

Fast enough for what? If you just want to replicate the 6ch R/C remote, then you need about 7 bytes per update at about 60 updates per second. Thats 420 Bytes/second, or 4200 bits/second.

All the XBees I see listed on SparkFun seem to claim a max of 250,000 bits per second. I don’t know how much you can absolutely count on getting through, but I’m pretty sure it is more than 4200b/s if the radios are in range.

Of course if you add more channels and/or increase the update rate, the required bandwidth goes up. You also have to add in the back-channel traffic, so if you want send 200 bytes per second of telemetry data back to the controller, that is another 2000b/s of bandwidth.

Cheers,

  • Dean

So what your saying is that a pair of XBee’s would be faster than the crystal antennas? Well then there is everything I send.