1
I Use This!
Very Low Activity

News

Analyzed about 10 hours ago. based on code collected about 10 hours ago.
Posted over 11 years ago by [email protected] (Matthias Hertel)
The last version of the shield with it’s features and internals can be found on http://www.mathertel.de/Arduino/DMXShield.aspx . This new version of the shield has no functional additions, so it works exactly like the shield in version v03 that is in ... [More] use in multiple installations. But there are some improvements by adjusting some values and make its use more flexible when using it on top of an Arduino MEGA and other shields. The most obvious features of the new (V04) version of the DMX Shield are the better placements of some of the components and the addition of all the shield connectors from the current Arduino boards. Fixes to resistor values The values from the optocoupler OK3 transferring the receiving signal in version v03 are adapted to the other optocouplers. The 3 resistors (R4, R5, R6) are used to limit the current for the internal LEDs of the optocouplers. They had 300 or 470 Ohm in the first layout. These values are now made equal to 470 Ohm which is sufficient. The 3 resistors (R7, R8, R9) are used to pull the output value of the optocoupler to HIGH also had different values of 470 or 4,7k Ohm. These values are now also made equal to 4,7k Ohm which is also sufficient. The downside of it is that the resistors are hard to distinguish. I use both adjustments in some installations and they run fine. The error in the naming of R1 and R2 is fixed. Here is a picture of the shield with some assembly hints: Flexibility for Arduino MEGA The signals RX, TX and D2 are now brought to the pins d0, d1, d2 via a solder jumper. These 3 jumpers should be closed by dropping a small part of solder upon them for normal operation with Arduino Uno or Leonardo Boards. If you like to use other serial ports or signals like on the Arduino MEGA you can leave these jumpers open and connect the signals the way you like. The ICSP header of the Arduino board can now be brought to the next shield above the DMX shield by soldering a stackable header. All the 4 holes from the Arduino Uno Board are now also available to the shield for building permanent robust stacks. ICSP header and more pins. All of these extensions are not needed by the DMX shield but it is a good practice to have connection pads and holes at these positions so the signals can be passed through. Some Arduino shields are using the ICSP header to access the SPI signals from the ATmega chip. The Ethernet shield is a good example for that and there are good reasons to do so. Not the new version of the DMX shield has 6 contacts right where a ICSP connector can be soldered to pass through the signals to a shield above. Also 2 of the Arduino header pins have been expanded since some versions. The POWER connector is now 8 pins long and includes IOREF signal. The upper digital connector is now 10 pins long and include the SDA and SCL signals. Because the DMX shield does not need these signals you can leave these pins without soldering a header or use the (old) shorter headers if you like. Partlist DMX Shield Here are the parts you need for a full assembly. It’s also a good order of soldering them. Part name Value Description Starting with the low parts... R4, R5, R6 470 Ω Bands: (yellow, purple, black, brown, brown*) or (yellow, purple, brown, silver*) R7, R8, R9 4,7 kΩ Bands: (yellow, purple, black, black, brown*) or (yellow, purple, red, silver*) The resistors R1 - R3 should be adjusted for the role of the DMX board in your DMX setup. This configuration is for a DMX / RDM Controller. Don't use them when implementing a DMX or RDM Slave. R1, R3 562 Ω Bands: (green, blue, red, black, brown*) R2 133 Ω Bands: (brown, orange, orange, black, brown*) Now the capacitators... C1,C2,C3,C4 100n Capacitors stabilizing the power. Label: 104 The dc-dc converter... DC1 NME 0505 A dc-dc-converter. The chip that provides another 5 v source for the DMX signal converter. Now you can check if the secondary 5v power is existing. Put it on top of an Arduino and measure the voltage at the capacitor C4. It should be near by 5V. The optocouplers and the driver chips... IC1 MAX481CPA A MAX481CPA or MAX485 CPA from Maxim or another supplier used to convert the differential DMX signal into a logical signal.The 8 pin chip can be soldered directly or put on a socket. Be sure to place it in the right direction. OK1, OK2, OK3 6N137 The optocouplers.The 8 pin chip can be soldered directly or put on a socket. Be sure to place it in the right direction. ...and the connectors DMX   1X03 pinhead. I cut it from a longer (20 pin) one. RGB   1X04 pinhead stackable headers   You can solder the usual stackable headers or if you use the shield at the uppermost shield on the Arduino you can solder simple pinheads too. ICSP   There is no need caused by this shield to solder a ICSP. You can solder one if you like to use the shield with another shield above that needs these connections. solder jumpers   Don’t forget to close the jumpers when using a standard Arduino. I will update the article on the web during the next days and will attach some pictures too. I ordered more than I need for my projects so if you are interested in the PCB – let me know. [Less]
Posted over 11 years ago by [email protected] (Matthias Hertel)
The last version of the shield with it’s features and internals can be found on http://www.mathertel.de/Arduino/DMXShield.aspx . This new version of the shield has no functional additions, so it works exactly like the shield in version v03 that is in ... [More] use in multiple installations. But there are some improvements by adjusting some values and make its use more flexible when using it on top of an Arduino MEGA and other shields. The most obvious features of the new (V04) version of the DMX Shield are the better placements of some of the components and the addition of all the shield connectors from the current Arduino boards. Fixes to resistor values The values from the optocoupler OK3 transferring the receiving signal in version v03 are adapted to the other optocouplers. The 3 resistors (R4, R5, R6) are used to limit the current for the internal LEDs of the optocouplers. They had 300 or 470 Ohm in the first layout. These values are now made equal to 470 Ohm which is sufficient. The 3 resistors (R7, R8, R9) are used to pull the output value of the optocoupler to HIGH also had different values of 470 or 4,7k Ohm. These values are now also made equal to 4,7k Ohm which is also sufficient. The downside of it is that the resistors are hard to distinguish. I use both adjustments in some installations and they run fine. The error in the naming of R1 and R2 is fixed. Here is a picture of the shield with some assembly hints: Flexibility for Arduino MEGA The signals RX, TX and D2 are now brought to the pins d0, d1, d2 via a solder jumper. These 3 jumpers should be closed by dropping a small part of solder upon them for normal operation with Arduino Uno or Leonardo Boards. If you like to use other serial ports or signals like on the Arduino MEGA you can leave these jumpers open and connect the signals the way you like. The ICSP header of the Arduino board can now be brought to the next shield above the DMX shield by soldering a stackable header. All the 4 holes from the Arduino Uno Board are now also available to the shield for building permanent robust stacks. ICSP header and more pins. All of these extensions are not needed by the DMX shield but it is a good practice to have connection pads and holes at these positions so the signals can be passed through. Some Arduino shields are using the ICSP header to access the SPI signals from the ATmega chip. The Ethernet shield is a good example for that and there are good reasons to do so. Not the new version of the DMX shield has 6 contacts right where a ICSP connector can be soldered to pass through the signals to a shield above. Also 2 of the Arduino header pins have been expanded since some versions. The POWER connector is now 8 pins long and includes IOREF signal. The upper digital connector is now 10 pins long and include the SDA and SCL signals. Because the DMX shield does not need these signals you can leave these pins without soldering a header or use the (old) shorter headers if you like. Partlist DMX Shield Here are the parts you need for a full assembly. It’s also a good order of soldering them. Part name Value Description Starting with the low parts... R4, R5, R6 470 Ω Bands: (yellow, purple, black, brown, brown*) or (yellow, purple, brown, silver*) R7, R8, R9 4,7 kΩ Bands: (yellow, purple, black, black, brown*) or (yellow, purple, red, silver*) The resistors R1 - R3 should be adjusted for the role of the DMX board in your DMX setup. This configuration is for a DMX / RDM Controller. Don't use them when implementing a DMX or RDM Slave. R1, R3 562 Ω Bands: (green, blue, red, black, brown*) R2 133 Ω Bands: (brown, orange, orange, black, brown*) Now the capacitators... C1,C2,C3,C4 100n Capacitors stabilizing the power. Label: 104 The dc-dc converter... DC1 NME 0505 A dc-dc-converter. The chip that provides another 5 v source for the DMX signal converter. Now you can check if the secondary 5v power is existing. Put it on top of an Arduino and measure the voltage at the capacitor C4. It should be near by 5V. The optocouplers and the driver chips... IC1 MAX481CPA A MAX481CPA or MAX485 CPA from Maxim or another supplier used to convert the differential DMX signal into a logical signal.The 8 pin chip can be soldered directly or put on a socket. Be sure to place it in the right direction. OK1, OK2, OK3 6N137 The optocouplers.The 8 pin chip can be soldered directly or put on a socket. Be sure to place it in the right direction. ...and the connectors DMX   1X03 pinhead. I cut it from a longer (20 pin) one. RGB   1X04 pinhead stackable headers   You can solder the usual stackable headers or if you use the shield at the uppermost shield on the Arduino you can solder simple pinheads too. ICSP   There is no need caused by this shield to solder a ICSP. You can solder one if you like to use the shield with another shield above that needs these connections. solder jumpers   Don’t forget to close the jumpers when using a standard Arduino. I will update the article on the web during the next days and will attach some pictures too. I ordered more than I need for my projects so if you are interested in the PCB – let me know. [Less]
Posted over 11 years ago by [email protected] (Matthias Hertel)
The last version of the shield with it’s features and internals can be found on http://www.mathertel.de/Arduino/DMXShield.aspx . This new version of the shield has no functional additions, so it works exactly like the shield in version v03 that is in ... [More] use in multiple installations. But there are some improvements by adjusting some values and make its use more flexible when using it on top of an Arduino MEGA and other shields. The most obvious features of the new (V04) version of the DMX Shield are the better placements of some of the components and the addition of all the shield connectors from the current Arduino boards. Fixes to resistor values The values from the optocoupler OK3 transferring the receiving signal in version v03 are adapted to the other optocouplers. The 3 resistors (R4, R5, R6) are used to limit the current for the internal LEDs of the optocouplers. They had 300 or 470 Ohm in the first layout. These values are now made equal to 470 Ohm which is sufficient. The 3 resistors (R7, R8, R9) are used to pull the output value of the optocoupler to HIGH also had different values of 470 or 4,7k Ohm. These values are now also made equal to 4,7k Ohm which is also sufficient. The downside of it is that the resistors are hard to distinguish. I use both adjustments in some installations and they run fine. The error in the naming of R1 and R2 is fixed. Here is a picture of the shield with some assembly hints: Flexibility for Arduino MEGA The signals RX, TX and D2 are now brought to the pins d0, d1, d2 via a solder jumper. These 3 jumpers should be closed by dropping a small part of solder upon them for normal operation with Arduino Uno or Leonardo Boards. If you like to use other serial ports or signals like on the Arduino MEGA you can leave these jumpers open and connect the signals the way you like. The ICSP header of the Arduino board can now be brought to the next shield above the DMX shield by soldering a stackable header. All the 4 holes from the Arduino Uno Board are now also available to the shield for building permanent robust stacks. ICSP header and more pins. All of these extensions are not needed by the DMX shield but it is a good practice to have connection pads and holes at these positions so the signals can be passed through. Some Arduino shields are using the ICSP header to access the SPI signals from the ATmega chip. The Ethernet shield is a good example for that and there are good reasons to do so. Not the new version of the DMX shield has 6 contacts right where a ICSP connector can be soldered to pass through the signals to a shield above. Also 2 of the Arduino header pins have been expanded since some versions. The POWER connector is now 8 pins long and includes IOREF signal. The upper digital connector is now 10 pins long and include the SDA and SCL signals. Because the DMX shield does not need these signals you can leave these pins without soldering a header or use the (old) shorter headers if you like. Partlist DMX Shield Here are the parts you need for a full assembly. It’s also a good order of soldering them. Part name Value Description Starting with the low parts... R4, R5, R6 470 Ω Bands: (yellow, purple, black, brown, brown*) or (yellow, purple, brown, silver*) R7, R8, R9 4,7 kΩ Bands: (yellow, purple, black, black, brown*) or (yellow, purple, red, silver*) The resistors R1 - R3 should be adjusted for the role of the DMX board in your DMX setup. This configuration is for a DMX / RDM Controller. Don't use them when implementing a DMX or RDM Slave. R1, R3 562 Ω Bands: (green, blue, red, black, brown*) R2 133 Ω Bands: (brown, orange, orange, black, brown*) Now the capacitators... C1,C2,C3,C4 100n Capacitors stabilizing the power. Label: 104 The dc-dc converter... DC1 NME 0505 A dc-dc-converter. The chip that provides another 5 v source for the DMX signal converter. Now you can check if the secondary 5v power is existing. Put it on top of an Arduino and measure the voltage at the capacitor C4. It should be near by 5V. The optocouplers and the driver chips... IC1 MAX481CPA A MAX481CPA or MAX485 CPA from Maxim or another supplier used to convert the differential DMX signal into a logical signal.The 8 pin chip can be soldered directly or put on a socket. Be sure to place it in the right direction. OK1, OK2, OK3 6N137 The optocouplers.The 8 pin chip can be soldered directly or put on a socket. Be sure to place it in the right direction. ...and the connectors DMX   1X03 pinhead. I cut it from a longer (20 pin) one. RGB   1X04 pinhead stackable headers   You can solder the usual stackable headers or if you use the shield at the uppermost shield on the Arduino you can solder simple pinheads too. ICSP   There is no need caused by this shield to solder a ICSP. You can solder one if you like to use the shield with another shield above that needs these connections. solder jumpers   Don’t forget to close the jumpers when using a standard Arduino. I will update the article on the web during the next days and will attach some pictures too. I ordered more than I need for my projects so if you are interested in the PCB – let me know. [Less]
Posted almost 12 years ago by [email protected] (Matthias Hertel)
Here you can find an Arduino compatible library for using rotary encoders. I was searching a library for using a rotary encoder in my latest project and found a lot of information on this topic but none of the existing libraries did immediately match ... [More] my expectations so I finally built my own. This article likes to explain the software mechanisms used in detail so you can understand the coding and might be able to adjust it to your needs if you like. There are various aspects when writing a library for rotary encoders and you can also find a lot of the sources I analyzed at the bottom of this article. Download from http://www.mathertel.de/Arduino/RotaryEncoderStart.aspx Rotary Encoder signals The signals a rotary encoder produces (and what can be handled by this library) are based on a 2-bit gray code available on 2 digital data signal lines. The typical encoders use 3 output pins: 2 for the signals and one for the common signal usually GND. There are 4 possible combinations of on and off on these 2 signal lines that can be seen on this video: Rotary Encoder signal generation The rotary encoder usually has a detent mechanism that holds the knob in place when both contacts are open.  when rotating the knob the two contacts will be connected to the common signal one by one. A common cabling is to use the ground as the common signal and use pull-up resistors to have a HIGH signal when the contacts are open. The Arduino processor has internal pull-up resistors on all input pins that can be enabled by software. Have a look at the inline comments of the library. The bouncing problem When using contacts there is no exact ON and OFF condition while switching because the contacts never close exactly and especially older contacts or dirty contacts generate a lot of fast ON/OFF sequences (sometimes called noise). Hopefully when you stop turning the knob the contact situation should be fixed. If not, try to clean or throw it away and buy a new one. By using a capacitor it is possible to build a low pass filter that reduce the bouncing effect and eliminates the very small spikes. If you ever have like to use this solution put the capacitor as near as possible to the contacts. 100nF will do here. Another solution is to detect changes of the signal in a very small timeframe and ignore them. You can find a solution using this approach on the Arduino playground article. The solution I found in some of the libraries around is to exactly follow all the 4 possible states of the signals that a switch will pass when being turned from one position to the next and detect the next position only when reaching a detent state. Even when a bouncing will occur it will not change the position counting more than once. High Frequency There are library approaches that can handle high frequency rotary encoders. I only use the rotary encoder with my fingers (not by using a motor) and have not found any problems for that speed. However with the library it is important to have a look at the signals every few microseconds or at least when a signal has changed. So give the library often a try to detect the situation or use an interrupt. You can tweak reading the ports by using the bitRead function or a direct read of the Port, but the library looses some of the compatibility with the Arduino style of programming because you have to know the exact hardware definitions. If you need more advanced support for decoding signals from encoders have a look at the optical solutions and processors like the ATXMEGA that includes hardware support for reading position fromQuadrature Encoders. Counting States Many of the sources use two variables for storing the levels of the 2 signal lines. I found it more practical to use a number between 0 and 3 for a specific state. The first signal line counts for the value 1 and the second counts for the value 2. The addition of both values is used. Because the digitalRead function returns 0 or 1 this can be done by using a bit-shift and addition:thisState = sig1 + 2 * sig2; or more effective:thisState = sig1 | (sig2 << 1); Transitions within states Detecting a movement of the knob is now identical to detect a transition from one state to the next one. Not all transitions are valid and when both signals change at once there is something wrong with the signals. Here is a straight forward implementation for calculating the position of the knob from an old (last known) state and the current state:if ((oldState == 3) && (thisState == 1)) { knobPosition++; } else if ((oldState == 1) && (thisState == 0)) { knobPosition++; } else if ((oldState == 0) && (thisState == 2)) { knobPosition++; } else if ((oldState == 2) && (thisState == 3)) { knobPosition++; } else if ((oldState == 3) && (thisState == 2)) { knobPosition--; } else if ((oldState == 2) && (thisState == 0)) { knobPosition--; } else if ((oldState == 0) && (thisState == 1)) { knobPosition--; } else if ((oldState == 1) && (thisState == 3)) { knobPosition--; } // if But this solution uses a lot of programming instructions and also seems to be slow (especially when turning left). A small static array can help reducing time and space. The implementation from brianlow also uses a  table and almost the same trick: calculate an unique index from the oldState and the newState and make a lookup into a array of integers:index = thisState + 4 * oldState; or more effective:index = thisState | (oldState<<2); The array holds the values –1 for the entries where a position was decremented, a 1 for the entries where the position was incremented and 0 in all the other (no change or not valid) cases:const int8_t KNOBDIR[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; Updating the position counter of the rotary encoder now is an simple formula: knobPosition += KNOBDIR[thisState | (oldPos<<2)]; Every time the current state is equal to 3 the rotary encoder is in the next valid position and a new official position can be made available by dividing the internal counter by 4 (or shifting right by 2):if (thisState == 3) knobPositionExtern = knobPosition>>2; The resulting implementation now is very small and obviously very fast. Also situations where the knob is not turned completely from one official position to another is handled correctly. The only thing that is critical is that every state change has to be detected and the check routine implementing this functionality has to be called often at minimum once per state change. The Return Most implementations I found calculate a integer number for the position of the knob others return a “right” or “left”. I found the support for a position value very useful in my projects and therefore stay with this approach. To read the current position just use the getPosition() function. However I added the possibility to change the position from a sketch by calling setPosition(newPosition) and you can use that for relative movement detection. Using Polling The simplest approach of checking the state of the rotary encoder is to poll the signals as often as you can. Just call the tick() function as often as you can and then use the position value for your needs. The SimplePollRotator example just does this and prints out the current position when changed. Using interrupts Constantly polling the current state of the rotary encoder is sometimes a void time and resource consumption. Especially when dealing with other topics in your sketch that can take a while you might not have the time for polling. A good approach is to use the pin change interrupt feature available in the ATMega processors. The Arduino environment has no direct support for this kind of interrupts so programming an Interrupt Service Routine (ISR) is required. It is important to keep ISR implementations as small and fast as possible. The only thing that has to be done is to call the tick() function. The logic of your sketch should be implemented in the loop function. All the IO pins on Atmega168 can be used for Pin Change Interrupts Here is the implementation for the pin change interrupt in the case you have used the A2 and A3 lines for the encoder. Enable the Pin Change Interrupt 1 in general that covers the Analog input pins or Port C:PCICR |= (1 << PCIE1); Now enable the interrupt for pin 2 and 3 of Port C:PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  Now the Interrupt Service Routine only has to call the tick function:ISR(PCINT1_vect) { encoder.tick(); // just call tick() to check the state. } You can also find this in the InterruptRotator example. The Examples SimplePollRotator This example checks the state of the rotary encoder in the loop() function. The current position is printed on output when changed. SimplePollRotatorLCD The same example as SimplePollRotator but output to an LCD display. You may need to include another LCD library when not using the LiquidCrystal_PCF8574 library. (LCD using SPI) InterruptRotator This example checks the state of the rotary encoder by using interrupts as described above. In this example, when reaching position 66 the output will freeze for 6.6 seconds. The further turned positions will be recognized anyway because the interrupt still works in the background.The output is correct 6.6 seconds later. Links Some discussions on simple rotary approaches: http://playground.arduino.cc/Main/RotaryEncoders A datasheet of a typical rotary encoder: http://www.hobbytronics.co.uk/datasheets/TW-700198.pdf The gray code explained: http://en.wikipedia.org/wiki/Gray_code. Some other rotary decoder implementations: https://github.com/brianlow/Rotary/blob/master/Rotary.cpp http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html IO Performance: http://www.instructables.com/id/Arduino-is-Slow-and-how-to-fix-it/ http://forum.arduino.cc/index.php/topic,68656.0.html http://jeelabs.org/2010/01/06/pin-io-performance/ http://garretlab.web.fc2.com/en/arduino/inside/arduino/wiring_digital.c/digitalRead.html Interrupts http://playground.arduino.cc/Main/PcIntMore: http://www.atmel.com/Images/doc8109.pdf [Less]
Posted almost 12 years ago by [email protected] (Matthias Hertel)
Here you can find an Arduino compatible library for using rotary encoders. I was searching a library for using a rotary encoder in my latest project and found a lot of information on this topic but none of the existing libraries did immediately match ... [More] my expectations so I finally built my own. This article likes to explain the software mechanisms used in detail so you can understand the coding and might be able to adjust it to your needs if you like. There are various aspects when writing a library for rotary encoders and you can also find a lot of the sources I analyzed at the bottom of this article. Download from http://www.mathertel.de/Arduino/RotaryEncoderStart.aspx Rotary Encoder signals The signals a rotary encoder produces (and what can be handled by this library) are based on a 2-bit gray code available on 2 digital data signal lines. The typical encoders use 3 output pins: 2 for the signals and one for the common signal usually GND. There are 4 possible combinations of on and off on these 2 signal lines that can be seen on this video: Rotary Encoder signal generation The rotary encoder usually has a detent mechanism that holds the knob in place when both contacts are open.  when rotating the knob the two contacts will be connected to the common signal one by one. A common cabling is to use the ground as the common signal and use pull-up resistors to have a HIGH signal when the contacts are open. The Arduino processor has internal pull-up resistors on all input pins that can be enabled by software. Have a look at the inline comments of the library. The bouncing problem When using contacts there is no exact ON and OFF condition while switching because the contacts never close exactly and especially older contacts or dirty contacts generate a lot of fast ON/OFF sequences (sometimes called noise). Hopefully when you stop turning the knob the contact situation should be fixed. If not, try to clean or throw it away and buy a new one. By using a capacitor it is possible to build a low pass filter that reduce the bouncing effect and eliminates the very small spikes. If you ever have like to use this solution put the capacitor as near as possible to the contacts. 100nF will do here. Another solution is to detect changes of the signal in a very small timeframe and ignore them. You can find a solution using this approach on the Arduino playground article. The solution I found in some of the libraries around is to exactly follow all the 4 possible states of the signals that a switch will pass when being turned from one position to the next and detect the next position only when reaching a detent state. Even when a bouncing will occur it will not change the position counting more than once. High Frequency There are library approaches that can handle high frequency rotary encoders. I only use the rotary encoder with my fingers (not by using a motor) and have not found any problems for that speed. However with the library it is important to have a look at the signals every few microseconds or at least when a signal has changed. So give the library often a try to detect the situation or use an interrupt. You can tweak reading the ports by using the bitRead function or a direct read of the Port, but the library looses some of the compatibility with the Arduino style of programming because you have to know the exact hardware definitions. If you need more advanced support for decoding signals from encoders have a look at the optical solutions and processors like the ATXMEGA that includes hardware support for reading position fromQuadrature Encoders. Counting States Many of the sources use two variables for storing the levels of the 2 signal lines. I found it more practical to use a number between 0 and 3 for a specific state. The first signal line counts for the value 1 and the second counts for the value 2. The addition of both values is used. Because the digitalRead function returns 0 or 1 this can be done by using a bit-shift and addition:thisState = sig1 + 2 * sig2; or more effective:thisState = sig1 | (sig2 << 1); Transitions within states Detecting a movement of the knob is now identical to detect a transition from one state to the next one. Not all transitions are valid and when both signals change at once there is something wrong with the signals. Here is a straight forward implementation for calculating the position of the knob from an old (last known) state and the current state:if ((oldState == 3) && (thisState == 1)) { knobPosition++; } else if ((oldState == 1) && (thisState == 0)) { knobPosition++; } else if ((oldState == 0) && (thisState == 2)) { knobPosition++; } else if ((oldState == 2) && (thisState == 3)) { knobPosition++; } else if ((oldState == 3) && (thisState == 2)) { knobPosition--; } else if ((oldState == 2) && (thisState == 0)) { knobPosition--; } else if ((oldState == 0) && (thisState == 1)) { knobPosition--; } else if ((oldState == 1) && (thisState == 3)) { knobPosition--; } // if But this solution uses a lot of programming instructions and also seems to be slow (especially when turning left). A small static array can help reducing time and space. The implementation from brianlow also uses a  table and almost the same trick: calculate an unique index from the oldState and the newState and make a lookup into a array of integers:index = thisState + 4 * oldState; or more effective:index = thisState | (oldState<<2); The array holds the values –1 for the entries where a position was decremented, a 1 for the entries where the position was incremented and 0 in all the other (no change or not valid) cases:const int8_t KNOBDIR[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; Updating the position counter of the rotary encoder now is an simple formula: knobPosition += KNOBDIR[thisState | (oldPos<<2)]; Every time the current state is equal to 3 the rotary encoder is in the next valid position and a new official position can be made available by dividing the internal counter by 4 (or shifting right by 2):if (thisState == 3) knobPositionExtern = knobPosition>>2; The resulting implementation now is very small and obviously very fast. Also situations where the knob is not turned completely from one official position to another is handled correctly. The only thing that is critical is that every state change has to be detected and the check routine implementing this functionality has to be called often at minimum once per state change. The Return Most implementations I found calculate a integer number for the position of the knob others return a “right” or “left”. I found the support for a position value very useful in my projects and therefore stay with this approach. To read the current position just use the getPosition() function. However I added the possibility to change the position from a sketch by calling setPosition(newPosition) and you can use that for relative movement detection. Using Polling The simplest approach of checking the state of the rotary encoder is to poll the signals as often as you can. Just call the tick() function as often as you can and then use the position value for your needs. The SimplePollRotator example just does this and prints out the current position when changed. Using interrupts Constantly polling the current state of the rotary encoder is sometimes a void time and resource consumption. Especially when dealing with other topics in your sketch that can take a while you might not have the time for polling. A good approach is to use the pin change interrupt feature available in the ATMega processors. The Arduino environment has no direct support for this kind of interrupts so programming an Interrupt Service Routine (ISR) is required. It is important to keep ISR implementations as small and fast as possible. The only thing that has to be done is to call the tick() function. The logic of your sketch should be implemented in the loop function. All the IO pins on Atmega168 can be used for Pin Change Interrupts Here is the implementation for the pin change interrupt in the case you have used the A2 and A3 lines for the encoder. Enable the Pin Change Interrupt 1 in general that covers the Analog input pins or Port C:PCICR |= (1 << PCIE1); Now enable the interrupt for pin 2 and 3 of Port C:PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  Now the Interrupt Service Routine only has to call the tick function:ISR(PCINT1_vect) { encoder.tick(); // just call tick() to check the state. } You can also find this in the InterruptRotator example. The Examples SimplePollRotator This example checks the state of the rotary encoder in the loop() function. The current position is printed on output when changed. SimplePollRotatorLCD The same example as SimplePollRotator but output to an LCD display. You may need to include another LCD library when not using the LiquidCrystal_PCF8574 library. (LCD using SPI) InterruptRotator This example checks the state of the rotary encoder by using interrupts as described above. In this example, when reaching position 66 the output will freeze for 6.6 seconds. The further turned positions will be recognized anyway because the interrupt still works in the background.The output is correct 6.6 seconds later. Links Some discussions on simple rotary approaches: http://playground.arduino.cc/Main/RotaryEncoders A datasheet of a typical rotary encoder: http://www.hobbytronics.co.uk/datasheets/TW-700198.pdf The gray code explained: http://en.wikipedia.org/wiki/Gray_code. Some other rotary decoder implementations: https://github.com/brianlow/Rotary/blob/master/Rotary.cpp http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html IO Performance: http://www.instructables.com/id/Arduino-is-Slow-and-how-to-fix-it/ http://forum.arduino.cc/index.php/topic,68656.0.html http://jeelabs.org/2010/01/06/pin-io-performance/ http://garretlab.web.fc2.com/en/arduino/inside/arduino/wiring_digital.c/digitalRead.html Interrupts http://playground.arduino.cc/Main/PcIntMore: http://www.atmel.com/Images/doc8109.pdf [Less]
Posted almost 12 years ago by [email protected] (Matthias Hertel)
Here you can find an Arduino compatible library for using rotary encoders. I was searching a library for using a rotary encoder in my latest project and found a lot of information on this topic but none of the existing libraries did immediately match ... [More] my expectations so I finally built my own. This article likes to explain the software mechanisms used in detail so you can understand the coding and might be able to adjust it to your needs if you like. There are various aspects when writing a library for rotary encoders and you can also find a lot of the sources I analyzed at the bottom of this article. Download from http://www.mathertel.de/Arduino/RotaryEncoderStart.aspx Rotary Encoder signals The signals a rotary encoder produces (and what can be handled by this library) are based on a 2-bit gray code available on 2 digital data signal lines. The typical encoders use 3 output pins: 2 for the signals and one for the common signal usually GND. There are 4 possible combinations of on and off on these 2 signal lines that can be seen on this video: Rotary Encoder signal generation The rotary encoder usually has a detent mechanism that holds the knob in place when both contacts are open.  when rotating the knob the two contacts will be connected to the common signal one by one. A common cabling is to use the ground as the common signal and use pull-up resistors to have a HIGH signal when the contacts are open. The Arduino processor has internal pull-up resistors on all input pins that can be enabled by software. Have a look at the inline comments of the library. The bouncing problem When using contacts there is no exact ON and OFF condition while switching because the contacts never close exactly and especially older contacts or dirty contacts generate a lot of fast ON/OFF sequences (sometimes called noise). Hopefully when you stop turning the knob the contact situation should be fixed. If not, try to clean or throw it away and buy a new one. By using a capacitor it is possible to build a low pass filter that reduce the bouncing effect and eliminates the very small spikes. If you ever have like to use this solution put the capacitor as near as possible to the contacts. 100nF will do here. Another solution is to detect changes of the signal in a very small timeframe and ignore them. You can find a solution using this approach on the Arduino playground article. The solution I found in some of the libraries around is to exactly follow all the 4 possible states of the signals that a switch will pass when being turned from one position to the next and detect the next position only when reaching a detent state. Even when a bouncing will occur it will not change the position counting more than once. High Frequency There are library approaches that can handle high frequency rotary encoders. I only use the rotary encoder with my fingers (not by using a motor) and have not found any problems for that speed. However with the library it is important to have a look at the signals every few microseconds or at least when a signal has changed. So give the library often a try to detect the situation or use an interrupt. You can tweak reading the ports by using the bitRead function or a direct read of the Port, but the library looses some of the compatibility with the Arduino style of programming because you have to know the exact hardware definitions. If you need more advanced support for decoding signals from encoders have a look at the optical solutions and processors like the ATXMEGA that includes hardware support for reading position fromQuadrature Encoders. Counting States Many of the sources use two variables for storing the levels of the 2 signal lines. I found it more practical to use a number between 0 and 3 for a specific state. The first signal line counts for the value 1 and the second counts for the value 2. The addition of both values is used. Because the digitalRead function returns 0 or 1 this can be done by using a bit-shift and addition:thisState = sig1 + 2 * sig2; or more effective:thisState = sig1 | (sig2 << 1); Transitions within states Detecting a movement of the knob is now identical to detect a transition from one state to the next one. Not all transitions are valid and when both signals change at once there is something wrong with the signals. Here is a straight forward implementation for calculating the position of the knob from an old (last known) state and the current state:if ((oldState == 3) && (thisState == 1)) { knobPosition++; } else if ((oldState == 1) && (thisState == 0)) { knobPosition++; } else if ((oldState == 0) && (thisState == 2)) { knobPosition++; } else if ((oldState == 2) && (thisState == 3)) { knobPosition++; } else if ((oldState == 3) && (thisState == 2)) { knobPosition--; } else if ((oldState == 2) && (thisState == 0)) { knobPosition--; } else if ((oldState == 0) && (thisState == 1)) { knobPosition--; } else if ((oldState == 1) && (thisState == 3)) { knobPosition--; } // if But this solution uses a lot of programming instructions and also seems to be slow (especially when turning left). A small static array can help reducing time and space. The implementation from brianlow also uses a  table and almost the same trick: calculate an unique index from the oldState and the newState and make a lookup into a array of integers:index = thisState + 4 * oldState; or more effective:index = thisState | (oldState<<2); The array holds the values –1 for the entries where a position was decremented, a 1 for the entries where the position was incremented and 0 in all the other (no change or not valid) cases:const int8_t KNOBDIR[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; Updating the position counter of the rotary encoder now is an simple formula: knobPosition += KNOBDIR[thisState | (oldPos<<2)]; Every time the current state is equal to 3 the rotary encoder is in the next valid position and a new official position can be made available by dividing the internal counter by 4 (or shifting right by 2):if (thisState == 3) knobPositionExtern = knobPosition>>2; The resulting implementation now is very small and obviously very fast. Also situations where the knob is not turned completely from one official position to another is handled correctly. The only thing that is critical is that every state change has to be detected and the check routine implementing this functionality has to be called often at minimum once per state change. The Return Most implementations I found calculate a integer number for the position of the knob others return a “right” or “left”. I found the support for a position value very useful in my projects and therefore stay with this approach. To read the current position just use the getPosition() function. However I added the possibility to change the position from a sketch by calling setPosition(newPosition) and you can use that for relative movement detection. Using Polling The simplest approach of checking the state of the rotary encoder is to poll the signals as often as you can. Just call the tick() function as often as you can and then use the position value for your needs. The SimplePollRotator example just does this and prints out the current position when changed. Using interrupts Constantly polling the current state of the rotary encoder is sometimes a void time and resource consumption. Especially when dealing with other topics in your sketch that can take a while you might not have the time for polling. A good approach is to use the pin change interrupt feature available in the ATMega processors. The Arduino environment has no direct support for this kind of interrupts so programming an Interrupt Service Routine (ISR) is required. It is important to keep ISR implementations as small and fast as possible. The only thing that has to be done is to call the tick() function. The logic of your sketch should be implemented in the loop function. All the IO pins on Atmega168 can be used for Pin Change Interrupts Here is the implementation for the pin change interrupt in the case you have used the A2 and A3 lines for the encoder. Enable the Pin Change Interrupt 1 in general that covers the Analog input pins or Port C:PCICR |= (1 << PCIE1); Now enable the interrupt for pin 2 and 3 of Port C:PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  Now the Interrupt Service Routine only has to call the tick function:ISR(PCINT1_vect) { encoder.tick(); // just call tick() to check the state. } You can also find this in the InterruptRotator example. The Examples SimplePollRotator This example checks the state of the rotary encoder in the loop() function. The current position is printed on output when changed. SimplePollRotatorLCD The same example as SimplePollRotator but output to an LCD display. You may need to include another LCD library when not using the LiquidCrystal_PCF8574 library. (LCD using SPI) InterruptRotator This example checks the state of the rotary encoder by using interrupts as described above. In this example, when reaching position 66 the output will freeze for 6.6 seconds. The further turned positions will be recognized anyway because the interrupt still works in the background.The output is correct 6.6 seconds later. Links Some discussions on simple rotary approaches: http://playground.arduino.cc/Main/RotaryEncoders A datasheet of a typical rotary encoder: http://www.hobbytronics.co.uk/datasheets/TW-700198.pdf The gray code explained: http://en.wikipedia.org/wiki/Gray_code. Some other rotary decoder implementations: https://github.com/brianlow/Rotary/blob/master/Rotary.cpp http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html IO Performance: http://www.instructables.com/id/Arduino-is-Slow-and-how-to-fix-it/ http://forum.arduino.cc/index.php/topic,68656.0.html http://jeelabs.org/2010/01/06/pin-io-performance/ http://garretlab.web.fc2.com/en/arduino/inside/arduino/wiring_digital.c/digitalRead.html Interrupts http://playground.arduino.cc/Main/PcIntMore: http://www.atmel.com/Images/doc8109.pdf [Less]
Posted about 12 years ago by [email protected] (Matthias Hertel)
  In the last weeks I got some very valuable feedback and some corrections for the DMXSerial2 library for Arduino from Felicitus and he asked me to put the sources into the GitHub repository. I am used to work with Subversion and never worked with ... [More] Git before but everything runs perfectly. I love the way how someone can add merge requests to an existing repository without the need to manage users and roles. So you can find the library now on:https://github.com/mathertel/DmxSerial2. You can download the complete library including the samples by using the “Download ZIP” button on the right-hand side or by using the linkhttps://github.com/mathertel/DmxSerial2/archive/master.zip I plan to also leave a copy of the other Arduino libraries there. [Less]
