Control: jrk 21v3 with arduino and potentiometer

We are building an ROV. We want to control motors through serial from an Arduino. To set the serial we want to use a potentiometer (joystick in the future). The data from the potentiometer is being sent correctly to the Arduino because we see the numbers changing in the serial monitor. Unfortunately, the data sent to the motor control device (jrk 21v3) does not read the serial input at all. Here is the code we are using. We think the problem is that the motor control is not reading the serial data correctly.

[code]
int potPin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
int motorPin = 16; // TX for motor
int motorPinRX = 17;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(motorPin, OUTPUT);
pinMode(potPin, INPUT);

}

// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);

val = analogRead(potPin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 1, 1023, 0, 4095); // scale it to use it with the servo (value between 0 and 180)
float voltage = val * (5.0 / 1023.0);//voltage readings

if (val >= 0)
{
Serial.println(val);
// Serial.println(voltage);
digitalWrite(motorPin, val);

}

delay(50); // delay in between reads for stability
}[/code]
Here’s how we have all the hardware setup:


We made sure everything is set up correctly. Any suggestions will help. thank you!

Hello.

Is that code the one you are using to send the serial commands to the jrk? I do not see any of the serial commands being sent in that sketch. It looks like it just prints out the remapped value. I am not sure what you expect to happen with the “digitalWrite(motorPin, val);” line of code. To send serial commands to set the target on the jrk, you will need to follow the serial protocols outlined in the Motor Control Commands section of the jrk user’s guide. If you are new to sending serial bytes, you might find the Set Target Low Resolution Forward command (with the compact protocol) easiest to use. For this command, you must first send the command byte (0xE1), followed by the magnitude (which is defined in the section I linked to above). If you try sending the correct commands and still have problems, you can post your updated sketch, and I would be glad to take a look.

By the way, the jrk has an analog input mode; is there a reason you do not want to connect the potentiometer directly to the jrk?

-Brandon

The reason we do not want to use an analog signal is it will be running down a 60 ft tether near a power wire. Shielding does not work in our application. We are using the Arduino to use serial to avoid this.

Honestly, we are very new to all of this digital stuff. We completely understand analog, but have found the benefits of digital to be strong enough to switch.
We don’t really know how to send serial commands. We thought we were doing that with the digitalWrite line of code. We are just having trouble grasping the concept I think.

Thank you for your help.

TTL serial uses digital signals, but it is different from digitalWrite(). You can find more information about using serial signals with Arduino on Arduino’s “Serial” reference page. In this case, you will want to use the Serial.write() function to send the command bytes that correspond to the jrk’s serial protocol (see the Motor Control Commands section of the jrk user’s guide I linked to in my previous response).

The snippet of example C code shown in the “Set Target High Resolution” command description (found in the Motor Control Commands section) shows how to get the correct serial bytes to send. The code you posted is already mapping the analog input to 0-4095, so you can use your “val” variable in place of the “target” variable shown in that example. Then you would need to send those serial bytes with Serial.write(). If you try updating your code to use serial and continue to have problems, you can post your new code and I’d be glad to take a look.

-Brandon

We must be doing something wrong. Here’s our new code, and we still are not seeing any input on the Pololu utility.

[code]#include <SoftwareSerial.h>
SoftwareSerial mySerial(19,18); // RX, TX, plug your control line into pin 8 and connect it to the RX pin on the JRK21v3
int serialBytes [10];
int potPin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
int motorPin = 18; // TX for motor
int motorPinRX = 19;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
mySerial.begin(4800);
}

// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
val = analogRead(potPin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 1, 1023, 0, 4095); // sca
serialBytes[0] = 0xC0 + (val & 0x1F); // Command byte holds the lower 5 bits of target.
serialBytes[1] = (val >> 5) & 0x7F;
// Serial.println(val);
// Serial.println(voltage);le it to use it with the servo (value between 0 and 180)
// float voltage = val * (5.0 / 1023.0);
mySerial.write(serialBytes[0]);
mySerial.write(serialBytes[1]);
Serial.print(serialBytes[0]);
Serial.println(serialBytes[1]);
Serial.println(val);

delay(50); // delay in between reads for stability
}[/code]

Hello.

