The example relies on both encoder pins being on the same underlying 8 bit port, not only that but bits 0 and 1 of that port. So it is dependent on the pins.
Adding another controller may not work as it is, because the pins may not be pins 0 and 1 of a port. I haven't checked.
Find two pins 0 and 1 on a different port and modify the sketch.
I don't know. Without really taking your code apart, I don't know what the problem is, and to be honest it would probably be quicker to write it for you. But sorry, I don't have the time.
Throw it away and start with a simple sketch with one rotary encoder that just uses getEncoderTurn() and have it report -1, 0, or 1 in the Serial monitor, then build it up from there, a tiny step at a time. And when it breaks go back and sort it out before adding to it.
Some hints.
Because this approach does not use interrupts, you have to keep the loop as fast as possible, on the final system, no delay() and no Serial.print. This will become apparent as some rotating events being missed as you turn the knob. But its not a problem while you are getting it working.
You will need to parameterise getEncoderTurn to take aPin and bPin as arguments. This can be one step once you have got it working with one encoder. Then add another and see how it goes.
Proceed logically in small steps and you will be fine.
Si, this is your code from your book. I just simply added a line to print to the serial the state it is in.
I have tried writing my own code, but I can't quit figure out this encoder business. Frustrating. I was hoping I could modify your code (or any code) to support another encoder.
How embarrasing. But thats the code for project 11 not project 14.
But anyway, don't give up yet! have you got your encoder connected up ok? Did you remember the pull-up resistors? Or use internal ones.
Get this going first:
int aPin = 6;
int bPin = 7;
void setup()
{
pinMode(aPin, INPUT);
pinMode(bPin, INPUT);
Serial.begin(9600);
}
void loop()
{
Serial.print(getEncoderTurn());
}
int getEncoderTurn()
{
// return -1, 0, or +1
static int oldA = LOW;
static int oldB = LOW;
int result = 0;
int newA = digitalRead(aPin);
int newB = digitalRead(bPin);
if (newA != oldA || newB != oldB)
{
// something has changed
if (oldA == LOW && newA == HIGH)
{
result = -(oldB * 2 - 1);
}
}
oldA = newA;
oldB = newB;
return result;
}
If that doesn't work, then your hardware is probably not wired up right.
When you move onto 2 controllers, you will need to modify getEncoderTurn quite a bit, OR just have 2 versions of it getEncoderTurn1 and getEncoderTurn2, because the function holds the state of the controller in static methods, so it would be confused by two rotary controllers.
I have seen that bit of code on a few examples. I can't follow it 100%, but I do know it returns 1,0, or -1. I think I can change it to spit out what I need.
Unfortunately, the code you post only spits out 0's so it must be my hardware. I have the encoders going straight from pin 6 and 7 to the encoder. And the middle pin of the encoder going to ground. I am guessing this is incorrect. What is the proper way to wire this up? Thanks.
Maybe you have some insight into a little bit of craziness. I have everything working, but not well. Here are the few things I can see going wrong.
This is the output, as viewed in serial monitor, of turning the encoder in one direction. "BABBAABABBBBAABABAABBAABBAA" Keep in mind, it prints A or B depending on the direction.
When I view the output from the serial monitor in Arduino, I get a pretty constant output (even if the output seems pretty random). When Processing prints the values, I seem to lose most of my values. For example, I turned the encoder in 1 direction 20 times. It displays only 12 of them. And again, not always in the right direction.
It seems like 90% of time, the encoders only go in one directions. Regardless of which way I turn them.
Arduino:
int Sel_1 = 5; //Select 1
int aPin = 6;
int bPin = 7;
int cPin = 8;
int dPin = 9;
int Sel_2 = 10;
void setup()
{
pinMode(aPin, INPUT);
digitalWrite(aPin, HIGH);
pinMode(bPin, INPUT);
digitalWrite(bPin, HIGH);
pinMode(cPin, INPUT);
digitalWrite(cPin, HIGH);
pinMode(dPin, INPUT);
digitalWrite(dPin, HIGH);
pinMode(Sel_1, INPUT);
pinMode(Sel_2, INPUT);
Serial.begin(115200);
}
void loop()
{
Serial.print(getEncoderTurn_1() );
delay(20);
Serial.print(getEncoderTurn_2() );
delay(20);
Serial.print(getSwitch_1() );
delay(6);
Serial.print(getSwitch_2() );
delay(6);
}
char getEncoderTurn_1()
{
// return -1, 0, or +1
static int oldA = LOW;
static int oldB = LOW;
int result = 0;
char change;
int newA = digitalRead(aPin);
int newB = digitalRead(bPin);
if (newA != oldA || newB != oldB)
{
// something has changed
if (oldA == LOW && newA == HIGH)
{
result = -(oldB * 2 - 1);
}
}
oldA = newA;
oldB = newB;
if ( result >= 1){
change = 'A';
}
else if ( result < 0){
change = 'B';
}
return change;
}
char getEncoderTurn_2()
{
// return -1, 0, or +1
static int oldA = LOW;
static int oldB = LOW;
int result = 0;
char change;
int newA = digitalRead(cPin);
int newB = digitalRead(dPin);
if (newA != oldA || newB != oldB)
{
// something has changed
if (oldA == LOW && newA == HIGH)
{
result = -(oldB * 2 - 1);
}
}
oldA = newA;
oldB = newB;
if ( result >= 1){
change = 'C';
}
else if ( result < 0){
change = 'D';
}
return change;
}
char getSwitch_1()
{
char sw;
int read_sw = digitalRead(Sel_1);
if (read_sw == HIGH){
sw = 'M';
}
else {
sw = 'm'; //Just to see what it's sending.
}
return sw;
}
char getSwitch_2()
{
char sw;
int read_sw = digitalRead(Sel_2);
if (read_sw == HIGH){
sw = 'N';
}
else {
sw = 'n'; //Just to see what it's sending.
}
return sw;
}
It seems like 90% of time, the encoders only go in one directions. Regardless of which way I turn them.
Thats because you have Serial.prints and delays in the loop. It slows it down so it skips transitions. I bet if you turn the knobs really slowly its ok.
I didn't realise the Serial.print was any more than trace. If you want to capture the turns and send them to Processing, then you need to buffer the events and send them to Processing in batches, when no knob turning is going on.
Is that possible? What is the end goal of your project? Etch-a-sketch?
Yes, the end project is an Etch-a-sketch. It's for an art project. I should mention, I am not an art major. I'm an electrical engineer who's not very good at coding.
I've changed my void loop to look like this
void loop()
{
for(int i = 0 ; i < 12 ; i = i+4){
d_send[i] = getEncoderTurn_1();
d_send[i+1] = getEncoderTurn_2();
d_send[i+2] = getSwitch_1();
d_send[i+3] = getSwitch_2();
}
//Serial.print(d_send);
for (int i = 0; i < 12; i++){
Serial.print(d_send[1]);
}
}
And added this variable:
char d_send[12];
But it seems to have a larger problem. When I open the serial monitor, it freezes the serial monitor. When I run the processing code, I just get blanks and then it freezes it too. Ha.
Also, before I changed the code, I noticed it would just keep sending m and n. These were dummy values I created to see what the Arduino was sending when I wasn't clicking the button. It should never be sending m and n. It should only send M or N depending which switch it pressed. This is part of the code I posted earlier. Thanks again for the help.
Imagiro1, all I meant was that you could use potentiometers (variable resistors) instead of the rotary encoders.
With one end connected to +V the other to GND and the slider to an analog in, you can read a value between 0 and 1023 for the position of the knob using analogRead(pin).