We are going to make a robot leq using an Arduino and 2 micro stepper motors. We will be connecting the two motors together using cool robot attachments.

Schematic

Arduino Code

// Aug 21 2021
// mini servo motor driver
//
//
// This program controls two servo motors 
// Each servo motor has 180 degrees of motion
// The pushbuttons move the motor CW or CCW
//
//
//
// Servo Mtr Wiring
//
//
// Servo Mtr 1
//
// brwn --- GND
// red (middle) -- 3.3V
// org -- pin 6 (PWM)
//
//
// Servo Mtr 2
//
// brwn --- GND
// red (middle) -- 3.3V
// org -- pin 3 (PWM)
//
//
// controller wiring
// 
// Mtr         1            2
// pin      13   12       8     7
//          pb1  pb2     pb3   pb4
// motion   cw   ccw     cw    ccw
//




// This code is for an optional LED Display
//
//
// I2C 128X64 Micro OLED 4-Wire Yellow and Blue Display
// ****************************************************
// **************************************************** 
// WIRING:
// Arduino Pins                                    Micro Oled Pins
//           A4 ---------------------------------- SCL
//           A5 ---------------------------------- SDA
//           3.3V (NOT 5V!!!) -------------------- VCC    (if you use 5V, Then you will get more PUL readings than you should. This is probably because impedence mismatch or too much current draw from the Arduino)
//           GND --------------------------------- GND
//
//
// The first top 16 Pixel rows are yellow (x,y) (x,0) to (x,15)
// The next 48 Pixel rows are blue        (x,y) (x,16) to (x,63)



// INCLUDE LIBRARIES
// *****************
#include <avr/interrupt.h>
#include <SPI.h>
#include <Wire.h>



#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// The first top 16 Pixel rows are yellow (x,y) (x,0) to (x,15)
// The next 48 Pixel rows are blue        (x,y) (x,16) to (x,63)

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)





// VARIABLE DEFINITIONS
// ********************

int pin_12_13_enabled = 0;
int pin_7_8_enabled = 0;

// initially these values shoud be at a non load-bearing state
int pin_12_13_last_OCR1B = 2000;
int pin_7_8_last_OCR1B = 2000;

// VOLATILE
// used to allow instant changes in ISR

volatile int a = 0;
volatile int b = 0;
volatile int c = 0;

volatile unsigned long CNTR = 0;
unsigned long prior_CNTR = 0;
unsigned long new_CNTR = 0;


volatile int PUL = 0; //PUL from Mach 3
volatile bool DIR = true; //DIR from Mach 3 , Mach 3 sends a high or low voltalge signal to indicate direction , volatile is used to allow instant changes in ISR 

volatile unsigned long CNT = 0; //CNT number of pulses counted from MACH III, volatile is used to allow instant changes in ISR
volatile unsigned long new_CNT = 0;
volatile unsigned long prior_CNT = 0;

volatile bool HA = false; //HA hall a from SERVO II
volatile bool HB = false; //HB hall b from SERVO II
volatile bool HI = false; //HI hall i from SERVO II
 







