Need help!! how to code pulse count from optical encoder to 360 degrees code

Hi all,

started from scratch almost (Basic stamp about 10+yrs ago minimal use) 2 days ago using the Uno board and writing code!!

After using a book for reference (Programming Arduino by Simon Monk) and the good old web for info and researching, im pretty happy with my build and coding so far.

But...

I've hit a brick wall and im looking for a fresh direction on code to try to solve the issue. :confused:

Question: How can i translate a numeric reading generated from my 'Rotary incremental Optical Encoder' to show rotational degrees (0-359 per revolution) in my sketch so that i can handle that better in my code?

As you can see in my sketch i get a signal count of 720 pulses per 360 degrees of the encoder (360ppr encoder, A+B inputs = 720).

I have set a reset for count = '0' if >719 so the count doesn't max out at 65535 and then back to 0 again which clearly is no use to me for the application. This gives me currently a 720ppr to handle in the code for my timings. '0' counted as a position so 719 max is 720 in real terms per revolution.

Although it works great at the moment it has a few failings in the use of the count and not actual degrees.

Issue:

If you rotate in reverse the outputs work fine as the count decreases but the value goes '0' and will not cycle to 719 and reduce again as it is a pulse count. This then affects '0' position (or TDC if you prefer) and has the affect of putting all timings out of the fixed datum position on the machine being TDC at a given fixed point in the machines cycle.

Result: All timings, all correct relative to each other but all out on the machine.

Solution: Translate count to rotational degrees, 0-359 to 0 again in one full forward revolution. Reverse encoder rotation shows 359-0 and 359 again. Modify required timings for outputs in 0-359 range in code.


###Sketch as follows### (first post so probably attached sketch incorrectly..sorry)


/*Electronic Cam switch sketch V.Sep25.1
 * Industrial application
 * 
 * Requirement to control various low voltage solenoids 'off/on/off' and sensor 'sense' timings repeatedly per 360 degree revolution 
 * from a mechanical shaft rotating once per machine cycle.
 * Proximity sensor will enable absolute TDC at '0' degrees on machine for reliable timing per revolution. Acting as a Reset. 
 * Sensor maybe be uninstalled if code makes obsolete and retains Encoder absolute position after power down/up. Encoder mounted on fixed position on machine shaft.

Equipment required:

Arduino Uno

8x solid state relay shield, 5vdc control voltage

Encoder type: LPD3806-360BM-G5-24C 360PPR (translates to 720ppr on count due to signal inputs A+B)
  Connections:   Red             5-24 vdc
                       Black           0v ground
                       Green           Input A
                       White           Input B
                       Cable braid     Ground to isolate possible interference form machine

Proximity sensor: Baumer IFRM 12P1702/L. 5-24vdc range. 

Arduino Input(5) wired through SSR no.1 using 5v load voltage to isolate non 5v proximity sensor output voltage. Not needed if 5v used.
  - external relay used to switch 12-24vdc output of proximity sensor etc. This may change when additional 5vdc power supply installed on machine.
*/

volatile unsigned int counter = 0; //This variable will increase or decrease depending on the rotation of encoder
    