Your serialBytes values look correct. What serial interface setting do you have the jrk set to? If it is configured for UART, detect baud rate, you will need to send the 0xAA byte first so it can detect the baud rate. If it is set to UART, fixed baud rate, you should make sure it matches the baud rate specified by your code (e.g. 4800 in the code you included in your last post). You might also double check that the serial connections are made correctly (e.g. the Arduino pin you designate as TX in your code should be connected to the jrk controller’s RX pin, and the pin you choose for RX should be connected to the jrk controller’s TX pin).

By the way, I noticed you have RX for your software serial defined as pin 19. It looks like you are using an Arduino Mega, which does not support change interrupts on pin 19. You can see a list of compatible pins on the SoftwareSerial Library Arduino Reference page.

If you change those things and it is still not working, can you include your updated code and jrk settings file in your next post? You can save your jrk settings file by selecting the “Save Settings File…” option within the “File” drop-down menu within the Jrk Configuration Utility.

-Brandon

[code]#include <SoftwareSerial.h>
SoftwareSerial mySerial(19,18); // RX, TX, plug your control line into pin 8 and connect it to the RX pin on the JRK21v3
int serialBytes [10];
int potPin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
int motorPin = 18; // TX for motor
int motorPinRX = 19;
char buffer[4];
//int val2;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
mySerial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
val = analogRead(potPin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 1, 1023, 0, 4095); // sca
//buffer[val] = Serial.read();
//val2 = (buffer[0]-48)*1000+(buffer[1]-48)*100+(buffer[2]-48)*10+(buffer[3]-48);

serialBytes[0] = 0xC0 + (val & 0x1F); // Command byte holds the lower 5 bits of target.
serialBytes[1] = (val >> 5) & 0x7F;
// Serial.println(val);
// Serial.println(voltage);le it to use it with the servo (value between 0 and 180)
// float voltage = val * (5.0 / 1023.0);
mySerial.write(serialBytes[0,1]);
// mySerial.write(serialBytes[1]);
// Serial.print(serialBytes[0]);
// Serial.println(serialBytes[1]);
// Serial.println(val);

delay(50); // delay in between reads for stability
}[/code]

Okay, so here is our new code. We’re not seeing any input on the Pololu program. We’re not getting errors in the program either, however. Just no indication it is reading the potentiometer.

Here’s our jrk settings file:

INITIALIZED 0 INPUT_MODE SERIAL INPUT_MINIMUM 0 INPUT_MAXIMUM 4095 OUTPUT_MINIMUM 0 OUTPUT_NEUTRAL 2048 OUTPUT_MAXIMUM 4095 INPUT_INVERT 0 INPUT_SCALING_DEGREE 0 INPUT_POWER_WITH_AUX 0 INPUT_ANALOG_SAMPLES_EXPONENT 8 INPUT_DISCONNECT_MINIMUM 1 INPUT_DISCONNECT_MAXIMUM 4093 INPUT_NEUTRAL_MAXIMUM 2048 INPUT_NEUTRAL_MINIMUM 2048 SERIAL_MODE UART_FIXED_BAUD_RATE SERIAL_FIXED_BAUD_RATE 9600 SERIAL_TIMEOUT 0 SERIAL_ENABLE_CRC 1 SERIAL_NEVER_SUSPEND 0 SERIAL_DEVICE_NUMBER 11 FEEDBACK_MODE NONE FEEDBACK_MINIMUM 1 FEEDBACK_MAXIMUM 4095 FEEDBACK_INVERT 0 FEEDBACK_POWER_WITH_AUX 0 FEEDBACK_DEAD_ZONE 0 FEEDBACK_ANALOG_SAMPLES_EXPONENT 5 FEEDBACK_DISCONNECT_MINIMUM 1 FEEDBACK_DISCONNECT_MAXIMUM 4095 PROPORTIONAL_MULTIPLIER 1 PROPORTIONAL_EXPONENT 0 INTEGRAL_MULTIPLIER 0 INTEGRAL_EXPONENT 0 DERIVATIVE_MULTIPLIER 0 DERIVATIVE_EXPONENT 0 PID_PERIOD 10 PID_INTEGRAL_LIMIT 1000 PID_RESET_INTEGRAL 0 MOTOR_PWM_FREQUENCY 0 MOTOR_INVERT 0 MOTOR_MAX_DUTY_CYCLE_WHILE_FEEDBACK_OUT_OF_RANGE 600 MOTOR_MAX_ACCELERATION_FORWARD 600 MOTOR_MAX_ACCELERATION_REVERSE 600 MOTOR_MAX_DUTY_CYCLE_FORWARD 600 MOTOR_MAX_DUTY_CYCLE_REVERSE 600 MOTOR_MAX_CURRENT_FORWARD 81 MOTOR_MAX_CURRENT_REVERSE 82 MOTOR_CURRENT_CALIBRATION_FORWARD 37 MOTOR_CURRENT_CALIBRATION_REVERSE 37 MOTOR_BRAKE_DURATION_FORWARD 0 MOTOR_BRAKE_DURATION_REVERSE 0 MOTOR_COAST_WHEN_OFF 0 ERROR_ENABLE 2072 ERROR_LATCH 2064

