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!