Australia
Offline
Full Member
Karma: 6
Posts: 161
You dont have to touch powerlines for them to kill you, even looking at them for too long will make them angry.
|
 |
« on: February 17, 2011, 04:55:32 am » |
Hi, I'm having a small issue with my rotary encoder. It seems to only ever count up (generally in multiples of two), I have a feeling it may be my logic, but I cant spot the issue. If someone can have a look, It would be much appreciated. #include <Wire.h>
//Initialise Pins //Encoder Pins static int encoder0PinA = 4; static int encoder0PinB = 5;
//Hold Button static int holdButton = 2;
//Other Variables //Initialise Encoder Variables int encoder0Pos = 0; int encoder0PinALast = LOW; int n = LOW; int rotateFlag = 1; // Flag set if rotation has changed
//Initialise Touchscreen Variables int x,y,ny,nx = 0; //X and Y variable holders for touch value int halfwidth = 500; //Midpoint on Touchscreen X int halfheight = 500; //Midpoint on Touchscreen Y int touchFlag = 0; //Flag set if touch enabled has been sent int prevSend = 0; // holder for previous values of y abnd x
//Initialise Hold Button Variables int holdFlag = 0; //Set if hold button toggled
//Initialise Blinkm Variables int redVal = 0, greenVal = 0, blueVal = 0; int scriptFlag = 0; //Flag set if BlinkM script active unsigned long seconds = millis(); // Used to time start of blinkm script after inactivity on touchscreen
void setup(){ //Init Hold Button pinMode(holdButton,INPUT); digitalWrite(holdButton,HIGH); //Pullup enabled attachInterrupt(0,holdToggle,FALLING); //Hold Button interrupt pin 0 is pin 2
//Initialise Encoder Pins pinMode (encoder0PinA,INPUT); digitalWrite(encoder0PinA,HIGH); //Pullup enabled pinMode (encoder0PinB,INPUT); digitalWrite(encoder0PinB,HIGH); //Pullup enabled
//Init MIDI port Serial.begin(31250);
//Init BlinkM Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("p"); Wire.send(0x00); Wire.send(0); Wire.send(0); Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("f"); Wire.send(20); Wire.endTransmission(); // leave I2C bus }
//Get X value from touchscreen int readX() { int xr=0; pinMode(14, INPUT); // A0 pinMode(15, OUTPUT); // A1 pinMode(16, INPUT); // A2 pinMode(17, OUTPUT); // A3 digitalWrite(15, LOW); // set A1 to GND digitalWrite(17, HIGH); // set A3 as 5V delay(5); // short delay is required to give the analog pins time to adjust to their new roles xr=analogRead(0) - 50; // return xr; }
//Get Y value from touchscreen int readY(){ int yr=0; pinMode(14, OUTPUT); // A0 pinMode(15, INPUT); // A1 pinMode(16, OUTPUT); // A2 pinMode(17, INPUT); // A3 digitalWrite(14, LOW); // set A0 to GND digitalWrite(16, HIGH); // set A2 as 5V delay(5); // short delay is required to give the analog pins time to adjust to their new roles yr=analogRead(1) -50; // return yr;
}
//Toggles Hold on interrupt void holdToggle(){ //Set to !holdflag if (holdFlag ==1){ holdFlag = 0; midiCC(0xB0,92,0x00); //Touchpad up command touchFlag=0; } else holdFlag = 1; }
//Get Rotary Encoder Status int getRot() { n = digitalRead(encoder0PinA); if ((encoder0PinALast == LOW) && (n == HIGH)) { if (digitalRead(encoder0PinB) == LOW) { encoder0Pos--; rotateFlag = 1; } else { encoder0Pos++; rotateFlag = 1; } //Normalise values to 7 bit midi if ( encoder0Pos < 0){ encoder0Pos = encoder0Pos + 127; } else if ( encoder0Pos > 127){ encoder0Pos = encoder0Pos -127; } } else{ rotateFlag = 0; } encoder0PinALast = n; return rotateFlag; //1 of rotated, 0 if not }
void loop() { if(holdFlag == 0){ prevSend = x+y; //quick easy fast calculation prep y = readY(); x = readX(); if(x <1000 && y < 1000){ if(prevSend != x+y){ //check if the buffers changed ny = map(y,0,1016,0,127); // maps the value range of the axis to midi 0->127 nx = map(x,0,1016,0,127); // maps the value range of the axis to midi 0->127 if(touchFlag == 0){ //check if touchpad is enabled. midiCC(0xB0,92,127); //Touchpad down command touchFlag = 1; //set touch flag } midiCC(0xB0, 12, nx); // sends midi control change for touch pad X axis midiCC(0xB0, 13, ny); // sends midi control change for touch pad y axis
//Colour code seconds = millis(); //Record current time int y1 =0, x1 = 0; if (x < halfwidth){ if (y <= halfheight){ //Purple CC 00 CC redVal = 0xCC; greenVal = 0x00; blueVal = 0xCC; } else { //Red FF 00 00 redVal = 0xFF; greenVal = 0x00; blueVal = 0x00;
} } else{ if (x >= halfwidth){ if (y <= halfheight){ //Yell FF FF 00 redVal = 0xFF; greenVal = 0xFF; blueVal = 0x00; } else { //Blue 00 00 FF redVal = 0x00; greenVal = 0x00; blueVal = 0xFF; } } } if (scriptFlag == 0){ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('c'); // ‘c’ == fade to color Wire.send(redVal); // value for red channel Wire.send(greenVal); // value for blue channel Wire.send(blueVal); // value for green channel Wire.endTransmission(); // leave I2C bus } else{ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('o'); // stop Script Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('c'); // ‘c’ == fade to color Wire.send(redVal); // value for red channel Wire.send(greenVal); // value for blue channel Wire.send(blueVal); // value for green channel Wire.endTransmission(); // leave I2C bus scriptFlag = 0; } } } else{ if(touchFlag){ //If touchpad still enabled midiCC(0xB0,92,0x00); //Touchpad up command touchFlag=0; } } } if((seconds + 1000)<millis() && scriptFlag == 0 && holdFlag == 0){ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("p"); Wire.send(0x00); Wire.send(0); Wire.send(0); Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("f"); Wire.send(20); Wire.endTransmission(); // leave I2C bus seconds = millis(); scriptFlag = 1; } if (getRot()){ //If rotary enc changed midiCC(0xC0,0,encoder0Pos); //send command } }
//Send MIDI command void midiCC(char command, char value1, char value2){ Serial.print(command, BYTE); Serial.print(value1, BYTE); Serial.print(value2, BYTE); }
|
|
|
|
|
Logged
|
"Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so." Douglas Adams
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 86
Posts: 9360
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #1 on: February 17, 2011, 06:48:22 am » |
Please try to minimize the sketch with only the rotary encoder that still shows the problem.
|
|
|
|
|
Logged
|
|
|
|
|
Australia
Offline
Full Member
Karma: 6
Posts: 161
You dont have to touch powerlines for them to kill you, even looking at them for too long will make them angry.
|
 |
« Reply #2 on: February 17, 2011, 07:55:11 am » |
I would love to, but my issue is affected by the sketch, Due to the amount of processing involved, it delays interrupts slightly i think. The code you are looking at is mainly the interrupt code called getLoc()
|
|
|
|
|
Logged
|
"Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so." Douglas Adams
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 86
Posts: 9360
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #3 on: February 17, 2011, 08:16:59 am » |
//Toggles Hold on interrupt void holdToggle(){ //Set to !holdflag if (holdFlag ==1){ holdFlag = 0; midiCC(0xB0,92,0x00); //Touchpad up command touchFlag=0; } else holdFlag = 1; } and //Send MIDI command void midiCC(char command, char value1, char value2){ Serial.print(command, BYTE); Serial.print(value1, BYTE); Serial.print(value2, BYTE); } Problem: you do slow serial communication during the IRQ. Sending 3 bytes @ 31250 takes in the order of 1 milliseconds, while IRQ's should be handled in the order of microseconds. Solution: What you should do is change the IRQ routine. The IRQ puts the bytes that need to be send by midiCC in a queue. And that queue will be emptied in the main loop. You have to search for a queue class on the forum or create a sketch specific yourself. IRQ code would become void holdToggle(){ //Set to !holdflag if (holdFlag ==1){ holdFlag = 0; Q.add(0xB0); Q.add(92); Q.add(0x00); touchFlag=0; } else holdFlag = 1; } and loop() void loop() { ... if (Queue.Size() > 3) midiCC(Q.get(), Q,get(), Q.get()); ... } Finally declare all vars used in an IRQ as volatile (that is a far nephew from static) - http://www.arduino.cc/en/Reference/Volatilesucces, Rob
|
|
|
|
|
Logged
|
|
|
|
|
Australia
Offline
Full Member
Karma: 6
Posts: 161
You dont have to touch powerlines for them to kill you, even looking at them for too long will make them angry.
|
 |
« Reply #4 on: February 17, 2011, 09:24:24 am » |
I have implemented your proposed changes, http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265230949/4 using this queue class. I still had the same issue with the encoder not decreasing. I have tried switching to the interrupt based encoder reading but now I cant even see a response. For reference, i am using the http://www.sparkfun.com/products/9786 encoder. The common pin is grounded, the two signal pins are digital 3,4 respectively. (pin 3 being interrupt1) #include <Wire.h> #include "Stack.h"
//Initialise Pins //Encoder Pins static int encoder0PinA = 3; static int encoder0PinB = 4;
//Hold Button static int holdButton = 2;
//Other Variables //Initialise Encoder Variables volatile int encoder0Pos = 0; volatile int encoder0PinALast = LOW; volatile int n = LOW; volatile int rotateFlag = 1; // Flag set if rotation has changed
//Initialise Touchscreen Variables int x,y,ny,nx = 0; //X and Y variable holders for touch value int halfwidth = 500; //Midpoint on Touchscreen X int halfheight = 500; //Midpoint on Touchscreen Y int touchFlag = 0; //Flag set if touch enabled has been sent int prevSend = 0; // holder for previous values of y abnd x
//Init Queue typedef Stack<int,12> IntStack; static IntStack Q;
//Initialise Hold Button Variables int holdFlag = 0; //Set if hold button toggled
//Initialise Blinkm Variables int redVal = 0, greenVal = 0, blueVal = 0; int scriptFlag = 0; //Flag set if BlinkM script active unsigned long seconds = millis(); // Used to time start of blinkm script after inactivity on touchscreen
void setup(){ //Init Hold Button pinMode(holdButton,INPUT); digitalWrite(holdButton,HIGH); //Pullup enabled attachInterrupt(0,holdToggle,FALLING); //Hold Button interrupt pin 0 is pin 2
//Initialise Encoder Pins pinMode (encoder0PinA,INPUT); digitalWrite(encoder0PinA,HIGH); //Pullup enabled pinMode (encoder0PinB,INPUT); digitalWrite(encoder0PinB,HIGH); //Pullup enabled attachInterrupt(1,getRot,LOW); //Hold Button interrupt pin 1 is pin 3
//Init MIDI port Serial.begin(31250);
//Init BlinkM Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("p"); Wire.send(0x00); Wire.send(0); Wire.send(0); Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("f"); Wire.send(20); Wire.endTransmission(); // leave I2C bus }
//Get X value from touchscreen int readX() { int xr=0; pinMode(14, INPUT); // A0 pinMode(15, OUTPUT); // A1 pinMode(16, INPUT); // A2 pinMode(17, OUTPUT); // A3 digitalWrite(15, LOW); // set A1 to GND digitalWrite(17, HIGH); // set A3 as 5V delay(5); // short delay is required to give the analog pins time to adjust to their new roles xr=analogRead(0) - 50; // return xr; }
//Get Y value from touchscreen int readY(){ int yr=0; pinMode(14, OUTPUT); // A0 pinMode(15, INPUT); // A1 pinMode(16, OUTPUT); // A2 pinMode(17, INPUT); // A3 digitalWrite(14, LOW); // set A0 to GND digitalWrite(16, HIGH); // set A2 as 5V delay(5); // short delay is required to give the analog pins time to adjust to their new roles yr=analogRead(1) -50; // return yr;
}
//Toggles Hold on interrupt void holdToggle(){ //Set to !holdflag if (holdFlag ==1){ holdFlag = 0; Q.push(0xB0); Q.push(92); Q.push(0x00); touchFlag=0; } else holdFlag = 1; }
//Get Rotary Encoder Status void getRot() { if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) { /*n = digitalRead(encoder0PinA); if ((encoder0PinALast == LOW) && (n == HIGH)) { if (digitalRead(encoder0PinB) == LOW) {*/ encoder0Pos--; rotateFlag = 1; } else { encoder0Pos++; rotateFlag = 1; } //Normalise values to 7 bit midi if ( encoder0Pos < 0){ encoder0Pos = encoder0Pos + 127; } else if ( encoder0Pos > 127){ encoder0Pos = encoder0Pos -127; } //} else{ rotateFlag = 0; } //encoder0PinALast = n; // return rotateFlag; //1 of rotated, 0 if not }
void loop() { if(holdFlag == 0){ while(Q.size() > 2) midiCC(Q.pop(), Q.pop(), Q.pop()); prevSend = x+y; //quick easy fast calculation prep y = readY(); x = readX(); if(x <1000 && y < 1000){ if(prevSend != x+y){ //check if the buffers changed ny = map(y,0,1016,0,127); // maps the value range of the axis to midi 0->127 nx = map(x,0,1016,0,127); // maps the value range of the axis to midi 0->127 if(touchFlag == 0){ //check if touchpad is enabled. midiCC(0xB0,92,127); //Touchpad down command touchFlag = 1; //set touch flag } midiCC(0xB0, 12, nx); // sends midi control change for touch pad X axis midiCC(0xB0, 13, ny); // sends midi control change for touch pad y axis
//Colour code seconds = millis(); //Record current time int y1 =0, x1 = 0; if (x < halfwidth){ if (y <= halfheight){ //Purple CC 00 CC redVal = 0xCC; greenVal = 0x00; blueVal = 0xCC; } else { //Red FF 00 00 redVal = 0xFF; greenVal = 0x00; blueVal = 0x00;
} } else{ if (x >= halfwidth){ if (y <= halfheight){ //Yell FF FF 00 redVal = 0xFF; greenVal = 0xFF; blueVal = 0x00; } else { //Blue 00 00 FF redVal = 0x00; greenVal = 0x00; blueVal = 0xFF; } } } if (scriptFlag == 0){ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('c'); // ‘c’ == fade to color Wire.send(redVal); // value for red channel Wire.send(greenVal); // value for blue channel Wire.send(blueVal); // value for green channel Wire.endTransmission(); // leave I2C bus } else{ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('o'); // stop Script Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('c'); // ‘c’ == fade to color Wire.send(redVal); // value for red channel Wire.send(greenVal); // value for blue channel Wire.send(blueVal); // value for green channel Wire.endTransmission(); // leave I2C bus scriptFlag = 0; } } } else{ if(touchFlag){ //If touchpad still enabled midiCC(0xB0,92,0x00); //Touchpad up command touchFlag=0; } } }
if((seconds + 1000)<millis() && scriptFlag == 0 && holdFlag == 0){ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("p"); Wire.send(0x00); Wire.send(0); Wire.send(0); Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("f"); Wire.send(20); Wire.endTransmission(); // leave I2C bus seconds = millis(); scriptFlag = 1; } if (rotateFlag){ //If rotary enc changed midiCC(0xC0,0,encoder0Pos); //send command rotateFlag=0; } }
//Send MIDI command void midiCC(char command, char value1, char value2){ Serial.print(command, BYTE); Serial.print(value1, BYTE); Serial.print(value2, BYTE); }
|
|
|
|
|
Logged
|
"Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so." Douglas Adams
|
|
|
|
New Hampshire
Offline
God Member
Karma: 13
Posts: 776
There are 10 kinds of people, those who know binary, and those who don't.
|
 |
« Reply #5 on: February 17, 2011, 12:59:30 pm » |
If I'm reading it right, you're using rotateflag to determine that the rotary dial has been moved. If that's the case, you shouldn't be setting rotateflag = 0 in your ISR. The only time rotateflag remains true after the ISR is executed is when it's wrapped past 0 or 127. So just remove the else { } block from your second if() statement.
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 86
Posts: 9360
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #6 on: February 17, 2011, 01:29:29 pm » |
First a stack is no queue, a stack has a LIFO order where a Queue has a FIFO order. But at least the IRQ is handled faster.
(diving into the code ...)
There are 2 things on pin3 => the IRQ and the static int encoder0PinA = 3; raises questions...
attachInterrupt(1,getRot, LOW); you generate an IRQ when pin 3 is low and in getrot() you test if it is HIGH? That might be the reason why one direction doesn't work...
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 1
Posts: 28
Arduino rocks
|
 |
« Reply #7 on: February 17, 2011, 04:20:00 pm » |
Possibly not germane to your immediate problem, but I think there is a problem with the logic of your roll over code - you describe it as "Normalise values to 7 bit midi".
You will only ever get a value of 127 in encoder0Pos if you approach it from a lower positive value (i.e. counting up as in 123, 124, 125, 126, 127). In the decreasing direction, you test if encoder0Pos is less than zero and then add 127 to it. Well, -1 + 127 = 126 in my part of the world.
Similarly, you will only ever get a value of zero when counting down (6, 5, 4, 3, 2, 1, 0) as your other test does 128 -127 = 1.
In both these cases with your current code, the value changes by two instead of one (i.e. 125, 126, 127, 1, 2, 3 and 2, 1, 0, 126, 125).
Since the count only changes by one each pulse, why do an inequality check when you only need to act if encoder0Pos is (equal to) 128 or -1?
|
|
|
|
|
Logged
|
|
|
|
|
Australia
Offline
Full Member
Karma: 6
Posts: 161
You dont have to touch powerlines for them to kill you, even looking at them for too long will make them angry.
|
 |
« Reply #8 on: February 18, 2011, 01:41:43 am » |
Thanks for the suggestions, As far as I know, this Stack is FIFO. The second usage of Encoder0PinA is to read a value from it in the interrupt code. I have Fixed the wrapping code too. I have now got it going down. At this stage, Turning the encoder one way will increase the value reliably 2 at a time. Turning it the other way will when averaged out, lower the value, but it will not only go down, it goes about 60/40 down to up values. Same 2 at a time value incrementing. #include <Wire.h> #include "Stack.h"
//Initialise Pins //Encoder Pins static int encoder0PinA = 3; static int encoder0PinB = 4;
//Hold Button static int holdButton = 2;
//Other Variables //Initialise Encoder Variables volatile int encoder0Pos = 0; volatile int encoder0PinALast = LOW; volatile int n = LOW; volatile int rotateFlag = 1; // Flag set if rotation has changed
//Initialise Touchscreen Variables int x,y,ny,nx = 0; //X and Y variable holders for touch value int halfwidth = 500; //Midpoint on Touchscreen X int halfheight = 500; //Midpoint on Touchscreen Y int touchFlag = 0; //Flag set if touch enabled has been sent int prevSend = 0; // holder for previous values of y abnd x
//Init Queue typedef Stack<int,3> IntStack; static IntStack Q;
//Initialise Hold Button Variables int holdFlag = 0; //Set if hold button toggled
//Initialise Blinkm Variables int redVal = 0, greenVal = 0, blueVal = 0; int scriptFlag = 0; //Flag set if BlinkM script active unsigned long seconds = millis(); // Used to time start of blinkm script after inactivity on touchscreen
void setup(){ //Init Hold Button pinMode(holdButton,INPUT); digitalWrite(holdButton,HIGH); //Pullup enabled attachInterrupt(0,holdToggle,FALLING); //Hold Button interrupt pin 0 is pin 2
//Initialise Encoder Pins pinMode (encoder0PinA,INPUT); digitalWrite(encoder0PinA,HIGH); //Pullup enabled pinMode (encoder0PinB,INPUT); digitalWrite(encoder0PinB,HIGH); //Pullup enabled attachInterrupt(1,getRot,CHANGE); //Hold Button interrupt pin 1 is pin 3
//Init MIDI port Serial.begin(31250);
//Init BlinkM Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("p"); Wire.send(0x00); Wire.send(0); Wire.send(0); Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("f"); Wire.send(20); Wire.endTransmission(); // leave I2C bus }
//Get X value from touchscreen int readX() { int xr=0; pinMode(14, INPUT); // A0 pinMode(15, OUTPUT); // A1 pinMode(16, INPUT); // A2 pinMode(17, OUTPUT); // A3 digitalWrite(15, LOW); // set A1 to GND digitalWrite(17, HIGH); // set A3 as 5V delay(5); // short delay is required to give the analog pins time to adjust to their new roles xr=analogRead(0) - 50; // return xr; }
//Get Y value from touchscreen int readY(){ int yr=0; pinMode(14, OUTPUT); // A0 pinMode(15, INPUT); // A1 pinMode(16, OUTPUT); // A2 pinMode(17, INPUT); // A3 digitalWrite(14, LOW); // set A0 to GND digitalWrite(16, HIGH); // set A2 as 5V delay(5); // short delay is required to give the analog pins time to adjust to their new roles yr=analogRead(1) -50; // return yr;
}
//Toggles Hold on interrupt void holdToggle(){ //Set to !holdflag if (holdFlag ==1){ holdFlag = 0; Q.push(0xB0); Q.push(92); Q.push(0x00); touchFlag=0; } else holdFlag = 1; }
//Get Rotary Encoder Status void getRot() { if (digitalRead(encoder0PinA) == HIGH) { // found a low-to-high on channel A if (digitalRead(encoder0PinB) == LOW) { // check channel B to see which way // encoder is turning encoder0Pos = encoder0Pos - 1; // CCW rotateFlag = 1; } else { encoder0Pos = encoder0Pos + 1; // CW rotateFlag = 1; } } else // found a high-to-low on channel A { if (digitalRead(encoder0PinB) == LOW) { // check channel B to see which way // encoder is turning encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } }
//Normalise values to 7 bit midi if ( encoder0Pos == -1){ encoder0Pos = encoder0Pos + 127; } else if ( encoder0Pos == 128){ encoder0Pos = encoder0Pos -127; } //} //encoder0PinALast = n; // return rotateFlag; //1 of rotated, 0 if not }
void loop() { if(holdFlag == 0){ while(Q.size() > 2) midiCC(Q.pop(), Q.pop(), Q.pop()); prevSend = x+y; //quick easy fast calculation prep y = readY(); x = readX(); if(x <1000 && y < 1000){ if(prevSend != x+y){ //check if the buffers changed ny = map(y,0,1016,0,127); // maps the value range of the axis to midi 0->127 nx = map(x,0,1016,0,127); // maps the value range of the axis to midi 0->127 if(touchFlag == 0){ //check if touchpad is enabled. midiCC(0xB0,92,127); //Touchpad down command touchFlag = 1; //set touch flag } midiCC(0xB0, 12, nx); // sends midi control change for touch pad X axis midiCC(0xB0, 13, ny); // sends midi control change for touch pad y axis
//Colour code seconds = millis(); //Record current time int y1 =0, x1 = 0; if (x < halfwidth){ if (y <= halfheight){ //Purple CC 00 CC redVal = 0xCC; greenVal = 0x00; blueVal = 0xCC; } else { //Red FF 00 00 redVal = 0xFF; greenVal = 0x00; blueVal = 0x00;
} } else{ if (x >= halfwidth){ if (y <= halfheight){ //Yell FF FF 00 redVal = 0xFF; greenVal = 0xFF; blueVal = 0x00; } else { //Blue 00 00 FF redVal = 0x00; greenVal = 0x00; blueVal = 0xFF; } } } if (scriptFlag == 0){ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('c'); // ‘c’ == fade to color Wire.send(redVal); // value for red channel Wire.send(greenVal); // value for blue channel Wire.send(blueVal); // value for green channel Wire.endTransmission(); // leave I2C bus } else{ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('o'); // stop Script Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send('c'); // ‘c’ == fade to color Wire.send(redVal); // value for red channel Wire.send(greenVal); // value for blue channel Wire.send(blueVal); // value for green channel Wire.endTransmission(); // leave I2C bus scriptFlag = 0; } } } else{ if(touchFlag){ //If touchpad still enabled midiCC(0xB0,92,0x00); //Touchpad up command touchFlag=0; } } }
if((seconds + 1000)<millis() && scriptFlag == 0 && holdFlag == 0){ Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("p"); Wire.send(0x00); Wire.send(0); Wire.send(0); Wire.endTransmission(); // leave I2C bus Wire.begin(); // set up I2C on 4 and 5 analog Wire.beginTransmission(0x09);// join I2C, talk to BlinkM 0x09 Wire.send("f"); Wire.send(20); Wire.endTransmission(); // leave I2C bus seconds = millis(); scriptFlag = 1; } if (rotateFlag){ //If rotary enc changed midiCC(0xC0,0,encoder0Pos); //send command rotateFlag=0; } }
//Send MIDI command void midiCC(char command, char value1, char value2){ Serial.print(command, BYTE); Serial.print(value1, BYTE); Serial.print(value2, BYTE); }
|
|
|
|
|
Logged
|
"Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so." Douglas Adams
|
|
|
|
New Hampshire
Offline
God Member
Karma: 13
Posts: 776
There are 10 kinds of people, those who know binary, and those who don't.
|
 |
« Reply #9 on: February 18, 2011, 09:57:12 am » |
You're only setting your rotateflag when PinA is high.
Since getRot() ONLY gets called when an encoder transition occurs, there's no need for multiple assignments of rotateflag. just set it at the very beginning of the function.
|
|
|
|
|
Logged
|
|
|
|
|
Australia
Offline
Full Member
Karma: 6
Posts: 161
You dont have to touch powerlines for them to kill you, even looking at them for too long will make them angry.
|
 |
« Reply #10 on: February 19, 2011, 05:25:05 am » |
I think i have an answer of sorts. I made a simple sketch in which the interrupt is triggered on CHANGE and set it to report the two pins status. This is the output turning it around one direction: 
|
|
|
|
|
Logged
|
"Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so." Douglas Adams
|
|
|
|
Australia
Offline
Full Member
Karma: 6
Posts: 161
You dont have to touch powerlines for them to kill you, even looking at them for too long will make them angry.
|
 |
« Reply #11 on: February 19, 2011, 06:30:26 am » |
Ah, Success at last. void setup(){ //Initialise Encoder Pins pinMode (encoder0PinA,INPUT); //set pin as input digitalWrite(encoder0PinA,HIGH); //Pullup enabled pinMode (encoder0PinB,INPUT); //set pin as input digitalWrite(encoder0PinB,HIGH); //Pullup enabled attachInterrupt(1,getRot,FALLING); //Rotary encoder interrupt pin 1 is pin 3, interrupt triggers on the pin falling to 0 Serial.begin(9600); }
void getRot() { if (digitalRead(encoder0PinA) == LOW) { // found a low-to-high on channel A if (digitalRead(encoder0PinB) == LOW) { // check pin B to see which way turn is. encoder0Pos = encoder0Pos - 1; // CCW } else { encoder0Pos = encoder0Pos + 1; // CW } } Serial.println(encoder0Pos); //Send value to PC }
void loop(){ //do nothing here because we are using interrupts }
Basically, the encoder is not standard, giving me erratic results when certain test cases were tested. I also added some hardware debouncing to the circuit too to make life easy.
|
|
|
|
|
Logged
|
"Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so." Douglas Adams
|
|
|
|
|