Go Down

Topic: Sand drawing robot. Problem with homing switches. (Read 2038 times) previous topic - next topic

OZYMAX

Hello.
I am building a sand drawing robot based on Rob Dobson's design.
I have attached some pics of my build, because a pic is worth a thousand words.











My build is using 2x nema17 motors driven from A4988 chips, mounted on a CNC V3 shield and an Arduino Uno, using a 12 volt power supply.
I'm using 2x optical switches for the homing.

I have compiled a sketch and it is partly successful. I should add that this is my very first attempt at coding.

I need the motor/arms to home in a CW direction on power up, then proceed to the void loop.

If the switch is uninterrupted on power up, the "if" code runs, then the "else" code runs perfectly and homes as I'd expect. I want it to ignore the "if" and go straight into the "else" section if the switch is uninterrupted.

However, if the switch happens to be already interrupted on power up, the code goes straight into the "loop" without homing the arm.

I have tried using the "if" and "else" statements to solve this issue. Where am I going wrong?

Your help is much appreciated.


Code: [Select]
//Current set up for the sand robot X axis only.

#include "AccelStepper.h"

// AccelStepper Setup
AccelStepper stepperX(AccelStepper::DRIVER, 2, 5);

// Define the Pins used
#define home_switch_X 9   // Pin 9 connected to Home Switch Stepper X

// Stepper Travel Variables
long initial_homing = -1; // Used to Home Stepper at startup

unsigned long pos1 = 200;  //Alters X arm distance. -# gives CCW rotation

void setup()
{
  pinMode(home_switch_X, INPUT_PULLUP);

  // Start Homing procedure of Stepper Motors at start up

  if (digitalRead(home_switch_X == LOW)) {
    stepperX.setMaxSpeed(100.0);
    stepperX.setAcceleration(500.0);
    stepperX.runToNewPosition(-300);  // move away from switch
    stepperX.run();  // Start moving the stepper
  }
  else (digitalRead(home_switch_X)); {  // Arm X move CW until switch is activated
    stepperX.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperX.setCurrentPosition(0);  // Set the current position as zero for now
    stepperX.setMaxSpeed(1000.0);      // Set Max Speed of StepperX (Homing speed)
    stepperX.setAcceleration(500.0);  // Set Acceleration of Stepper
    stepperX.run();  // Start moving the stepper
    initial_homing = 1;
  }
  while (!digitalRead(home_switch_X)) { // Make X arm move CCW until switch is deactivated
    stepperX.moveTo(initial_homing);
    stepperX.run();
    initial_homing--;     //-- to ++ changes arm direction
    delay(3);
  }
  {
    delay(2000);//delay between homing and motion routine
  }
  stepperX.setCurrentPosition(0);
  stepperX.setMaxSpeed(100.0);      // Set Max Speed of StepperX (Faster for regular movements)
  stepperX.setAcceleration(500.0);  // Set Acceleration of Stepper (higher number creats sharp corners)
}
void loop()
{
  if (stepperX.distanceToGo() == 0)
    pos1 = -pos1;
  stepperX.moveTo(pos1);

  stepperX.run();
}

AWOL

Code: [Select]
if (digitalRead(home_switch_X == LOW))
 Oops
Code: [Select]
else (digitalRead(home_switch_X)); Did you intend to do something with the value you read?

OZYMAX

I figured that I would need to read the switch state before setting the current position in the next set of commands.

Code: [Select]
else (digitalRead(home_switch_X)); {  // Arm X move CW until switch is activated
    stepperX.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperX.setCurrentPosition(0);  // Set the current position as zero for now
    stepperX.setMaxSpeed(1000.0);      // Set Max Speed of StepperX (Homing speed)
    stepperX.setAcceleration(500.0);  // Set Acceleration of Stepper
    stepperX.run();  // Start moving the stepper
    initial_homing = 1;


Is this where I've gone wrong?
Do I need to give the switch a value?

AWOL

I pointed-out two issues.


The first is reading pin zero in the "if" condition.
Pin zero is part of the serial interface.

The second is reading pin "home_switch_X" in the "else', but not doing anything with the value you read. The code after the "else" will be executed unconditionally.

OZYMAX

I pointed-out two issues.


The first is reading pin zero in the "if" condition.
Pin zero is part of the serial interface.

The second is reading pin "home_switch_X" in the "else', but not doing anything with the value you read. The code after the "else" will be executed unconditionally.
Ah ok. I saw the oops and figured that you made a miss quote. Sorry.

1st...I don't understand what you mean by reading pin zero in the "if" condition.
I've defined the switch pin as #9.
"Pin zero is part of the serial interface" Not sure what is meant by this.

2nd...So isn't this reading the state of the pin and if true, carrying on with the rest of the code?
Can I delete that line of code and have the rest of it still run?

How can I tell the Arduino that the switch is interrupted and to move off the switch?
I'm really getting lost now.

Thanks for your help though.




AWOL

Code: [Select]
if (digitalRead(home_switch_X == LOW))1st. home_switch_X has the value nine.
LOW has the value zero.

Nine is not equal to zero, so the result of the comparison is false, aka zero.

So, you are reading pin zero, which is half of the serial interface.

2nd. It is reading the state of the pin, but not doing anything with the result.

TomGeorge

#6
Jun 29, 2019, 07:27 pm Last Edit: Jun 29, 2019, 07:28 pm by TomGeorge
Hi,
Your interrupters appear to have open collector outputs, how have you got  them connected to the UNO?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Do you have a DMM to check that the input to the UNO from the interrupters does change HIGH/LOW when you test them?

Thanks.. Tom... :)
PS, Given you a karma for reading the forum sticky and posting your code correctly.
Everything runs on smoke, let the smoke out, it stops running....

