servo reverse on one channel

Hi, I have a working sketch that is great and works well. but, I need to reverse one channel.
The sketch operates two 270deg servos, but I need one to do the same as the other but rotate the other way around. I know I could change the servo motor and pot wires, I have done this on one other set up but its far from ideal. the display should display the same deg

Can any one help please.

sketch_apr01ab.ino (4.03 KB)

"do the same as the other but rotate the other way round" isn't easy to understand. If it's doing the same how can it be rotating in the other direction?

I think what you may want is what would normally be write(x) to one and write(180-x) to the other. You've confused it a bit by using microseconds but it's still just arithmetic. If your range is 600-2300 then it will be x and 2900-x.

Unless of course that isn't what you mean.

Steve

Hi Steve,
yes sorry, one servo has to go one way and the other has to be going in the opposite direction. like one clock wise and the other anti clock wise. (but stay in sync with each other)
The two servos are rotating a platform, there is one servo on one side and the other servo is on the other side, both work together.
How did you get 2900-x this 2900 would be over the servo limit, or am I not understanding, I can see you added 600 and 2300 to get 2900
would it be -600-2300
please could you explain or poss edit the line for me then i could see how this works.
Mike

Servo a can go 0 - 270
Servo b can go 0 - 270

if I move servo a to 100, I move servo b to 270-100
This way they will still be in tandem but mirrored.

If you're writing 600 to one servo the other needs 2300 doesn't it? And vice versa. Hence 2900-x.

Anyway try it out and check it really is what you want.

Steve

HI ill give it go both ways, i will let you know
Head is spinning, trying at the mo to get some RC nav lights working without an RC input aghh..
sketch seems to work ish..

Hope this is what you both mean, i had to change the angle numbers a tad, I'm still playing with the stop angles
servoLeft.attach(servoLeftPin, 544, 2400); // <<<<<<<< set these min and max to suit a 270 servo
servoRight.attach(servoRightPin, 2400, 544);

You'd normally do the reverse in the servo write/writeMicroseconds.

int time = 1234;

...
....
fwdServo.writeMicroseconds (time);
revServo.writeMicroseconds (2944 - time);

MikeMCA:
Hope this is what you both mean, i had to change the angle numbers a tad, I'm still playing with the stop angles
servoLeft.attach(servoLeftPin, 544, 2400); // <<<<<<<< set these min and max to suit a 270 servo
servoRight.attach(servoRightPin, 2400, 544);

No! I have no idea what the servo library does if you claim that 2400 is the MINIMUM value and 544 is the MAXIMUM but I wouldn't think it's anything good.

It is the values in the writeMicroseconds() commands that you need to change.

Steve

TheMemberFormerlyKnownAsAWOL:
You'd normally do the reverse in the servo write/writeMicroseconds.

// same as 31 mar 2020

//  but 1 april changed lcd to be non-i2c

//***************************************************************************
// ************* check the screen, pin and button pin numbers ***************
//***************************************************************************

// *** this version V2 uses microseconds not degrees ***
//    but still uses degrees for display purposes
//    V2.1 is non-i2c lcd

// not clear from those ^^^^ instructions if the servo has to go in sequence
//    *** code below allows movement in any order

//    *** code below is tested with 2x "normal" 0-180 servos ***
//    *** change these values for the real 0-270 servos ***
// V2: these pos values are for the LCD display

const byte pos1 = 0;
const byte pos2 = 90;  //will be 90
const byte pos3 = 180; //will be 180
const byte pos4 = 270; //will be 270
byte pos;
// V2: these microPos values are for the write.microseconds <<<< adjust these
const int micropos1 = 600; // <<<< adjust these, I just stuck some values in to test
const int micropos2 = 1200;
const int micropos3 = 1800;
const int micropos4 = 2300;
int micropos;

char posMessage[] = "  DOWN"; // later will hold the actual word to display

//                **** V2.1 i2c lcd stuff commented out
/*
  //bperrybap library for lcd
  // install from ide: Sketch > Include Library > Manage Libraries, search hd44780
  #include <Wire.h>
  #include <hd44780.h>                      // main hd44780 header
  #include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
  hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
  // LCD geometry
  const int LCD_COLS = 16;
  const int LCD_ROWS = 2;
*/
//              *** and replaced with
#include <LiquidCrystal.h>
//const int rs = 6, en = 7, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
//LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  //dfr0009 shield uses different pins