// START void setup() 
// ******************************************************************************************************************************************
void setup()
{
//DDRD = B00000000; //  set pin 3,5,6 as OUTPUTS

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally

//DDRD = B00000000; //  set pin 3,5,6 as OUTPUTS

//CLEAR THE ADAFRUIT LOGO



// Pin 7 
pinMode(7, INPUT);           // set pin A0 to input
digitalWrite(7, HIGH);       // turn on pullup resistors on pin A0

// Pin 8 
pinMode(8, INPUT);           // set pin A0 to input
digitalWrite(8, HIGH);       // turn on pullup resistors on pin A0

// Pin 12
pinMode(12, INPUT);           // set pin 12 to input for OCR1B--
digitalWrite(12, HIGH);       // turn on pullup resistors on pin 12

// Pin 13
pinMode(13, INPUT);           // set pin 13 to input for OCR1B++
digitalWrite(13, HIGH);       // turn on pullup resistors on pin 13



// DIR from Mach 3 --> ARDUINO
// HA, HB from SERVO II Motor
// this is for PCINT0-PCINT23
// **************************
cli(); // stop interrupts
//PCICR |= 0b00000111; // Enable Ports B, C, and D pin change interrupts
//PCICR |= 0b00000001; // Enable Ports B pin change interrupts
PCICR |= (1<<PCIE0);//enable group interrupts on PORTB PCINT[7:0]
//PCMSK0 |= 0b00000010; // DIR -> PCINT4 -> printed_pin_12
//PCMSK0 |= (1<<PCINT4);// DIR -> PCINT4 -> printed_pin_12
//PCMSK0 |= (1 << PCINT4);  //Set PCINT0 (digital input 12) to trigger an interrupt on state change.
PCMSK0 |= (1<<PCINT4);//enable interrupt pin 12
//PCMSK1 |= 0b00000001; // HA ->  PCINT13 -> printed_pin_A0
//PCMSK2 |= 0b10000000; // HB ->  PCINT16 -> printed_pin_0
sei(); // start interrupts



// PUL from MachIII --> UC100-pin3 --> ARDUINO-pin2
// this is for INT0 = printed_pin_2
// UC100 pin is 3 the Arduino pin is 2
// ********************************
 attachInterrupt (digitalPinToInterrupt (2), pulse, FALLING);  // attach interrupt handler
// Serial.begin(9600);
 

// ARDUINO(pins3,5,6)5vOUTPUT --> MOSFETs(A,B,C)GATES --> SERVOII_Motor_Coils(A,B,C) 
// *********************************************************************************
// The arduino will send 5V to the MOSFET gates by changing the DDRD ports 3,5,6 from 0 to 1


// PWM Duty Cycle
// **************
// 20 - 255 :  10% - 100%
// OC0A is pin 6 is PhA
// OC0B is pin 5 is PhB
// OC2B is pin 3 is PhC
// 100 good for x & y axis using 24 v ,130-140 good for z axis using 24v, 
// 40 is good for z axis using 120v about 5 bumps per inch of travel
// 20 is better at 240volts 2 bumps per inch of travel
// note 3/31/2021: z axis has jumpy spots even using 120 volts. the wheel 
// feels looser after lostening nuts on saddle that gous up and down and adding lube. 
// I will probably mess with the OCRB stuffs
OCR0A = 255;  
OCR0B = 255;  
OCR2B = 255;  

// Timer/Counter0
// *************
// pin5 & pin6
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00); // Set bit to 1 at these locations
// set to clkio/64 to give 976.56Hz
//TCCR0B &= ~(1 << CS02); // set bit to 0
//TCCR0B |= (1 << CS01); // set bit to 1
//TCCR0B |= (1 << CS00); // set bit to 1

// set to clkio/1024 to give ???hz
TCCR0B |= (1 << CS02); // set bit to 1
TCCR0B &= ~(1 << CS01); // set bit to 0
TCCR0B &= ~(1 << CS00); // set bit to 0

// Timer/Counter2
// *****************
// pin3 & pin11
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); // Set bit to 1 where specified
// set to clkio/64 to give 980.39Hz
//TCCR2B |= (1 << CS22); // set bit to 1
//TCCR2B &= ~(1 << CS21); // set bit to 0
//TCCR2B &= ~(1 << CS20); // set bit to 0


// set to clkio/1024 to give ??HZ 
TCCR2B |= (1 << CS22); // set bit to 1
TCCR2B |= (1 << CS21); // set bit to 1
TCCR2B &= ~(1 << CS20); // set bit to 0

