Code port and assistace please

Hello,

Some years ago I made a basic AVR program for a friend for his brake-press in his workshop.
It is written in Basic using Bascom AVR, and we would like to convert it to use the Arduino IDE and also make a modification.

The AVR is a 644P on a custom veraboard circuitboard, which takes a quadrature input from an encoder, and has a couple of inputs, and outputs pulses which drives 2 stepper motor drivers.

The purpose of the project is to adjust the stops of the brake press, so when the hydraulic press is lowered, it lowers to the stop - rather than adjusting the hydraulics to lower to a level.
It is very accurate and my mate is very happy with it, and it has been running for a few years.

The encoder is attached to a hand wheel crank, and from memory is a 250 pulses per revolution encoder, quadrature output.
The output pulses drive 2 stepper motor drivers, which drive 2 stepper motors and move the stop.

There are inputs to select the ratio, ie 1:1, 1:5 or 1:10, so 1 input pulse makes 1 output pulse, or 5 input pulses makes 1 output pulse, or 10 input pulses makes 1 output pulse.
What he is wanting is instead of a reduction, he wants an option for multiplication. So 1 input pulse makes 5 output pulses for example. He said its currently a bit slow and takes a while to move the stop, and would ideally like a faster ratio.

I cant see how to do this though, other than telling him to get hold of a higher pulse count encoder. Getting it to output more pulses than it is receiving, before it gets the next input pulse...

Does anyone have any ideas?

Also is someone able to help port this code. There is nothing complex about it however I am not fully up to the play with the Arduino language yet, that is this weekends mission. It currently runs on 8mhz, but I have a 16mhz crystal on there already but we didnt end up using it for some reason, so its just using the internal oscillator at the moment.
Mainly though I am wanting assistance to ideas for changing the ratio.

Kind Regards
J

Bascom AVR Code to follow (appoligies if its written poorly):

'==============================================================================
' Project:  Quadrature input with pulse + direction ouput
' By: JADB
' Description:
'   It is controlled by an Atmel ATmega644P 8bit micro controller.
'   Quadrature input with pulse + direction ouput, with limit switch cut off
'   and limit switch outputs for LED's or PIZO. Pulse output scalable from 1:1,
'   1:5 or 1:10 based on selector switch position.
'==============================================================================


'=====[ Compiler Directives ]==================================================
$crystal = 8000000                                          ' set via fuse bits to internal RC at 8megs
$regfile = "m644Pdef.dat"
$hwstack = 256
$swstack = 256
$framesize = 256
'------------------------------------------------------------------------------

'=====[ Global Vars ]==========================================================
Dim Lastdirection As Bit                                    ' Stores last direction, 0 or 1.
Dim Countvalue As Integer                                   ' Stores the number of pulses
Dim Q_newvalue(2) As Byte                                   ' Used in Quadrature ISR
Dim Q_oldvalue(2) As Byte                                   ' Used in Quadrature ISR
Dim Q_direction(2) As Byte                                  ' Used in Quadrature ISR