OZYMAX

Hi,
Your interrupters appear to have open collector outputs, how have you got  them connected to the UNO?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Do you have a DMM to check that the input to the UNO from the interrupters does change HIGH/LOW when you test them?

Thanks.. Tom... :)
PS, Given you a karma for reading the forum sticky and posting your code correctly.
Hello Tom.

Yes I have a DMM and have tested the switches.
If you can refer to the previous pic of the switch circuit board , you can trace the circuit.
I have the RED wire connected to the 5v pin on the shield.
I have the GREY (middle) wire connected to the X- limit SW pin on the shield. #9 on the UNO.
I have the BLACK wire connected to the GND pin on the shield.

The switches work fine, it's just the if else section of the code that I don't seem to have right.

Thanks for the Karma.  :)
Before I joined the forum, I'd read many posts where people were told to read the forum sticky.
I must admit, I found some of those posts quite intimidating and it was that fact that made me hesitate on becoming a member.
I totally understand why though, as I'm sure there are people that come on expecting stuff to be done for them etc.

TomGeorge

#8
Jul 01, 2019, 09:13 am Last Edit: Jul 01, 2019, 09:14 am by TomGeorge
Hi,
Your if statement format should be like this;

Code: [Select]
if (digitalRead(home_switch_X == LOW))
  {
    stepperX.setMaxSpeed(100.0);
    stepperX.setAcceleration(500.0);
    stepperX.runToNewPosition(-300);  // move away from switch
    stepperX.run();  // Start moving the stepper
  }
  else
  {  // Arm X move CW until switch is activated
    stepperX.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperX.setCurrentPosition(0);  // Set the current position as zero for now
    stepperX.setMaxSpeed(1000.0);      // Set Max Speed of StepperX (Homing speed)
    stepperX.setAcceleration(500.0);  // Set Acceleration of Stepper
    stepperX.run();  // Start moving the stepper
    initial_homing = 1;
  }

Note that also the semicolon is not needed.

Having checked if the switch is LOW then the  only other condition of that switch is HIGH.

https://www.arduino.cc/reference/en/language/structure/control-structure/else/

Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

OZYMAX

#9
Jul 05, 2019, 02:41 am Last Edit: Jul 05, 2019, 06:34 am by OZYMAX
I found myself struggling with the if else functions, so decided to rework my code.
I came across another forum member with a similar setup and set about adjusting their code to see if it could work for me.
At this stage, this code seems to be working for what I want and it will allow me to proceed to the next step.  :) 
I did make a rookie mistake and accidentally over wrote my code. Lucky for me I could get it back from the forum. I've now decided to save a pasted copy in a word doc to play it safe.

Code: [Select]
//Current set up for the sand robot X and Y axis.

#include "AccelStepper.h"

// AccelStepper Setup
AccelStepper stepperX(AccelStepper::DRIVER, 2, 5);
AccelStepper stepperY(AccelStepper::DRIVER, 3, 6);

// Define the Arduino pins used
#define home_switch_stepperX 9 // Pin 9 connected to Home Switch X
#define home_switch_stepperY 10 // Pin 9 connected to Home Switch Y

// Stepper variables
long initial_homing_stepperX = -1; // Used to Home StepperX at startup
long initial_homing_stepperY = -1; // Used to Home StepperY at startup

unsigned long pos1 = -5000000; //Alters X arm pattern. 2776 steps per/rev. Max 4,294,967,295. Minus gives CCW rotation
unsigned long pos2 = 1000; //Alters Y arm pattern. 2776 steps per/rev. Max 4,294,967,295. Minus gives CCW rotation