I was able to load your settings onto a jrk controller here, and tried your code without modification, and it did not work; however, after I modified the mySerial.write() lines slightly, it worked fine. To demonstrate the change I made, I simplified your code by taking out the unnecessary and commented out code:

[code]
#include <SoftwareSerial.h>

int motorPin = 18; // TX for motor
int motorPinRX = 19; // RX pin. Note that pin 19 on the Arduino Mega is not compatible
int serialBytes [2];
int potPin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin

SoftwareSerial mySerial(motorPinRX, motorPin);

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

void loop() {

val = analogRead(potPin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 1, 1023, 0, 4095); // scale to the appropriate target values

serialBytes[0] = 0xC0 + (val & 0x1F);
serialBytes[1] = (val >> 5) & 0x7F;

mySerial.write(serialBytes[0]);
mySerial.write(serialBytes[1]);

delay(50); // delay in between reads for stability
}[/code]

Please note, as I mentioned in the comments of this code and my previous post, pin 19 will not work for the RX pin when using SoftwareSerial. You should change it to one of the pins specified as compatible with the Arduino Mega on the SoftwareSerial Library reference page on Arduino’s website.

-Brandon

I’ve loaded up your code and in the Pololu configuration utility and I’m getting an 0x0800 Serial Protocol Error. Why would this be?

Sorry about the confusion. I forgot to mention that you should also uncheck the “Enable CRC” option in the “Input” tab of the Jrk Configuration Utility since the code is not sending any of the necessary bytes for the Cyclic Redundancy Check. You can see more about this in the “Cyclic Redundancy Check (CRC) Error Detection” section of he jrk user’s guide. With CRC disabled, the serial protocol error should go away.

-Brandon

We figured it out. Here’s the code that worked for us (for anyone that might have a similar problem):

[code]/*
AnalogToSerial
Reads an analog input on pin 0, outputs to TX.
*/
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10,18); // RX, TX, plug your control line into pin 16 and connect it to the RX pin on the JRK21v3
//SoftwareSerial mySerial(11,10); // for UNO RX, TX, plug your control line into pin 16 and connect it to the RX pin on the JRK21v3
int serialBytes [10];
int potPin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
char buffer[4];

void setup() {
Serial.begin(9600);
mySerial.begin(9600);
pinMode(10, INPUT);
pinMode(18,OUTPUT);
//pinMode(11, INPUT); // for UNO
//pinMode(10,OUTPUT); // for UNO
}

void loop() {

val = analogRead(potPin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 4095); // scales value to desired numbers
Serial.print(val);
Serial.print (" ");

// compact hi res mode
serialBytes[0] = 0xC0 + (val & 0x1F); //this line and the one below
serialBytes[1] = (val >> 5) & 0x7F; //are the bytes we are sending
//we are using compact protocol for setting target to low resolution https://www.pololu.com/docs/0J38/4.e

mySerial.write(0xAA);
mySerial.write(serialBytes[0]); //bytes that are sent 
mySerial.write(serialBytes[1]); //bytes that are sent 

Serial.print(serialBytes[0]); //numbers on serial monitor
Serial.print (" ");
Serial.println(serialBytes[1]); //numbers on serial monitor

delay(50); // delay in between reads for stability
}[/code]

Hello.

I am glad you were able to get it working. Thank you for posting your working code.

Good luck with your project!

-Brandon