void setup() {
  Serial.begin (9600);

  
  pinMode(2, INPUT_PULLUP);    // internal pullup input pin 2 for encoder input A - green wire
  pinMode(3, INPUT_PULLUP);    // internal pullup input pin 3 for encoder input B - white wire
  pinMode(5, INPUT);           // set pin to input - proximity sensor looped through SSR #1 to isolate 12vdc signal to 5vdc input on Micro PLC.
  pinMode(6, OUTPUT);          // set pin to output - SS relay #2 on relay board
  pinMode(7, OUTPUT);          // set pin to output - SS relay #3 on relay board
  pinMode(8, OUTPUT);          // set pin to output - SS relay #4 on relay board
  pinMode(9, OUTPUT);          // set pin to output - SS relay #5 on relay board
  pinMode(10, OUTPUT);         // set pin to output - SS relay #6 on relay board
  pinMode(11, OUTPUT);         // set pin to output - SS relay #7 on relay board
  pinMode(12, OUTPUT);         // set pin to output - SS relay #8 on relay board


  
//Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
  attachInterrupt(0, ai0, RISING);
   
  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on moust Arduino.
  attachInterrupt(1, ai1, RISING);
  }
   
  void loop() {
   // Send the value of counter (debug - remember to comment out before final program run,
   // you don't want serial slowing down your program if not needed)
  Serial.println (counter);
  if (counter >719) {
    counter = 0;
  }
 // if (digitalRead(5)==HIGH)  { (TEMP BLOCKED OUT AS FOR SOME REASON NOT FUNCTIONING FULLY) WORK AROUND LATER ;), wiring logic correct, sketch not liking the code,
 //  counter = 0;
  }
   
  void ai0() {
  // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
  // Check pin 3 to determine the direction
  if(digitalRead(3)==LOW) {
  counter++;
  }else{
  counter--;
  }
  }
   
  void ai1() {
  // ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if(digitalRead(2)==LOW) {
  counter--;
  }else{
  counter++;
  }
 
  if (counter <100) digitalWrite(6, LOW);{
  }
  if ((counter >=100) && (counter <=200)) digitalWrite(6, HIGH);{
  }
  if (counter >200) digitalWrite(6, LOW);{
  }

  
  if (counter <200) digitalWrite(7, LOW);{
  }
  if ((counter >=200) && (counter <=300)) digitalWrite(7, HIGH);{
  }
  if (counter >300) digitalWrite(7, LOW);{
  }

  
  if (counter <300) digitalWrite(8, LOW);{
  }
  if ((counter >=300) && (counter <=400)) digitalWrite(8, HIGH);{
  }
  if (counter >400) digitalWrite(8, LOW);{
  }

  
  if (counter <400) digitalWrite(9, LOW);{
  }
  if ((counter >=400) && (counter <=500)) digitalWrite(9, HIGH);{
  }
  if (counter >500) digitalWrite(9, LOW);{
  }

  if (counter <100) digitalWrite(10, LOW);{
  }
  if ((counter >=100) && (counter <=200)) digitalWrite(10, HIGH);{
  }
  if (counter >200) digitalWrite(10, LOW);{
  }

  
  if (counter <200) digitalWrite(11, LOW);{
  }
  if ((counter >=200) && (counter <=300)) digitalWrite(11, HIGH);{
  }
  if (counter >300) digitalWrite(11, LOW);{
  }

  
  if (counter <300) digitalWrite(12, LOW);{
  }
  if ((counter >=300) && (counter <=400)) digitalWrite(12, HIGH);{
  }
  if (counter >400) digitalWrite(12, LOW);{
  }
}

Any help would be appreciated. I'm Using the Arduino for this application as im many years with industrial control systems electrically but not PLC and programming so thought this is an ideal chance to finally get more skilled in the world or Arduino. Impressed so far!

I've a few projects in my head for collecting telemetry from by motorbike on track days but first things first and learn the basics.

Thanks for looking at my lengthy post but info is king in my world.

Gav.
26/09/18
12:32 GMT
UK.

With 720 pulses per one 360 degree rotation each pulse is .5 degrees and + and - would just be direction of rotation.

Some math could be used to determine zero crossing.

Such as the encoder is at +2 degrees and it is to be sent to 358 degrees, would be a - directional rotation of 8 pulses from its current location.

Or you could forget about using a absolute reference and, instead, use a relative reference. Upon start up allow the encoder to find the first .5 degree point it comes upon and declare that point as zero. From there rotations are just a matter of counting +/-.5 degree pulses and keeping track of the current position.

Yeah the .5 degrees is not an issue and gives a higher 'degree' (no pun intended) of timing.

The later suggestion wont work for the application though as the timings are relative to the machine position so the position or reference would need to be the same as when powered off. when you power back on it naturally defaults the count to '0' as its had no pulses as yet. the machine may of turned off at any value other than '0' so timings would be out unless a 1 in 720 chance it was switched off in position '0' on the counter. clearly not good.

But... zero crossing would be a solution! how do you code that??

That would give a virtual 'position of degrees' in an acceptable format of 720 pulse (positions) per physical revolution.

As said im learning and im on day 3 of Arduino.

dmaintenance:
The later suggestion wont work for the application though as the timings are relative to the machine position so the position or reference would need to be the same as when powered off. when you power back on it naturally defaults the count to '0' as its had no pulses as yet. the machine may of turned off at any value other than '0' so timings would be out unless a 1 in 720 chance it was switched off in position '0' on the counter. clearly not good.