// ALIGN MOTORS TO PHASE A
// ***********************
// phase A of Servo II corresponds to Arduino Digital Pin #6
/*
  DDRD |= (1 << DDD3); //////////////////////////////////////////////////6 on
  a = 1;
  b = 1;
  delay(50);
  DDRD &= ~(1 << DDD3); //////////////////////////////////////////////////6 off
  delay(100);
  
  DDRD |= (1 << DDD3); //////////////////////////////////////////////////6 on
  a = 1;
  b = 1;
  delay(50);
  DDRD &= ~(1 << DDD3); //////////////////////////////////////////////////6 off
  delay(100);

  DDRD |= (1 << DDD3); //////////////////////////////////////////////////6 on
  a = 1;
  b = 1;
  delay(50);
  DDRD &= ~(1 << DDD3); //////////////////////////////////////////////////6 off
  delay(100);
  /*
  DDRD |= (1 << DDD5); ///////////////////////////////////////////////// 5 on
  a = 1;
  b = 1;
  delay(100);
  DDRD &= ~(1 << DDD5); ///////////////////////////////////////////////// 5 off
  delay(100);
  DDRD |= (1 << DDD3); ///////////////////////////////////////////////// 3 on
  a = 1;
  b = 1;
  delay(100);
  DDRD &= ~(1 << DDD3); ///////////////////////////////////////////////// 3 off
*/

cli(); // stop interrupts

// Timer/Counter1
// *************
// This timer is in charge of triggering the SERVO II motor phase A, B, and C on and off
//set timer1 interrupt
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  // OCR1A must be < 65536 
  // t_on = OCR1B
  // t_off = OCR1A - OCR1B
  //OCR1A = 7875;  // TEST ZONE works good on X-axis 
  OCR1A = 40000;  // value of 30,  z-axis -- as of Mar-2-2021 WORKS AWESOME on Z-axis:  1680 steps per inch, 1.5 in per min using 120 volts, 100 accel, 
 // ocr1a();
    
  // set compare match register for 1hz increments
  // OCR1B must be < 65536 
  // t_on = OCR1B
  // t_off = OCR1A - OCR1B
  // OCR1B = 6250;  // TEST ZONE
  OCR1B = 4000;  // 700 to 5200 for MG90S
  //ocr1b(); 
  
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 bit for 8 prescaler
  TCCR1B &= ~(1 << CS12) ; // set to 0
  TCCR1B |= (1 << CS11) ; // set to 1
  TCCR1B &= ~(1 << CS10) ; // set to 0
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A); // OCR1A
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1B); // OCR1B

sei(); // start interrupts

}
// ***********************************************************************************************************************************************************
// END void setup()






// PCINT0
//  ISR ISR ISR ISR ISR ISR ISR ISR ISR
// (ISR) Interrupt Service Routine (ISR)
//  DIR -> printed_pin_12 
//  ************************************
//Serial.println("Inside ISR(PCINT0_vect)");
//DIR -> printed_pin_12 
//+DIR -> printed_pin_12 is HIGH --> boolean true
//-DIR -> printed_pin_12 is LOW  --> boolean false
//int DIR = true default value at start-up
//int new_DIR = 0; default value at start-up
//int prior_DIR = 0; default value at start-up
// the pin on UC100 is 2 and the pin on Arduino is 12
ISR(PCINT0_vect)
{
 // DIR = !DIR;
 // if(PINB & (1 << 4))   // if pin 12 -> DIR is 5V
 // Serial.println(DIR);
} 


// PCINT1
//  ISR ISR ISR ISR ISR ISR ISR ISR ISR
// (ISR) Interrupt Service Routine (ISR)
//  HA -> printed_pin_A0
// *************************************
//ISR(PCINT1_vect)
//{
// HA -> printed_pin_A0
//} 


//  ISR ISR ISR ISR ISR ISR ISR ISR ISR
// (ISR) Interrupt Service Routine (ISR)
//  HB -> printed_pin_A0
// *************************************
//ISR(PCINT2_vect)
//{
// HB
//} 


//  ISR ISR ISR ISR ISR ISR ISR ISR ISR
// (ISR) Interrupt Service Routine (ISR)
// *************************************
//pulse_counter ++; inside voide pulse()
void pulse()
{
  CNTR++;
  CNT++;
} 


