Arduino and SyRen motor controller

I am trying to use an Arduino Duemilnouve (Atmega 328) to control two large wheelchair motors (24v, 25A?), running concurrently from one signal (not differential drive), with a pair of SyRen 25 motor controllers. I understand from previous threads that I am limited to simplified serial communication mode, since the Arduino lacks a genuine (non PWM) analog output.

I wrote a sketch for simplified serial mode to try to produce values the SyRen is looking for. Dimension Engr says “Commands are sent as single bytes. Sending a value of 0 will cause the motor to drive full forward and sending a value of 255 will cause the motor to drive reverse.. A value of 127 will cause the motor to stop.”

So here is the sketch I tried. It compiles and uploads without errors:

int motorPin = 5;

void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps

pinMode(motorPin, OUTPUT);

}

void loop() {

digitalWrite(motorPin, 127); // set motor to stop
delay(10000);

digitalWrite(motorPin, 65); // set motor to 1/2 throttle forward
delay(10000);

digitalWrite(motorPin, 0); // set motor to full throttle forward
delay(10000);

digitalWrite(motorPin, 65); // set motor to half throttle forward
delay(10000);

digitalWrite(motorPin, 127); // set motor to stop
delay(10000);

digitalWrite(motorPin, 190); // set motor to half throttle reverse
delay(10000);

}