But... zero crossing would be a solution! how do you code that??

That would give a virtual 'position of degrees' in an acceptable format of 720 pulse (positions) per physical revolution.

As said im learning and im on day 3 of Arduino.

1). If the machine, when it is shut off, remains in the shut off position when powered back on, the Arduino has an EEPROM which can record the position at shut off and that position can be retrieved at power on.

2). Zero crossing, would rely on the machine, in my mind, of, at power on, resetting to 0 degrees.

3). I do not write the code, you do.

Thanks for the basic principles.

No.1) suggestion wont work as simply you are relying on the status of the machine not to change during power off. What if the machine is moved even slightly by hand during servicing for example. The stored count in the eprom would be as it was when the system was powered down and the machine in a different position.

Zero crossing... i cant find any examples or reference to it?

I appreciate i write the code and for a couple of days with a book and the web i think i've done pretty well so far, but as mentioned, im stuck with what functions to use to achieve the solution, so just looking for some friendly help to move on with the sketch.

Thanks anyway.

Hi dmaintenance

to get the counter issue overflowing properly, I'd do a couple of things

first off, as far as I can see, counter does not need to the an unsigned int. Make it an ordinary int.
you can then do the rollover in both of your interrupts, eg:

void ai0() {
  // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
  // Check pin 3 to determine the direction
  if(digitalRead(3)==LOW) {
    counter++;
    if (counter > 719)
      counter = 0;
  }
  else {
    counter--;
    if (counter < 0)
      counter = 719;
  }
}

you can now divide count by 2 to get your 0 .. 359 range. However... You're only doing something in your code every second tick. So what's the point of counting every tick? Just increment/decrement your count each time you're going to to actually do something. This will, by default, give you a range of 0..356

thanks darrob. that pushed me along a bit. Not sure if entered in correctly tho as it worked in 2 ways, neither 100%.

I pasted your much appreciated code in to my sketch and it maxed at 719 and started at '0' again as before but this time when in reverse past '0' it scrolled brilliantly decreasing but from 65535.

So i duplicated your sample code in to both parts of the sketch as follows thinking thats what i should of done in the first place and it hangs at 65535 when you reverse like before.

 void ai0() {
    // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
    // Check pin 3 to determine the direction
    if(digitalRead(3)==LOW) {
      counter++;
      if (counter > 719)
        counter = 0;
    }
    else {
      counter--;
      if (counter < 0)
        counter = 719;
  }
  } 
  void ai1() {
  // ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if(digitalRead(2)==LOW) {
  counter--;
    if (counter > 719)
        counter = 0;
    }
    else{
      counter++;
      if (counter < 0)
        counter = 719;
  }

I think im missing the basis of the code to modify it correctly.

so ive just blocked a few lines of code to see the difference it makes with the counter output.

//Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
  attachInterrupt(0, ai0, RISING);
   
  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on moust Arduino.