'=====[ Set IO Pins ]==========================================================
''' set data direction registors for io pins
Ddra = &B00000000
'0 & 1 & 2 Limit inputs, bits 6 & 7 are for quadrature input ticks

Ddrb = &B00000000
      ' bits 0 to 7 not used

Ddrc = &B11111111
      ' bits 0 output for direction, bit 1 output for pulses, bits 2 & 3 & 4 Limit Indicator Ouputs

Ddrd = &B00000000
      ' bits 3,5,7 used for Selector Switch,

Switch1_input Alias Pind.3
Switch2_input Alias Pind.5
Switch3_input Alias Pind.7
Direction_output Alias Portc.0
Pulse_output Alias Portc.1
Limit1_output Alias Portc.2
Limit2_output Alias Portc.3
Limit3_output Alias Portc.4
Quada_input Alias Pina.6
Quadb_input Alias Pina.7
Limit1_input Alias Pina.0
Limit2_input Alias Pina.1
Limit3_input Alias Pina.2

'------------------------------------------------------------------------------

'=====[ Enable Pin change interrupt ]==========================================
' The Pin Change Interupts are used for the quadrature imputs.
Pcmsk0 = &B11000000                                         ' Set mask for pcint0 (PortA.6&7)
Pcicr.0 = 1                                                 ' Enable Pcint0 (Pin Change Interrupt)
On Pcint0 Quad_count_isr                                    ' Set interrupt vector for PCINT0

Pcmsk3 = &B10101000                                         ' Set mask for pcint3 (PortD.3&5&7)
Pcicr.3 = 1                                                 ' Enable Pcint3 (Pin Change Interrupt)
On Pcint3 Switch_change_isr                                 ' Set interrupt vector for PCINT3

On Compare1a Output_pulse_isr                               ' Set interrupt vector for Timer1 Compare1a
'------------------------------------------------------------------------------

'=====[ Config misc stuff ]====================================================

Config Timer1 = Timer , Prescale = 1                        'Clear Timer = 1
Stop Timer1
Timer1 = 0
Compare1a = 32                                              '16 = 250kHz, ie 4uS pulse
Enable Timer1
Enable Compare1a
Enable Interrupts

Countvalue = 0
'------------------------------------------------------------------------------

'******************************************************************************
'*****[ Start of main loop ]***************************************************
'******************************************************************************
Do
   'Checks which selector switch is on and if the counter has reached the SP
   If Switch3_input = 0 And Countvalue >= 40 Then
      Countvalue = 0
      Set Pulse_output
      Timer1 = 0
      Start Timer1
   Elseif Switch2_input = 0 And Countvalue >= 20 Then
      Countvalue = 0
      Set Pulse_output
      Timer1 = 0
      Start Timer1
   Elseif Switch1_input = 0 And Countvalue >= 4 Then
      Countvalue = 0
      Set Pulse_output
      Timer1 = 0
      Start Timer1
   End If

   If Limit1_input = 1 Then
      Limit1_output = 0
   Else
      Limit1_output = 1
   End If

   If Limit2_input = 1 Then
      Limit2_output = 0
   Else
      Limit2_output = 1
   End If

   If Limit3_input = 1 Then
      Limit3_output = 0
   Else
      Limit3_output = 1
   End If
Loop
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

'=====[ Quadrature ISR routine ]============================================
Quad_count_isr:
  Q_newvalue(2) = Pina                                      'copies value of entire port D
  Q_direction(2) = Q_oldvalue(2).6 Xor Q_newvalue(2).7      'XOR to get direction of Bits 6 and 7
  If Q_direction(2) = 1 Then
    Set Direction_output
    If Lastdirection = 0 Then                               'Handles if the direction is changed, starts conting again
      Countvalue = 0                                        'Write countvalue to 0
    Else
      If Limit1_input = 1 And Limit2_input = 1 Then         'Ensures it wont move further if a limit is made
         Countvalue = Countvalue + 1                        'increase the count of countvalue
      Else
         Countvalue = 0                                     'stops the counting as the limit has been made
      End If
    End If
    Lastdirection = 1                                       'sets this as the last direction
  Else
    Reset Direction_output
    If Lastdirection = 1 Then                               'Handles if the direction is changed, starts conting again
      Countvalue = 0                                        'write countvalue to 0
    Else
      If Limit3_input = 1 Then                              'Ensures it wont move further if a limit is made
         Countvalue = Countvalue + 1                        'increase the count of countvalue
      Else
         Countvalue = 0                                     'stops the counting as the limit has been made
      End If
    End If
    Lastdirection = 0                                       'sets this as the last direction
  End If
  Q_oldvalue(2) = Q_newvalue(2)
Return
'------------------------------------------------------------------------------

'=====[ Switch Change ISR Routine ]============================================
Switch_change_isr:
   Countvalue = 0
   Lastdirection = 0
   Reset Direction_output
   Reset Pulse_output
Return
'------------------------------------------------------------------------------

'=====[ Output Pulse period setter ]===========================================
Output_pulse_isr:
   Reset Pulse_output
   Stop Timer1
   Timer1 = 0
   Compare1a = 32
Return

'------------------------------------------------------------------------------
End

I cant see how to do this though, other than telling him to get hold of a higher pulse count encoder. Getting it to output more pulses than it is receiving, before it gets the next input pulse...

I think the confusion comes from your use of the single word pulse to mean two different things.

An encoder is basically a switch. It allows current to flow, for a brief period of time, every time the switch the switch is closed. That is a pulse.

The microcontroller that is reading the pulses does something every time it sees a pulse (1:1), every 5th time (1:5), or every tenth time (1:10). (Technically, it does something every time it sees a pulse - it counts it - but only performs some useful action after some number of counts.)

You are also using the term pulse to refer to this "something" that the microcontroller does. The microcontroller can just as easily do something 5 times for every pulse it receives, or 10 times, or 100 times.

The tricky part will be spacing the "something"s evenly between the pulses. It's easy to do if the pulses are uniformly spaced. It's a lot more complicated if the pulses are not uniformly spaced.

If it doesn't matter that the "something"s are uniformly spaced (step a motor 5 times, instead of 1), then it is not a problem.

Thanks PaulS,

Yes I am aware of what I said, but I didnt think generalising to explain the project in a few lines would hurt.

Ideally the output pulses would be spaced uniformly, however this would be impossible to do as they are based on how fast the input wheel attached to the encoder is turned.

I may just have to experiment and try 2:1, so pulse sequence of the quadrature encoder makes 2 output pulses, and space them a set duation apart.

Regards
J

What are the "output pulses" driving? Generating an output pulse at fixed intervals will be tricky, because all the output pulses need to be sent before the next input pulse, and you have no control over when that will occur.

however this would be impossible to do as they are based on how fast the input wheel attached to the encoder is turned.

You can base your 5 (10 whatever) pulses on the last cycle, so as long as the rate of change from the wheel isn't too great that should work, in fact it should be perfect, just delayed by one input pulse time.


Rob

PaulS - mentioned above but some more detail, the output pulse train is driving two stepper motor controllers and thus two stepper motors, which control the positioning of the stop with a worm gear. So the press will lower to the position of the stop, and ... well... stop.

Graynomad - now that is using your noodle! That is a very good idea. I will put some thought into this.
I suppose I just need to capture the time (uS) between input pulses (well pair of pulses as its quadrature) prior, and use that to set the duration of the output pulses to follow.
I will have a play.

Thanks very much

J

Hi again

I have started porting the code, however I am stuck with the timers and pin change interrupts.
I thought it was going to be semi straight forward to set them up, but I have found that they are not supported but the IDE like the normal interrupts are? Or am I mistaken?
Can someone assist?

This is what I have so far, with the commented bits I am unsure about.
I dont know how to read an entire port at either.

If someone can spare the time, I would really appreciate it. This is just the porting process, I will attempt to nut out the additional code to change the ratio etc. Just trying to get what I already have, into the Arduino IDE for now.

//==============================================================================
// Project:  Quadrature input with pulse + direction ouput
// By: JADB
// Description:
//   It is controlled by an Atmel ATmega644P 8bit micro controller.
//   Quadrature input with pulse + direction ouput, with limit switch cut off
//   and limit switch outputs for LED's or PIZO. Pulse output scalable from 1:1,
//   1:5 or 1:10 based on selector switch position.
//==============================================================================

//=====[ Global Vars ]==========================================================
boolean Lastdirection                                // Stores last direction, 0 or 1.
int Countvalue                                       // Stores the number of pulses
volatile byte Q_newvalue(2)                                   // Used in Quadrature ISR
volatile byte Q_oldvalue(2)                                   // Used in Quadrature ISR
volatile byte Q_direction(2)                                  // Used in Quadrature ISR

void setup()
{
  //=====[ Set IO Pins ]==========================================================
  //set data direction registors for io pins
  Switch1_input = 11; //Pind.3
  Switch2_input = 13; //Pind.5
  Switch3_input = 15; //Pind.7
  Direction_output = 16; //Portc.0
  Pulse_output = 17; //Portc.1
  Limit1_output = 18; //Portc.2
  Limit2_output = 19; //Portc.3
  Limit3_output = 20; //Portc.4
  Quada_input = 25; //Pina.6
  Quadb_input = 24; //Pina.7
  Limit1_input = 31; //Pina.0
  Limit2_input = 30; //Pina.1
  Limit3_input = 20; //Pina.2
  
  pinMode(Switch1_input, INPUT);
  pinMode(Switch2_input, INPUT);
  pinMode(Switch3_input, INPUT);
  pinMode(Direction_output, OUTPUT);
  pinMode(Pulse_output, OUTPUT);
  pinMode(Limit1_output, OUTPUT);
  pinMode(Limit2_output, OUTPUT);
  pinMode(Limit3_output, OUTPUT);
  pinMode(Quada_input, INPUT);
  pinMode(Quadb_input, INPUT);
  pinMode(Limit1_input, INPUT);
  pinMode(Limit2_input, INPUT);
  pinMode(Limit3_input, INPUT);
  
  //------------------------------------------------------------------------------
  
  //=====[ Enable Pin change interrupt ]==========================================
  // The Pin Change Interupts are used for the quadrature imputs.
  //Pcmsk0 = &B11000000                                         ' Set mask for pcint0 (PortA.6&7)
  //Pcicr.0 = 1                                                 ' Enable Pcint0 (Pin Change Interrupt)
  //On Pcint0 Quad_count_isr                                    ' Set interrupt vector for PCINT0
  
  //Pcmsk3 = &B10101000                                         ' Set mask for pcint3 (PortD.3&5&7)
  //Pcicr.3 = 1                                                 ' Enable Pcint3 (Pin Change Interrupt)
  //On Pcint3 Switch_change_isr                                 ' Set interrupt vector for PCINT3
  
  //On Compare1a Output_pulse_isr                               ' Set interrupt vector for Timer1 Compare1a
  //------------------------------------------------------------------------------
  
  //=====[ Config misc stuff ]====================================================
  
  //Config Timer1 = Timer , Prescale = 1                        'Clear Timer = 1
  //Stop Timer1
  //Timer1 = 0
  //Compare1a = 32                                              '16 = 250kHz, ie 4uS pulse
  //Enable Timer1
  //Enable Compare1a
  //Enable Interrupts
  Countvalue = 0;
  //------------------------------------------------------------------------------ 
}

//******************************************************************************
//*****[ Start of main loop ]***************************************************
//******************************************************************************
void loop()
{
   //Checks which selector switch is on and if the counter has reached the SP
   if (Switch3_input == 0 && Countvalue >= 40)
   {
      Countvalue = 0;
      Pulse_output = 1;
      Timer1 = 0;
      //Start Timer1
   }
   else if (Switch2_input == 0 && Countvalue >= 20)
   {
      Countvalue = 0;
      Pulse_output = 1;
      Timer1 = 0;
      //Start Timer1
   }
   else if (Switch1_input == 0 && Countvalue >= 4)
   {
      Countvalue = 0;
      Pulse_output = 1;
      Timer1 = 0;
      //Start Timer1
   }

   if (Limit1_input == 1)
   {
      Limit1_output = 0;
   }
   else
   {
      Limit1_output = 1;
   }

   if (Limit2_input = 1)
   {
      Limit2_output = 0;
   }
   else
   {
      Limit2_output = 1;
   }

   if (Limit3_input == 1)
   {
      Limit3_output = 0;
   }
   else
   {
      Limit3_output = 1;
   }
}
//------------------------------------------------------------------------------

//=====[ Quadrature ISR routine ]============================================
void Quad_count_isr()
{
/*  Q_newvalue(2) = Pina;                                     //copies value of entire port A
  Q_direction(2) = Q_oldvalue(2).6 Xor Q_newvalue(2).7      //XOR to get direction of Bits 6 and 7
  If Q_direction(2) = 1 Then
    Set Direction_output
    If Lastdirection = 0 Then                               //Handles if the direction is changed, starts conting again
      Countvalue = 0                                        //Write countvalue to 0
    Else
      If Limit1_input = 1 And Limit2_input = 1 Then         //Ensures it wont move further if a limit is made
         Countvalue = Countvalue + 1                        //increase the count of countvalue
      Else
         Countvalue = 0                                     //stops the counting as the limit has been made
      End If
    End If
    Lastdirection = 1                                       //sets this as the last direction
  Else
    Reset Direction_output
    If Lastdirection = 1 Then                               //Handles if the direction is changed, starts conting again
      Countvalue = 0                                        //write countvalue to 0
    Else
      If Limit3_input = 1 Then                              //Ensures it wont move further if a limit is made
         Countvalue = Countvalue + 1                        //increase the count of countvalue
      Else
         Countvalue = 0                                     //stops the counting as the limit has been made
      End If
    End If
    Lastdirection = 0                                       //sets this as the last direction
  End If
  Q_oldvalue(2) = Q_newvalue(2)*/
}
//------------------------------------------------------------------------------

//=====[ Switch Change ISR Routine ]============================================
void Switch_change_isr()
{
   Countvalue = 0;
   Lastdirection = 0;
   Direction_output = 0;
   Pulse_output = 0;
}
'------------------------------------------------------------------------------

//=====[ Output Pulse period setter ]===========================================
void Output_pulse_isr()
{
   Pulse_output = 0;
   //Stop Timer1
   //Timer1 = 0;
   //Compare1a = 32
}

Question...

Is this achieving the same thing? It appears to be alot easier to set up timers in Bascom AVR, so struggling a bit here.

  //Config Timer1 = Timer , Prescale = 1                        'Clear Timer = 1
  //Stop Timer1
  //Timer1 = 0
  //Compare1a = 32                                              '16 = 250kHz, ie 4uS pulse
  //Enable Timer1
  //Enable Compare1a
  //Enable Interrupts

As

TCCR1A = 0; // Reset control registers
  TCCR1B = 0; // Reset control registers
  TCCR1B |= (1 << WGM12); // Clear Timer on Compare Match (CTC) Mode
  TCCR1B |= (1 << CS10); // Prescaler x1
  OCR1A = 32; // Set compared value
  TIMSK1 = 0; // Reset Timer/Counter2 Interrupt Mask Register
  TIMSK1 |= (1 << OCIE1A); // Enable Output Compare Match A Interrupt 
  TCNT1 = 0; // Clear Timer 1
  sei(); // Enable Interrupts

I stole bits of code from other peoples posts.

And then the ISR would be this?

ISR(TIMER1_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
  Pulse_output = 0;
  //Stop Timer1 - Unsure how to do this
  TCNT1 = 0; //Clear Timer 1
  OCR1A = 32; // Set compared value
}

Can someone tell me if I have done this correctly?
I want Timer1 to have a prescale of 1, and run when triggered until OCR1A (Compare1a value) which I have at 32, and then disable the timer.
I dont understand yet how to enable and disable the timer.

Thanks
J

Oh...

Does this start the timer:
TIMSK1 |= (1 << OCIE1A);

And this stops the timer:
TIMSK1 &= ~(1<<OCIE1A);

Is that correct?
Is that the only method to do this?
Again, I stole this from another post...

I think I am getting there.
I still am not sure how to configure the Pin Change Interrupts however.
Does what I have so far look ok?
Lots of mistakes in my last few posts, I never tried to compile until now.

Please assist if you can, I am not having any luck with the pin change interrupts.
I did find an example, however not for the 644P - which is kind of to be expected - however I do not understand it.
Here is the playground link I came across: Arduino Playground - PinChangeInt

//==============================================================================

//=====[ Global Vars ]==========================================================
boolean Lastdirection;                                         // Stores last direction, 0 or 1.
int Countvalue;                                                // Stores the number of pulses
volatile byte Q_newvalue;                                      // Used in Quadrature ISR
volatile byte Q_oldvalue;                                      // Used in Quadrature ISR
volatile byte Q_direction;                                     // Used in Quadrature ISR

//Define the variables used to represent the inputs/outputs
boolean Switch1_input;
boolean Switch2_input;
boolean Switch3_input;
boolean Direction_output;
boolean Pulse_output;
boolean Limit1_output;
boolean Limit2_output;
boolean Limit3_output;
boolean Quada_input;
boolean Quadb_input;
boolean Limit1_input;
boolean Limit2_input;
boolean Limit3_input;

//Define the pins used for each of the inputs/outputs
int Switch1_input_pin = 11; //Pind.3
int Switch2_input_pin = 13; //Pind.5
int Switch3_input_pin = 15; //Pind.7
int Direction_output_pin = 16; //Portc.0
int Pulse_output_pin = 17; //Portc.1
int Limit1_output_pin = 18; //Portc.2
int Limit2_output_pin = 19; //Portc.3
int Limit3_output_pin = 20; //Portc.4
int Quada_input_pin = 25; //Pina.6
int Quadb_input_pin = 24; //Pina.7
int Limit1_input_pin = 31; //Pina.0
int Limit2_input_pin = 30; //Pina.1
int Limit3_input_pin = 20; //Pina.2

void setup()
{
  //=====[ Set IO Pins ]==========================================================
  
  //Select the mode of each of the inputs/outputs
  pinMode(Switch1_input_pin, INPUT);
  pinMode(Switch2_input_pin, INPUT);
  pinMode(Switch3_input_pin, INPUT);
  pinMode(Direction_output_pin, OUTPUT);
  pinMode(Pulse_output_pin, OUTPUT);
  pinMode(Limit1_output_pin, OUTPUT);
  pinMode(Limit2_output_pin, OUTPUT);
  pinMode(Limit3_output_pin, OUTPUT);
  pinMode(Quada_input_pin, INPUT);
  pinMode(Quadb_input_pin, INPUT);
  pinMode(Limit1_input_pin, INPUT);
  pinMode(Limit2_input_pin, INPUT);
  pinMode(Limit3_input_pin, INPUT);  
  //------------------------------------------------------------------------------
  
  //=====[ Enable Pin change interrupt ]==========================================
  // The Pin Change Interupts are used for the quadrature imputs.
  //Pcmsk0 = &B11000000                                         ' Set mask for pcint0 (PortA.6&7)
  //Pcicr.0 = 1                                                 ' Enable Pcint0 (Pin Change Interrupt)
  //On Pcint0 Quad_count_isr                                    ' Set interrupt vector for PCINT0
  
  //Pcmsk3 = &B10101000                                         ' Set mask for pcint3 (PortD.3&5&7)
  //Pcicr.3 = 1                                                 ' Enable Pcint3 (Pin Change Interrupt)
  //On Pcint3 Switch_change_isr                                 ' Set interrupt vector for PCINT3  
  //------------------------------------------------------------------------------
  
  //=====[ Config misc stuff ]====================================================  
  cli(); // Disable Interrupts
  
  TCCR1A = 0; // Reset control registers
  TCCR1B = 0; // Reset control registers
  TCCR1B |= (1 << WGM12); // Clear Timer on Compare Match (CTC) Mode
  TCCR1B |= (1 << CS10); // Prescaler x1
  OCR1A = 32; // Set compared value
  TIMSK1 = 0; // Reset Timer/Counter2 Interrupt Mask Register
  
  sei(); // Enable Interrupts
  
  Countvalue = 0;  
  //------------------------------------------------------------------------------ 
}

//******************************************************************************
//*****[ Start of main loop ]***************************************************
//******************************************************************************
void loop()
{
   //Checks which selector switch is on and if the counter has reached the SP
   Switch1_input = digitalRead(Switch1_input_pin);
   Switch2_input = digitalRead(Switch2_input_pin);
   Switch3_input = digitalRead(Switch3_input_pin);
   if (Switch3_input == 0 && Countvalue >= 40)
   {
      Countvalue = 0;
      digitalWrite(Pulse_output, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }
   else if (Switch2_input == 0 && Countvalue >= 20)
   {
      Countvalue = 0;
      digitalWrite(Pulse_output, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }
   else if (Switch1_input == 0 && Countvalue >= 4)
   {
      Countvalue = 0;
      digitalWrite(Pulse_output, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }

   //Checks which limit switch is on/made 
   Limit1_input = digitalRead(Limit1_input_pin);
   Limit2_input = digitalRead(Limit2_input_pin);
   Limit3_input = digitalRead(Limit3_input_pin);   
   if (Limit1_input == 1)
      digitalWrite(Limit1_output, 0);
   else
      digitalWrite(Limit1_output, 1);
   
   if (Limit2_input == 1)
      digitalWrite(Limit2_output, 0);
   else
      digitalWrite(Limit2_output, 1);

   if (Limit3_input == 1)
      digitalWrite(Limit3_output, 0);
   else
      digitalWrite(Limit3_output, 1);
}
//------------------------------------------------------------------------------

//=====[ Quadrature ISR routine ]============================================
void Quad_count_isr()
{
  Q_newvalue = PINA;                                                     //copies value of entire port A
  Q_direction = bitRead(Q_oldvalue,6) ^ bitRead(Q_newvalue,7);     //XOR to get direction of Bits 6 and 7
  if (Q_direction == 1)
  {
    digitalWrite(Direction_output, 1);
    if (Lastdirection == 0)                                 //Handles if the direction is changed, starts conting again
    {
      Countvalue = 0;                                       //Write countvalue to 0
    }
    else
    {
      Limit1_input = digitalRead(Limit1_input_pin);
      Limit2_input = digitalRead(Limit2_input_pin);
      if (Limit1_input == 1 && Limit2_input == 1)           //Ensures it wont move further if a limit is made
      {
        Countvalue = Countvalue + 1;                       //increase the count of countvalue
      }
      else
      {
        Countvalue = 0;         //stops the counting as the limit has been made
      }
    }
    Lastdirection = 1;                                      //sets this as the last direction
  }
  else
  {
    digitalWrite(Direction_output, 0);
    if (Lastdirection == 1)                                 //Handles if the direction is changed, starts conting again
    {
      Countvalue = 0;                                       //write countvalue to 0
    }
    else
    {
      Limit3_input = digitalRead(Limit3_input_pin);
      if (Limit3_input == 1)                                //Ensures it wont move further if a limit is made
      {
        Countvalue = Countvalue + 1;                       //increase the count of countvalue
      }
      else
      {
        Countvalue = 0;                                    //stops the counting as the limit has been made
      }
    }
    Lastdirection = 0;                                      //sets this as the last direction
  }
  Q_oldvalue = Q_newvalue;
}
//------------------------------------------------------------------------------

//=====[ Switch Change ISR Routine ]============================================
void Switch_change_isr()
{
   Countvalue = 0;
   Lastdirection = 0;
   digitalWrite(Direction_output, 0);
   digitalWrite(Pulse_output, 0);
}
//------------------------------------------------------------------------------

//=====[ Output Pulse period setter ]===========================================
ISR(TIMER1_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
  digitalWrite(Pulse_output, 0);
  TIMSK1 &= ~(1<<OCIE1A); //Stop Timer1
  TCNT1 = 0; //Clear Timer 1
  OCR1A = 32; // Set compared value
}

Thanks in advance
Time to catch some Zzzz's

It's real late here so I haven't got the energy to properly look at the spec sheet so the following might be wrong, but I think it should be close

PCICR = (1<<PCIE2) | (1<<PCIE0);  // enable PCI 2 and 0
PCMSK2 = B10101000; // Set mask for pcint3 (PortD.3&5&7)  pcint3??
PCMSK0 = B11000000; // Set mask for pcint0 (PortA.6&7)

Then have two ISRs

ISR(PCINT0_vect) {

}

ISR(PCINT2_vect) {

}

Within each ISR you'll have to test the pins to see which one(s) actually caused the interrupt.


Rob

Thanks Rob
I will do some more reading today and try and understand this.

I have figured this table out for the 644P, so that is a start.

// Pin to interrupt map:
// (D8-D15) = PCINT 24-31 = PCIR3 = PD = PCIE3 = pcmsk3
// (D16-D23) = PCINT 16-23 = PCIR2 = PC = PCIE2 = pcmsk2
// (D0-D7) = PCINT 8-15 = PCIR1 = PB = PCIE1 = pcmsk1
// (D24-D31) = PCINT 0-7 = PCIR0 = PA = PCIE0 = pcmsk0

Thanks
J

Is there something I need to set in order to make the PCINT go to CHANGE mode, or is it default at CHANGE, and you need to set somehing else to make it RISING or FALLING etc?
I want it on CHANGE.

This is what I have so far.

  //=====[ Enable Pin change interrupt ]==========================================
  // The Pin Change Interupts are used for the quadrature imputs.
  // Pin to interrupt map:
  // (D8-D15) = PCINT 24-31 = PCIR3 = PD = PCIE3 = pcmsk3
  // (D16-D23) = PCINT 16-23 = PCIR2 = PC = PCIE2 = pcmsk2
  // (D0-D7) = PCINT 8-15 = PCIR1 = PB = PCIE1 = pcmsk1
  // (D24-D31) = PCINT 0-7 = PCIR0 = PA = PCIE0 = pcmsk0
  
  PCMSK3 = B10101000; // Set mask for pcint3 (PortD 3&5&7) (Arduino Pins D11, D13, D15)
  PCMSK0 = B11000000; // Set mask for pcint0 (PortA 6&7) (Arduino Pins D25, D24)
  PCICR = (1<<PCIE3) | (1<<PCIE0);  // enable PCI 3 and 0
  //------------------------------------------------------------------------------

I then have the two ISR's also.

Do I need to do anything further?

Full code so far (ported original, no mods)
Does this look correct?

//==============================================================================
// Project:  Quadrature input with pulse + direction ouput
// By: JADB
// Description:
//   It is controlled by an Atmel ATmega644P 8bit micro controller.
//   Quadrature input with pulse + direction ouput, with limit switch cut off
//   and limit switch outputs for LED's or PIZO. Pulse output scalable from 1:1,
//   1:5 or 1:10 based on selector switch position.
//==============================================================================

//=====[ Global Vars ]==========================================================
///Define the Arduino Pins used for each of the inputs/outputs
#define Switch1_input_pin 11        //PD3
#define Switch2_input_pin 13        //PD5
#define Switch3_input_pin 15        //PD7
#define Direction_output_pin 16     //PC0
#define Pulse_output_pin 17         //PC1
#define Limit1_output_pin 18        //PC2
#define Limit2_output_pin 19        //PC3
#define Limit3_output_pin 20        //PC4
#define Quada_input_pin 25          //PA6
#define Quadb_input_pin 24          //PA7
#define Limit1_input_pin 31         //PA0
#define Limit2_input_pin 30         //PA1
#define Limit3_input_pin 20         //PA2

volatile boolean Lastdirection;     // Stores last direction, 0 or 1.
volatile int Countvalue;            // Stores the number of pulses
volatile byte Q_newvalue;           // Used in Quadrature ISR
volatile byte Q_oldvalue;           // Used in Quadrature ISR
volatile byte Q_direction;          // Used in Quadrature ISR

void setup()
{
  //=====[ Set IO Pins ]==========================================================  
  //Select the mode of each of the inputs/outputs
  pinMode(Switch1_input_pin, INPUT);
  pinMode(Switch2_input_pin, INPUT);
  pinMode(Switch3_input_pin, INPUT);
  pinMode(Direction_output_pin, OUTPUT);
  pinMode(Pulse_output_pin, OUTPUT);
  pinMode(Limit1_output_pin, OUTPUT);
  pinMode(Limit2_output_pin, OUTPUT);
  pinMode(Limit3_output_pin, OUTPUT);
  pinMode(Quada_input_pin, INPUT);
  pinMode(Quadb_input_pin, INPUT);
  pinMode(Limit1_input_pin, INPUT);
  pinMode(Limit2_input_pin, INPUT);
  pinMode(Limit3_input_pin, INPUT);  
  //------------------------------------------------------------------------------
  
  //=====[ Enable Pin change interrupt ]==========================================
  // The Pin Change Interupts are used for the quadrature imputs.
  // Pin to interrupt map:
  // (D8-D15) = PCINT 24-31 = PCIR3 = PD = PCIE3 = pcmsk3
  // (D16-D23) = PCINT 16-23 = PCIR2 = PC = PCIE2 = pcmsk2
  // (D0-D7) = PCINT 8-15 = PCIR1 = PB = PCIE1 = pcmsk1
  // (D24-D31) = PCINT 0-7 = PCIR0 = PA = PCIE0 = pcmsk0
  
  PCMSK3 = B10101000; // Set mask for pcint3 (PortD 3&5&7) (Arduino Pins D11, D13, D15)
  PCMSK0 = B11000000; // Set mask for pcint0 (PortA 6&7) (Arduino Pins D25, D24)
  PCICR = (1<<PCIE3) | (1<<PCIE0);  // enable PCI 3 and 0
  //------------------------------------------------------------------------------
  
  //=====[ Config misc stuff ]====================================================    
  TCCR1A = 0; // Reset control registers
  TCCR1B = 0; // Reset control registers
  TCCR1B |= (1 << WGM12); // Clear Timer on Compare Match (CTC) Mode
  TCCR1B |= (1 << CS10); // Prescaler x1
  OCR1A = 32; // Set compared value
  TIMSK1 = 0; // Reset Timer/Counter2 Interrupt Mask Register
  
  sei(); // Enable Interrupts
  
  Countvalue = 0;  
  //------------------------------------------------------------------------------ 
}

//******************************************************************************
//*****[ Start of main loop ]***************************************************
//******************************************************************************
void loop()
{
   //Checks which selector switch is on and if the counter has reached the SP
   //1:10 Ratio
   if (digitalRead(Switch3_input_pin) == 0 && Countvalue >= 40)
   {
      Countvalue = 0;
      digitalWrite(Pulse_output_pin, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }
   //1:5 Ratio
   else if (digitalRead(Switch2_input_pin) == 0 && Countvalue >= 20)
   {
      Countvalue = 0;
      digitalWrite(Pulse_output_pin, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }
   //1:1 Ratio
   else if (digitalRead(Switch1_input_pin) == 0 && Countvalue >= 4)
   {
      Countvalue = 0;
      digitalWrite(Pulse_output_pin, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }

   //Checks which limit switch is on/made 
   if (digitalRead(Limit1_input_pin) == 1)
      digitalWrite(Limit1_output_pin, 0);
   else
      digitalWrite(Limit1_output_pin, 1);
   
   if (digitalRead(Limit2_input_pin) == 1)
      digitalWrite(Limit2_output_pin, 0);
   else
      digitalWrite(Limit2_output_pin, 1);

   if (digitalRead(Limit3_input_pin) == 1)
      digitalWrite(Limit3_output_pin, 0);
   else
      digitalWrite(Limit3_output_pin, 1);
}
//------------------------------------------------------------------------------

//=====[ Quadrature ISR routine ]============================================
ISR(PCINT0_vect)
{
  Q_newvalue = PINA;                                               //copies value of entire port A
  Q_direction = bitRead(Q_oldvalue,6) ^ bitRead(Q_newvalue,7);     //XOR to get direction of Bits 6 and 7
  if (Q_direction == 1)
  {
    digitalWrite(Direction_output_pin, 1);
    if (Lastdirection == 0)                                 //Handles if the direction is changed, starts conting again
    {
      Countvalue = 0;                                       //Write countvalue to 0
    }
    else
    {
      if (digitalRead(Limit1_input_pin) == 1 && digitalRead(Limit2_input_pin) == 1)           //Ensures it wont move further if a limit is made
      {
        Countvalue = Countvalue + 1;                        //increase the count of countvalue
      }
      else
      {
        Countvalue = 0;         //stops the counting as the limit has been made
      }
    }
    Lastdirection = 1;                                      //sets this as the last direction
  }
  else
  {
    digitalWrite(Direction_output_pin, 0);
    if (Lastdirection == 1)                                 //Handles if the direction is changed, starts conting again
    {
      Countvalue = 0;                                       //write countvalue to 0
    }
    else
    {
      if (digitalRead(Limit3_input_pin) == 1)               //Ensures it wont move further if a limit is made
      {
        Countvalue = Countvalue + 1;                        //increase the count of countvalue
      }
      else
      {
        Countvalue = 0;                                     //stops the counting as the limit has been made
      }
    }
    Lastdirection = 0;                                      //sets this as the last direction
  }
  Q_oldvalue = Q_newvalue;
}
//------------------------------------------------------------------------------

//=====[ Switch Change ISR Routine ]============================================
ISR(PCINT3_vect)
{
   Countvalue = 0;
   Lastdirection = 0;
   digitalWrite(Direction_output_pin, 0);
   digitalWrite(Pulse_output_pin, 0);
}
//------------------------------------------------------------------------------

//=====[ Output Pulse period setter ]===========================================
ISR(TIMER1_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
  digitalWrite(Pulse_output_pin, 0);
  TIMSK1 &= ~(1<<OCIE1A); //Stop Timer1
  TCNT1 = 0; //Clear Timer 1
  OCR1A = 32; // Set compared value
}

Apart from the switch read the tests in loop() all seem to do the same thing, ie,

     Countvalue = 0;
      digitalWrite(Pulse_output_pin, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)

What's happening there?


Rob

Hi Rob,

Sorry I dont quite follow the question...
Are you asking what those lines of code are aiming to achieve?

In the original BASIC code:

'Checks which selector switch is on and if the counter has reached the SP
   If Switch3_input = 0 And Countvalue >= 40 Then
      Countvalue = 0
      Set Pulse_output
      Timer1 = 0
      Start Timer1

It checks the status of the switch (Switch 3 is the one to select 10:1 mode), and whether the count value is Greater/Equal to 40 (ie ratio if 10:1), as 4 changes to the input ISR is 2 pulses, ie 1 Quadrature sequence.
If its true, then it resets the count, turns the ouput on, clears Timer1 and starts the timer. (Switch2 is 5:1 mode, and switch1 is 1:1 mode).
The timer then runs for the predetermined time in its ISR, and then turns the output off. This effectively makes a single output pulse with set period every 10th quadrature sequence, ie 10:1.

I admit the code could be made more efficient, however it was written for a person with no programming experience who wanted to understand what the machine was doing, so I expanded it out so I could explain each step as easily as possible.

Does that answer your question?

The Arduino IDE code:

//Checks which selector switch is on and if the counter has reached the SP
   //1:10 Ratio
   if (digitalRead(Switch3_input_pin) == 0 && Countvalue >= 40)
   {
      Countvalue = 0;
      digitalWrite(Pulse_output_pin, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }

Should be the same thing (hopefully, that is what I am aiming to get someone to assist with).
When the input switch 3 reads 0 (ie in 10:1 mode) and the count is GE 40, then clear the count, set the output to high, clear the timer1 and start the timer. The ISR then hopefully gets triggered when the timer reaches its preset time, sets the output low and turns the timer off. So making the same output pulse after 10 input pulse sequences.

Thanks
J

Yes but the code inside the if for every switch is exactly the same so no matter what condition is true the same code gets run.


Rob

Correct, but the condition to enter that are different, so a different number of input pulses have to be received before that code is run, which simply produces an output pulse.
ie Countvalue >= 40
Countvalue >= 20
Countvalue >= 4

So yes, it could all be combined and have an || between conditions and it would do the same thing.

OK, then it can be simplified a bit

  if ( (digitalRead(Switch3_input_pin) == 0 && Countvalue >= 40) ||
		(digitalRead(Switch2_input_pin) == 0 && Countvalue >= 20) ||
		(digitalRead(Switch1_input_pin) == 0 && Countvalue >= 4) {
      Countvalue = 0;
      digitalWrite(Pulse_output_pin, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }

Rob

Yep thats the one.
Thanks for approving of the rest of the code, now its just a case of testing it.

//==============================================================================
// Project:  Quadrature input with pulse + direction ouput
// By: JADB
// Description:
//   It is controlled by an Atmel ATmega644P 8bit micro controller.
//   Quadrature input with pulse + direction ouput, with limit switch cut off
//   and limit switch outputs for LED's or PIZO. Pulse output scalable from 1:1,
//   1:5 or 1:10 based on selector switch position.
//==============================================================================
/*
                               +---\/---+
             PCINT8 (D0) PB0  1|        |40  PA0 (AI0 / D31) PCINT0
             PCINT9 (D1) PB1  2|        |39  PA1 (AI1 / D30) PCINT1
       PCINT10 INT2 (D2) PB2  3|        |38  PA2 (AI2 / D29) PCINT2
       PCINT11  PWM (D3) PB3  4|        |37  PA3 (AI3 / D28) PCINT3
       PCINT12  PWM (D4) PB4  5|        |36  PA4 (AI4 / D27) PCINT4
       PCINT13 MOSI (D5) PB5  6|        |35  PA5 (AI5 / D26) PCINT5
       PCINT14 MISO (D6) PB6  7|        |34  PA6 (AI6 / D25) PCINT6
       PCINT15  SCK (D7) PB7  8|        |33  PA7 (AI7 / D24) PCINT7
                         RST  9|        |32  AREF
                         VCC 10|        |31  GND 
                         GND 11|        |30  AVCC
                       XTAL2 12|        |29  PC7 (D23) PCINT23
                       XTAL1 13|        |28  PC6 (D22) PCINT22
       PCINT24 RX0 (D8)  PD0 14|        |27  PC5 (D21) TDI PCINT21
       PCINT25 TX0 (D9)  PD1 15|        |26  PC4 (D20) TDO PCINT20
  INT0 PCINT26 RX1 (D10) PD2 16|        |25  PC3 (D19) TMS PCINT19
  INT1 PCINT27 TX1 (D11) PD3 17|        |24  PC2 (D18) TCK PCINT18
       PCINT28 PWM (D12) PD4 18|        |23  PC1 (D17) SDA PCINT17
       PCINT29 PWM (D13) PD5 19|        |22  PC0 (D16) SCL PCINT16
       PCINT30 PWM (D14) PD6 20|        |21  PD7 (D15) PWM PCINT31
                               +--------+
*/
//=====[ Global Vars ]==========================================================
///Define the Arduino Pins used for each of the inputs/outputs
#define Switch1_input_pin 11        //PD3
#define Switch2_input_pin 13        //PD5
#define Switch3_input_pin 15        //PD7
#define Direction_output_pin 16     //PC0
#define Pulse_output_pin 17         //PC1
#define Limit1_output_pin 18        //PC2
#define Limit2_output_pin 19        //PC3
#define Limit3_output_pin 20        //PC4
#define Quada_input_pin 25          //PA6
#define Quadb_input_pin 24          //PA7
#define Limit1_input_pin 31         //PA0
#define Limit2_input_pin 30         //PA1
#define Limit3_input_pin 20         //PA2

volatile boolean Lastdirection;     // Stores last direction, 0 or 1.
volatile int Countvalue;            // Stores the number of pulses
volatile byte Q_newvalue;           // Used in Quadrature ISR
volatile byte Q_oldvalue;           // Used in Quadrature ISR
volatile byte Q_direction;          // Used in Quadrature ISR

void setup()
{
  //=====[ Set IO Pins ]==========================================================  
  //Select the mode of each of the inputs/outputs
  pinMode(Switch1_input_pin, INPUT);
  pinMode(Switch2_input_pin, INPUT);
  pinMode(Switch3_input_pin, INPUT);
  pinMode(Direction_output_pin, OUTPUT);
  pinMode(Pulse_output_pin, OUTPUT);
  pinMode(Limit1_output_pin, OUTPUT);
  pinMode(Limit2_output_pin, OUTPUT);
  pinMode(Limit3_output_pin, OUTPUT);
  pinMode(Quada_input_pin, INPUT);
  pinMode(Quadb_input_pin, INPUT);
  pinMode(Limit1_input_pin, INPUT);
  pinMode(Limit2_input_pin, INPUT);
  pinMode(Limit3_input_pin, INPUT);  
  //------------------------------------------------------------------------------
  
  //=====[ Enable Pin change interrupt ]==========================================
  // The Pin Change Interupts are used for the quadrature imputs.
  // Pin to interrupt map:
  // (D8-D15) = PCINT 24-31 = PCIR3 = PD = PCIE3 = pcmsk3
  // (D16-D23) = PCINT 16-23 = PCIR2 = PC = PCIE2 = pcmsk2
  // (D0-D7) = PCINT 8-15 = PCIR1 = PB = PCIE1 = pcmsk1
  // (D24-D31) = PCINT 0-7 = PCIR0 = PA = PCIE0 = pcmsk0
  
  PCMSK3 = B10101000; // Set mask for pcint3 (PortD 3&5&7) (Arduino Pins D11, D13, D15)
  PCMSK0 = B11000000; // Set mask for pcint0 (PortA 6&7) (Arduino Pins D25, D24)
  PCICR = (1<<PCIE3) | (1<<PCIE0);  // enable PCI 3 and 0
  //------------------------------------------------------------------------------
  
  //=====[ Config misc stuff ]====================================================    
  TCCR1A = 0; // Reset control registers
  TCCR1B = 0; // Reset control registers
  TCCR1B |= (1 << WGM12); // Clear Timer on Compare Match (CTC) Mode
  TCCR1B |= (1 << CS10); // Prescaler x1
  OCR1A = 32; // Set compared value
  TIMSK1 = 0; // Reset Timer/Counter2 Interrupt Mask Register
  
  sei(); // Enable Interrupts
  
  Countvalue = 0;  
  //------------------------------------------------------------------------------ 
}

//******************************************************************************
//*****[ Start of main loop ]***************************************************
//******************************************************************************
void loop()
{
   //Checks which selector switch is on and if the counter has reached the SP
   //1:10 Ratio || 1:5 Ratio || 1:1 Ratio
   if ((digitalRead(Switch3_input_pin) == 0 && Countvalue >= 40) || (digitalRead(Switch2_input_pin) == 0 && Countvalue >= 20) || (digitalRead(Switch1_input_pin) == 0 && Countvalue >= 4))
   {
      Countvalue = 0;
      digitalWrite(Pulse_output_pin, 1);
      TIMSK1 = 0;                     // Reset Timer/Counter2 Interrupt Mask Register
      TIMSK1 |= (1 << OCIE1A);        // Enable Output Compare Match A Interrupt (Start Timer1)
   }

   //Checks which limit switch is on/made 
   if (digitalRead(Limit1_input_pin) == 1)
      digitalWrite(Limit1_output_pin, 0);
   else
      digitalWrite(Limit1_output_pin, 1);
   
   if (digitalRead(Limit2_input_pin) == 1)
      digitalWrite(Limit2_output_pin, 0);
   else
      digitalWrite(Limit2_output_pin, 1);

   if (digitalRead(Limit3_input_pin) == 1)
      digitalWrite(Limit3_output_pin, 0);
   else
      digitalWrite(Limit3_output_pin, 1);
}
//------------------------------------------------------------------------------

//=====[ Quadrature ISR routine ]============================================
//Determines direction and counts number of quadrature input pulse sequences
ISR(PCINT0_vect)
{
  Q_newvalue = PINA;                                               //copies value of entire port A
  Q_direction = bitRead(Q_oldvalue,6) ^ bitRead(Q_newvalue,7);     //XOR to get direction of Bits 6 and 7
  if (Q_direction == 1)
  {
    digitalWrite(Direction_output_pin, 1);
    if (Lastdirection == 0)                                 //Handles if the direction is changed, starts conting again
    {
      Countvalue = 0;                                       //Write countvalue to 0
    }
    else
    {
      if (digitalRead(Limit1_input_pin) == 1 && digitalRead(Limit2_input_pin) == 1)           //Ensures it wont move further if a limit is made
      {
        Countvalue = Countvalue + 1;                        //increase the count of countvalue
      }
      else
      {
        Countvalue = 0;         //stops the counting as the limit has been made
      }
    }
    Lastdirection = 1;                                      //sets this as the last direction
  }
  else
  {
    digitalWrite(Direction_output_pin, 0);
    if (Lastdirection == 1)                                 //Handles if the direction is changed, starts conting again
    {
      Countvalue = 0;                                       //write countvalue to 0
    }
    else
    {
      if (digitalRead(Limit3_input_pin) == 1)               //Ensures it wont move further if a limit is made
      {
        Countvalue = Countvalue + 1;                        //increase the count of countvalue
      }
      else
      {
        Countvalue = 0;                                     //stops the counting as the limit has been made
      }
    }
    Lastdirection = 0;                                      //sets this as the last direction
  }
  Q_oldvalue = Q_newvalue;
}
//------------------------------------------------------------------------------

//=====[ Switch Change ISR Routine ]============================================
//If the ratio switch(s) is changed, clear counters and outputs and start again
ISR(PCINT3_vect)
{
   Countvalue = 0;
   Lastdirection = 0;
   digitalWrite(Direction_output_pin, 0);
   digitalWrite(Pulse_output_pin, 0);
}
//------------------------------------------------------------------------------

//=====[ Output Pulse period setter ]===========================================
//Determines the length of the output pulse
ISR(TIMER1_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
  digitalWrite(Pulse_output_pin, 0);
  TIMSK1 &= ~(1<<OCIE1A); //Stop Timer1
  TCNT1 = 0; //Clear Timer 1
  OCR1A = 32; // Set compared value
}