void setup() {
  Serial.begin(9600);  // Start the Serial monitor

  pinMode(home_switch_stepperX, INPUT_PULLUP);
  pinMode(home_switch_stepperY, INPUT_PULLUP);

// Start homing procedure of stepper motors at startup

  Serial.println("Arm X homing");

  while (digitalRead(home_switch_stepperX)) {  // Make X arm move CW till switch is interupted
    stepperX.moveTo(initial_homing_stepperX);  // Set the position to move to
    initial_homing_stepperX++;  // Increase by 1 for next move if needed
    stepperX.run();  // Start moving the stepper
  }
  stepperX.setCurrentPosition(0);  // Set the current position to zero
  stepperX.setMaxSpeed(200.0);      // Set Max Speed of StepperX (Homing speed)
  stepperX.setAcceleration(500.0);  // Set Acceleration of StepperX
  initial_homing_stepperX = 1;

  while (!digitalRead(home_switch_stepperX)) { // Make X arm move CCW till switch is open
    stepperX.moveTo(initial_homing_stepperX);
    stepperX.run();
    initial_homing_stepperX--;
  }
  stepperX.setCurrentPosition(0);
  Serial.println("Homing arm X completed");
  stepperX.setMaxSpeed(5000.0);      // Max Speed of arm X (Alter for various patterns)
  stepperX.setAcceleration(1000.0);  // Set Acceleration of arm X (Higher number creates sharp corners)
  {
    delay(1000);//delay between X and Y homing.
  }
  Serial.println("Arm Y homing");

  while (digitalRead(home_switch_stepperY)) {  // Make the Stepper move CW till switch is interupted
    stepperY.moveTo(initial_homing_stepperY);  // Set the position to move to
    initial_homing_stepperY--;  // Decrease by 1 for next move if needed
    stepperY.run();  // Start moving the stepper
  }
  stepperY.setCurrentPosition(0);  // Set the current position to zero
  stepperY.setMaxSpeed(200.0);      // Set Max Speed of Stepper (Homing speed)
  stepperY.setAcceleration(500.0);  // Set Acceleration of StepperY
  initial_homing_stepperY = 1;

  while (!digitalRead(home_switch_stepperY)) { // Make the Stepper move CCW till switch is open
    stepperY.moveTo(initial_homing_stepperY);
    stepperY.run();
    initial_homing_stepperY++;
  }
  stepperY.setCurrentPosition(0);
  Serial.println("Homing arm Y Completed");
  stepperY.setMaxSpeed(3000.0);      // Max Speed of arm Y (Alter for various patterns)
  stepperY.setAcceleration(1000.0);  // Set Acceleration of arm Y (Higher number creates sharp corners)
  {
    delay(2000);//delay between homing and motion routine
  }
}
void loop() {

  if (stepperX.distanceToGo() == 0)
    pos1 = -pos1;
  stepperX.moveTo(pos1);

  if (stepperY.distanceToGo() == 0)
    pos2 = -pos2;
  stepperY.moveTo(pos2);

  stepperX.run();
  stepperY.run();
  Serial.println("loop");
}


Tom... you got me thinking about my switches.
Although they seemed to work ok, after reading this site, I figured I'd better double check them.
I was possibly not getting a clean signal from the switch.
I simply soldered a 10kΩ resistor between the signal and 5v wires.
Checking with a DMM shows a definite clean voltage shift.


OZYMAX

#10
Jul 05, 2019, 03:09 am Last Edit: Jul 05, 2019, 03:12 am by OZYMAX
Now I have the robot running, I've been playing around with some patterns and getting my lighting ring dialed in.
The height of the lights makes a huge difference to the visual effect of the pattern.
Here's a couple of pics so far.





So by varying some of the settings within the sketch, I can vary the pattern.
So this leads me to my next question.
I have an LCD and keypad for the Arduino.



Would it be possible to set this table up in a similar way to a jukebox, where you punch in a number on the keypad and the Arduino would execute a different pattern without having to upload a new sketch?
I'm assuming I'd need to add something like an SD card to house the patterns etc.
This is just an idea that I'd like to explore later down the track.
Thanks for any input. :)



Paul_KD7HB

Your use of the keypad is very doable! Many examples of code. May I suggest you identify one of the non-number keys as the "enter" key and another one as "reset" key.

The entering of number of more than 1 digit can be done by initially zeroing the accumulator. Then as each number is entered, multiply the accumulator by 10 and add the new number. This will avoid all the screwing around with strings, etc.

Paul

OZYMAX

Thanks Paul.
That at least gives me the encouragement to take it that bit further.

Go Up