#include <Servo.h>
Servo servoLeft;
Servo servoRight;
// ******** check pins in next lines
//dfr0009 shield leaves different pins vacant
const byte servoLeftPin = 2; //was 8
const byte servoRightPin = 3; //was 9

const byte button1 = 19; //aka A5, was 10
const byte button2 = 11;
const byte button3 = 12;
const byte button4 = 13;

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

servoLeft.attach(servoLeftPin, 544, 2400); // <<<<<<<< set these min and max to suit a 270 servo
  servoRight.attach(servoRightPin, 2400, 544); // <<<<<<<< set these min and max  to suit a 270 servo

pinMode(13, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(button3, INPUT_PULLUP);
  pinMode(button4, INPUT_PULLUP);

//lcd.begin(LCD_COLS, LCD_ROWS); //out
  lcd.begin(16, 2); //in
  lcd.setCursor(0, 0);
  lcd.print("  673090..V2.1  ");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("Pos: ");

}//setup

void loop()
{
  if (!digitalRead(button1))
  {
    pos = pos1; // for the display
    strcpy(posMessage, "  DOWN"); // for the display, I may have these wrong for the degrees :wink: <<<<
    micropos = micropos1; //for the servo
  }
  if (!digitalRead(button2))
  {
    pos = pos2;
    strcpy(posMessage, "  RIGHT"); // for the display, I may have these wrong for the degrees :wink:
    micropos = micropos2;
  }
  if (!digitalRead(button3))
  {
    pos = pos3;
    strcpy(posMessage, "    UP"); // for the display, I may have these wrong for the degrees :wink:
    micropos = micropos3;
  }
  if (!digitalRead(button4))
  {
    pos = pos4;
    strcpy(posMessage, "  LEFT"); // for the display, I may have these wrong for the degrees :wink:
    micropos = micropos4;
  }

//servoLeft.write(pos);
  //servoRight.write(pos);  //these replaced by next 2:
  servoLeft.writeMicroseconds(micropos);
  servoRight.writeMicroseconds(micropos);
  lcd.setCursor(5, 1);
  if (pos < 10) lcd.print(" ");
  if (pos < 100) lcd.print(" ");
  lcd.print(pos);
  lcd.print((char)223); //degree symbol
  lcd.print(posMessage);
}//loop

here is the sketch

servoRight.attach(servoRightPin, 2400, 544); I don't think the Servo library will allow this.
I'm posting from my phone, and don't have access to the source of the Servo library, so I can't check.

But, it shouldn't be necessary, if you follow the advice in reply #7.

Its like they can't hear you.

-jim lee

Yes jim i get this all the time, i am not a software person hardware is my thing.
Mike

Yeah, I actually know the feeling. I have a really nice digital scope on my desk. When I need to use it I prefer to have my EE buddy drive it. I'm totally lost in electronics.

RC servos typically run on around a 20 ms frequency with a 1..2 ms pulse. The position is given by the pulse width, with 1.5 ms being center. The frequency is a very sloppy number and can sometimes be cut down as much as 10ms. I've seen it where it actually works better like that. (Some servos can read a wider pulse with band and give a larger swing)

AWOL is giving you the most common solution from our software world. Its a way to feed your value into the servo backwards (with a simple subtraction) Effectively reversing your servo.

Good luck!

-Jim lee

Hi, well I tried what they said, it didn't work, i spent an hour rewiring the servo just to get me going on the project.

But I still need the code fix, the servo project is part of a very large multiple project so I have to do this in software as hard wiring changes will take to much time plus for swop outs it will be a nightmare.

I do hope someone will edit the code for me, I am crap at software lol

Mike

it didn't work,

The single most useless phrase you could type on this forum.

What did it do that you didn't expect?
What didn't it do that you did expect?

i spent an hour rewiring the servo just to get me going on the project.

Don't bother describing why you rewired the servo, or how - we love guessing games.

Ok, lets try this.. (With standard wired servos.)

#include <mapper.h>

// same as 31 mar 2020
//  but 1 april changed lcd to be non-i2c

//***************************************************************************
// ************* check the screen, pin and button pin numbers ***************
//***************************************************************************

// *** this version V2 uses microseconds not degrees ***
//    but still uses degrees for display purposes
//    V2.1 is non-i2c lcd



// not clear from those ^^^^ instructions if the servo has to go in sequence
//    *** code below allows movement in any order

//    *** code below is tested with 2x "normal" 0-180 servos ***
//    *** change these values for the real 0-270 servos ***
// V2: these pos values are for the LCD display