Posted about 12 years ago by [email protected] (Matthias Hertel)
  In the last weeks I got some very valuable feedback and some corrections for the DMXSerial2 library for Arduino from Felicitus and he asked me to put the sources into the GitHub repository. I am used to work with Subversion and never worked with ... [More] Git before but everything runs perfectly. I love the way how someone can add merge requests to an existing repository without the need to manage users and roles. So you can find the library now on:https://github.com/mathertel/DmxSerial2. You can download the complete library including the samples by using the “Download ZIP” button on the right-hand side or by using the linkhttps://github.com/mathertel/DmxSerial2/archive/master.zip I plan to also leave a copy of the other Arduino libraries there. [Less]
Posted over 12 years ago by [email protected] (Matthias Hertel)
IT’s some months ago since I released the first version of DMXSerial2. Now there is an update with some fixes and some more complete functionality. First of all thanks to Simon Newton who shared the link to a copy of the RDM standard E1.20. A ... [More] download is available at http://tsp.plasa.org/freestandards. “Now there are no more excuses for not complying with the standard” – he writes and I will try to do so. In the update you can the following additions: The serial port definitions now also support Arduino MEGA 2560 (port 0 and 1) and Arduino Leonardo (port 1) boards. I registered my own manufacurer id, now #0987 for mathertel.de. There is a functionality that creates random device ids in the code. If a board once has started to work the device id will be stored into the eeprom and will remain there even when new software is uploaded. I added the required RDM parameters SOFTWARE_VERSION_LABEL and SUPPORTED_PARAMETERS to comply with the standard. Finally I removed some DMX-only specific code and did some simplifications and memory optimizations. The initialization data for the library is now combined into a new structure. It was an easy job to register a manufacturer id to myself as explained on http://tsp.plasa.org/tsp/working_groups/CP/mfctrIDs.php. Feel free to use my manufacturer id yourself if you promise only to use it for experiments and never to put a real device that leaves your hands.If you plan for more please request your own manufacturer id and adjust the _devID definition to use it. You can find the new version of the library now on http://www.mathertel.de/Arduino/DMXSerial2.aspx. I will update the text of this site in the next days. [Less]
Posted over 12 years ago by [email protected] (Matthias Hertel)
IT’s some months ago since I released the first version of DMXSerial2. Now there is an update with some fixes and some more complete functionality. First of all thanks to Simon Newton who shared the link to a copy of the RDM standard E1.20. A ... [More] download is available at http://tsp.plasa.org/freestandards. “Now there are no more excuses for not complying with the standard” – he writes and I will try to do so. In the update you can the following additions: The serial port definitions now also support Arduino MEGA 2560 (port 0 and 1) and Arduino Leonardo (port 1) boards. I registered my own manufacurer id, now #0987 for mathertel.de. There is a functionality that creates random device ids in the code. If a board once has started to work the device id will be stored into the eeprom and will remain there even when new software is uploaded. I added the required RDM parameters SOFTWARE_VERSION_LABEL and SUPPORTED_PARAMETERS to comply with the standard. Finally I removed some DMX-only specific code and did some simplifications and memory optimizations. The initialization data for the library is now combined into a new structure. It was an easy job to register a manufacturer id to myself as explained on http://tsp.plasa.org/tsp/working_groups/CP/mfctrIDs.php. Feel free to use my manufacturer id yourself if you promise only to use it for experiments and never to put a real device that leaves your hands.If you plan for more please request your own manufacturer id and adjust the _devID definition to use it. You can find the new version of the library now on http://www.mathertel.de/Arduino/DMXSerial2.aspx. I will update the text of this site in the next days. [Less]