The result is that the motor (I'm testing with one motor running off one 35AH 12V battery) will start and run at full speed CW after a delay of about 22 seconds. If I decrease the delay period in the sketch, say from 10000 to 3000, the motor starts up after about 7 seconds. I presently have no other control over the motor. Dip switch on the SyRen is set according to manual. I have tried Arduino pins 1, 4 and 5; all with the same results.

I also tried running the the controller in R/C Input mode, where the controller is looking for pulses of 1000 mil Sec (Full Reverse), 1500 mil Sec (stop) or 2000 mil Sec (Full Forward), with this script:

int motorPin = 4;

void setup() {

pinMode(motorPin, OUTPUT);

}

void loop() {

digitalWrite(motorPin, HIGH ); // set motor to full reverse
delay(1000);

}

Result: no movement of motor.

As a newbie, I am beginning to realize that there are issues/problems that are presently beyond me. The conspicuous lack of projects combining Arduino boards with battlebots reinforces that feeling.

I am now at a dead end. If anyone can provide any advice on how to proceed (besides converting to the Basic Stamp II controller SyRen provides support for) I would be very grateful..

Rick :-/

I think you have a couple of misunderstandings of how this motor driver works.

In simplified serial mode, you cannot just call digitalWrite() as that simply sets a pin high or low. You do not write a byte to a port using digitalWrite()...you have to use a software serial driver or some such to send 8 bits in a row.

In R/C mode, those pulses are measured in microseconds (e.g., 1500us==1500 microseconds==1.5 milliseconds).

Thanks for the corrections Ruggedcircuits.

I am now thinking that the easiest way to interface the Arduino to the SyRen 25 motor controller is to use R/C communication and translate the Pbasic / Basic Stamp 2 code, provided by Dimension Engr, to the wiring code.

Here is the Pbasic. My question is, do I use some AnalogWrite command to substitute for PULSOUT?
' {$STAMP BS2}
' {$PBASIC 2.5}
SyRen PIN 1 ' I/O Pin 1 is connected to S1 on SyRen

throttle VAR Word ' throttle variable used later on in loop

PAUSE 500 'wait for everything else to start up

'---speed and direction control------------
PULSOUT SyRen, 500 'full reverse: 1000us pulse width
PAUSE 1000 'stay at full reverse for a moment
PULSOUT SyRen, 625 'half throttle reverse: 1250us pulse width
PAUSE 1000
PULSOUT SyRen, 750 'complete stop: 1500us pulse width
PAUSE 1000
PULSOUT SyRen, 875 'half throttle forwards: 1750us pulse width
PAUSE 1000
PULSOUT SyRen, 1000 'full forward: 2000us pulse width
PAUSE 1000

PULSOUT SyRen, 750 'stop
PAUSE 1000 'stay stopped for a second

'---slow ramping of throttle------------------
' go from stopped to full forwards
FOR throttle = 0 TO 250
PULSOUT SyRen, 750 + throttle '750 is the neutral point, then add the throttle for forwards
PAUSE 10 ' wait 10ms before the next change in speed
NEXT

PAUSE 1000 'stay at full forwards for a second

' go from stopped to full reverse
FOR throttle = 0 TO 250
PULSOUT SyRen, 750 - throttle '750 is the neutral point, then subtract throttle for reverse
PAUSE 10 'wait 10ms before the next change in speed
NEXT

PAUSE 1000 'stay at full reverse for a second

PULSOUT SyRen, 750 'stop

STOP

Again, thanks very much for your help.

I should add that R/C input mode is an input mode used here for interfacing (hard-wired) with low-speed microcontrollers.....

thanks

The Arduino should be able to communicate with the controller via any of the supported modes.
Mode 1: analog
Use the analogWrite() command. They say you'll need a resistor/capacitor filter on the output pin. You'll have to use one of the pins labeled with "PWM".
Mode 2: R/C
Use the Servo library. Treat it like a continuous-rotation servo. You'll have to use either pin 9 or pin 10.
Mode 3: simplified serial
Connect the Rx/Tx lines (pins 0 and 1, they're labeled) to the controller as per the spec. Use code like the following:

Serial.begin(9600);
Serial.print(127); // idle
Serial.print(255); // full forward
Serial.print(0); // full reverse

Note that you'll have to set the baud rate using DIP switches on the motor controller.
Mode 4: Packeted serial
Physical connections will be exactly the same as the serial. You'll just need to send slightly more complex packets over the serial interface.

Let me know if you need more help. :smiley:
Edit: Leaving for the weekend. I'll check back on Monday or Tuesday.

Thanks so much for your detailed reply.

I have been able to get the 24v wheelchair motor to turn using the analog, R/C-Servo, and Simplified Serial modes...thanks to your guidance.
However, the motor is not responding in the manner that I thought the code would have dictated. For example;

Using the R/C (continuous rotation servo) mode, I modified the Duke code at http://dukevisualstudies.org/lastmiles/?p=11 because it lacked a pause between running CW and reversing to CCW. While this may be ok for an actual servo, making a big DC motor jerk back and forth between forward and backward is detrimental. So here the modified code:

int servoPin = 9;
void setup()
{
pinMode(servoPin,OUTPUT);
}
void loop()

{
digitalWrite(servoPin,HIGH);
delayMicroseconds(1500); // 1.5ms
digitalWrite(servoPin,LOW);
delay(1000); // 1 second pause

digitalWrite(servoPin,HIGH);
delayMicroseconds(1800); // 1.8ms
digitalWrite(servoPin,LOW);
delay(2000); // 2 seconds 1/2 throttle CW

digitalWrite(servoPin,HIGH);
delayMicroseconds(1500); // 1.5ms
digitalWrite(servoPin,LOW);
delay(2000); // 2 seconds pause

digitalWrite(servoPin,HIGH);
delayMicroseconds(1200); // 1.2ms
digitalWrite(servoPin,LOW);
delay(2000); // 2 seconds 1/2 throttle CCW
}

This code fails to produce the desired pause between CW and CCW rotation. Any ideas on how to corect this?

Again, thanks for your help....you have already saved me hours of frustration.

Rix-xster

I think I figured out the problem....inductive spikes from motor are walloping Arduino memory.

Solution at Yahoo | Mail, Weather, Search, Politics, News, Finance, Sports & Videos

I'm not so sure that's it. Try this first:

#include <Servo.h>

// must be either 9 or 10
#define OUTPUT_PIN 9
// measured in microseconds
#define PULSE_MIN 1000
#define PULSE_MAX 2000

Servo m_controller;

void setup()
{
  m_controller.attach(OUTPUT_PIN, PULSE_MIN, PULSE_MAX);
}

void loop()
{
  m_controller.write(90); // idle
  delay(1000);
  
  m_controller.write(135); // half-throttle forwards, I think (could be reverse)
  delay(2000);
  
  m_controller.write(90); // idle
  delay(2000);
  
  m_controller.write(45); // half-throttle backwards (could be forwards)
  delay(2000);
}

The pulse can't be a single pulse - it has to be a continued pulse. The Servo library will use hardware to handle generating the pulse. The motor controller itself should take care of all the isolation issues.
So, pass a value between 0 and 180 to write(). By passing 1000 and 2000 to the attach() method, we set the pulse lengths according to the datasheet. Let me know if that works.

Hey A Morrow: Thanks for your continued input is resolving this motor control issue. I tried your latest code and it successfully runs the motor CW and CCW, each at two speeds. Well Done! The idle setting does not completely stop the motor from turning, but I can live with that. What is a problem is that the motor still jerks at each speed change....I need to be able to ramp the speed up and down to preserve the drivetrain. I tried doubling the four speed settings in your code (90 to 112 to 135 to 112 to 90 to 67 loop) and that greatly reduced, but did not eliminate, the motor's jerking.

I tried some code where a speed setting variable would be incremented and decremented ....but it didn't work (too demented).

A little research shows that this problem has already been addressed on the Stamp platform:

http://www.bluebelldesign.com/code_examples/Servo_ramping_code.htm

However, translating that to the Arduino is a little over my head at this time.

A.Morrow: Rather than my continuing to rely on your goodwill, I'm wondering if you would be interested in doing some paid coding in your spare time? This motor control issue is part of a larger project involving ultrasonic and flex sensors, 3 - 24V DC motors and 2 solenoids....plus possibly two Arduinos (or AVR); one for sensor input and one for processing the input data and controlling the motors.

Please let me know if you have any interest in discussing this.

swampmonster@verizon.net

hello. need help urgent.

i have my arduino and syen connected to a dc motor with brakes and battery

however, i used the code provide by A Morrow but it only runs my motor in one direction. a quick troubleshoot let me knew that my motor could only run when the code was

m_controller.write(180);

and it did not turn the other way when i set the write to 0.

i need urgent help guys. thanks alot and regards!