const byte pos1 = 0;
const byte pos2 = 90;  //will be 90
const byte pos3 = 180; //will be 180
const byte pos4 = 270; //will be 270
byte pos;
// V2: these microPos values are for the write.microseconds <<<< adjust these
const int micropos1 = 600; // <<<< adjust these, I just stuck some values in to test
const int micropos2 = 1200;
const int micropos3 = 1800;
const int micropos4 = 2300;
int micropos;

char posMessage[] = "   DOWN"; // later will hold the actual word to display


#include <LiquidCrystal.h>
//const int rs = 6, en = 7, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
//LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  //dfr0009 shield uses different pins

#include <Servo.h>

Servo servoLeft;
Servo servoRight;

// ******** check pins in next lines
//dfr0009 shield leaves different pins vacant
const byte servoLeftPin = 2; //was 8
const byte servoRightPin = 3; //was 9

const byte button1 = 19; //aka A5, was 10
const byte button2 = 11;
const byte button3 = 12;
const byte button4 = 13;
mapper reverseMap(544,2400,2400,544);
void setup()
{
  Serial.begin(9600);

  servoLeft.attach(servoLeftPin, 544, 2400); // <<<<<<<< set these min and max to suit a 270 servo
  servoRight.attach(servoRightPin, 544, 2400); // <<<<<<<< set these min and max  to suit a 270 servo

  pinMode(13, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(button3, INPUT_PULLUP);
  pinMode(button4, INPUT_PULLUP);

  //lcd.begin(LCD_COLS, LCD_ROWS); //out
  lcd.begin(16, 2); //in
  lcd.setCursor(0, 0);
  lcd.print("  673090..V2.1  ");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("Pos: ");

}//setup

void loop()
{
  if (!digitalRead(button1))
  {
    pos = pos1; // for the display
    strcpy(posMessage, "   DOWN"); // for the display, I may have these wrong for the degrees ;) <<<<
    micropos = micropos1; //for the servo
  }
  if (!digitalRead(button2))
  {
    pos = pos2;
    strcpy(posMessage, "  RIGHT"); // for the display, I may have these wrong for the degrees ;)
    micropos = micropos2;
  }
  if (!digitalRead(button3))
  {
    pos = pos3;
    strcpy(posMessage, "     UP"); // for the display, I may have these wrong for the degrees ;)
    micropos = micropos3;
  }
  if (!digitalRead(button4))
  {
    pos = pos4;
    strcpy(posMessage, "   LEFT"); // for the display, I may have these wrong for the degrees ;)
    micropos = micropos4;
  }

  //servoLeft.write(pos);
  //servoRight.write(pos);  //these replaced by next 2:
  servoLeft.writeMicroseconds(micropos);
  
  servoRight.writeMicroseconds(round(reverseMap.map(micropos)));
  lcd.setCursor(5, 1);
  if (pos < 10) lcd.print(" ");
  if (pos < 100) lcd.print(" ");
  lcd.print(pos);
  lcd.print((char)223); //degree symbol
  lcd.print(posMessage);
}//loop

I -[THINK]- I reversed servoRight by remapping its timing. Lets see if it works? You will need to install LC_baseTools from using the library manager to compile it.

Let me know.

-jim lee

Hi, jim I compiled it with out errors, will try it out in the morning.
Thank you so much, you are so helpfull

Hi Jim,
Thank you for doing that for me, the reverse direction does work. However the display shows 14 deg when the 270deg button is pressed, all the others are as they should be. 0-90-180deg on the LCD
Also how and where do I adjust the servo rotation as 90 deg is 75 deg, 180deg is 160deg and the 270deg is approx 200deg.

is it here that needs to be changed

servoLeft.attach(servoLeftPin, 544, 2400); // <<<<<<<< set these min and max to suit a 270 servo
servoRight.attach(servoRightPin, 544, 2400); // <<<<<<<< set these min and max to suit a 270 servo

thank you again
Mike.

No mainly you will need to change the micropos1, 2, 3,4 values where the comment says "<<<< adjust these, I just stuck some values in to test". You need to experiment and change the 600, 1200, 1800, 2300 so that each one sends the servo to where you want it to go.

To get the display right change the pos definitions into ints. The value 270 won't fit into a byte. I.e.

const int pos1 = 0;
const int pos2 = 90;  //will be 90
const int pos3 = 180; //will be 180
const int pos4 = 270; //will be 270
int pos;

Steve