Note that 8 signals are sent out by the transmitter and only six signals are used.
So now I have code using the arduino to control the robot wirelessly. To use it, run a terminal on the serial port you are connected to at 57600 baud. For example on my mac I used screen as a terminal i.e., screen /dev/tty.usbserial-A8004IJh 57600
Enter a value of 0 - 9 separated by spaces to set the value of each successive channel followed by a carriage return. (note: entering values into the arduino terminal will not work since it does not pass carriage returns) Entering a value of 999 will set an ALL STOP condition for all channels.
ex: 5 5 5 5 5 5 - all motors not moving
ex: 5 5 5 9 5 9 - full speed ahead because I have channels 4 and 6 connected to the wheels
ex: 999 - ALL STOP
#include <Messenger.h>
/*
 * Vexduino Interface
 * -------------------
 *
 * 03/28/2009
 * Copyleft 2008 Jeremy Espino MD
 * Licensed under the the Apache 2.0 License
 * espinoj@gmail.com
 * vexduino.blogspot.com
 * modified for vexplorer compatibility
 *
 */
#define SERVO_PIN 12     // which pin to output the PPM signal on
#define FRAME_LENGTH 20  // length of PPM frame in ms
#define PULSE_START 300  // pulse start width
#define PULSE_MIN 600    // pulse minimum width in microsecs
#define PULSE_MAX 1700   // pulse max width in microsecs
#define SERVO_MAX 9    // max servo value
#define SERVO_CNTR 5   // servo center value
#define CHANNEL_NUM 8    // number of channels in the PPM 
// Instantiate Messenger object with the default separator (the space character)
Messenger message = Messenger(); 
// A pulse starts with a high signal of fixed width (0.3ms),
// followed by a low signal for the remainder of the pulse.
// Total pulse width is proportional to servo position (.6 to 1.7ms)
// conversion factor for servo to signal pulse width
int conversionFactor = (PULSE_MAX - PULSE_MIN)/ SERVO_MAX; 
// A frame is a succession of pulses, in order of channels,
// followed by a synchronisation pulse to fill out the frame.
// A frame's total length is fixed (20ms)
long lastFrame = 0;         // The time in millisecs of the last frame
int servo[CHANNEL_NUM];      // Values to set for the servos in degrees
int channel[CHANNEL_NUM];    // Values to send on channels (duration of pulse minus start, in microseconds)
int mapping[CHANNEL_NUM];    // map of vex "channels" to radio channels
int i;                 // Counter in for loop
int j = 0;                 // Counter for servo updates
byte isAllStop = 0;          // flag to set all channels to center
int inputValue;              // input value from the serial
  
// initialize servo and channel values to center points
void allStop() {
  for ( i = 0; i < CHANNEL_NUM; i = i + 1 ) {
    servo[i] = SERVO_CNTR;
  }
  for ( i = 0; i < CHANNEL_NUM; i = i + 1 ) {
    channel[i] = (PULSE_MAX - PULSE_MIN) / 2;
  }
}
void setup() {
  // Initiate Serial Communication
  Serial.begin(57600); 
  // setup mapping channel to pulse sequence
  mapping[6]=0;
  mapping[5]=1;
  mapping[4]=2;
  mapping[3]=4;
  mapping[2]=5;
  mapping[1]=6;
  pinMode(SERVO_PIN, OUTPUT);  // Set servo pin as an output pin
  allStop();
  Serial.println("\nVexduino Transmitter Interface ready!");
}
void loop() {
  // Save the time of frame start
  lastFrame = millis();
  // This for loop generates the pulse train, one per channel
  for ( i = 0; i < CHANNEL_NUM; i = i + 1 ) {
    digitalWrite(SERVO_PIN, HIGH);   // Initiate pulse start
    delayMicroseconds(PULSE_START);  // Duration of pulse start
    digitalWrite(SERVO_PIN, LOW);    // Stop pulse start
    delayMicroseconds(channel[i]);   // Finish off pulse
  }
  digitalWrite(SERVO_PIN, HIGH);     // Initiate synchronisation pulse
  delayMicroseconds(PULSE_START);    // Duration of start of synchronisation pulse
  digitalWrite(SERVO_PIN, LOW);      // Stop synchronisation pulse start
  // read the next set of servo settings from serial input
  while ( Serial.available() ) {
    if ( message.process(Serial.read() ) ){
      int p = 1;
      
      while( message.available() ) {
        inputValue = message.readInt();
        
        // a value of 999 indicates all stop position
        if (inputValue == 999) isAllStop = 1;
        
        servo[mapping[p]] =  inputValue;
        
        // if invalid servo position set to center
        if ( servo[mapping[p]] > SERVO_MAX) servo[mapping[p]] = SERVO_CNTR;
        p = p + 1;
      }
      if (isAllStop == 1) {
        allStop();
        isAllStop = 0;
      }
    }
  }
  // Calculate pulse durations from servo positions
  for ( i = 0; i < CHANNEL_NUM; i = i + 1 ) {
    channel[i] = int(servo[i]*conversionFactor) + PULSE_MIN;
  }
  // show current settings
  // skip vex "channels" 0 and 7 since they are numbered 1 thru 6
  Serial.print("\r");
  for ( i = 1; i < 7; i = i + 1 ) {
    Serial.print(i);
    Serial.print(":");
    Serial.print(servo[mapping[i]]);
    //Serial.print(":");
    //Serial.print(channel[mapping[i]]);
    Serial.print(" ");
  }
  Serial.print("                ");
  // We're ready to wait for the next frame
  // Some jitter is allowed, so to the closest ms
  while (millis() - lastFrame < FRAME_LENGTH) {
    delay(1);
  }
} 
Hello!
ReplyDeleteThanks for sharing this code! I am trying to do the same thing but not having any luck. I've got the code running and hooked up, but nothing is happening to the motors. I cut the connection and soldered in two wires like you describe, and when I bridge them the remote works like normal. Just to clarify, I have the pin 20 i believe of the chip inside the remote connecting to pin 12 of the arduino (SERVO_PIN in the code). I then turn on the controller but no luck. I can see the values changes in the serial output so I imagine the arduino is sending out what it should. Any ideas on what I could do to figure out whats wrong?
Thanks!!
I figured it out! All I needed to do was share the ground!!
ReplyDeleteThanks for sharing your code!