//  attachInterrupt(1, ai1, RISING);
  }
   
  void loop() {
 Serial.println (counter);
  }
  
  //if (counter >719) {
  //  counter = 0;

  
 // if (digitalRead(5)==HIGH)  { (TEMP BLOCKED OUT AS FOR SOME REASON NOT FUCTIONING FULLY) WORK AROUND LATER ;), wiring logic correct, sketch not liking the code,
 //  counter = 0;

   
 
 void ai0() {
    // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
    // Check pin 3 to determine the direction
    if(digitalRead(3)==LOW) {
      counter++;
      if (counter > 719)
        counter = 0;
    }
    else {
      counter--;
      if (counter < 0)
        counter = 719;

/*  void ai1() {
  // ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if(digitalRead(2)==LOW) {
  counter--;
    if (counter > 719)
        counter = 0;
    }
    else{
      counter++;
      if (counter < 0)
        counter = 719;
  }

 */
  }

  if (counter <100) digitalWrite(6, LOW);{
  }
  if ((counter >=100) && (counter <=200)) digitalWrite(6, HIGH);{
  }
  if (counter >200) digitalWrite(6, LOW);{
  }

only the first interrupt running now as in code relating to Input A. It makes the value max out at 359!! Brilliant.

And not sure why still shows direction as in decreasing value in reverse. Thought i needed A+B for that?

So... the only issue at this pint is the fact that it scrolls down past '0' as before decreasing but from 65535.

Being that your simple code has achieved so much im thinking this issue is simple enough also?

Feels like jumping hurdles!!

Hi dmaintenance

The reason the the code start counting down from 65535 is because you have declared count as unsigned int. [0 .. 65535] at the top of your code. It does not need to be. As I pointed out in my previous post, declare count as int [-32766 .. 32767] this will make the reverse direction flip back to 719 once you go past 0

as to your code, double check what you have done in void a1(). You appear to have the reset logic reversed

If you really need to have count as an unsigned in, then do a check (when rotating in the reverse direction) for when count hits 65535 and reset count to 719

eg

count--
if (count == 65535)
  count = 719
[code]

"constrain"!!! wow the solution finally.

  void loop() {
 Serial.println (counter);
 counter = constrain (counter, 0, 719);
  }

scrolls up to 719 and then starts at '0' again.

scrolls down to '0' and then 719 and down again!!!

outputs work in forward and reverse direction the same. BINGO!!!!! :slight_smile:

ill try your method also in the morning.

Finally something that works. 2 methods of code!!

Its gone 6pm and i think its time for a 'Pint'!!

Thanks darrob. A++++++

So...

I'm almost complete but i still keep getting inconsistent readings from my brand new optical rotary encoder, that is verified with the scope as ok and functioning as it should. I also wired a higher quality brand new OMRON encoder to see if spec was an issue (same 360ppr) and no change.

I've installed fastRead/Write etc that im sure helps but has no effect just in case the code is getting slow looping.

Running on an UNO, tried on my bench Mega with fastRead removed as it didn't work and presume it was written for the different chip with different configuration. Same issue with the variation in the encoder 'counter' value though.

I have now installed Bounce2 and it appears better, but not 100% solved the issue.

I have an '0' position reset installed to help keep the 'TDC' in check but really i shouldn't need this after the first cycle to set '0' and then let the encoder values maintain this correctly.

Its a work around using reset value every 360 degrees but would rather fix the issue and learn from it.

I'm not sure if the bounce code is correct as i hoped this would finally sort any 'ghost' signals from the encoder (if thats the issue, still think its bad code). I noticed on the scope the minutest of steps in the signal 'Raising' from LOW. I really clutching at straws as its so small and rare i dint think its the issue causing the variable reads.

When i say variable, inconsistent, i mean if i rotate slowly or quickly by hand the encoder shaft (fitted with control knob with arrow for test purposes only) 360 degrees to best by my eye to a preset mark on the encoder body, some times the value is '0' every time, then randomly it will drift up or down by as many as 5 degrees value. The more you do it without the '0' reset feature the more it drifts out.

I have tried many variations with RAISING, FALLING, CHANGE, HIGH or LOW but some settings don't work or some with no improvement.

I have thought maybe im asking too much from an UNO but my gut feeling is a problem with the code.

The UNO can do so much more than blink LED's but i don't know as yet its limits. You guys would be able to advise me of that im sure??

I've used the interrupts so the 'counter' value from the encoder should be reliable in my mind and if anything the outputs would be an issue with lag. I've even tested with a small drill on the encoder to spin at high revs and the outputs work fabulously. The OLED screen showing each output struggles at high speed but thats just for my reference purposes at low speed so all fine there.

Is the Bounce code working is my thought?? (i still don't think i should need it for an optical digital encoder)

// Encoder outputs for counter
 void ai0() {
    // ai0 is activated if DigitalPin(2) is going from LOW to HIGH
    // Check pin(3) to determine the direction
 if(digitalRead(3)==LOW) {
      if (bouncer.update() && bouncer.read() == LOW);
      {
        int counterValue = LOW;
        counterValue = ! counterValue;
        digitalWrite(inputPinA, counterValue);
      }
      counter++;
   
      if (counter > 719)      //counter roll over to '0'
        counter = 0;
    }
    else {
      counter--;
      
      if (counter < 0)        //counter roll back to '719'
        counter = 719;
  }
 }
   
  void ai1() {
  // ai0 is activated if DigitalPin(3) is going from LOW to HIGH
  // Check with pin(2) to determine the direction
  if(digitalRead(2)==LOW) {
      if (bouncer.update() && bouncer.read() == LOW);
      {
        int counterValue = LOW;
        counterValue = ! counterValue;
        digitalWrite(inputPinB, counterValue);
      }
      counter--;
   }else{
      counter++;
  }

I have tried variations of code for the counter ++ and counter -- in case thats the issue but unless you mirror the change in the opposite code it doesn't work so i think thats not where the problem is...

Any ideas???

(i'm still very impressed with my progress so far though for a newbie with a book and the web for reference)
(Hats of to Arduino).

Hi dmaintenance

I think one of the major problems is that you've got interrupts on both pulses,
You're counting 720 pulses per complete rotation.

Output A (which is the one to count) will pulse 360 times per rotation (hence the name of your device, LPD3806-360BM-G5-24C 360PPR)

Output B is always 90 degrees out of phase output A. This output should only used to determine the direction of travel.

You look at the status of Output B on the falling edge of Output A to get the direction.

I am also pretty certain that counting both pulses becomes an issue when reversing direction.
I don't have a device to test or an oscilloscope/logic analyser, but I would love to see the waveforms of Output A and Output B when you change direction. I'm pretty certain that Output B will stay at one level for a complete period of Output A, which in turn will throw your count out.

So I think you should leave this in your code, (but change from RISING to FALLING)

//Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
  attachInterrupt(0, ai0, FALLING);

but remove this

  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on moust Arduino.
  attachInterrupt(1, ai1, RISING);

Your ISR for pulse A would then become

// Encoder outputs for counter
 void ai0() {
    // ai0 is activated if DigitalPin(2) is going from HIGH to LOW
    // Check pin(3) to determine the direction
 if(digitalRead(3)==LOW) {

// I've commented these lines out, rather than remove them because I'm not sure what you're
// doing, or why you need to write to inputPinA.
// I've not used the debounce library before.
/*
      if (bouncer.update() && bouncer.read() == LOW);
      {
        int counterValue = LOW;
        counterValue = ! counterValue;
        digitalWrite(inputPinA, counterValue);
      }
*/
      counter++;
  
      if (counter == 360)      //counter roll over to '0'
        counter = 0;
    }
    else {
      if (counter == 0)
        counter = 360  //counter roll back to '360'. The next line will bring it 359
      counter--;
      
  }
 }

You should not need an ISR for OutputB

Post the specs on the encoder, on at least a model number. You've eluded to A and B outputs which suggests it a quadrature encoder and if so, you're going about this the wrong way.

DKWatson:
Post the specs on the encoder, on at least a model number. You've eluded to A and B outputs which suggests it a quadrature encoder and if so, you're going about this the wrong way.

The encoder is LPD3806-360BM-G5-24C 360PPR (from the first post)
Similar to this one Incremental, 2 phase

Hi darrob,

yeah i get what you say about 360ppr and 2x inputs gives 720 which is not needed for the counter but if you run it without the InputB the value naturally halves to 360ppr but you loose the reverse detection function.

If the machine for example was to stop and mechanically increment back slightly it would not reduce the count accordingly. Mechanical resistance from a cam up-slope for example.

It would give you the other issue of incrementing the count up when going in reverse. Gave it try and worse than current setup.

Both inputs are needed and have the interrupt so they always register the value as they are the most important part as all other code is defined from an accurate counter value scrolling reliably mostly in forward rotation but in reverse just to register any slight reverse movement when coming to a halt on the machine.

if you scroll down on the page from the link above they have a diagram/image explaining how the pulse phases give the information of direction. They use a basic encoder but i couldn't jump on a better image quicker. same principle requiring 2 signals for direction.

My mind is leaning towards the ++ and -- code but it works and without it doesn't.

still pondering and scratching my head about it.

#include <Bounce2.h>

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>

#include <Adafruit_SSD1306.h>

#include <digitalWriteFast.h>

/*Electronic Cam switch sketch V.Oct.05.18.V15
  Industrial application:
  
  Requirement to control SSR outputs 'off/on/off' and sensor 'sense' timings repeatedly per 360 degree revolution 
  from a mechanical shaft rotating once per machine cycle.
  
  Proximity sensor will enable absolute TDC at '0' dgerees on machine for reliable timing per revolution. Acting as a Reset. 


  Equipmnet required:

  Arduino Uno

  8x solid state relay sheild, 5vdc control voltage

  Encoder type: LPD3806-360BM-G5-24C 360PPR (translates to 720ppr on count due to signal inputs A+B)
    Connections: Red             5-24 vdc
                 Black           0v ground
                 Green           Input A
                 White           Input B
                 Cable braid     Ground to isolate possible interference form machine

  Proximity sensor: Baumer IFRM 12P1702/L. 5-24vdc range. 

  Rotary Potentiometer, 10k preferable. 4k tested ok.

  Arduino Input(5) wired through SSR no.1 using 5v load volatage to isloate non 5v proximty sensor output volatge. Not needed if 5v used.
  - external relay used to switch 12-24vdc output of proximty sensor etc. This may change when additional 5vdc power supply installed on machine.

  Connections:

  ##Power##
  Vin             5vdc+ power supply for Arduino board or use Jack plug as alternate.
  GND             0vdc- Ground for Arduino board or use Jack plug as alternate.
  5V              common 5vdc+ supply for devices if needed (clean filtered supply)

  ##Analogue inputs##
  A0              rotary potentiometer middle terminal input to Arduino

  ##Digital Input/Outputs##
  2               encoder green wire
  3               encoder white wire
  4               run mode 5v output supply for input (5)
  5               run mode input from main motor inverter (drop down to 5vdc+ max!!!!)
  6               ch2 to ssr board  // 6x station insert vacuum
  7               ch3 to ssr board  // 6x insert miss/double detect sense
  8               ch4 to ssr board  // envlope feed vacuum
  9               ch5 to ssr board  // envelope insertion vacuum
  10              ch6 to ssr board  // envlope flap wetting device
  11              ch7 to ssr board  // spare
  12              ch8 to ssr board  // spare
  13              proximity sensor switched 0vdc-GND contact on (A1)SSR1 load side on ssr board
  GND             GND to ssr board
  
*/

volatile int counter = 0;              // This variable will increase or decrease depending on the rotation of Encoder
   const int inputPinA = 2;
   const int inputPinB = 3;
   Bounce bouncer = Bounce();               

         
         int inputState = HIGH;        // Current INPUT state of Proximity sensor
         int lastInputState = HIGH;    // Previous INPUT state of Proximity sensor
volatile int firstCycle = 0;
         
         int sensorPin = A0;           // set analogue INPUT
         int voltage = 0;
volatile int potValue = 0;             // variable to store the value coming from the potentiometer wiper (middle) pin
volatile int potValue2 = 0;            // variable to store the value coming from the potValue, divided by factor 2

Adafruit_SSD1306 display(A5);          // define display reset input


void setup() {
  Serial.begin (19200);            // 19200 is the Baud rate (speed) to communicate with


display.begin(SSD1306_SWITCHCAPVCC, 0x3c);
display.setTextSize(1);
display.setTextColor (WHITE);


  
  pinMode(2, INPUT_PULLUP);        // internal pullup input pin 2 for encoder input A - green wire
  pinMode(3, INPUT_PULLUP);        // internal pullup input pin 3 for encoder input B - white wire
  pinMode(4, OUTPUT);              // set pin to output for input 5 run mode
  pinMode(5, INPUT_PULLUP);        // set pin to digital input for machine runMode status from main motor inverter (A1 on inverter +20vdc signal) ISOLATE TO 5VDC!!
  pinModeFast(6, OUTPUT);          // set pin to output - SS relay #2 on relay board
  pinModeFast(7, OUTPUT);          // set pin to output - SS relay #3 on relay board
  pinModeFast(8, OUTPUT);          // set pin to output - SS relay #4 on relay board
  pinModeFast(9, OUTPUT);          // set pin to output - SS relay #5 on relay board
  pinModeFast(10, OUTPUT);         // set pin to output - SS relay #6 on relay board
  pinModeFast(11, OUTPUT);         // set pin to output - SS relay #7 on relay board
  pinModeFast(12, OUTPUT);         // set pin to output - SS relay #8 on relay board
  pinMode(13, INPUT_PULLUP);       // set pin to input pullup - proximity sensor looped through SSR #1 to isolate 12vdc signal to 0vdc input on Micro PLC.

  digitalWrite(4, LOW);

  bouncer.attach(inputPinA);
  bouncer.attach(inputPinB);

//#define ssr1_start 0        // dissabled due to SSR #1 use d externally
//#define ssr1_end   0        // dissabled due to SSR #1 used externally
  
  #define ssr2_start 0        // 6x station insert vacuum
  #define ssr2_end   100

  #define ssr3_start 100      // 6x insert miss/double detect sense
  #define ssr3_end   200
  
  #define ssr4_start 200      // envlope feed vacuum
  #define ssr4_end   300
   
  #define ssr5_start 300      // envelope insertion vacuum
  #define ssr5_end   400
  
  #define ssr6_start 0        // envlope flap wetting device, duration set bewteen potValue & potValue2
  #define ssr6_end   0

  #define ssr7_start 500      // spare
  #define ssr7_end   600
  
  #define ssr8_start 600      // spare
  #define ssr8_end   700  
  
//Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
  attachInterrupt(0, ai0, RISING);
   
  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on moust Arduino.
  attachInterrupt(1, ai1, RISING);
  }
   
 void loop() {
{
  
//### rest of same sketch in next post### - to big for 1 post apparently.
// #### part2 of same sketch ###
   
 void loop() {
{
  
// Serial moniter settings
  counter = constrain (counter, 0, 719);          // limit counter to values from '0' to '719'    
  Serial.print ("Ref=");
  Serial.print (counter);
  
  potValue = analogRead(sensorPin);               // read A0 input and name 'potValue'
  potValue = min(potValue,719);                   // set max value of potValue to 719 to match counter max value
  Serial.print ("\t\tPot=");
  Serial.print (potValue);
  
  voltage = potValue / 204.6;                     // coversion from potValue to Voltage value
  Serial.print ("\t\tVolts=");
  Serial.print (voltage);

  potValue2 = potValue / 5;                       // increase number to increase range beteween potValue & potValue2. 2 = 0-359, 5 = 0-143.8
  Serial.print ("\t\tPot2=");
  Serial.print (potValue2); 

  Serial.print ("\t\tCycle=");
  Serial.println (firstCycle); 
  }
  {

display.clearDisplay();                         // clear default "Adafruit" logo from screen memory
display.drawRoundRect(0, 0, 127, 31, 8, WHITE);
display.setCursor(12,3);                        // sets offset of pixels from top left, accross then down

// OLED display composition
display.print ("Cyc:");
display.print (firstCycle);
display.print (":");
display.print (digitalRead(13)==LOW); 

display.print ("  Enc:");
display.println(counter);

potValue = analogRead(sensorPin);               // read A0 input and name 'potValue'
potValue = min(potValue,719);                   // set max value of potValue to 719 to match counter max value
display.print("  Pot:");
display.print (potValue2);

potValue2 = potValue / 5;                       // increase number to increase range between potValue & potValue2. 2 = 0-359, 5 = 0-143.8
display.print ("  Pot2:");
display.println(potValue); 

display.print ("  Outputs:");
display.print (digitalRead(5)==LOW);
display.print (":");
display.print (digitalRead(6));           // ssr 2
display.print (digitalRead(7));           // ssr 3
display.print (digitalRead(8));           // ssr 4
display.print (digitalRead(9));           // ssr 5
display.print (digitalRead(10));          // ssr 6
display.print (digitalRead(11));          // ssr 7
display.print (digitalRead(12));          // ssr 8
 
display.display();

}

     
//Input (13) from proximity sensor for '0' reset
    inputState = digitalRead(13);                 // set 'inputState' reference in code to read Pin(13)

   
    if (inputState != lastInputState)             // input change of state check, now to last
  
    if (inputState == LOW)                        // input state now check
      counter = 0;                                // conter reset to '0' if state change from LOW to HIGH
    
    if (inputState == LOW)      
      firstCycle = 1;                             // enable SSR outputs after first machine cycle

    lastInputState = inputState;                  // inputState stored for next run through loop to compare last state
}
   
// Encoder outputs for counter
 void ai0() {
    // ai0 is activated if DigitalPin(2) is going from LOW to HIGH
    // Check pin(3) to determine the direction
 if(digitalRead(3)==LOW) {
      if (bouncer.update() && bouncer.read() == LOW);
      {
        int counterValue = LOW;
        counterValue = ! counterValue;
        digitalWrite(inputPinA, counterValue);
      }
      counter++;
   
      if (counter > 719)      //counter roll over to '0'
        counter = 0;
    }
    else {
      counter--;
      
      if (counter < 0)        //counter roll back to '719'
        counter = 719;
  }
 }
   
  void ai1() {
  // ai0 is activated if DigitalPin(3) is going from LOW to HIGH
  // Check with pin(2) to determine the direction
  if(digitalRead(2)==LOW) {
      if (bouncer.update() && bouncer.read() == LOW);
      {
        int counterValue = LOW;
        counterValue = ! counterValue;
        digitalWrite(inputPinB, counterValue);
      }
      counter--;
   }else{
      counter++;
  }

// SSR outputs for machine
/* 
  if (counter < ssr1_start) digitalWriteFast(5, LOW);{
  }
  if ((firstCycle == 1) && (counter > ssr1_start) && (counter < ssr1_end)) digitalWriteFast(5, HIGH);{
  }
  if (counter > ssr1_end) digitalWriteFast(5, LOW);{
  }
*/
  
  if (counter < ssr2_start) digitalWriteFast(6, LOW);{
  }
  if ((firstCycle == 1) && (counter > ssr2_start) && (counter < ssr2_end)) digitalWriteFast(6, HIGH);{
  }
  if (counter > ssr2_end) digitalWriteFast(6, LOW);{
  }


  if (counter < ssr3_start) digitalWriteFast(7, LOW);{
  }
  if ((firstCycle == 1) && (counter > ssr3_start) && (counter < ssr3_end)) digitalWriteFast(7, HIGH);{
  }
  if (counter > ssr3_end) digitalWriteFast(7, LOW);{
  }
  
  
  if (counter < ssr4_start) digitalWriteFast(8, LOW);{
  }
  if ((firstCycle == 1) && (counter > ssr4_start) && (counter < ssr4_end)) digitalWriteFast(8, HIGH);{
  }
  if (counter > ssr4_end) digitalWriteFast(8, LOW);{
  }

  
  if (counter < ssr5_start) digitalWriteFast(9, LOW);{
  }
  if ((firstCycle == 1) && (counter > ssr5_start) && (counter < ssr5_end)) digitalWriteFast(9, HIGH);{
  }
  if (counter > ssr5_end) digitalWriteFast(9, LOW);{
  }


  if (counter < potValue2) digitalWriteFast(10, LOW);{
  }
  if ((firstCycle == 1) && (digitalRead(5)== LOW) && (counter > potValue2) && (counter < potValue)) digitalWriteFast(10, HIGH);{
  }
  if (counter > potValue) digitalWriteFast(10, LOW);{
  }

  
  if (counter < ssr7_start) digitalWriteFast(11, LOW);{
  }
  if ((firstCycle == 1) && (counter > ssr7_start) && (counter < ssr7_end)) digitalWriteFast(11, HIGH);{
  }
  if (counter > ssr7_end) digitalWriteFast(11, LOW);{
  }
   
  if (counter < ssr8_start) digitalWriteFast(12, LOW);{
  }
  if ((firstCycle == 1) && (counter > ssr8_start) && (counter < ssr8_end)) digitalWriteFast(12, HIGH);{
  }
  if (counter > ssr8_end) digitalWriteFast(12, LOW);{
  }
}

dmaintenance:
Hi darrob,

yeah i get what you say about 360ppr and 2x inputs gives 720 which is not needed for the counter but if you run it without the InputB the value naturally halves to 360ppr but you loose the reverse detection function.

it's not quite how th encoder is supposed to work, but if you're going to count both phases, you will need to implement the rollover on InputB as well

  void ai1() {
  // ai0 is activated if DigitalPin(3) is going from LOW to HIGH
  // Check with pin(2) to determine the direction
  if(digitalRead(2)==LOW) {
      if (bouncer.update() && bouncer.read() == LOW);
      {
        int counterValue = LOW;
        counterValue = ! counterValue;
        digitalWrite(inputPinB, counterValue);
      }
      if (counter == 0)
        counter = 720;
      counter--;
   }else{
      counter++;
      if (counter == 720)
        counter = 0;
  }

Leave the rest of your sketch as it ws, but just change the ISR for InputB

As I say, I would love to look at the output of one of these when the direction actually changes, I'm sure that there will be a discrepancy in the counts.