I have 4 rotary encoders driving 4 quadrature encoder chips, LS7184, that output some pulses and an up/down direction line.
I bring the pulses into the arduino on D2, D3 (INT0, 1) and D4, D5 (PCINT20, 21).
The up/down lines go in on D6, D7, D14, D15.
I have the ISRs written to set bits in a byte when an interrupt occurs. I want to send the byte out over the serial lines, or at least make an LED flash at the top of loop when I see that an interrupt bit has been set.
I can't seem to get any interrupt created tho. Looking for some help.
There are variables here that read 3 switches and an octal DAC every 5mS and send that out blink without delay style, that works great and is deleted here to meet post length.
Thanks
/* Sketch for Remote Control Transmitter board.
Set up to read from 4-channel ADC and send int values to the Receive board over the serial interface every 10mS.
2 INTs & 2 PCINT's used to detect pulses from four Quadrature Encoders and send out over the RS232 as well with direction.
Also send the state of 2 push buttons.
Octal ADC MCP3208
S3 LED on D8
SYNC LED on D9
*/
/*
Revision to use interrupts
Rewired board some:
D0 - RX - no change
D1 - Tx - no change
D2 - INT0, Optical encoder 0 clk via LS7184
D3 - INT1, Optical encoder 1 clk
D4 - PCINT20, mechanical encoder 0 clk
D5 - PCINT21, mechanical encoder 1 clk
D6 - Optical encoder 0 Up/Down
D7 - Optical encoder 1 Up/Down
D8 - S3 status from Rx card - no change
D9 - Sync status from Rx card - no change
D10 - ADC_SS - no change
D11 - MOSI - no change
D12 - MISO - no change
D13 - SCK - no change
D14 - mechanical encoder 0 Up/Down
D15 - mechanical encoder 1 Up/Down
D16 - S0 switch input - no change
D17 - S1 switch input - no change
D18 - S2 switch input - no change
D19 - not used
*/
// call libraries
#include <SPI.h>
// declare the pins used
// Port B
byte ADC_SS = 10; // SPI SS for ADC
// D11,12,13 - SPI for ADC
byte Syncpin = 9; // Sync output
byte S3pin = 8; // Switch2 output, Hi/Lo received from Serial
// Port C
byte D19 = 19; // not used
byte S2pin = 18; // Switch2 input, Hi/Lo
byte S1pin = 17; // Switch1 input, Hi/Lo
byte S0pin = 16; // Switch0 input, Hi/Lo
byte updown3 = 15;
byte updown2 = 14;
// Port D
byte updown1 = 7;
byte updown0 = 6;
byte enc_clk3 = 5;
byte enc_clk2 = 4;
byte enc_clk1 = 3;
byte enc_clk0 = 2;
// D1, D0 used by Serial
// declare variables
byte ADCsyncbyte = 0x33; // b00110011 sync byte when send ADC data
byte Encsyncbyte = 0xAA; // B10101010 sync byte when send quadrature encoder data
int ADCaddress = 0x0600; // 600, 640, 680, 6C0, 700, 740, 780, 7C0
byte dummyADC = 0;
byte highADC = 0;
byte lowADC = 0;
int x= 0;
byte volatile quadEncoder = 0; // volatile for the interrupts
/* quadEncoder bit assigments:
BIT7 - optical encoder 1 up/down direction
BIT6 - optical encoder 0 up/down direction
BIT5 - mechanical encoder 1 pulse
BIT4 - mechanical encoder 0 pulse
BIT3 - optical encoder 1 pulse
BIT2 - optical encoder 0 pulse
BIT1 - mechanical encoder 1 up/down direction
BIT0 - mechanical encoder 0 up/down direction
Works out well for masking off & mixing in results!
*/
// other variables used in the interrupts
byte volatile dir0;
byte volatile dir1;
byte volatile dir2;
byte volatile dir3;
byte volatile p;
byte volatile oldPortD;
unsigned long previousMillis;
byte address_count;
void setup(){
// setup the I/O pins
pinMode (ADC_SS, OUTPUT);
digitalWrite (ADC_SS, HIGH);
pinMode(enc_clk0, INPUT);
digitalWrite (enc_clk0, HIGH); // enable pullup resistor
pinMode(enc_clk1, INPUT);
digitalWrite (enc_clk1, HIGH); // enable pullup resistor
pinMode(enc_clk2, INPUT);
digitalWrite (enc_clk2, HIGH); // enable pullup resistor
pinMode(enc_clk3, INPUT);
digitalWrite (enc_clk3, HIGH); // enable pullup resistor
pinMode(updown0, INPUT);
digitalWrite (updown0, HIGH); // enable pullup resistor
pinMode(updown1, INPUT);
digitalWrite (updown1, HIGH); // enable pullup resistor
pinMode(updown2, INPUT);
digitalWrite (updown2, HIGH); // enable pullup resistor
pinMode(updown3, INPUT);
digitalWrite (updown3, HIGH); // enable pullup resistor
pinMode(S0pin, INPUT);
digitalWrite (S0pin, HIGH); // enable pullup resistor
pinMode(S1pin, INPUT);
digitalWrite (S1pin, HIGH); // enable pullup resistor
pinMode(S2pin, INPUT);
digitalWrite (S2pin, HIGH); // enable pullup resistor
pinMode(S3pin, OUTPUT);
digitalWrite (S3pin, LOW); // add new wiring to drive LED anode High when S3 on receiver is closed
pinMode(Syncpin, INPUT);
digitalWrite (Syncpin, LOW); // add new wiring to drive LED anode High when Sync message from receiver is returned
// free pin
pinMode (D19, INPUT);
digitalWrite (D19, HIGH);
PCMSK2 = _BV (PCINT4) | _BV (PCINT5); // want pins 20, 21 >> PCMSK2 is port D
PCIFR = _BV (PCIF2) ; // Clear any existing interrupts
PCICR |= _BV (PCIE2) ; // enable pin change interrupts for PCINT20,21 on port D
// Open Serial interface
Serial.begin (115200);
// Open SPI interface
SPI.begin (); // leave blank, we are master
} // end void setup
/*
> 1 Reset
> 2 External Interrupt Request 0 (pin D2) (INT0_vect)
> 3 External Interrupt Request 1 (pin D3) (INT1_vect)
> 6 Pin Change Interrupt Request 2 (pins D0 to D7) (PCINT2_vect)
*/
// ISRs for Hardware interrupts
// Hardware interrupt 0
ISR (INT0_vect) //
{
// optical encoder 0 pulse
dir0 = PORTD & B01000000; // 40
quadEncoder = quadEncoder | B00000100 | dir0; // 04
}
// Hardware interrupt 1
ISR (INT1_vect) //
{
// optical encoder 1 pulse
dir1 = PORTD & B10000000; // 80
quadEncoder = quadEncoder | B0001000 | dir1; // 08
}
// PCINTs for mechanical encoders 0 & 1
ISR (PCINT2_vect) // PCINT2 for port D
{
byte p = PORTD;
// mechanical encoder 0 pulse
if ((p & 0x10) != (oldPortD & 0x10))
{
// portD4, PCINT20, has changed
dir2 = PORTC & B00000001; // 01
quadEncoder = quadEncoder | B00010000 | dir2; // 10
}
// mechanical encoder 0 pulse
if ((p & 0x20) != (oldPortD & 0x020))
{
// portD5, PCINT21, has changed
dir3 = PORTC & B00000010; // 02
quadEncoder = quadEncoder | B00100000 | dir3; // 20
}
// remember for next time
oldPortD = p;
} // end of PCINT2_vect
/*
Watch for an encoder clock pulse, if a pulse occurs then capture that in the ISR with the direction, and at the top of loop set the bits/direction for any of the four that occurred and RS232 message.
On the receive side, set the output bits accordingly & clear.
Change the bias resistor on the LS7184s to shorten up the pulses that create the interrupt, currently around 25uS.
*/
void loop(){
// send out quad encoder data if any occured
if ((quadEncoder & B00111100) !=0){
// serial.println for serial monitor testing
// serial.write for actual use
Serial.println (Encsyncbyte, HEX); // syncbyte = B10101010, 0xAA
Serial.println (quadEncoder, HEX);
quadEncoder = quadEncoder & B11000011; // clear the interrupt bits
}
/* added to make sure loop was running
else{
digitalWrite (Syncpin, HIGH);
delay (50);
digitalWrite (Syncpin, LOW);
delay (50);}
*/
// Split up for DAC & INT responses?
if (Serial.available()>0){
digitalWrite (Syncpin, HIGH); // show receive comimg back
}
else {
digitalWrite (Syncpin, LOW);
}
} // end void loop
LS7183_LS7184.pdf (190 KB)