// FUNCTION
// ********
void read_write_inputs()
{
  // MACH 3 STEP PULSES sent to SERIAL MONITOR
  new_CNT = CNT;
  if (new_CNT != prior_CNT) 
  {
       
    //Serial.println("Inside void read_write_inputs()") 
    //Serial.print("CNT: ");
    //Serial.println(new_CNT);
    prior_CNT = new_CNT;
    //delay(10); // print at reasonable speed
  }
  
  // MACH 3 DIR sent to SERIAL MONITOR
  if(PINB & (1 << 4))   // if pin12/DIR is 5V
  {
   DIR = 1;
  }
  else
  {
   DIR = 0;
  }

  
}













// 
// -------------------------------
void ocr1a(void) 
{
    OCR1A = 40000;
}


// 
// -------------------------------
void ocr1b(void) 
{
//700 - 5200
    OCR1B = 2000 ;
}







//  TIMER 1 COMPA OCR1A
// (ISR) Interrupt Service Routine (ISR)
//  ************************************
ISR(TIMER1_COMPA_vect)
{
  if(pin_12_13_enabled == 1)
  {
  DDRD |= (1 << DDD6);  ///////////////////////////////////////////////// 6 on
  }

  else if(pin_7_8_enabled == 1)
  {
  DDRD |= (1 << DDD3);  ///////////////////////////////////////////////// 3 on
  }
}
// END ISR(Timer1_COMPB_vect)


//  TIMER 1 COMPB OCR1B
// (ISR) Interrupt Service Routine (ISR)
//  ************************************
ISR(TIMER1_COMPB_vect)
{
  if(pin_12_13_enabled == 1)
  {
  DDRD &= ~(1 << DDD6);  ///////////////////////////////////////////////// 6 off
  }
  
  else if(pin_7_8_enabled == 1)
  {
  DDRD &= ~(1 << DDD3);  ///////////////////////////////////////////////// 3 off 
  }
  
}
// END ISR(Timer1_COMPA_vect)




// MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP
// ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* *********
void loop()
{
//read_write_inputs();       // Arduino to Serial Monitor
//display_HMI_text();        // Arduino to HMI

// Check the state of input pin 12 from the push button

if (!digitalRead(12))
{

OCR1B = pin_12_13_last_OCR1B;

pin_12_13_enabled = 1;
pin_7_8_enabled = 0;
 

  if (OCR1B > 700)
  {
    delay(10);
    OCR1B = OCR1B - 25;
    pin_12_13_last_OCR1B = OCR1B;
  }
}


// Check the state of input pin 13 from the push button
else if (!digitalRead(13))
{
  
OCR1B = pin_12_13_last_OCR1B;

pin_12_13_enabled = 1;
pin_7_8_enabled = 0;
  
  if (OCR1B < 4500)
  {
    delay(10);
    OCR1B = OCR1B + 25;
    pin_12_13_last_OCR1B = OCR1B;
  }
}




else if (!digitalRead(7))
{

OCR1B = pin_7_8_last_OCR1B;

pin_7_8_enabled = 1;
pin_12_13_enabled = 0; 


  if (OCR1B >= 700)
  {
    delay(10);
    OCR1B = OCR1B - 25;
    pin_7_8_last_OCR1B = OCR1B;
  }
}


// Check the state of input pin 8 from the push button
else if (!digitalRead(8))
{

OCR1B = pin_7_8_last_OCR1B;

pin_7_8_enabled = 1;
pin_12_13_enabled = 0;

  if (OCR1B <= 5200)
  {
    delay(10);
    OCR1B = OCR1B + 25;
    pin_7_8_last_OCR1B = OCR1B;
  }
}






//  new_CNTR = CNTR;
//  if (new_CNTR != prior_CNTR) 
//  {
//    Serial.println(new_CNTR);
//    prior_CNTR = new_CNTR;
//    delay(10); // print at reasonable speed
//  }


}
// MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP MAIN LOOP
// ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* *********